static void ComputeFogValues(vec4_t fogDistanceVector, vec4_t fogDepthVector, float *eyeT) { // from RB_CalcFogTexCoords() fog_t *fog; vec3_t local; if (!tess.fogNum) return; fog = tr.world->fogs + tess.fogNum; VectorSubtract( backEnd.or.origin, backEnd.viewParms.or.origin, local ); fogDistanceVector[0] = -backEnd.or.modelMatrix[2]; fogDistanceVector[1] = -backEnd.or.modelMatrix[6]; fogDistanceVector[2] = -backEnd.or.modelMatrix[10]; fogDistanceVector[3] = DotProduct( local, backEnd.viewParms.or.axis[0] ); // scale the fog vectors based on the fog's thickness VectorScale4(fogDistanceVector, fog->tcScale, fogDistanceVector); // rotate the gradient vector for this orientation if ( fog->hasSurface ) { fogDepthVector[0] = fog->surface[0] * backEnd.or.axis[0][0] + fog->surface[1] * backEnd.or.axis[0][1] + fog->surface[2] * backEnd.or.axis[0][2]; fogDepthVector[1] = fog->surface[0] * backEnd.or.axis[1][0] + fog->surface[1] * backEnd.or.axis[1][1] + fog->surface[2] * backEnd.or.axis[1][2]; fogDepthVector[2] = fog->surface[0] * backEnd.or.axis[2][0] + fog->surface[1] * backEnd.or.axis[2][1] + fog->surface[2] * backEnd.or.axis[2][2]; fogDepthVector[3] = -fog->surface[3] + DotProduct( backEnd.or.origin, fog->surface ); *eyeT = DotProduct( backEnd.or.viewOrigin, fogDepthVector ) + fogDepthVector[3]; } else { *eyeT = 1; // non-surface fog always has eye inside } }
/* ============== RB_SurfaceSprite ============== */ static void RB_SurfaceSprite( void ) { vec3_t left, up; float radius; float colors[4]; trRefEntity_t *ent = backEnd.currentEntity; // calculate the xyz locations for the four corners radius = ent->e.radius; if ( ent->e.rotation == 0 ) { VectorScale( backEnd.viewParms.or.axis[1], radius, left ); VectorScale( backEnd.viewParms.or.axis[2], radius, up ); } else { float s, c; float ang; ang = M_PI * ent->e.rotation / 180; s = sin( ang ); c = cos( ang ); VectorScale( backEnd.viewParms.or.axis[1], c * radius, left ); VectorMA( left, -s * radius, backEnd.viewParms.or.axis[2], left ); VectorScale( backEnd.viewParms.or.axis[2], c * radius, up ); VectorMA( up, s * radius, backEnd.viewParms.or.axis[1], up ); } if ( backEnd.viewParms.isMirror ) { VectorSubtract( vec3_origin, left, left ); } VectorScale4(ent->e.shaderRGBA, 1.0f / 255.0f, colors); RB_AddQuadStamp( ent->e.origin, left, up, colors ); }
static void RB_IterateStagesGeneric( shaderCommands_t *input ) { int stage; vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0}; float eyeT = 0; int deformGen; vec5_t deformParams; ComputeDeformValues(&deformGen, deformParams); ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT); for ( stage = 0; stage < MAX_SHADER_STAGES; stage++ ) { shaderStage_t *pStage = input->xstages[stage]; shaderProgram_t *sp; vec4_t texMatrix; vec4_t texOffTurb; if ( !pStage ) { break; } if (backEnd.depthFill) { if (pStage->glslShaderGroup == tr.lightallShader) { int index = 0; if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) { index |= LIGHTDEF_ENTITY; } if (pStage->stateBits & GLS_ATEST_BITS) { index |= LIGHTDEF_USE_TCGEN_AND_TCMOD; } sp = &pStage->glslShaderGroup[index]; } else { int shaderAttribs = 0; if (tess.shader->numDeforms && !ShaderRequiresCPUDeforms(tess.shader)) { shaderAttribs |= GENERICDEF_USE_DEFORM_VERTEXES; } if (glState.vertexAnimation) { shaderAttribs |= GENERICDEF_USE_VERTEX_ANIMATION; } if (pStage->stateBits & GLS_ATEST_BITS) { shaderAttribs |= GENERICDEF_USE_TCGEN_AND_TCMOD; } sp = &tr.genericShader[shaderAttribs]; } } else if (pStage->glslShaderGroup == tr.lightallShader) { int index = pStage->glslShaderIndex; if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) { index |= LIGHTDEF_ENTITY; } if (r_sunlightMode->integer && (backEnd.viewParms.flags & VPF_USESUNLIGHT) && (index & LIGHTDEF_LIGHTTYPE_MASK)) { index |= LIGHTDEF_USE_SHADOWMAP; } if (r_lightmap->integer && index & LIGHTDEF_USE_LIGHTMAP) { index = LIGHTDEF_USE_LIGHTMAP; } sp = &pStage->glslShaderGroup[index]; backEnd.pc.c_lightallDraws++; } else { sp = GLSL_GetGenericShaderProgram(stage); backEnd.pc.c_genericDraws++; } GLSL_BindProgram(sp); GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); GLSL_SetUniformVec3(sp, UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin); GLSL_SetUniformVec3(sp, UNIFORM_LOCALVIEWORIGIN, backEnd.or.viewOrigin); GLSL_SetUniformFloat(sp, UNIFORM_VERTEXLERP, glState.vertexAttribsInterpolation); GLSL_SetUniformInt(sp, UNIFORM_DEFORMGEN, deformGen); if (deformGen != DGEN_NONE) { GLSL_SetUniformFloat5(sp, UNIFORM_DEFORMPARAMS, deformParams); GLSL_SetUniformFloat(sp, UNIFORM_TIME, tess.shaderTime); } if ( input->fogNum ) { GLSL_SetUniformVec4(sp, UNIFORM_FOGDISTANCE, fogDistanceVector); GLSL_SetUniformVec4(sp, UNIFORM_FOGDEPTH, fogDepthVector); GLSL_SetUniformFloat(sp, UNIFORM_FOGEYET, eyeT); } GL_State( pStage->stateBits ); { vec4_t baseColor; vec4_t vertColor; ComputeShaderColors(pStage, baseColor, vertColor, pStage->stateBits); if ((backEnd.refdef.colorScale != 1.0f) && !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL)) { // use VectorScale to only scale first three values, not alpha VectorScale(baseColor, backEnd.refdef.colorScale, baseColor); VectorScale(vertColor, backEnd.refdef.colorScale, vertColor); } GLSL_SetUniformVec4(sp, UNIFORM_BASECOLOR, baseColor); GLSL_SetUniformVec4(sp, UNIFORM_VERTCOLOR, vertColor); } if (pStage->rgbGen == CGEN_LIGHTING_DIFFUSE) { vec4_t vec; VectorScale(backEnd.currentEntity->ambientLight, 1.0f / 255.0f, vec); GLSL_SetUniformVec3(sp, UNIFORM_AMBIENTLIGHT, vec); VectorScale(backEnd.currentEntity->directedLight, 1.0f / 255.0f, vec); GLSL_SetUniformVec3(sp, UNIFORM_DIRECTEDLIGHT, vec); VectorCopy(backEnd.currentEntity->lightDir, vec); vec[3] = 0.0f; GLSL_SetUniformVec4(sp, UNIFORM_LIGHTORIGIN, vec); GLSL_SetUniformVec3(sp, UNIFORM_MODELLIGHTDIR, backEnd.currentEntity->modelLightDir); GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, 0.0f); } if (pStage->alphaGen == AGEN_PORTAL) { GLSL_SetUniformFloat(sp, UNIFORM_PORTALRANGE, tess.shader->portalRange); } GLSL_SetUniformInt(sp, UNIFORM_COLORGEN, pStage->rgbGen); GLSL_SetUniformInt(sp, UNIFORM_ALPHAGEN, pStage->alphaGen); if ( input->fogNum ) { vec4_t fogColorMask; ComputeFogColorMask(pStage, fogColorMask); GLSL_SetUniformVec4(sp, UNIFORM_FOGCOLORMASK, fogColorMask); } ComputeTexMods( pStage, TB_DIFFUSEMAP, texMatrix, texOffTurb ); GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, texMatrix); GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, texOffTurb); GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen); if (pStage->bundle[0].tcGen == TCGEN_VECTOR) { vec3_t vec; VectorCopy(pStage->bundle[0].tcGenVectors[0], vec); GLSL_SetUniformVec3(sp, UNIFORM_TCGEN0VECTOR0, vec); VectorCopy(pStage->bundle[0].tcGenVectors[1], vec); GLSL_SetUniformVec3(sp, UNIFORM_TCGEN0VECTOR1, vec); } GLSL_SetUniformMat4(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix); GLSL_SetUniformVec4(sp, UNIFORM_NORMALSCALE, pStage->normalScale); GLSL_SetUniformVec4(sp, UNIFORM_SPECULARSCALE, pStage->specularScale); //GLSL_SetUniformFloat(sp, UNIFORM_MAPLIGHTSCALE, backEnd.refdef.mapLightScale); // // do multitexture // if ( backEnd.depthFill ) { if (!(pStage->stateBits & GLS_ATEST_BITS)) GL_BindToTMU( tr.whiteImage, 0 ); else if ( pStage->bundle[TB_COLORMAP].image[0] != 0 ) R_BindAnimatedImageToTMU( &pStage->bundle[TB_COLORMAP], TB_COLORMAP ); } else if ( pStage->glslShaderGroup == tr.lightallShader ) { int i; vec4_t enableTextures; if (r_sunlightMode->integer && (backEnd.viewParms.flags & VPF_USESUNLIGHT) && (pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK)) { GL_BindToTMU(tr.screenShadowImage, TB_SHADOWMAP); GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTAMBIENT, backEnd.refdef.sunAmbCol); GLSL_SetUniformVec3(sp, UNIFORM_PRIMARYLIGHTCOLOR, backEnd.refdef.sunCol); GLSL_SetUniformVec4(sp, UNIFORM_PRIMARYLIGHTORIGIN, backEnd.refdef.sunDir); } VectorSet4(enableTextures, 0, 0, 0, 0); if ((r_lightmap->integer == 1 || r_lightmap->integer == 2) && pStage->bundle[TB_LIGHTMAP].image[0]) { for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) { if (i == TB_LIGHTMAP) R_BindAnimatedImageToTMU( &pStage->bundle[TB_LIGHTMAP], i); else GL_BindToTMU( tr.whiteImage, i ); } } else if (r_lightmap->integer == 3 && pStage->bundle[TB_DELUXEMAP].image[0]) { for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) { if (i == TB_LIGHTMAP) R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], i); else GL_BindToTMU( tr.whiteImage, i ); } } else { qboolean light = (pStage->glslShaderIndex & LIGHTDEF_LIGHTTYPE_MASK) != 0; qboolean fastLight = !(r_normalMapping->integer || r_specularMapping->integer); if (pStage->bundle[TB_DIFFUSEMAP].image[0]) R_BindAnimatedImageToTMU( &pStage->bundle[TB_DIFFUSEMAP], TB_DIFFUSEMAP); if (pStage->bundle[TB_LIGHTMAP].image[0]) R_BindAnimatedImageToTMU( &pStage->bundle[TB_LIGHTMAP], TB_LIGHTMAP); // bind textures that are sampled and used in the glsl shader, and // bind whiteImage to textures that are sampled but zeroed in the glsl shader // // alternatives: // - use the last bound texture // -> costs more to sample a higher res texture then throw out the result // - disable texture sampling in glsl shader with #ifdefs, as before // -> increases the number of shaders that must be compiled // if (light && !fastLight) { if (pStage->bundle[TB_NORMALMAP].image[0]) { R_BindAnimatedImageToTMU( &pStage->bundle[TB_NORMALMAP], TB_NORMALMAP); enableTextures[0] = 1.0f; } else if (r_normalMapping->integer) GL_BindToTMU( tr.whiteImage, TB_NORMALMAP ); if (pStage->bundle[TB_DELUXEMAP].image[0]) { R_BindAnimatedImageToTMU( &pStage->bundle[TB_DELUXEMAP], TB_DELUXEMAP); enableTextures[1] = 1.0f; } else if (r_deluxeMapping->integer) GL_BindToTMU( tr.whiteImage, TB_DELUXEMAP ); if (pStage->bundle[TB_SPECULARMAP].image[0]) { R_BindAnimatedImageToTMU( &pStage->bundle[TB_SPECULARMAP], TB_SPECULARMAP); enableTextures[2] = 1.0f; } else if (r_specularMapping->integer) GL_BindToTMU( tr.whiteImage, TB_SPECULARMAP ); } enableTextures[3] = (r_cubeMapping->integer && !(tr.viewParms.flags & VPF_NOCUBEMAPS) && input->cubemapIndex) ? 1.0f : 0.0f; } GLSL_SetUniformVec4(sp, UNIFORM_ENABLETEXTURES, enableTextures); } else if ( pStage->bundle[1].image[0] != 0 ) { R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 ); R_BindAnimatedImageToTMU( &pStage->bundle[1], 1 ); } else { // // set state // R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 ); } // // testing cube map // if (!(tr.viewParms.flags & VPF_NOCUBEMAPS) && input->cubemapIndex && r_cubeMapping->integer) { vec4_t vec; GL_BindToTMU( tr.cubemaps[input->cubemapIndex - 1], TB_CUBEMAP); vec[0] = tr.cubemapOrigins[input->cubemapIndex - 1][0] - backEnd.viewParms.or.origin[0]; vec[1] = tr.cubemapOrigins[input->cubemapIndex - 1][1] - backEnd.viewParms.or.origin[1]; vec[2] = tr.cubemapOrigins[input->cubemapIndex - 1][2] - backEnd.viewParms.or.origin[2]; vec[3] = 1.0f; VectorScale4(vec, 1.0f / 1000.0f, vec); GLSL_SetUniformVec4(sp, UNIFORM_CUBEMAPINFO, vec); } // // draw // if (input->multiDrawPrimitives) { R_DrawMultiElementsVao(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { R_DrawElementsVao(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); } // allow skipping out to show just lightmaps during development if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) ) { break; } if (backEnd.depthFill) break; } }
/* ============= RB_StretchPic ============= */ const void *RB_StretchPic ( const void *data ) { const stretchPicCommand_t *cmd; shader_t *shader; int numVerts, numIndexes; cmd = (const stretchPicCommand_t *)data; // FIXME: HUGE hack if (glRefConfig.framebufferObject) { if (!tr.renderFbo || backEnd.framePostProcessed) { FBO_Bind(NULL); } else { FBO_Bind(tr.renderFbo); } } RB_SetGL2D(); shader = cmd->shader; if ( shader != tess.shader ) { if ( tess.numIndexes ) { RB_EndSurface(); } backEnd.currentEntity = &backEnd.entity2D; RB_BeginSurface( shader, 0, 0 ); } RB_CHECKOVERFLOW( 4, 6 ); numVerts = tess.numVertexes; numIndexes = tess.numIndexes; tess.numVertexes += 4; tess.numIndexes += 6; tess.indexes[ numIndexes ] = numVerts + 3; tess.indexes[ numIndexes + 1 ] = numVerts + 0; tess.indexes[ numIndexes + 2 ] = numVerts + 2; tess.indexes[ numIndexes + 3 ] = numVerts + 2; tess.indexes[ numIndexes + 4 ] = numVerts + 0; tess.indexes[ numIndexes + 5 ] = numVerts + 1; { vec4_t color; VectorScale4(backEnd.color2D, 1.0f / 255.0f, color); VectorCopy4(color, tess.vertexColors[ numVerts ]); VectorCopy4(color, tess.vertexColors[ numVerts + 1]); VectorCopy4(color, tess.vertexColors[ numVerts + 2]); VectorCopy4(color, tess.vertexColors[ numVerts + 3 ]); } tess.xyz[ numVerts ][0] = cmd->x; tess.xyz[ numVerts ][1] = cmd->y; tess.xyz[ numVerts ][2] = 0; tess.texCoords[ numVerts ][0][0] = cmd->s1; tess.texCoords[ numVerts ][0][1] = cmd->t1; tess.xyz[ numVerts + 1 ][0] = cmd->x + cmd->w; tess.xyz[ numVerts + 1 ][1] = cmd->y; tess.xyz[ numVerts + 1 ][2] = 0; tess.texCoords[ numVerts + 1 ][0][0] = cmd->s2; tess.texCoords[ numVerts + 1 ][0][1] = cmd->t1; tess.xyz[ numVerts + 2 ][0] = cmd->x + cmd->w; tess.xyz[ numVerts + 2 ][1] = cmd->y + cmd->h; tess.xyz[ numVerts + 2 ][2] = 0; tess.texCoords[ numVerts + 2 ][0][0] = cmd->s2; tess.texCoords[ numVerts + 2 ][0][1] = cmd->t2; tess.xyz[ numVerts + 3 ][0] = cmd->x; tess.xyz[ numVerts + 3 ][1] = cmd->y + cmd->h; tess.xyz[ numVerts + 3 ][2] = 0; tess.texCoords[ numVerts + 3 ][0][0] = cmd->s1; tess.texCoords[ numVerts + 3 ][0][1] = cmd->t2; return (const void *)(cmd + 1); }