void DrawSingleDecal( decal_t *pDecal, msurface_t *fa ) { float *v; int i, numVerts; v = R_DecalSetupVerts( pDecal, fa, pDecal->texture, &numVerts ); if( !numVerts ) return; GL_Bind( GL_TEXTURE0, pDecal->texture ); pglBegin( GL_POLYGON ); for( i = 0; i < numVerts; i++, v += VERTEXSIZE ) { pglTexCoord2f( v[3], v[4] ); pglVertex3fv( v ); } pglEnd(); }
/* ==================== R_BuildMeshForDecal creates mesh for decal on first rendering ==================== */ msurfmesh_t *R_DecalCreateMesh( decalinfo_t *decalinfo, decal_t *pdecal, msurface_t *surf ) { float *v; uint i, bufSize; qboolean createSTverts = false; int numVerts, numElems; byte *buffer; msurfmesh_t *mesh; if( pdecal->mesh ) { // already have mesh return pdecal->mesh; } v = R_DecalSetupVerts( pdecal, surf, pdecal->texture, &numVerts ); if( !numVerts ) return NULL; // probably this never happens // allocate mesh numElems = (numVerts - 2) * 3; bufSize = sizeof( msurfmesh_t ) + numVerts * sizeof( glvert_t ) + numElems * sizeof( word ); buffer = Mem_Alloc( cls.mempool, bufSize ); mesh = (msurfmesh_t *)buffer; buffer += sizeof( msurfmesh_t ); mesh->numVerts = numVerts; mesh->numElems = numElems; // setup pointers mesh->verts = (glvert_t *)buffer; buffer += numVerts * sizeof( glvert_t ); mesh->elems = (word *)buffer; buffer += numElems * sizeof( word ); mesh->surf = surf; // NOTE: meshchains can be linked with one surface // create indices for( i = 0; i < mesh->numVerts - 2; i++ ) { mesh->elems[i*3+0] = 0; mesh->elems[i*3+1] = i + 1; mesh->elems[i*3+2] = i + 2; } #ifdef __arm__ float inv_w = 1.0f / surf->texinfo->texture->width; float inv_h = 1.0f / surf->texinfo->texture->height; #endif // fill the mesh for( i = 0; i < numVerts; i++, v += VERTEXSIZE ) { glvert_t *out = &mesh->verts[i]; VectorCopy( v, out->vertex ); VectorCopy( decalinfo->m_Basis[0], out->tangent ); VectorCopy( decalinfo->m_Basis[1], out->binormal ); VectorCopy( decalinfo->m_Basis[2], out->normal ); out->stcoord[0] = v[3]; out->stcoord[1] = v[4]; out->lmcoord[0] = v[5]; out->lmcoord[1] = v[6]; out->sccoord[0] = (( DotProduct( v , surf->texinfo->vecs[0] ) + surf->texinfo->vecs[0][3] ) #ifdef __arm__ * inv_w ); #else / surf->texinfo->texture->width ); #endif out->sccoord[1] = (( DotProduct( v , surf->texinfo->vecs[1] ) + surf->texinfo->vecs[1][3] ) #ifdef __arm__ * inv_h ); #else / surf->texinfo->texture->height );
void DrawSurfaceDecals( msurface_t *fa ) { decal_t *p; cl_entity_t *e; if( !fa->pdecals ) return; e = RI.currententity; ASSERT( e != NULL ); if( e->curstate.rendermode == kRenderNormal || e->curstate.rendermode == kRenderTransAlpha ) { pglDepthMask( GL_FALSE ); pglEnable( GL_BLEND ); if( e->curstate.rendermode == kRenderTransAlpha ) pglDisable( GL_ALPHA_TEST ); } if( e->curstate.rendermode == kRenderTransColor ) pglEnable( GL_TEXTURE_2D ); if( e->curstate.rendermode == kRenderTransTexture || e->curstate.rendermode == kRenderTransAdd ) GL_Cull( GL_NONE ); pglEnable( GL_POLYGON_OFFSET_FILL ); pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); if( fa->flags & SURF_TRANSPARENT && glState.stencilEnabled ) { mtexinfo_t *tex = fa->texinfo; for( p = fa->pdecals; p; p = p->pnext ) { if( p->texture ) { float *o, *v; int i, numVerts; o = R_DecalSetupVerts( p, fa, p->texture, &numVerts ); pglEnable( GL_STENCIL_TEST ); pglStencilFunc( GL_ALWAYS, 1, 0xFFFFFFFF ); pglColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE ); pglStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE ); pglBegin( GL_POLYGON ); for( i = 0, v = o; i < numVerts; i++, v += VERTEXSIZE ) { v[5] = ( DotProduct( v, tex->vecs[0] ) + tex->vecs[0][3] ) / tex->texture->width; v[6] = ( DotProduct( v, tex->vecs[1] ) + tex->vecs[1][3] ) / tex->texture->height; pglTexCoord2f( v[5], v[6] ); pglVertex3fv( v ); } pglEnd(); pglStencilOp( GL_KEEP, GL_KEEP, GL_DECR ); pglEnable( GL_ALPHA_TEST ); pglBegin( GL_POLYGON ); for( i = 0, v = o; i < numVerts; i++, v += VERTEXSIZE ) { pglTexCoord2f( v[5], v[6] ); pglVertex3fv( v ); } pglEnd(); pglDisable( GL_ALPHA_TEST ); pglColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); pglStencilFunc( GL_EQUAL, 0, 0xFFFFFFFF ); pglStencilOp( GL_KEEP, GL_KEEP, GL_KEEP ); } } } for( p = fa->pdecals; p; p = p->pnext ) { if( p->texture ) { gltexture_t *glt = R_GetTexture( p->texture ); // normal HL decal with alpha-channel if( glt->flags & TF_HAS_ALPHA ) { // draw transparent decals with GL_MODULATE if( glt->fogParams[3] > DECAL_TRANSPARENT_THRESHOLD ) pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE ); else pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); pglBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); } else { // color decal like detail texture. Base color is 127 127 127 pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); pglBlendFunc( GL_DST_COLOR, GL_SRC_COLOR ); } DrawSingleDecal( p, fa ); } } if( fa->flags & SURF_TRANSPARENT && glState.stencilEnabled ) pglDisable( GL_STENCIL_TEST ); if( e->curstate.rendermode == kRenderNormal || e->curstate.rendermode == kRenderTransAlpha ) { pglDepthMask( GL_TRUE ); pglDisable( GL_BLEND ); if( e->curstate.rendermode == kRenderTransAlpha ) pglEnable( GL_ALPHA_TEST ); } pglDisable( GL_POLYGON_OFFSET_FILL ); if( e->curstate.rendermode == kRenderTransTexture || e->curstate.rendermode == kRenderTransAdd ) GL_Cull( GL_FRONT ); if( e->curstate.rendermode == kRenderTransColor ) pglDisable( GL_TEXTURE_2D ); // restore blendfunc here if( e->curstate.rendermode == kRenderTransAdd || e->curstate.rendermode == kRenderGlow ) pglBlendFunc( GL_SRC_ALPHA, GL_ONE ); }