This is triangle.c in view mode; [Download] [Up]
/* $Id: triangle.c,v 1.5 1996/10/01 03:31:17 brianp Exp $ */ /* * Mesa 3-D graphics library * Version: 2.0 * Copyright (C) 1995-1996 Brian Paul * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * $Log: triangle.c,v $ * Revision 1.5 1996/10/01 03:31:17 brianp * use new FixedToDepth() macro * * Revision 1.4 1996/09/27 01:30:37 brianp * removed unneeded INTERP_ALPHA from flat_rgba_triangle() * * Revision 1.3 1996/09/15 14:19:16 brianp * now use GLframebuffer and GLvisual * * Revision 1.2 1996/09/15 01:48:58 brianp * removed #define NULL 0 * * Revision 1.1 1996/09/13 01:38:16 brianp * Initial revision * */ /* * Triangle rasterizers */ #include <assert.h> #include <math.h> #include <stdio.h> #include "depth.h" #include "feedback.h" #include "macros.h" #include "span.h" #include "triangle.h" #include "types.h" #include "vb.h" /* * Put triangle in feedback buffer. */ static void feedback_triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv ) { struct vertex_buffer *VB = ctx->VB; GLfloat x, y, z, w; GLfloat tc[4]; GLfloat color[4]; GLuint i, v; FEEDBACK_TOKEN( ctx, (GLfloat) GL_POLYGON_TOKEN ); FEEDBACK_TOKEN( ctx, (GLfloat) 3 ); /* three vertices */ for (i=0;i<3;i++) { if (i==0) v = v0; else if (i==1) v = v1; else v = v2; x = VB->Win[v][0]; y = VB->Win[v][1]; z = VB->Win[v][2] / DEPTH_SCALE; w = VB->Clip[v][3]; /* convert color from integer back to a float in [0,1] */ color[0] = (GLfloat) VB->Color[v][0] * ctx->Visual->InvRedScale; color[1] = (GLfloat) VB->Color[v][1] * ctx->Visual->InvGreenScale; color[2] = (GLfloat) VB->Color[v][2] * ctx->Visual->InvBlueScale; color[3] = (GLfloat) VB->Color[v][3] * ctx->Visual->InvAlphaScale; tc[0] = VB->TexCoord[v][0]; tc[1] = VB->TexCoord[v][1]; tc[2] = 0.0F; /* TODO: R, Q components */ tc[3] = 1.0F; gl_feedback_vertex( ctx, x, y, z, w, color, (GLfloat) VB->Index[v], tc ); } } /* * Put triangle in selection buffer. */ static void select_triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv ) { struct vertex_buffer *VB = ctx->VB; gl_update_hitflag( ctx, VB->Win[v0][2] / DEPTH_SCALE ); gl_update_hitflag( ctx, VB->Win[v1][2] / DEPTH_SCALE ); gl_update_hitflag( ctx, VB->Win[v2][2] / DEPTH_SCALE ); } /* * Render a flat-shaded color index triangle. */ static void flat_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv ) { #define INTERP_Z 1 #define SETUP_CODE \ GLuint index = VB->Index[pv]; \ if (!VB->MonoColor) { \ /* set the color index */ \ (*ctx->Driver.Index)( ctx, index ); \ } #define INNER_LOOP( LEFT, RIGHT, Y ) \ { \ GLint i, n = RIGHT-LEFT; \ GLdepth zspan[MAX_WIDTH]; \ if (n>0) { \ for (i=0;i<n;i++) { \ zspan[i] = FixedToDepth(ffz); \ ffz += fdzdx; \ } \ gl_write_monoindex_span( ctx, n, LEFT, Y, \ zspan, index, GL_POLYGON ); \ } \ } #include "tritemp.h" } /* * Render a smooth-shaded color index triangle. */ static void smooth_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv ) { #define INTERP_Z 1 #define INTERP_INDEX 1 #define INNER_LOOP( LEFT, RIGHT, Y ) \ { \ GLint i, n = RIGHT-LEFT; \ GLdepth zspan[MAX_WIDTH]; \ GLuint index[MAX_WIDTH]; \ if (n>0) { \ for (i=0;i<n;i++) { \ zspan[i] = FixedToDepth(ffz); \ index[i] = FixedToInt(ffi); \ ffz += fdzdx; \ ffi += fdidx; \ } \ gl_write_index_span( ctx, n, LEFT, Y, zspan, \ index, GL_POLYGON ); \ } \ } #include "tritemp.h" } /* * Render a flat-shaded RGBA triangle. */ static void flat_rgba_triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv ) { #define INTERP_Z 1 #define SETUP_CODE \ if (!VB->MonoColor) { \ /* set the color */ \ GLubyte r = VB->Color[pv][0]; \ GLubyte g = VB->Color[pv][1]; \ GLubyte b = VB->Color[pv][2]; \ GLubyte a = VB->Color[pv][3]; \ (*ctx->Driver.Color)( ctx, r, g, b, a ); \ } #define INNER_LOOP( LEFT, RIGHT, Y ) \ { \ GLint i, n = RIGHT-LEFT; \ GLdepth zspan[MAX_WIDTH]; \ if (n>0) { \ for (i=0;i<n;i++) { \ zspan[i] = FixedToDepth(ffz); \ ffz += fdzdx; \ } \ gl_write_monocolor_span( ctx, n, LEFT, Y, zspan, \ VB->Color[pv][0], VB->Color[pv][1],\ VB->Color[pv][2], VB->Color[pv][3],\ GL_POLYGON ); \ } \ } #include "tritemp.h" } /* * Render a smooth-shaded RGBA triangle. */ static void smooth_rgba_triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv ) { #define INTERP_Z 1 #define INTERP_RGB 1 #define INTERP_ALPHA 1 #define INNER_LOOP( LEFT, RIGHT, Y ) \ { \ GLint i, n = RIGHT-LEFT; \ GLdepth zspan[MAX_WIDTH]; \ GLubyte red[MAX_WIDTH], green[MAX_WIDTH]; \ GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH]; \ if (n>0) { \ for (i=0;i<n;i++) { \ zspan[i] = FixedToDepth(ffz); \ red[i] = FixedToInt(ffr); \ green[i] = FixedToInt(ffg); \ blue[i] = FixedToInt(ffb); \ alpha[i] = FixedToInt(ffa); \ ffz += fdzdx; \ ffr += fdrdx; \ ffg += fdgdx; \ ffb += fdbdx; \ ffa += fdadx; \ } \ gl_write_color_span( ctx, n, LEFT, Y, zspan, \ red, green, blue, alpha, \ GL_POLYGON ); \ } \ } #include "tritemp.h" } /* * Render an RGB, GL_DECAL, textured triangle. * Interpolate S,T only w/out mipmapping or perspective correction. */ static void simple_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv ) { #define INTERP_ST 1 #define S_SCALE twidth #define T_SCALE theight #define SETUP_CODE \ GLfloat twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width; \ GLfloat theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;\ GLint twidth_log2 = ctx->Texture.Current2D->Image[0]->WidthLog2; \ GLubyte *texture = ctx->Texture.Current2D->Image[0]->Data; \ GLint smask = ctx->Texture.Current2D->Image[0]->Width - 1; \ GLint tmask = ctx->Texture.Current2D->Image[0]->Height - 1; #define INNER_LOOP( LEFT, RIGHT, Y ) \ { \ GLint i, n = RIGHT-LEFT; \ GLubyte red[MAX_WIDTH], green[MAX_WIDTH]; \ GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH]; \ if (n>0) { \ for (i=0;i<n;i++) { \ GLint s = FixedToInt(ffs) & smask; \ GLint t = FixedToInt(fft) & tmask; \ GLint pos = (t << twidth_log2) + s; \ pos = pos + pos + pos; /* multiply by 3 */ \ red[i] = texture[pos]; \ green[i] = texture[pos+1]; \ blue[i] = texture[pos+2]; \ alpha[i] = 255; \ ffs += fdsdx; \ fft += fdtdx; \ } \ (*ctx->Driver.WriteColorSpan)( ctx, n, LEFT, Y, \ red, green, blue, alpha, NULL ); \ } \ } #include "tritemp.h" } /* * Render an RGB, GL_DECAL, textured triangle. * Interpolate S,T, GL_LESS depth test, w/out mipmapping or * perspective correction. */ static void simple_z_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv ) { #define INTERP_Z 1 #define INTERP_ST 1 #define S_SCALE twidth #define T_SCALE theight #define SETUP_CODE \ GLfloat twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width; \ GLfloat theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;\ GLint twidth_log2 = ctx->Texture.Current2D->Image[0]->WidthLog2; \ GLubyte *texture = ctx->Texture.Current2D->Image[0]->Data; \ GLint smask = ctx->Texture.Current2D->Image[0]->Width - 1; \ GLint tmask = ctx->Texture.Current2D->Image[0]->Height - 1; #define INNER_LOOP( LEFT, RIGHT, Y ) \ { \ GLint i, n = RIGHT-LEFT; \ GLubyte red[MAX_WIDTH], green[MAX_WIDTH]; \ GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH]; \ GLubyte mask[MAX_WIDTH]; \ if (n>0) { \ for (i=0;i<n;i++) { \ GLdepth z = FixedToDepth(ffz); \ if (z < zRow[i]) { \ GLint s = FixedToInt(ffs) & smask; \ GLint t = FixedToInt(fft) & tmask; \ GLint pos = (t << twidth_log2) + s; \ pos = pos + pos + pos; /* multiply by 3 */\ red[i] = texture[pos]; \ green[i] = texture[pos+1]; \ blue[i] = texture[pos+2]; \ alpha[i] = 255; \ zRow[i] = z; \ mask[i] = 1; \ } \ else { \ mask[i] = 0; \ } \ ffz += fdzdx; \ ffs += fdsdx; \ fft += fdtdx; \ } \ (*ctx->Driver.WriteColorSpan)( ctx, n, LEFT, Y, \ red, green, blue, alpha, mask ); \ } \ } #include "tritemp.h" } /* * Render a smooth-shaded, textured, RGBA triangle. * Interpolate S,T with perspective correction, w/out mipmapping. */ static void general_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv ) { #define INTERP_Z 1 #define INTERP_RGB 1 #define INTERP_ALPHA 1 #define INTERP_STW 1 #define S_SCALE 100.0F #define T_SCALE 100.0F #define SETUP_CODE \ GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \ GLint r, g, b, a; \ if (flat_shade) { \ r = VB->Color[pv][0]; \ g = VB->Color[pv][1]; \ b = VB->Color[pv][2]; \ a = VB->Color[pv][3]; \ } #define INNER_LOOP( LEFT, RIGHT, Y ) \ { \ GLint i, n = RIGHT-LEFT; \ GLdepth zspan[MAX_WIDTH]; \ GLubyte red[MAX_WIDTH], green[MAX_WIDTH]; \ GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH]; \ GLfloat s[MAX_WIDTH], t[MAX_WIDTH]; \ if (n>0) { \ if (flat_shade) { \ for (i=0;i<n;i++) { \ zspan[i] = FixedToDepth(ffz); \ red[i] = r; \ green[i] = g; \ blue[i] = b; \ alpha[i] = a; \ s[i] = ss/ww; \ t[i] = tt/ww; \ ffz += fdzdx; \ ss += dsdx; \ tt += dtdx; \ ww += dwdx; \ } \ } \ else { \ for (i=0;i<n;i++) { \ zspan[i] = FixedToDepth(ffz); \ red[i] = FixedToInt(ffr); \ green[i] = FixedToInt(ffg); \ blue[i] = FixedToInt(ffb); \ alpha[i] = FixedToInt(ffa); \ s[i] = ss/ww; \ t[i] = tt/ww; \ ffz += fdzdx; \ ffr += fdrdx; \ ffg += fdgdx; \ ffb += fdbdx; \ ffa += fdadx; \ ss += dsdx; \ tt += dtdx; \ ww += dwdx; \ } \ } \ gl_write_texture_span( ctx, n, LEFT, Y, zspan, \ s, t, NULL, \ red, green, blue, alpha, \ GL_POLYGON ); \ } \ } #include "tritemp.h" } /* * Compute the lambda (texture level value) for a fragment. */ static GLfloat compute_lambda( GLfloat s, GLfloat t, GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, GLfloat w, GLfloat width, GLfloat height ) { /* TODO: this function can probably be optimized a bit */ GLfloat invw = 1.0F / w; GLfloat s0, t0, s1, t1, s2, t2; GLfloat dudx, dudy, dvdx, dvdy; GLfloat r1, r2, rho; s0 = s * invw; t0 = t * invw; s1 = (s+dsdx) * invw; t1 = (t+dtdx) * invw; s2 = (s+dsdy) * invw; t2 = (t+dtdy) * invw; dudx = (s1-s0) * width; dudy = (s2-s0) * width; dvdx = (t1-t0) * height; dvdy = (t2-t0) * height; /* r1 = sqrt( dudx * dudx + dvdx * dvdx ); */ /* r2 = sqrt( dudy * dudy + dvdy * dvdy ); */ if (dudx<0.0F) dudx = -dudx; if (dudy<0.0F) dudy = -dudy; if (dvdx<0.0F) dvdx = -dvdx; if (dvdy<0.0F) dvdy = -dvdy; r1 = MAX2( dudx, dudy ); r2 = MAX2( dvdx, dvdy ); rho = MAX2(r1,r2); if (rho<=0.0F) { return 0.0F; } else { /* return log base 2 of rho */ return log(rho) * 1.442695; /* 1.442695 = 1/log(2) */ } } /* * Render a smooth-shaded, textured, RGBA triangle. * Interpolate S,T with perspective correction and mipmapping. */ static void mipmap_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv ) { #define INTERP_Z 1 #define INTERP_RGB 1 #define INTERP_ALPHA 1 #define INTERP_STW 1 #define SETUP_CODE \ GLfloat twidth = (GLfloat) ctx->Texture.Current2D->Image[0]->Width; \ GLfloat theight = (GLfloat) ctx->Texture.Current2D->Image[0]->Height;\ GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \ GLint r, g, b, a; \ if (flat_shade) { \ r = VB->Color[pv][0]; \ g = VB->Color[pv][1]; \ b = VB->Color[pv][2]; \ a = VB->Color[pv][3]; \ } #define INNER_LOOP( LEFT, RIGHT, Y ) \ { \ GLint i, n = RIGHT-LEFT; \ GLdepth zspan[MAX_WIDTH]; \ GLubyte red[MAX_WIDTH], green[MAX_WIDTH]; \ GLubyte blue[MAX_WIDTH], alpha[MAX_WIDTH]; \ GLfloat s[MAX_WIDTH], t[MAX_WIDTH]; \ GLfloat lambda[MAX_WIDTH]; \ if (n>0) { \ if (flat_shade) { \ for (i=0;i<n;i++) { \ zspan[i] = FixedToDepth(ffz); \ red[i] = r; \ green[i] = g; \ blue[i] = b; \ alpha[i] = a; \ s[i] = ss/ww; \ t[i] = tt/ww; \ lambda[i] = compute_lambda( s[i], t[i], \ dsdx, dsdy, \ dtdx, dtdy, ww, \ twidth, theight ); \ ffz += fdzdx; \ ss += dsdx; \ tt += dtdx; \ ww += dwdx; \ } \ } \ else { \ for (i=0;i<n;i++) { \ zspan[i] = FixedToDepth(ffz); \ red[i] = FixedToInt(ffr); \ green[i] = FixedToInt(ffg); \ blue[i] = FixedToInt(ffb); \ alpha[i] = FixedToInt(ffa); \ s[i] = ss/ww; \ t[i] = tt/ww; \ lambda[i] = compute_lambda( s[i], t[i], \ dsdx, dsdy, \ dtdx, dtdy, ww, \ twidth, theight ); \ ffz += fdzdx; \ ffr += fdrdx; \ ffg += fdgdx; \ ffb += fdbdx; \ ffa += fdadx; \ ss += dsdx; \ tt += dtdx; \ ww += dwdx; \ } \ } \ gl_write_texture_span( ctx, n, LEFT, Y, zspan, \ s, t, lambda, \ red, green, blue, alpha, \ GL_POLYGON ); \ } \ } #include "tritemp.h" } /* * Determine which triangle rendering function to use given the current * rendering context. */ void gl_set_triangle_function( GLcontext *ctx ) { GLboolean rgbmode = ctx->Visual->RGBAflag; if (ctx->RenderMode==GL_RENDER) { if (ctx->Driver.TriangleFunc) { /* Device driver will draw triangles. */ ctx->TriangleFunc = ctx->Driver.TriangleFunc; } else if (ctx->Texture.Enabled) { if ( (ctx->Texture.Enabled & 2) && ctx->Texture.Current2D->Complete && ctx->Texture.Current2D->MinFilter==GL_NEAREST && ctx->Texture.Current2D->MagFilter==GL_NEAREST && ctx->Texture.Current2D->WrapS==GL_REPEAT && ctx->Texture.Current2D->WrapT==GL_REPEAT && ctx->Texture.Current2D->Image[0]->Format==GL_RGB && (ctx->Texture.EnvMode==GL_DECAL || ctx->Texture.EnvMode==GL_REPLACE) && ctx->Hint.PerspectiveCorrection==GL_FASTEST && (ctx->RasterMask==DEPTH_BIT || ctx->RasterMask==0) && ctx->Depth.Func==GL_LESS && ctx->Depth.Mask==GL_TRUE && ctx->Polygon.StippleFlag==GL_FALSE && ctx->Visual->EightBitColor) { if (ctx->RasterMask==DEPTH_BIT) { ctx->TriangleFunc = simple_z_textured_triangle; } else { ctx->TriangleFunc = simple_textured_triangle; } } else { GLboolean mipmap = GL_TRUE; if (ctx->Texture.Enabled & 2) { if ( ctx->Texture.Current2D->MinFilter==GL_NEAREST || ctx->Texture.Current2D->MinFilter==GL_LINEAR) { mipmap = GL_FALSE; } } else { if ( ctx->Texture.Current1D->MinFilter==GL_NEAREST || ctx->Texture.Current1D->MinFilter==GL_LINEAR) { mipmap = GL_FALSE; } } ctx->TriangleFunc = mipmap ? mipmap_textured_triangle : general_textured_triangle; } } else { if (ctx->Light.ShadeModel==GL_SMOOTH) { /* smooth shaded, no texturing, stippled or some raster ops */ ctx->TriangleFunc = rgbmode ? smooth_rgba_triangle : smooth_ci_triangle; } else { /* flat shaded, no texturing, stippled or some raster ops */ ctx->TriangleFunc = rgbmode ? flat_rgba_triangle : flat_ci_triangle; } } } else if (ctx->RenderMode==GL_FEEDBACK) { ctx->TriangleFunc = feedback_triangle; } else { /* GL_SELECT mode */ ctx->TriangleFunc = select_triangle; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.