/** * Apply antialiasing coverage value to alpha values. */ static inline void apply_aa_coverage(SWspan *span) { const GLfloat *coverage = span->array->coverage; GLuint i; if (span->array->ChanType == GL_UNSIGNED_BYTE) { GLubyte (*rgba)[4] = span->array->rgba8; for (i = 0; i < span->end; i++) { const GLfloat a = rgba[i][ACOMP] * coverage[i]; rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0); ASSERT(coverage[i] >= 0.0); ASSERT(coverage[i] <= 1.0); } } else if (span->array->ChanType == GL_UNSIGNED_SHORT) { GLushort (*rgba)[4] = span->array->rgba16; for (i = 0; i < span->end; i++) { const GLfloat a = rgba[i][ACOMP] * coverage[i]; rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0); } } else { GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL]; for (i = 0; i < span->end; i++) { rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i]; /* clamp later */ } } }
/** * Apply fog to a span of RGBA pixels. * The fog value are either in the span->array->fog array or interpolated from * the fog/fogStep values. * They fog values are either fog coordinates (Z) or fog blend factors. * _PreferPixelFog should be in sync with that state! */ void _swrast_fog_rgba_span( const GLcontext *ctx, SWspan *span ) { const SWcontext *swrast = CONST_SWRAST_CONTEXT(ctx); GLfloat rFog, gFog, bFog; ASSERT(swrast->_FogEnabled); ASSERT(span->arrayMask & SPAN_RGBA); /* compute (scaled) fog color */ if (span->array->ChanType == GL_UNSIGNED_BYTE) { rFog = ctx->Fog.Color[RCOMP] * 255.0F; gFog = ctx->Fog.Color[GCOMP] * 255.0F; bFog = ctx->Fog.Color[BCOMP] * 255.0F; } else if (span->array->ChanType == GL_UNSIGNED_SHORT) { rFog = ctx->Fog.Color[RCOMP] * 65535.0F; gFog = ctx->Fog.Color[GCOMP] * 65535.0F; bFog = ctx->Fog.Color[BCOMP] * 65535.0F; } else { rFog = ctx->Fog.Color[RCOMP]; gFog = ctx->Fog.Color[GCOMP]; bFog = ctx->Fog.Color[BCOMP]; } if (swrast->_PreferPixelFog) { /* The span's fog values are fog coordinates, now compute blend factors * and blend the fragment colors with the fog color. */ switch (swrast->_FogMode) { case GL_LINEAR: { const GLfloat fogEnd = ctx->Fog.End; const GLfloat fogScale = (ctx->Fog.Start == ctx->Fog.End) ? 1.0F : 1.0F / (ctx->Fog.End - ctx->Fog.Start); if (span->array->ChanType == GL_UNSIGNED_BYTE) { GLubyte (*rgba)[4] = span->array->rgba8; FOG_LOOP(GLubyte, LINEAR_FOG); } else if (span->array->ChanType == GL_UNSIGNED_SHORT) { GLushort (*rgba)[4] = span->array->rgba16; FOG_LOOP(GLushort, LINEAR_FOG); } else { GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; ASSERT(span->array->ChanType == GL_FLOAT); FOG_LOOP(GLfloat, LINEAR_FOG); } } break; case GL_EXP: { const GLfloat density = -ctx->Fog.Density; if (span->array->ChanType == GL_UNSIGNED_BYTE) { GLubyte (*rgba)[4] = span->array->rgba8; FOG_LOOP(GLubyte, EXP_FOG); } else if (span->array->ChanType == GL_UNSIGNED_SHORT) { GLushort (*rgba)[4] = span->array->rgba16; FOG_LOOP(GLushort, EXP_FOG); } else { GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; ASSERT(span->array->ChanType == GL_FLOAT); FOG_LOOP(GLfloat, EXP_FOG); } } break; case GL_EXP2: { const GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density; if (span->array->ChanType == GL_UNSIGNED_BYTE) { GLubyte (*rgba)[4] = span->array->rgba8; FOG_LOOP(GLubyte, EXP2_FOG); } else if (span->array->ChanType == GL_UNSIGNED_SHORT) { GLushort (*rgba)[4] = span->array->rgba16; FOG_LOOP(GLushort, EXP2_FOG); } else { GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; ASSERT(span->array->ChanType == GL_FLOAT); FOG_LOOP(GLfloat, EXP2_FOG); } } break; default: _mesa_problem(ctx, "Bad fog mode in _swrast_fog_rgba_span"); return; } } else { /* The span's fog start/step/array values are blend factors in [0,1]. * They were previously computed per-vertex. */ if (span->array->ChanType == GL_UNSIGNED_BYTE) { GLubyte (*rgba)[4] = span->array->rgba8; FOG_LOOP(GLubyte, BLEND_FOG); } else if (span->array->ChanType == GL_UNSIGNED_SHORT) { GLushort (*rgba)[4] = span->array->rgba16; FOG_LOOP(GLushort, BLEND_FOG); } else { GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; ASSERT(span->array->ChanType == GL_FLOAT); FOG_LOOP(GLfloat, BLEND_FOG); } } }
void CreateHeightFieldMesh (NewtonCollision* collision, Entity* ent) { int width; int height; dFloat hScale; dFloat vScale; unsigned short* elevations; NewtonCollisionInfoRecord collisionInfo; // keep the compiler happy memset (&collisionInfo, 0, sizeof (NewtonCollisionInfoRecord)); NewtonCollisionGetInfo (collision, &collisionInfo); // get the info from the collision mesh and create a visual mesh width = collisionInfo.m_heightField.m_width; height = collisionInfo.m_heightField.m_height; elevations = collisionInfo.m_heightField.m_elevation; vScale = collisionInfo.m_heightField.m_verticalScale; hScale = collisionInfo.m_heightField.m_horizonalScale; // allocate space to store vertex data ent->m_vertexCount = width * height; ent->m_vertex = (dFloat*) malloc (3 * width * height * sizeof (dFloat)); ent->m_normal = (dFloat*) malloc (3 * width * height * sizeof (dFloat)); ent->m_uv = (dFloat*) malloc (2 * width * height * sizeof (dFloat)); // scan the height field and convert every cell into two triangles for (int z = 0; z < height; z ++) { int z0; int z1; z0 = ((z - 1) < 0) ? 0 : z - 1; z1 = ((z + 1) > (height - 1)) ? height - 1 : z + 1 ; for (int x = 0; x < width; x ++) { int x0; int x1; x0 = ((x - 1) < 0) ? 0 : x - 1; x1 = ((x + 1) > (width - 1)) ? width - 1 : x + 1 ; dVector p0 (hScale * x0, elevations[z * width + x1] * vScale, hScale * z); dVector p1 (hScale * x1, elevations[z * width + x0] * vScale, hScale * z); dVector x10 (p1 - p0); dVector q0 (hScale * x, elevations[z0 * width + x] * vScale, hScale * z0); dVector q1 (hScale * x, elevations[z1 * width + x] * vScale, hScale * z1); dVector z10 (q1 - q0); dVector normal (z10 * x10); normal = normal.Scale (dSqrt (1.0f / (normal % normal))); dVector point (hScale * x, elevations[z * width + x] * vScale, hScale * z); ent->m_vertex[(z * width + x) * 3 + 0] = point.m_x; ent->m_vertex[(z * width + x) * 3 + 1] = point.m_y; ent->m_vertex[(z * width + x) * 3 + 2] = point.m_z; ent->m_normal[(z * width + x) * 3 + 0] = normal.m_x; ent->m_normal[(z * width + x) * 3 + 1] = normal.m_y; ent->m_normal[(z * width + x) * 3 + 2] = normal.m_z; ent->m_uv[(z * width + x) * 2 + 0] = x * TEXTURE_SCALE; ent->m_uv[(z * width + x) * 2 + 1] = z * TEXTURE_SCALE; } } // since the bitmap sample is 256 x 256, i fix into a single 16 bit index vertex array with ent->m_subMeshCount = 1; ent->m_subMeshes = (Entity::SubMesh*) malloc (sizeof (Entity::SubMesh)); // allocate space to the index list ent->m_subMeshes[0].m_textureHandle = LoadTexture ("grassAndDirt.tga"); ent->m_subMeshes[0].m_indexCount = (width - 1) * (height - 1) * 6; ent->m_subMeshes[0].m_indexArray = (unsigned short*) malloc (ent->m_subMeshes[0].m_indexCount * sizeof (unsigned short)); // now following the grid pattern and create and index list int index; int vertexIndex; index = 0; vertexIndex = 0; for (int z = 0; z < height - 1; z ++) { vertexIndex = z * width; for (int x = 0; x < width - 1; x ++) { ent->m_subMeshes[0].m_indexArray[index + 0] = GLushort (vertexIndex); ent->m_subMeshes[0].m_indexArray[index + 1] = GLushort (vertexIndex + width); ent->m_subMeshes[0].m_indexArray[index + 2] = GLushort (vertexIndex + 1); index += 3; ent->m_subMeshes[0].m_indexArray[index + 0] = GLushort (vertexIndex + 1); ent->m_subMeshes[0].m_indexArray[index + 1] = GLushort (vertexIndex + width); ent->m_subMeshes[0].m_indexArray[index + 2] = GLushort (vertexIndex + width + 1); index += 3; vertexIndex ++; } } // Optimize the mesh for hardware rendering if possible ent->OptimizeMesh(); /* dVector boxP0; dVector boxP1; // get the position of the aabb of this geometry dMatrix matrix (ent->m_curRotation, ent->m_curPosition); NewtonCollisionCalculateAABB (collision, &matrix[0][0], &boxP0.m_x, &boxP1.m_x); // place the origin of the visual mesh at the center of the height field matrix.m_posit = (boxP0 + boxP1).Scale (-0.5f); matrix.m_posit.m_w = 1.0f; ent->m_curPosition = matrix.m_posit; ent->m_prevPosition = matrix.m_posit; // create the level rigid body body = NewtonCreateBody(world, collision); // release the collision tree (this way the application does not have to do book keeping of Newton objects NewtonReleaseCollision (world, collision); // save the pointer to the graphic object with the body. NewtonBodySetUserData (body, ent); // set the global position of this body NewtonBodySetMatrix (body, &matrix[0][0]); // set the destructor for this object // NewtonBodySetDestructorCallback (body, Destructor); // get the position of the aabb of this geometry NewtonCollisionCalculateAABB (collision, &matrix[0][0], &boxP0.m_x, &boxP1.m_x); // add some extra padding the world size boxP0.m_x -= 10.0f; boxP0.m_y -= 10.0f; boxP0.m_z -= 10.0f; boxP1.m_x += 10.0f; boxP1.m_y += 400.0f; boxP1.m_z += 10.0f; // set the world size NewtonSetWorldSize (world, &boxP0.m_x, &boxP1.m_x); return body; */ }
/** * Interpolate primary colors to fill in the span->array->rgba8 (or rgb16) * color array. */ static inline void interpolate_int_colors(struct gl_context *ctx, SWspan *span) { #if CHAN_BITS != 32 const GLuint n = span->end; GLuint i; ASSERT(!(span->arrayMask & SPAN_RGBA)); #endif switch (span->array->ChanType) { #if CHAN_BITS != 32 case GL_UNSIGNED_BYTE: { GLubyte (*rgba)[4] = span->array->rgba8; if (span->interpMask & SPAN_FLAT) { GLubyte color[4]; color[RCOMP] = FixedToInt(span->red); color[GCOMP] = FixedToInt(span->green); color[BCOMP] = FixedToInt(span->blue); color[ACOMP] = FixedToInt(span->alpha); for (i = 0; i < n; i++) { COPY_4UBV(rgba[i], color); } } else { GLfixed r = span->red; GLfixed g = span->green; GLfixed b = span->blue; GLfixed a = span->alpha; GLint dr = span->redStep; GLint dg = span->greenStep; GLint db = span->blueStep; GLint da = span->alphaStep; for (i = 0; i < n; i++) { rgba[i][RCOMP] = FixedToChan(r); rgba[i][GCOMP] = FixedToChan(g); rgba[i][BCOMP] = FixedToChan(b); rgba[i][ACOMP] = FixedToChan(a); r += dr; g += dg; b += db; a += da; } } } break; case GL_UNSIGNED_SHORT: { GLushort (*rgba)[4] = span->array->rgba16; if (span->interpMask & SPAN_FLAT) { GLushort color[4]; color[RCOMP] = FixedToInt(span->red); color[GCOMP] = FixedToInt(span->green); color[BCOMP] = FixedToInt(span->blue); color[ACOMP] = FixedToInt(span->alpha); for (i = 0; i < n; i++) { COPY_4V(rgba[i], color); } } else { GLushort (*rgba)[4] = span->array->rgba16; GLfixed r, g, b, a; GLint dr, dg, db, da; r = span->red; g = span->green; b = span->blue; a = span->alpha; dr = span->redStep; dg = span->greenStep; db = span->blueStep; da = span->alphaStep; for (i = 0; i < n; i++) { rgba[i][RCOMP] = FixedToChan(r); rgba[i][GCOMP] = FixedToChan(g); rgba[i][BCOMP] = FixedToChan(b); rgba[i][ACOMP] = FixedToChan(a); r += dr; g += dg; b += db; a += da; } } } break; #endif case GL_FLOAT: interpolate_active_attribs(ctx, span, FRAG_BIT_COL); break; default: _mesa_problem(ctx, "bad datatype 0x%x in interpolate_int_colors", span->array->ChanType); } span->arrayMask |= SPAN_RGBA; }
/** * Apply the color mask to a span of rgba values. */ void _swrast_mask_rgba_span(struct gl_context *ctx, struct gl_renderbuffer *rb, SWspan *span) { const GLuint n = span->end; void *rbPixels; ASSERT(n < MAX_WIDTH); ASSERT(span->arrayMask & SPAN_RGBA); rbPixels = _swrast_get_dest_rgba(ctx, rb, span); /* * Do component masking. * Note that we're not using span->array->mask[] here. We could... */ if (span->array->ChanType == GL_UNSIGNED_BYTE) { /* treat 4xGLubyte as 1xGLuint */ const GLuint srcMask = *((GLuint *) ctx->Color.ColorMask); const GLuint dstMask = ~srcMask; const GLuint *dst = (const GLuint *) rbPixels; GLuint *src = (GLuint *) span->array->rgba8; GLuint i; for (i = 0; i < n; i++) { src[i] = (src[i] & srcMask) | (dst[i] & dstMask); } } else if (span->array->ChanType == GL_UNSIGNED_SHORT) { /* 2-byte components */ /* XXX try to use 64-bit arithmetic someday */ const GLushort rMask = ctx->Color.ColorMask[RCOMP] ? 0xffff : 0x0; const GLushort gMask = ctx->Color.ColorMask[GCOMP] ? 0xffff : 0x0; const GLushort bMask = ctx->Color.ColorMask[BCOMP] ? 0xffff : 0x0; const GLushort aMask = ctx->Color.ColorMask[ACOMP] ? 0xffff : 0x0; const GLushort (*dst)[4] = (const GLushort (*)[4]) rbPixels; GLushort (*src)[4] = span->array->rgba16; GLuint i; for (i = 0; i < n; i++) { src[i][RCOMP] = (src[i][RCOMP] & rMask) | (dst[i][RCOMP] & ~rMask); src[i][GCOMP] = (src[i][GCOMP] & gMask) | (dst[i][GCOMP] & ~gMask); src[i][BCOMP] = (src[i][BCOMP] & bMask) | (dst[i][BCOMP] & ~bMask); src[i][ACOMP] = (src[i][ACOMP] & aMask) | (dst[i][ACOMP] & ~aMask); } } else { /* 4-byte components */ const GLuint rMask = ctx->Color.ColorMask[RCOMP] ? ~0x0 : 0x0; const GLuint gMask = ctx->Color.ColorMask[GCOMP] ? ~0x0 : 0x0; const GLuint bMask = ctx->Color.ColorMask[BCOMP] ? ~0x0 : 0x0; const GLuint aMask = ctx->Color.ColorMask[ACOMP] ? ~0x0 : 0x0; const GLuint (*dst)[4] = (const GLuint (*)[4]) rbPixels; GLuint (*src)[4] = (GLuint (*)[4]) span->array->attribs[FRAG_ATTRIB_COL]; GLuint i; for (i = 0; i < n; i++) { src[i][RCOMP] = (src[i][RCOMP] & rMask) | (dst[i][RCOMP] & ~rMask); src[i][GCOMP] = (src[i][GCOMP] & gMask) | (dst[i][GCOMP] & ~gMask); src[i][BCOMP] = (src[i][BCOMP] & bMask) | (dst[i][BCOMP] & ~bMask); src[i][ACOMP] = (src[i][ACOMP] & aMask) | (dst[i][ACOMP] & ~aMask); } } }
void xglrenderer::ev_sphere(xobjevent *pev) { xobject *pNotifier; int evid; float detail; if(!((xpackev*)pev)->unpack("odf",&pNotifier,&evid,&detail)) { wyc_error("xglrenderer::sphere: bad args"); return; } unsigned batchid=strhash("sphere"); xvertex_batch *pbatch=(xvertex_batch*)m_groups[GROUP_BATCH]->request(batchid); if(pbatch==0) { // a quarter of circle have 4~16 points unsigned quarter=4+unsigned(detail*12); unsigned circle=quarter*4; float step=float(XMATH_HPI/quarter); float rad=step; // pre-compute the sin & cos float *sina=new float[quarter], *cosa=new float[quarter]; sina[0]=0, cosa[0]=1; for(unsigned i=1; i<quarter; ++i) { sina[i]=sin(rad); cosa[i]=cos(rad); rad+=step; } // fill vertex positions unsigned vertexCount=(2*quarter-1)*quarter*4+2; xvec3f_t *buffer=new xvec3f_t[vertexCount]; xvec3f_t *part1=buffer, *part2, *part3, *part4; // top half of sphere part1->set(0,1,0); part1+=1; for(int i=quarter-1; i>=0; --i) { float y=sina[i], len=cosa[i]; part2=part1+quarter; part3=part2+quarter; part4=part3+quarter; part1->set(len,y,0); part2->set(0,y,len); part3->set(-len,y,0); part4->set(0,y,-len); part2+=quarter; part4+=quarter; for(unsigned j=1; j<quarter; ++j) { float x=len*cosa[j], z=len*sina[j]; ++part1; part1->set(x,y,z); --part2; part2->set(-x,y,z); ++part3; part3->set(-x,y,-z); --part4; part4->set(x,y,-z); } part1=part4+quarter-1; } // bottom half of sphere part1=buffer+1; part2=buffer+vertexCount-1; part2->set(0,-1,0); for(unsigned i=quarter-1; i>0; --i) { part2-=circle; for(unsigned j=0; j<circle; ++j, ++part1) part2[j].set(part1->x,-part1->y,part1->z); } assert(unsigned(part2-part1)==circle); // vertex buffer GLuint vertbuffs[2]; glGenBuffers(2,vertbuffs); glBindBuffer(GL_ARRAY_BUFFER,vertbuffs[0]); glBufferData(GL_ARRAY_BUFFER,vertexCount*sizeof(xvec3f_t),buffer,GL_STATIC_DRAW); delete [] buffer; delete [] sina; delete [] cosa; // index buffer unsigned indexCount=48*quarter*quarter-24*quarter; assert(indexCount<65536); GLushort *index=new GLushort[indexCount]; GLushort *iter=index; GLushort vidx=1; while(vidx<circle) { *iter++=0; *iter++=vidx+1; *iter++=vidx; ++vidx; } *iter++=0; *iter++=1; *iter++=vidx; vidx=1; for(unsigned i=2*quarter-2; i>0; --i) { unsigned end=vidx+circle-1; while(vidx<end) { iter[0]=vidx; iter[1]=vidx+1; iter[2]=GLushort(vidx+circle); iter[3]=iter[2]; iter[4]=iter[1]; iter[5]=GLushort(iter[1]+circle); iter+=6; ++vidx; } iter[0]=vidx; iter[1]=GLushort(vidx+1-circle); iter[2]=GLushort(vidx+circle); iter[3]=iter[2]; iter[4]=iter[1]; iter[5]=vidx+1; iter+=6; ++vidx; } GLushort last=GLushort(vertexCount-1); for(unsigned i=1; i<circle; ++i) { *iter++=last; *iter++=vidx; *iter++=vidx+1; ++vidx; } *iter++=last; *iter++=vidx; *iter++=GLushort(vidx+1-circle); assert(unsigned(iter-index)==indexCount); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,vertbuffs[1]); glBufferData(GL_ELEMENT_ARRAY_BUFFER,indexCount*sizeof(GLushort),index,GL_STATIC_DRAW); delete [] index; xvertex_buffer *pvb; if(GLEW_ARB_vertex_array_object) { GLuint vao; glGenVertexArrays(1,&vao); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER,vertbuffs[0]); glVertexAttribPointer(USAGE_POSITION,3,GL_FLOAT,GL_FALSE,0,(void*)0); glEnableVertexAttribArray(USAGE_POSITION); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,vertbuffs[1]); glBindVertexArray(0); pbatch=(xvertex_batch*)m_groups[GROUP_BATCH]->create(batchid,(void*)vao); pvb=wycnew xvertex_buffer; pvb->create(vertbuffs[0]); pbatch->add_buffer(pvb); } else { pbatch=(xvertex_batch*)m_groups[GROUP_BATCH]->create(batchid,0); pvb=wycnew xvertex_buffer; pvb->create(vertbuffs[0]); pbatch->add_buffer(pvb,USAGE_POSITION,3,GL_FLOAT,false,0,0); } pvb=wycnew xvertex_buffer; pvb->create(vertbuffs[1]); pbatch->set_index(pvb,GL_UNSIGNED_SHORT); pbatch->set_mode(GL_TRIANGLES,indexCount,0); } // if (pbatch==0) if(pNotifier) { pev=xpackev::pack("o",pbatch); pNotifier->on_event(evid,pev); } }
/** * Apply fog to a span of RGBA pixels. * The fog value are either in the span->array->fog array or interpolated from * the fog/fogStep values. * They fog values are either fog coordinates (Z) or fog blend factors. * _PreferPixelFog should be in sync with that state! */ void _swrast_fog_rgba_span( const GLcontext *ctx, SWspan *span ) { const SWcontext *swrast = SWRAST_CONTEXT(ctx); GLfloat rFog, gFog, bFog; const GLuint haveW = (span->interpMask & SPAN_W); ASSERT(swrast->_FogEnabled); ASSERT((span->interpMask | span->arrayMask) & SPAN_FOG); ASSERT(span->arrayMask & SPAN_RGBA); if (span->array->ChanType == GL_UNSIGNED_BYTE) { rFog = ctx->Fog.Color[RCOMP] * 255.0; gFog = ctx->Fog.Color[GCOMP] * 255.0; bFog = ctx->Fog.Color[BCOMP] * 255.0; } else if (span->array->ChanType == GL_UNSIGNED_SHORT) { rFog = ctx->Fog.Color[RCOMP] * 65535.0; gFog = ctx->Fog.Color[GCOMP] * 65535.0; bFog = ctx->Fog.Color[BCOMP] * 65535.0; } else { rFog = ctx->Fog.Color[RCOMP]; gFog = ctx->Fog.Color[GCOMP]; bFog = ctx->Fog.Color[BCOMP]; } /* NOTE: if haveW is true, that means the fog start/step values are * perspective-corrected and we have to divide each fog coord by W. */ /* we need to compute fog blend factors */ if (swrast->_PreferPixelFog) { /* The span's fog values are fog coordinates, now compute blend factors * and blend the fragment colors with the fog color. */ const GLfloat fogEnd = ctx->Fog.End; const GLfloat fogScale = (ctx->Fog.Start == ctx->Fog.End) ? 1.0F : 1.0F / (ctx->Fog.End - ctx->Fog.Start); const GLfloat density = -ctx->Fog.Density; const GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density; switch (swrast->_FogMode) { case GL_LINEAR: #define COMPUTE_F f = (fogEnd - FABSF(fogCoord) / w) * fogScale; if (span->array->ChanType == GL_UNSIGNED_BYTE) { GLubyte (*rgba)[4] = span->array->color.sz1.rgba; FOG_LOOP(GLubyte, COMPUTE_F); } else if (span->array->ChanType == GL_UNSIGNED_SHORT) { GLushort (*rgba)[4] = span->array->color.sz2.rgba; FOG_LOOP(GLushort, COMPUTE_F); } else { GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; ASSERT(span->array->ChanType == GL_FLOAT); FOG_LOOP(GLfloat, COMPUTE_F); } #undef COMPUTE_F break; case GL_EXP: #define COMPUTE_F f = EXPF(density * FABSF(fogCoord) / w); if (span->array->ChanType == GL_UNSIGNED_BYTE) { GLubyte (*rgba)[4] = span->array->color.sz1.rgba; FOG_LOOP(GLubyte, COMPUTE_F); } else if (span->array->ChanType == GL_UNSIGNED_SHORT) { GLushort (*rgba)[4] = span->array->color.sz2.rgba; FOG_LOOP(GLushort, COMPUTE_F); } else { GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; ASSERT(span->array->ChanType == GL_FLOAT); FOG_LOOP(GLfloat, COMPUTE_F); } #undef COMPUTE_F break; case GL_EXP2: #define COMPUTE_F const GLfloat coord = fogCoord / w; \ GLfloat tmp = negDensitySquared * coord * coord; \ if (tmp < FLT_MIN_10_EXP) \ tmp = FLT_MIN_10_EXP; \ f = EXPF(tmp); if (span->array->ChanType == GL_UNSIGNED_BYTE) { GLubyte (*rgba)[4] = span->array->color.sz1.rgba; FOG_LOOP(GLubyte, COMPUTE_F); } else if (span->array->ChanType == GL_UNSIGNED_SHORT) { GLushort (*rgba)[4] = span->array->color.sz2.rgba; FOG_LOOP(GLushort, COMPUTE_F); } else { GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; ASSERT(span->array->ChanType == GL_FLOAT); FOG_LOOP(GLfloat, COMPUTE_F); } #undef COMPUTE_F break; default: _mesa_problem(ctx, "Bad fog mode in _swrast_fog_rgba_span"); return; } } else if (span->arrayMask & SPAN_FOG) { /* The span's fog array values are blend factors. * They were previously computed per-vertex. */ GLuint i; if (span->array->ChanType == GL_UNSIGNED_BYTE) { GLubyte (*rgba)[4] = span->array->color.sz1.rgba; for (i = 0; i < span->end; i++) { const GLfloat f = span->array->attribs[FRAG_ATTRIB_FOGC][i][0]; const GLfloat oneMinusF = 1.0F - f; rgba[i][RCOMP] = (GLubyte) (f * rgba[i][RCOMP] + oneMinusF * rFog); rgba[i][GCOMP] = (GLubyte) (f * rgba[i][GCOMP] + oneMinusF * gFog); rgba[i][BCOMP] = (GLubyte) (f * rgba[i][BCOMP] + oneMinusF * bFog); } } else if (span->array->ChanType == GL_UNSIGNED_SHORT) { GLushort (*rgba)[4] = span->array->color.sz2.rgba; for (i = 0; i < span->end; i++) { const GLfloat f = span->array->attribs[FRAG_ATTRIB_FOGC][i][0]; const GLfloat oneMinusF = 1.0F - f; rgba[i][RCOMP] = (GLushort) (f * rgba[i][RCOMP] + oneMinusF * rFog); rgba[i][GCOMP] = (GLushort) (f * rgba[i][GCOMP] + oneMinusF * gFog); rgba[i][BCOMP] = (GLushort) (f * rgba[i][BCOMP] + oneMinusF * bFog); } } else { GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; ASSERT(span->array->ChanType == GL_FLOAT); for (i = 0; i < span->end; i++) { const GLfloat f = span->array->attribs[FRAG_ATTRIB_FOGC][i][0]; const GLfloat oneMinusF = 1.0F - f; rgba[i][RCOMP] = f * rgba[i][RCOMP] + oneMinusF * rFog; rgba[i][GCOMP] = f * rgba[i][GCOMP] + oneMinusF * gFog; rgba[i][BCOMP] = f * rgba[i][BCOMP] + oneMinusF * bFog; } } } else { /* The span's fog start/step values are blend factors. * They were previously computed per-vertex. */ #define COMPUTE_F f = fogCoord / w; if (span->array->ChanType == GL_UNSIGNED_BYTE) { GLubyte (*rgba)[4] = span->array->color.sz1.rgba; FOG_LOOP(GLubyte, COMPUTE_F); } else if (span->array->ChanType == GL_UNSIGNED_SHORT) { GLushort (*rgba)[4] = span->array->color.sz2.rgba; FOG_LOOP(GLushort, COMPUTE_F); } else { GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; ASSERT(span->array->ChanType == GL_FLOAT); FOG_LOOP(GLfloat, COMPUTE_F); } #undef COMPUTE_F } }