/* ================ DrawTris Draws triangle outlines for debugging ================ */ static void DrawTris (shaderCommands_t *input) { GL_Bind( tr.whiteImage ); GL_State( GLS_POLYMODE_LINE | GLS_DEPTHMASK_TRUE ); qglDepthRange( 0, 0 ); { shaderProgram_t *sp = &tr.textureColorShader; vec4_t color; GLSL_VertexAttribsState(ATTR_POSITION); GLSL_BindProgram(sp); GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); VectorSet4(color, 1, 1, 1, 1); GLSL_SetUniformVec4(sp, UNIFORM_COLOR, color); if (input->multiDrawPrimitives) { R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); } } qglDepthRange( 0, 1 ); }
static void RB_RenderShadowmap( shaderCommands_t *input ) { int deformGen; vec5_t deformParams; ComputeDeformValues(&deformGen, deformParams); { shaderProgram_t *sp = &tr.shadowmapShader; vec4_t vector; GLSL_BindProgram(sp); GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); GLSL_SetUniformMatrix16(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix); 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); } VectorCopy(backEnd.viewParms.or.origin, vector); vector[3] = 1.0f; GLSL_SetUniformVec4(sp, UNIFORM_LIGHTORIGIN, vector); GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, backEnd.viewParms.zFar); GL_State( 0 ); // // do multitexture // //if ( pStage->glslShaderGroup ) { // // draw // if (input->multiDrawPrimitives) { R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); } } } }
void RB_InstantQuad(vec4_t quadVerts[4]) { vec2_t texCoords[4]; VectorSet2(texCoords[0], 0.0f, 0.0f); VectorSet2(texCoords[1], 1.0f, 0.0f); VectorSet2(texCoords[2], 1.0f, 1.0f); VectorSet2(texCoords[3], 0.0f, 1.0f); GLSL_BindProgram(&tr.textureColorShader); GLSL_SetUniformMat4(&tr.textureColorShader, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); GLSL_SetUniformVec4(&tr.textureColorShader, UNIFORM_COLOR, colorWhite); RB_InstantQuad2(quadVerts, texCoords); }
static void RB_IterateStagesGeneric( shaderCommands_t *input ) { int stage; matrix_t matrix; 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; if ( !pStage ) { break; } if (backEnd.depthFill) { if (pStage->glslShaderGroup) { 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.vertexAttribsInterpolation > 0.0f && backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) { 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) { int index = pStage->glslShaderIndex; if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) { index |= LIGHTDEF_ENTITY; } if (r_lightmap->integer && index & LIGHTDEF_USE_LIGHTMAP) { index = LIGHTDEF_USE_LIGHTMAP; } sp = &pStage->glslShaderGroup[index]; if (pStage->glslShaderGroup == tr.lightallShader) { backEnd.pc.c_lightallDraws++; } } else { sp = GLSL_GetGenericShaderProgram(stage); backEnd.pc.c_genericDraws++; } GLSL_BindProgram(sp); GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); GLSL_SetUniformVec3(sp, UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin); 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; qboolean tint = qtrue; int stage2; ComputeShaderColors(pStage, baseColor, vertColor); for ( stage2 = stage + 1; stage2 < MAX_SHADER_STAGES; stage2++ ) { shaderStage_t *pStage2 = input->xstages[stage2]; unsigned int srcBlendBits; //unsigned int dstBlendBits; if ( !pStage2 ) { break; } srcBlendBits = pStage2->stateBits & GLS_SRCBLEND_BITS; //dstBlendBits = pStage2->stateBits & GLS_DSTBLEND_BITS; if (srcBlendBits == GLS_SRCBLEND_DST_COLOR) { tint = qfalse; break; } } if (!((tr.sunShadows || r_forceSun->integer) && tess.shader->sort <= SS_OPAQUE && !(tess.shader->surfaceFlags & (SURF_NODLIGHT | SURF_SKY) ) && tess.xstages[0]->glslShaderGroup == tr.lightallShader)) { tint = qfalse; } if (tint) { // 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_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, 999999.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); } ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix ); { vec4_t vector; VectorSet4(vector, matrix[0], matrix[1], matrix[4], matrix[5]); GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, vector); VectorSet4(vector, matrix[8], matrix[9], matrix[12], matrix[13]); GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector); } 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_SetUniformMatrix16(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix); GLSL_SetUniformVec2(sp, UNIFORM_MATERIALINFO, pStage->materialInfo); //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 ) { int i; 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[i], i); } else if (pStage->bundle[i].image[0]) { 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 if (pStage->bundle[i].image[0]) { GL_BindToTMU( tr.whiteImage, i); } } } else { for (i = 0; i < NUM_TEXTURE_BUNDLES; i++) { if (pStage->bundle[i].image[0]) { R_BindAnimatedImageToTMU( &pStage->bundle[i], i); } } } } else if ( pStage->bundle[1].image[0] != 0 ) { R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 ); // // lightmap/secondary pass // if ( r_lightmap->integer ) { GLSL_SetUniformInt(sp, UNIFORM_TEXTURE1ENV, GL_REPLACE); } else { GLSL_SetUniformInt(sp, UNIFORM_TEXTURE1ENV, tess.shader->multitextureEnv); } R_BindAnimatedImageToTMU( &pStage->bundle[1], 1 ); } else { // // set state // if ( pStage->bundle[0].vertexLightmap && ( (r_vertexLight->integer && !r_uiFullScreen->integer) || glConfig.hardwareType == GLHW_PERMEDIA2 ) && r_lightmap->integer ) { GL_BindToTMU( tr.whiteImage, 0 ); } else R_BindAnimatedImageToTMU( &pStage->bundle[0], 0 ); GLSL_SetUniformInt(sp, UNIFORM_TEXTURE1ENV, 0); } // // draw // if (input->multiDrawPrimitives) { R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { R_DrawElementsVBO(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 || pStage->bundle[0].vertexLightmap ) ) { break; } if (backEnd.depthFill) break; } }
/* =================== RB_FogPass Blends a fog texture on top of everything else =================== */ static void RB_FogPass( void ) { fog_t *fog; vec4_t color; vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0}; float eyeT = 0; shaderProgram_t *sp; int deformGen; vec5_t deformParams; ComputeDeformValues(&deformGen, deformParams); { int index = 0; if (deformGen != DGEN_NONE) index |= FOGDEF_USE_DEFORM_VERTEXES; if (glState.vertexAttribsInterpolation) index |= FOGDEF_USE_VERTEX_ANIMATION; sp = &tr.fogShader[index]; } backEnd.pc.c_fogDraws++; GLSL_BindProgram(sp); fog = tr.world->fogs + tess.fogNum; GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); 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); } color[0] = ((unsigned char *)(&fog->colorInt))[0] / 255.0f; color[1] = ((unsigned char *)(&fog->colorInt))[1] / 255.0f; color[2] = ((unsigned char *)(&fog->colorInt))[2] / 255.0f; color[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f; GLSL_SetUniformVec4(sp, UNIFORM_COLOR, color); ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT); GLSL_SetUniformVec4(sp, UNIFORM_FOGDISTANCE, fogDistanceVector); GLSL_SetUniformVec4(sp, UNIFORM_FOGDEPTH, fogDepthVector); GLSL_SetUniformFloat(sp, UNIFORM_FOGEYET, eyeT); if ( tess.shader->fogPass == FP_EQUAL ) { GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL ); } else { GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); } if (tess.multiDrawPrimitives) { shaderCommands_t *input = &tess; R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); } }
static void ProjectPshadowVBOGLSL( void ) { int l; vec3_t origin; float radius; int deformGen; vec5_t deformParams; shaderCommands_t *input = &tess; if ( !backEnd.refdef.num_pshadows ) { return; } ComputeDeformValues(&deformGen, deformParams); for ( l = 0 ; l < backEnd.refdef.num_pshadows ; l++ ) { pshadow_t *ps; shaderProgram_t *sp; vec4_t vector; if ( !( tess.pshadowBits & ( 1 << l ) ) ) { continue; // this surface definately doesn't have any of this shadow } ps = &backEnd.refdef.pshadows[l]; VectorCopy( ps->lightOrigin, origin ); radius = ps->lightRadius; sp = &tr.pshadowShader; GLSL_BindProgram(sp); GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); VectorCopy(origin, vector); vector[3] = 1.0f; GLSL_SetUniformVec4(sp, UNIFORM_LIGHTORIGIN, vector); VectorScale(ps->lightViewAxis[0], 1.0f / ps->viewRadius, vector); GLSL_SetUniformVec3(sp, UNIFORM_LIGHTFORWARD, vector); VectorScale(ps->lightViewAxis[1], 1.0f / ps->viewRadius, vector); GLSL_SetUniformVec3(sp, UNIFORM_LIGHTRIGHT, vector); VectorScale(ps->lightViewAxis[2], 1.0f / ps->viewRadius, vector); GLSL_SetUniformVec3(sp, UNIFORM_LIGHTUP, vector); GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, radius); // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light // where they aren't rendered GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL ); GL_BindToTMU( tr.pshadowMaps[l], TB_DIFFUSEMAP ); // // draw // if (input->multiDrawPrimitives) { R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); } backEnd.pc.c_totalIndexes += tess.numIndexes; //backEnd.pc.c_dlightIndexes += tess.numIndexes; } }
static void ForwardSunlight( void ) { // int l; //vec3_t origin; //float scale; int stage; int stageGlState[2]; qboolean alphaOverride = qfalse; int deformGen; vec5_t deformParams; vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0}; float eyeT = 0; shaderCommands_t *input = &tess; ComputeDeformValues(&deformGen, deformParams); ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT); // deal with vertex alpha blended surfaces if (input->xstages[0] && input->xstages[1] && (input->xstages[1]->alphaGen == AGEN_VERTEX || input->xstages[1]->alphaGen == AGEN_ONE_MINUS_VERTEX)) { stageGlState[0] = input->xstages[0]->stateBits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS); if (stageGlState[0] == 0 || stageGlState[0] == (GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO)) { stageGlState[1] = input->xstages[1]->stateBits & (GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS); if (stageGlState[1] == (GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA)) { alphaOverride = qtrue; stageGlState[0] = GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL; stageGlState[1] = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL; } else if (stageGlState[1] == (GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA | GLS_DSTBLEND_SRC_ALPHA)) { alphaOverride = qtrue; stageGlState[0] = GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL; stageGlState[1] = GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL; } } } if (!alphaOverride) { stageGlState[0] = stageGlState[1] = GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL; } for ( stage = 0; stage < 2 /*MAX_SHADER_STAGES */; stage++ ) { shaderStage_t *pStage = input->xstages[stage]; shaderProgram_t *sp; vec4_t vector; matrix_t matrix; if ( !pStage ) { break; } //VectorCopy( dl->transformed, origin ); //if (pStage->glslShaderGroup == tr.lightallShader) { int index = pStage->glslShaderIndex; index &= ~(LIGHTDEF_LIGHTTYPE_MASK | LIGHTDEF_USE_DELUXEMAP); index |= LIGHTDEF_USE_LIGHT_VECTOR | LIGHTDEF_USE_SHADOWMAP; if (backEnd.currentEntity && backEnd.currentEntity != &tr.worldEntity) { index |= LIGHTDEF_ENTITY; } sp = &tr.lightallShader[index]; } backEnd.pc.c_lightallDraws++; GLSL_BindProgram(sp); GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); GLSL_SetUniformVec3(sp, UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin); 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 ) { vec4_t fogColorMask; GLSL_SetUniformVec4(sp, UNIFORM_FOGDISTANCE, fogDistanceVector); GLSL_SetUniformVec4(sp, UNIFORM_FOGDEPTH, fogDepthVector); GLSL_SetUniformFloat(sp, UNIFORM_FOGEYET, eyeT); ComputeFogColorMask(pStage, fogColorMask); GLSL_SetUniformVec4(sp, UNIFORM_FOGCOLORMASK, fogColorMask); } { vec4_t baseColor; vec4_t vertColor; ComputeShaderColors(pStage, baseColor, vertColor); if (alphaOverride) { if (input->xstages[1]->alphaGen == AGEN_VERTEX) { baseColor[3] = 0.0f; vertColor[3] = 1.0f; } else if (input->xstages[1]->alphaGen == AGEN_ONE_MINUS_VERTEX) { baseColor[3] = 1.0f; vertColor[3] = -1.0f; } } GLSL_SetUniformVec4(sp, UNIFORM_BASECOLOR, baseColor); GLSL_SetUniformVec4(sp, UNIFORM_VERTCOLOR, vertColor); } 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); GLSL_SetUniformVec3(sp, UNIFORM_DIRECTEDLIGHT, backEnd.refdef.sunCol); GLSL_SetUniformVec3(sp, UNIFORM_AMBIENTLIGHT, backEnd.refdef.sunAmbCol); GLSL_SetUniformVec4(sp, UNIFORM_LIGHTORIGIN, backEnd.refdef.sunDir); GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, 9999999999.9f); GLSL_SetUniformVec2(sp, UNIFORM_MATERIALINFO, pStage->materialInfo); GL_State( stageGlState[stage] ); GLSL_SetUniformMatrix16(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix); if (pStage->bundle[TB_DIFFUSEMAP].image[0]) R_BindAnimatedImageToTMU( &pStage->bundle[TB_DIFFUSEMAP], TB_DIFFUSEMAP); if (pStage->bundle[TB_NORMALMAP].image[0]) R_BindAnimatedImageToTMU( &pStage->bundle[TB_NORMALMAP], TB_NORMALMAP); if (pStage->bundle[TB_SPECULARMAP].image[0]) R_BindAnimatedImageToTMU( &pStage->bundle[TB_SPECULARMAP], TB_SPECULARMAP); /* { GL_BindToTMU(tr.sunShadowDepthImage[0], TB_SHADOWMAP); GL_BindToTMU(tr.sunShadowDepthImage[1], TB_SHADOWMAP2); GL_BindToTMU(tr.sunShadowDepthImage[2], TB_SHADOWMAP3); GLSL_SetUniformMatrix16(sp, UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[0]); GLSL_SetUniformMatrix16(sp, UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]); GLSL_SetUniformMatrix16(sp, UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]); } */ GL_BindToTMU(tr.screenShadowImage, TB_SHADOWMAP); ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix ); VectorSet4(vector, matrix[0], matrix[1], matrix[4], matrix[5]); GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, vector); VectorSet4(vector, matrix[8], matrix[9], matrix[12], matrix[13]); GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector); GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen); // // draw // if (input->multiDrawPrimitives) { R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); } backEnd.pc.c_totalIndexes += tess.numIndexes; backEnd.pc.c_dlightIndexes += tess.numIndexes; } }
/* ============= RB_DrawSurfs ============= */ const void *RB_DrawSurfs( const void *data ) { const drawSurfsCommand_t *cmd; // finish any 2D drawing if needed if ( tess.numIndexes ) { RB_EndSurface(); } cmd = (const drawSurfsCommand_t *)data; backEnd.refdef = cmd->refdef; backEnd.viewParms = cmd->viewParms; // clear the z buffer, set the modelview, etc RB_BeginDrawingView (); if (glRefConfig.framebufferObject && (backEnd.viewParms.flags & VPF_DEPTHCLAMP) && glRefConfig.depthClamp) { qglEnable(GL_DEPTH_CLAMP); } if (glRefConfig.framebufferObject && !(backEnd.refdef.rdflags & RDF_NOWORLDMODEL) && (r_depthPrepass->integer || (backEnd.viewParms.flags & VPF_DEPTHSHADOW))) { FBO_t *oldFbo = glState.currentFBO; backEnd.depthFill = qtrue; qglColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs ); qglColorMask(!backEnd.colorMask[0], !backEnd.colorMask[1], !backEnd.colorMask[2], !backEnd.colorMask[3]); backEnd.depthFill = qfalse; if (tr.msaaResolveFbo) { // If we're using multisampling, resolve the depth first FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_DEPTH_BUFFER_BIT, GL_NEAREST); } else if (tr.renderFbo == NULL) { // If we're rendering directly to the screen, copy the depth to a texture GL_BindToTMU(tr.renderDepthImage, 0); qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 0, 0, glConfig.vidWidth, glConfig.vidHeight, 0); } if (r_ssao->integer) { // need the depth in a texture we can do GL_LINEAR sampling on, so copy it to an HDR image FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, tr.hdrDepthFbo, NULL, NULL, NULL, 0); } if (r_sunlightMode->integer && backEnd.viewParms.flags & VPF_USESUNLIGHT) { vec4_t quadVerts[4]; vec2_t texCoords[4]; vec4_t box; FBO_Bind(tr.screenShadowFbo); box[0] = backEnd.viewParms.viewportX * tr.screenShadowFbo->width / (float)glConfig.vidWidth; box[1] = backEnd.viewParms.viewportY * tr.screenShadowFbo->height / (float)glConfig.vidHeight; box[2] = backEnd.viewParms.viewportWidth * tr.screenShadowFbo->width / (float)glConfig.vidWidth; box[3] = backEnd.viewParms.viewportHeight * tr.screenShadowFbo->height / (float)glConfig.vidHeight; qglViewport(box[0], box[1], box[2], box[3]); qglScissor(box[0], box[1], box[2], box[3]); box[0] = backEnd.viewParms.viewportX / (float)glConfig.vidWidth; box[1] = backEnd.viewParms.viewportY / (float)glConfig.vidHeight; box[2] = box[0] + backEnd.viewParms.viewportWidth / (float)glConfig.vidWidth; box[3] = box[1] + backEnd.viewParms.viewportHeight / (float)glConfig.vidHeight; texCoords[0][0] = box[0]; texCoords[0][1] = box[3]; texCoords[1][0] = box[2]; texCoords[1][1] = box[3]; texCoords[2][0] = box[2]; texCoords[2][1] = box[1]; texCoords[3][0] = box[0]; texCoords[3][1] = box[1]; box[0] = -1.0f; box[1] = -1.0f; box[2] = 1.0f; box[3] = 1.0f; VectorSet4(quadVerts[0], box[0], box[3], 0, 1); VectorSet4(quadVerts[1], box[2], box[3], 0, 1); VectorSet4(quadVerts[2], box[2], box[1], 0, 1); VectorSet4(quadVerts[3], box[0], box[1], 0, 1); GL_State( GLS_DEPTHTEST_DISABLE ); GLSL_BindProgram(&tr.shadowmaskShader); GL_BindToTMU(tr.renderDepthImage, TB_COLORMAP); if (r_shadowCascadeZFar->integer != 0) { GL_BindToTMU(tr.sunShadowDepthImage[0], TB_SHADOWMAP); GL_BindToTMU(tr.sunShadowDepthImage[1], TB_SHADOWMAP2); GL_BindToTMU(tr.sunShadowDepthImage[2], TB_SHADOWMAP3); GL_BindToTMU(tr.sunShadowDepthImage[3], TB_SHADOWMAP4); GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[0]); GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP2, backEnd.refdef.sunShadowMvp[1]); GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP3, backEnd.refdef.sunShadowMvp[2]); GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP4, backEnd.refdef.sunShadowMvp[3]); } else { GL_BindToTMU(tr.sunShadowDepthImage[3], TB_SHADOWMAP); GLSL_SetUniformMat4(&tr.shadowmaskShader, UNIFORM_SHADOWMVP, backEnd.refdef.sunShadowMvp[3]); } GLSL_SetUniformVec3(&tr.shadowmaskShader, UNIFORM_VIEWORIGIN, backEnd.refdef.vieworg); { vec4_t viewInfo; vec3_t viewVector; float zmax = backEnd.viewParms.zFar; float ymax = zmax * tan(backEnd.viewParms.fovY * M_PI / 360.0f); float xmax = zmax * tan(backEnd.viewParms.fovX * M_PI / 360.0f); float zmin = r_znear->value; VectorScale(backEnd.refdef.viewaxis[0], zmax, viewVector); GLSL_SetUniformVec3(&tr.shadowmaskShader, UNIFORM_VIEWFORWARD, viewVector); VectorScale(backEnd.refdef.viewaxis[1], xmax, viewVector); GLSL_SetUniformVec3(&tr.shadowmaskShader, UNIFORM_VIEWLEFT, viewVector); VectorScale(backEnd.refdef.viewaxis[2], ymax, viewVector); GLSL_SetUniformVec3(&tr.shadowmaskShader, UNIFORM_VIEWUP, viewVector); VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0); GLSL_SetUniformVec4(&tr.shadowmaskShader, UNIFORM_VIEWINFO, viewInfo); } RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); } if (r_ssao->integer) { vec4_t quadVerts[4]; vec2_t texCoords[4]; FBO_Bind(tr.quarterFbo[0]); qglViewport(0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height); qglScissor(0, 0, tr.quarterFbo[0]->width, tr.quarterFbo[0]->height); VectorSet4(quadVerts[0], -1, 1, 0, 1); VectorSet4(quadVerts[1], 1, 1, 0, 1); VectorSet4(quadVerts[2], 1, -1, 0, 1); VectorSet4(quadVerts[3], -1, -1, 0, 1); texCoords[0][0] = 0; texCoords[0][1] = 1; texCoords[1][0] = 1; texCoords[1][1] = 1; texCoords[2][0] = 1; texCoords[2][1] = 0; texCoords[3][0] = 0; texCoords[3][1] = 0; GL_State( GLS_DEPTHTEST_DISABLE ); GLSL_BindProgram(&tr.ssaoShader); GL_BindToTMU(tr.hdrDepthImage, TB_COLORMAP); { vec4_t viewInfo; float zmax = backEnd.viewParms.zFar; float zmin = r_znear->value; VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0); GLSL_SetUniformVec4(&tr.ssaoShader, UNIFORM_VIEWINFO, viewInfo); } RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); FBO_Bind(tr.quarterFbo[1]); qglViewport(0, 0, tr.quarterFbo[1]->width, tr.quarterFbo[1]->height); qglScissor(0, 0, tr.quarterFbo[1]->width, tr.quarterFbo[1]->height); GLSL_BindProgram(&tr.depthBlurShader[0]); GL_BindToTMU(tr.quarterImage[0], TB_COLORMAP); GL_BindToTMU(tr.hdrDepthImage, TB_LIGHTMAP); { vec4_t viewInfo; float zmax = backEnd.viewParms.zFar; float zmin = r_znear->value; VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0); GLSL_SetUniformVec4(&tr.depthBlurShader[0], UNIFORM_VIEWINFO, viewInfo); } RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); FBO_Bind(tr.screenSsaoFbo); qglViewport(0, 0, tr.screenSsaoFbo->width, tr.screenSsaoFbo->height); qglScissor(0, 0, tr.screenSsaoFbo->width, tr.screenSsaoFbo->height); GLSL_BindProgram(&tr.depthBlurShader[1]); GL_BindToTMU(tr.quarterImage[1], TB_COLORMAP); GL_BindToTMU(tr.hdrDepthImage, TB_LIGHTMAP); { vec4_t viewInfo; float zmax = backEnd.viewParms.zFar; float zmin = r_znear->value; VectorSet4(viewInfo, zmax / zmin, zmax, 0.0, 0.0); GLSL_SetUniformVec4(&tr.depthBlurShader[1], UNIFORM_VIEWINFO, viewInfo); } RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); } // reset viewport and scissor FBO_Bind(oldFbo); SetViewportAndScissor(); } if (glRefConfig.framebufferObject && (backEnd.viewParms.flags & VPF_DEPTHCLAMP) && glRefConfig.depthClamp) { qglDisable(GL_DEPTH_CLAMP); } if (!(backEnd.viewParms.flags & VPF_DEPTHSHADOW)) { RB_RenderDrawSurfList( cmd->drawSurfs, cmd->numDrawSurfs ); if (r_drawSun->integer) { RB_DrawSun(0.1, tr.sunShader); } if (r_drawSunRays->integer) { FBO_t *oldFbo = glState.currentFBO; FBO_Bind(tr.sunRaysFbo); qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); qglClear( GL_COLOR_BUFFER_BIT ); if (glRefConfig.occlusionQuery) { tr.sunFlareQueryActive[tr.sunFlareQueryIndex] = qtrue; qglBeginQueryARB(GL_SAMPLES_PASSED_ARB, tr.sunFlareQuery[tr.sunFlareQueryIndex]); } RB_DrawSun(0.3, tr.sunFlareShader); if (glRefConfig.occlusionQuery) { qglEndQueryARB(GL_SAMPLES_PASSED_ARB); } FBO_Bind(oldFbo); } // darken down any stencil shadows RB_ShadowFinish(); // add light flares on lights that aren't obscured RB_RenderFlares(); } if (glRefConfig.framebufferObject && tr.renderCubeFbo && backEnd.viewParms.targetFbo == tr.renderCubeFbo) { FBO_Bind(NULL); GL_SelectTexture(TB_CUBEMAP); GL_BindToTMU(tr.cubemaps[backEnd.viewParms.targetFboCubemapIndex], TB_CUBEMAP); qglGenerateMipmapEXT(GL_TEXTURE_CUBE_MAP); GL_SelectTexture(0); } return (const void *)(cmd + 1); }
/* ============= RE_StretchRaw FIXME: not exactly backend Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle. Used for cinematics. ============= */ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) { int i, j; int start, end; vec4_t quadVerts[4]; vec2_t texCoords[4]; if ( !tr.registered ) { return; } R_IssuePendingRenderCommands(); if ( tess.numIndexes ) { RB_EndSurface(); } // we definately want to sync every frame for the cinematics qglFinish(); start = 0; if ( r_speeds->integer ) { start = ri.Milliseconds(); } // make sure rows and cols are powers of 2 for ( i = 0 ; ( 1 << i ) < cols ; i++ ) { } for ( j = 0 ; ( 1 << j ) < rows ; j++ ) { } if ( ( 1 << i ) != cols || ( 1 << j ) != rows) { ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows); } RE_UploadCinematic (w, h, cols, rows, data, client, dirty); if ( r_speeds->integer ) { end = ri.Milliseconds(); ri.Printf( PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start ); } // FIXME: HUGE hack if (glRefConfig.framebufferObject) { if (!tr.renderFbo || backEnd.framePostProcessed) { FBO_Bind(NULL); } else { FBO_Bind(tr.renderFbo); } } RB_SetGL2D(); VectorSet4(quadVerts[0], x, y, 0.0f, 1.0f); VectorSet4(quadVerts[1], x + w, y, 0.0f, 1.0f); VectorSet4(quadVerts[2], x + w, y + h, 0.0f, 1.0f); VectorSet4(quadVerts[3], x, y + h, 0.0f, 1.0f); VectorSet2(texCoords[0], 0.5f / cols, 0.5f / rows); VectorSet2(texCoords[1], (cols - 0.5f) / cols, 0.5f / rows); VectorSet2(texCoords[2], (cols - 0.5f) / cols, (rows - 0.5f) / rows); VectorSet2(texCoords[3], 0.5f / cols, (rows - 0.5f) / rows); GLSL_BindProgram(&tr.textureColorShader); GLSL_SetUniformMat4(&tr.textureColorShader, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); GLSL_SetUniformVec4(&tr.textureColorShader, UNIFORM_COLOR, colorWhite); RB_InstantQuad2(quadVerts, texCoords); }
void FBO_BlitFromTexture(struct image_s *src, vec4_t inSrcTexCorners, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend) { ivec4_t dstBox; vec4_t color; vec4_t quadVerts[4]; vec2_t texCoords[4]; vec2_t invTexRes; FBO_t *oldFbo = glState.currentFBO; mat4_t projection; int width, height; if (!src) { ri.Printf(PRINT_WARNING, "Tried to blit from a NULL texture!\n"); return; } width = dst ? dst->width : glConfig.vidWidth; height = dst ? dst->height : glConfig.vidHeight; if (inSrcTexCorners) { VectorSet2(texCoords[0], inSrcTexCorners[0], inSrcTexCorners[1]); VectorSet2(texCoords[1], inSrcTexCorners[2], inSrcTexCorners[1]); VectorSet2(texCoords[2], inSrcTexCorners[2], inSrcTexCorners[3]); VectorSet2(texCoords[3], inSrcTexCorners[0], inSrcTexCorners[3]); } else { VectorSet2(texCoords[0], 0.0f, 1.0f); VectorSet2(texCoords[1], 1.0f, 1.0f); VectorSet2(texCoords[2], 1.0f, 0.0f); VectorSet2(texCoords[3], 0.0f, 0.0f); } // framebuffers are 0 bottom, Y up. if (inDstBox) { dstBox[0] = inDstBox[0]; dstBox[1] = height - inDstBox[1] - inDstBox[3]; dstBox[2] = inDstBox[0] + inDstBox[2]; dstBox[3] = height - inDstBox[1]; } else { VectorSet4(dstBox, 0, height, width, 0); } if (inSrcTexScale) { VectorCopy2(inSrcTexScale, invTexRes); } else { VectorSet2(invTexRes, 1.0f, 1.0f); } if (inColor) { VectorCopy4(inColor, color); } else { VectorCopy4(colorWhite, color); } if (!shaderProgram) { shaderProgram = &tr.textureColorShader; } FBO_Bind(dst); qglViewport( 0, 0, width, height ); qglScissor( 0, 0, width, height ); Mat4Ortho(0, width, height, 0, 0, 1, projection); GL_Cull( CT_TWO_SIDED ); GL_BindToTMU(src, TB_COLORMAP); VectorSet4(quadVerts[0], dstBox[0], dstBox[1], 0.0f, 1.0f); VectorSet4(quadVerts[1], dstBox[2], dstBox[1], 0.0f, 1.0f); VectorSet4(quadVerts[2], dstBox[2], dstBox[3], 0.0f, 1.0f); VectorSet4(quadVerts[3], dstBox[0], dstBox[3], 0.0f, 1.0f); invTexRes[0] /= src->width; invTexRes[1] /= src->height; GL_State( blend ); GLSL_BindProgram(shaderProgram); GLSL_SetUniformMat4(shaderProgram, UNIFORM_MODELVIEWPROJECTIONMATRIX, projection); GLSL_SetUniformVec4(shaderProgram, UNIFORM_COLOR, color); GLSL_SetUniformVec2(shaderProgram, UNIFORM_INVTEXRES, invTexRes); GLSL_SetUniformVec2(shaderProgram, UNIFORM_AUTOEXPOSUREMINMAX, tr.refdef.autoExposureMinMax); GLSL_SetUniformVec3(shaderProgram, UNIFORM_TONEMINAVGMAXLINEAR, tr.refdef.toneMinAvgMaxLinear); RB_InstantQuad2(quadVerts, texCoords); FBO_Bind(oldFbo); }
void FBO_BlitFromTexture(struct image_s *src, ivec4_t inSrcBox, vec2_t inSrcTexScale, FBO_t *dst, ivec4_t inDstBox, struct shaderProgram_s *shaderProgram, vec4_t inColor, int blend) { ivec4_t dstBox, srcBox; vec2_t srcTexScale; vec4_t color; vec4_t quadVerts[4]; vec2_t texCoords[4]; vec2_t invTexRes; FBO_t *oldFbo = glState.currentFBO; mat4_t projection; int width, height; if (!src) return; if (inSrcBox) { VectorSet4(srcBox, inSrcBox[0], inSrcBox[1], inSrcBox[0] + inSrcBox[2], inSrcBox[1] + inSrcBox[3]); } else { VectorSet4(srcBox, 0, 0, src->width, src->height); } // framebuffers are 0 bottom, Y up. if (inDstBox) { if (dst) { dstBox[0] = inDstBox[0]; dstBox[1] = dst->height - inDstBox[1] - inDstBox[3]; dstBox[2] = inDstBox[0] + inDstBox[2]; dstBox[3] = dst->height - inDstBox[1]; } else { dstBox[0] = inDstBox[0]; dstBox[1] = glConfig.vidHeight - inDstBox[1] - inDstBox[3]; dstBox[2] = inDstBox[0] + inDstBox[2]; dstBox[3] = glConfig.vidHeight - inDstBox[1]; } } else if (dst) { VectorSet4(dstBox, 0, dst->height, dst->width, 0); } else { VectorSet4(dstBox, 0, glConfig.vidHeight, glConfig.vidWidth, 0); } if (inSrcTexScale) { VectorCopy2(inSrcTexScale, srcTexScale); } else { srcTexScale[0] = srcTexScale[1] = 1.0f; } if (inColor) { VectorCopy4(inColor, color); } else { VectorCopy4(colorWhite, color); } if (!shaderProgram) { shaderProgram = &tr.textureColorShader; } FBO_Bind(dst); if (glState.currentFBO) { width = glState.currentFBO->width; height = glState.currentFBO->height; } else { width = glConfig.vidWidth; height = glConfig.vidHeight; } qglViewport( 0, 0, width, height ); qglScissor( 0, 0, width, height ); Mat4Ortho(0, width, height, 0, 0, 1, projection); qglDisable( GL_CULL_FACE ); GL_BindToTMU(src, TB_COLORMAP); VectorSet4(quadVerts[0], dstBox[0], dstBox[1], 0, 1); VectorSet4(quadVerts[1], dstBox[2], dstBox[1], 0, 1); VectorSet4(quadVerts[2], dstBox[2], dstBox[3], 0, 1); VectorSet4(quadVerts[3], dstBox[0], dstBox[3], 0, 1); texCoords[0][0] = srcBox[0] / (float)src->width; texCoords[0][1] = 1.0f - srcBox[1] / (float)src->height; texCoords[1][0] = srcBox[2] / (float)src->width; texCoords[1][1] = 1.0f - srcBox[1] / (float)src->height; texCoords[2][0] = srcBox[2] / (float)src->width; texCoords[2][1] = 1.0f - srcBox[3] / (float)src->height; texCoords[3][0] = srcBox[0] / (float)src->width; texCoords[3][1] = 1.0f - srcBox[3] / (float)src->height; invTexRes[0] = 1.0f / src->width * srcTexScale[0]; invTexRes[1] = 1.0f / src->height * srcTexScale[1]; GL_State( blend ); GLSL_BindProgram(shaderProgram); GLSL_SetUniformMat4(shaderProgram, UNIFORM_MODELVIEWPROJECTIONMATRIX, projection); GLSL_SetUniformVec4(shaderProgram, UNIFORM_COLOR, color); GLSL_SetUniformVec2(shaderProgram, UNIFORM_INVTEXRES, invTexRes); GLSL_SetUniformVec2(shaderProgram, UNIFORM_AUTOEXPOSUREMINMAX, tr.refdef.autoExposureMinMax); GLSL_SetUniformVec3(shaderProgram, UNIFORM_TONEMINAVGMAXLINEAR, tr.refdef.toneMinAvgMaxLinear); RB_InstantQuad2(quadVerts, texCoords); //, color, shaderProgram, invTexRes); FBO_Bind(oldFbo); }
/* =================== RB_FogPass Blends a fog texture on top of everything else =================== */ static void RB_FogPass( int wolfFog ) { fog_t *fog = NULL; vec4_t color; vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0}; float eyeT = 0; shaderProgram_t *sp; glfog_t *glFog = NULL; int deformGen; vec5_t deformParams; if ( tr.refdef.rdflags & RDF_SNOOPERVIEW ) { // no fog pass in snooper return; } if (!fogIsOn) return; if (wolfFog) { // from R_Fog(), altered slightly if ( backEnd.projection2D ) { return; } if ( backEnd.refdef.rdflags & RDF_DRAWINGSKY ) { if ( glfogsettings[FOG_SKY].registered ) { glFog = &glfogsettings[FOG_SKY]; } } if ( skyboxportal && backEnd.refdef.rdflags & RDF_SKYBOXPORTAL ) { if ( glfogsettings[FOG_PORTALVIEW].registered ) { glFog = &glfogsettings[FOG_PORTALVIEW]; } } else { if ( glfogNum > FOG_NONE ) { glFog = &glfogsettings[FOG_CURRENT]; } } if (!glFog) return; } ComputeDeformValues(&deformGen, deformParams); { int index = 0; if (deformGen != DGEN_NONE) index |= FOGDEF_USE_DEFORM_VERTEXES; if (glState.vertexAnimation) index |= FOGDEF_USE_VERTEX_ANIMATION; if (wolfFog) { if (glFog->mode == GL_LINEAR) index |= FOGDEF_USE_WOLF_FOG_LINEAR; else // if (glFog->mode == GL_EXP) index |= FOGDEF_USE_WOLF_FOG_EXPONENTIAL; } sp = &tr.fogShader[index]; } backEnd.pc.c_fogDraws++; GLSL_BindProgram(sp); if (!wolfFog) fog = tr.world->fogs + tess.fogNum; GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); 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 (wolfFog) { color[0] = glFog->color[0]; color[1] = glFog->color[1]; color[2] = glFog->color[2]; color[3] = glFog->color[3]; } else { color[0] = ((unsigned char *)(&fog->colorInt))[0] / 255.0f; color[1] = ((unsigned char *)(&fog->colorInt))[1] / 255.0f; color[2] = ((unsigned char *)(&fog->colorInt))[2] / 255.0f; color[3] = ((unsigned char *)(&fog->colorInt))[3] / 255.0f; } GLSL_SetUniformVec4(sp, UNIFORM_COLOR, color); ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT, glFog); GLSL_SetUniformVec4(sp, UNIFORM_FOGDISTANCE, fogDistanceVector); GLSL_SetUniformVec4(sp, UNIFORM_FOGDEPTH, fogDepthVector); GLSL_SetUniformFloat(sp, UNIFORM_FOGEYET, eyeT); if ( tess.shader->fogPass == FP_EQUAL ) { GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA | GLS_DEPTHFUNC_EQUAL ); } else { GL_State( GLS_SRCBLEND_SRC_ALPHA | GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA ); } if (tess.multiDrawPrimitives) { shaderCommands_t *input = &tess; R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); } }
/* ============= RB_PostProcess ============= */ const void *RB_PostProcess(const void *data) { const postProcessCommand_t *cmd = data; FBO_t *srcFbo; ivec4_t srcBox, dstBox; qboolean autoExposure; // finish any 2D drawing if needed if(tess.numIndexes) RB_EndSurface(); if (!glRefConfig.framebufferObject || !r_postProcess->integer) { // do nothing return (const void *)(cmd + 1); } if (cmd) { backEnd.refdef = cmd->refdef; backEnd.viewParms = cmd->viewParms; } srcFbo = tr.renderFbo; if (tr.msaaResolveFbo) { // Resolve the MSAA before anything else // Can't resolve just part of the MSAA FBO, so multiple views will suffer a performance hit here FBO_FastBlit(tr.renderFbo, NULL, tr.msaaResolveFbo, NULL, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); srcFbo = tr.msaaResolveFbo; } dstBox[0] = backEnd.viewParms.viewportX; dstBox[1] = backEnd.viewParms.viewportY; dstBox[2] = backEnd.viewParms.viewportWidth; dstBox[3] = backEnd.viewParms.viewportHeight; if (r_ssao->integer) { srcBox[0] = backEnd.viewParms.viewportX * tr.screenSsaoImage->width / (float)glConfig.vidWidth; srcBox[1] = backEnd.viewParms.viewportY * tr.screenSsaoImage->height / (float)glConfig.vidHeight; srcBox[2] = backEnd.viewParms.viewportWidth * tr.screenSsaoImage->width / (float)glConfig.vidWidth; srcBox[3] = backEnd.viewParms.viewportHeight * tr.screenSsaoImage->height / (float)glConfig.vidHeight; FBO_Blit(tr.screenSsaoFbo, srcBox, NULL, srcFbo, dstBox, NULL, NULL, GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ZERO); } srcBox[0] = backEnd.viewParms.viewportX; srcBox[1] = backEnd.viewParms.viewportY; srcBox[2] = backEnd.viewParms.viewportWidth; srcBox[3] = backEnd.viewParms.viewportHeight; if (srcFbo) { if (r_hdr->integer && (r_toneMap->integer || r_forceToneMap->integer)) { autoExposure = r_autoExposure->integer || r_forceAutoExposure->integer; RB_ToneMap(srcFbo, srcBox, NULL, dstBox, autoExposure); } else if (r_cameraExposure->value == 0.0f) { FBO_FastBlit(srcFbo, srcBox, NULL, dstBox, GL_COLOR_BUFFER_BIT, GL_NEAREST); } else { vec4_t color; color[0] = color[1] = color[2] = pow(2, r_cameraExposure->value); //exp2(r_cameraExposure->value); color[3] = 1.0f; FBO_Blit(srcFbo, srcBox, NULL, NULL, dstBox, NULL, color, 0); } } if (r_drawSunRays->integer) RB_SunRays(NULL, srcBox, NULL, dstBox); if (1) RB_BokehBlur(NULL, srcBox, NULL, dstBox, backEnd.refdef.blurFactor); else RB_GaussianBlur(backEnd.refdef.blurFactor); #if 0 if (0) { vec4_t quadVerts[4]; vec2_t texCoords[4]; ivec4_t iQtrBox; vec4_t box; vec4_t viewInfo; static float scale = 5.0f; scale -= 0.005f; if (scale < 0.01f) scale = 5.0f; FBO_FastBlit(NULL, NULL, tr.quarterFbo[0], NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR); iQtrBox[0] = backEnd.viewParms.viewportX * tr.quarterImage[0]->width / (float)glConfig.vidWidth; iQtrBox[1] = backEnd.viewParms.viewportY * tr.quarterImage[0]->height / (float)glConfig.vidHeight; iQtrBox[2] = backEnd.viewParms.viewportWidth * tr.quarterImage[0]->width / (float)glConfig.vidWidth; iQtrBox[3] = backEnd.viewParms.viewportHeight * tr.quarterImage[0]->height / (float)glConfig.vidHeight; qglViewport(iQtrBox[0], iQtrBox[1], iQtrBox[2], iQtrBox[3]); qglScissor(iQtrBox[0], iQtrBox[1], iQtrBox[2], iQtrBox[3]); VectorSet4(box, 0.0f, 0.0f, 1.0f, 1.0f); texCoords[0][0] = box[0]; texCoords[0][1] = box[3]; texCoords[1][0] = box[2]; texCoords[1][1] = box[3]; texCoords[2][0] = box[2]; texCoords[2][1] = box[1]; texCoords[3][0] = box[0]; texCoords[3][1] = box[1]; VectorSet4(box, -1.0f, -1.0f, 1.0f, 1.0f); VectorSet4(quadVerts[0], box[0], box[3], 0, 1); VectorSet4(quadVerts[1], box[2], box[3], 0, 1); VectorSet4(quadVerts[2], box[2], box[1], 0, 1); VectorSet4(quadVerts[3], box[0], box[1], 0, 1); GL_State(GLS_DEPTHTEST_DISABLE); VectorSet4(viewInfo, backEnd.viewParms.zFar / r_znear->value, backEnd.viewParms.zFar, 0.0, 0.0); viewInfo[2] = scale / (float)(tr.quarterImage[0]->width); viewInfo[3] = scale / (float)(tr.quarterImage[0]->height); FBO_Bind(tr.quarterFbo[1]); GLSL_BindProgram(&tr.depthBlurShader[2]); GL_BindToTMU(tr.quarterImage[0], TB_COLORMAP); GLSL_SetUniformVec4(&tr.depthBlurShader[2], UNIFORM_VIEWINFO, viewInfo); RB_InstantQuad2(quadVerts, texCoords); FBO_Bind(tr.quarterFbo[0]); GLSL_BindProgram(&tr.depthBlurShader[3]); GL_BindToTMU(tr.quarterImage[1], TB_COLORMAP); GLSL_SetUniformVec4(&tr.depthBlurShader[3], UNIFORM_VIEWINFO, viewInfo); RB_InstantQuad2(quadVerts, texCoords); SetViewportAndScissor(); FBO_FastBlit(tr.quarterFbo[1], NULL, NULL, NULL, GL_COLOR_BUFFER_BIT, GL_LINEAR); FBO_Bind(NULL); } #endif if (0 && r_sunlightMode->integer) { ivec4_t dstBox; VectorSet4(dstBox, 0, 0, 128, 128); FBO_BlitFromTexture(tr.sunShadowDepthImage[0], NULL, NULL, NULL, dstBox, NULL, NULL, 0); VectorSet4(dstBox, 128, 0, 128, 128); FBO_BlitFromTexture(tr.sunShadowDepthImage[1], NULL, NULL, NULL, dstBox, NULL, NULL, 0); VectorSet4(dstBox, 256, 0, 128, 128); FBO_BlitFromTexture(tr.sunShadowDepthImage[2], NULL, NULL, NULL, dstBox, NULL, NULL, 0); VectorSet4(dstBox, 384, 0, 128, 128); FBO_BlitFromTexture(tr.sunShadowDepthImage[3], NULL, NULL, NULL, dstBox, NULL, NULL, 0); } if (0) { ivec4_t dstBox; VectorSet4(dstBox, 256, glConfig.vidHeight - 256, 256, 256); FBO_BlitFromTexture(tr.renderDepthImage, NULL, NULL, NULL, dstBox, NULL, NULL, 0); VectorSet4(dstBox, 512, glConfig.vidHeight - 256, 256, 256); FBO_BlitFromTexture(tr.screenShadowImage, NULL, NULL, NULL, dstBox, NULL, NULL, 0); } if (0) { ivec4_t dstBox; VectorSet4(dstBox, 256, glConfig.vidHeight - 256, 256, 256); FBO_BlitFromTexture(tr.sunRaysImage, NULL, NULL, NULL, dstBox, NULL, NULL, 0); } #if 0 if (r_cubeMapping->integer && tr.numCubemaps) { ivec4_t dstBox; int cubemapIndex = R_CubemapForPoint( backEnd.viewParms.or.origin ); if (cubemapIndex) { VectorSet4(dstBox, 0, glConfig.vidHeight - 256, 256, 256); //FBO_BlitFromTexture(tr.renderCubeImage, NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0); FBO_BlitFromTexture(tr.cubemaps[cubemapIndex - 1].image, NULL, NULL, NULL, dstBox, &tr.testcubeShader, NULL, 0); } } #endif backEnd.framePostProcessed = qtrue; return (const void *)(cmd + 1); }
/* ============== RB_SurfaceBeam ============== */ static void RB_SurfaceBeam( void ) { #define NUM_BEAM_SEGS 6 refEntity_t *e; shaderProgram_t *sp = &tr.textureColorShader; int i; vec3_t perpvec; vec3_t direction, normalized_direction; vec3_t start_points[NUM_BEAM_SEGS], end_points[NUM_BEAM_SEGS]; vec3_t oldorigin, origin; e = &backEnd.currentEntity->e; oldorigin[0] = e->oldorigin[0]; oldorigin[1] = e->oldorigin[1]; oldorigin[2] = e->oldorigin[2]; origin[0] = e->origin[0]; origin[1] = e->origin[1]; origin[2] = e->origin[2]; normalized_direction[0] = direction[0] = oldorigin[0] - origin[0]; normalized_direction[1] = direction[1] = oldorigin[1] - origin[1]; normalized_direction[2] = direction[2] = oldorigin[2] - origin[2]; if ( VectorNormalize( normalized_direction ) == 0 ) return; PerpendicularVector( perpvec, normalized_direction ); VectorScale( perpvec, 4, perpvec ); for ( i = 0; i < NUM_BEAM_SEGS ; i++ ) { RotatePointAroundVector( start_points[i], normalized_direction, perpvec, (360.0/NUM_BEAM_SEGS)*i ); // VectorAdd( start_points[i], origin, start_points[i] ); VectorAdd( start_points[i], direction, end_points[i] ); } GL_BindToTMU( tr.whiteImage, TB_COLORMAP ); GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE ); // FIXME: Quake3 doesn't use this, so I never tested it tess.numVertexes = 0; tess.numIndexes = 0; tess.firstIndex = 0; for ( i = 0; i <= NUM_BEAM_SEGS; i++ ) { VectorCopy(start_points[ i % NUM_BEAM_SEGS ], tess.xyz[tess.numVertexes++]); VectorCopy(end_points [ i % NUM_BEAM_SEGS ], tess.xyz[tess.numVertexes++]); } for ( i = 0; i < NUM_BEAM_SEGS; i++ ) { tess.indexes[tess.numIndexes++] = i * 2; tess.indexes[tess.numIndexes++] = (i + 1) * 2; tess.indexes[tess.numIndexes++] = 1 + i * 2; tess.indexes[tess.numIndexes++] = 1 + i * 2; tess.indexes[tess.numIndexes++] = (i + 1) * 2; tess.indexes[tess.numIndexes++] = 1 + (i + 1) * 2; } // FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function RB_UpdateTessVao(ATTR_POSITION); GLSL_BindProgram(sp); GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); GLSL_SetUniformVec4(sp, UNIFORM_COLOR, colorRed); GLSL_SetUniformInt(sp, UNIFORM_ALPHATEST, 0); R_DrawElements(tess.numIndexes, tess.firstIndex); tess.numIndexes = 0; tess.numVertexes = 0; tess.firstIndex = 0; }
static void ProjectDlightTexture( void ) { int l; vec3_t origin; float scale; float radius; int deformGen; vec5_t deformParams; if ( !backEnd.refdef.num_dlights ) { return; } ComputeDeformValues(&deformGen, deformParams); for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { dlight_t *dl; shaderProgram_t *sp; vec4_t vector; if ( !( tess.dlightBits & ( 1 << l ) ) ) { continue; // this surface definately doesn't have any of this light } dl = &backEnd.refdef.dlights[l]; VectorCopy( dl->transformed, origin ); radius = dl->radius; scale = 1.0f / radius; sp = &tr.dlightShader[deformGen == DGEN_NONE ? 0 : 1]; backEnd.pc.c_dlightDraws++; GLSL_BindProgram(sp); GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); 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); } vector[0] = dl->color[0]; vector[1] = dl->color[1]; vector[2] = dl->color[2]; vector[3] = 1.0f; GLSL_SetUniformVec4(sp, UNIFORM_COLOR, vector); vector[0] = origin[0]; vector[1] = origin[1]; vector[2] = origin[2]; vector[3] = scale; GLSL_SetUniformVec4(sp, UNIFORM_DLIGHTINFO, vector); GL_Bind( tr.dlightImage ); // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light // where they aren't rendered if ( dl->additive ) { GL_State( GLS_ATEST_GT_0 | GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } else { GL_State( GLS_ATEST_GT_0 | GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); } if (tess.multiDrawPrimitives) { shaderCommands_t *input = &tess; R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { R_DrawElementsVBO(tess.numIndexes, tess.firstIndex, tess.minIndex, tess.maxIndex); } backEnd.pc.c_totalIndexes += tess.numIndexes; backEnd.pc.c_dlightIndexes += tess.numIndexes; } }
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; } }
static void ForwardDlight( void ) { int l; //vec3_t origin; //float scale; float radius; int deformGen; vec5_t deformParams; vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0}; float eyeT = 0; shaderCommands_t *input = &tess; shaderStage_t *pStage = tess.xstages[0]; if ( !backEnd.refdef.num_dlights ) { return; } ComputeDeformValues(&deformGen, deformParams); ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT); for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { dlight_t *dl; shaderProgram_t *sp; vec4_t vector; matrix_t matrix; if ( !( tess.dlightBits & ( 1 << l ) ) ) { continue; // this surface definately doesn't have any of this light } dl = &backEnd.refdef.dlights[l]; //VectorCopy( dl->transformed, origin ); radius = dl->radius; //scale = 1.0f / radius; //if (pStage->glslShaderGroup == tr.lightallShader) { int index = pStage->glslShaderIndex; index &= ~(LIGHTDEF_LIGHTTYPE_MASK | LIGHTDEF_USE_DELUXEMAP); index |= LIGHTDEF_USE_LIGHT_VECTOR; sp = &tr.lightallShader[index]; } backEnd.pc.c_lightallDraws++; GLSL_BindProgram(sp); GLSL_SetUniformMatrix16(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); GLSL_SetUniformVec3(sp, UNIFORM_VIEWORIGIN, backEnd.viewParms.or.origin); 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 ) { vec4_t fogColorMask; GLSL_SetUniformVec4(sp, UNIFORM_FOGDISTANCE, fogDistanceVector); GLSL_SetUniformVec4(sp, UNIFORM_FOGDEPTH, fogDepthVector); GLSL_SetUniformFloat(sp, UNIFORM_FOGEYET, eyeT); ComputeFogColorMask(pStage, fogColorMask); GLSL_SetUniformVec4(sp, UNIFORM_FOGCOLORMASK, fogColorMask); } { vec4_t baseColor; vec4_t vertColor; ComputeShaderColors(pStage, baseColor, vertColor); GLSL_SetUniformVec4(sp, UNIFORM_BASECOLOR, baseColor); GLSL_SetUniformVec4(sp, UNIFORM_VERTCOLOR, vertColor); } 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); GLSL_SetUniformVec3(sp, UNIFORM_DIRECTEDLIGHT, dl->color); VectorSet(vector, 0, 0, 0); GLSL_SetUniformVec3(sp, UNIFORM_AMBIENTLIGHT, vector); VectorCopy(dl->origin, vector); vector[3] = 1.0f; GLSL_SetUniformVec4(sp, UNIFORM_LIGHTORIGIN, vector); GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, radius); GLSL_SetUniformVec2(sp, UNIFORM_MATERIALINFO, pStage->materialInfo); // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light // where they aren't rendered GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); GLSL_SetUniformMatrix16(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix); if (pStage->bundle[TB_DIFFUSEMAP].image[0]) R_BindAnimatedImageToTMU( &pStage->bundle[TB_DIFFUSEMAP], TB_DIFFUSEMAP); if (pStage->bundle[TB_NORMALMAP].image[0]) R_BindAnimatedImageToTMU( &pStage->bundle[TB_NORMALMAP], TB_NORMALMAP); if (pStage->bundle[TB_SPECULARMAP].image[0]) R_BindAnimatedImageToTMU( &pStage->bundle[TB_SPECULARMAP], TB_SPECULARMAP); if (r_dlightMode->integer >= 2) { GL_SelectTexture(TB_SHADOWMAP); GL_BindCubemap(tr.shadowCubemaps[l]); GL_SelectTexture(0); } ComputeTexMatrix( pStage, TB_DIFFUSEMAP, matrix ); VectorSet4(vector, matrix[0], matrix[1], matrix[4], matrix[5]); GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, vector); VectorSet4(vector, matrix[8], matrix[9], matrix[12], matrix[13]); GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector); GLSL_SetUniformInt(sp, UNIFORM_TCGEN0, pStage->bundle[0].tcGen); // // draw // if (input->multiDrawPrimitives) { R_DrawMultiElementsVBO(input->multiDrawPrimitives, input->multiDrawMinIndex, input->multiDrawMaxIndex, input->multiDrawNumIndexes, input->multiDrawFirstIndex); } else { R_DrawElementsVBO(input->numIndexes, input->firstIndex, input->minIndex, input->maxIndex); } backEnd.pc.c_totalIndexes += tess.numIndexes; backEnd.pc.c_dlightIndexes += tess.numIndexes; } }
static void ForwardDlight( void ) { int l; //vec3_t origin; //float scale; float radius; int deformGen; vec5_t deformParams; vec4_t fogDistanceVector, fogDepthVector = {0, 0, 0, 0}; float eyeT = 0; shaderCommands_t *input = &tess; shaderStage_t *pStage = tess.xstages[0]; if ( !backEnd.refdef.num_dlights ) { return; } ComputeDeformValues(&deformGen, deformParams); ComputeFogValues(fogDistanceVector, fogDepthVector, &eyeT); for ( l = 0 ; l < backEnd.refdef.num_dlights ; l++ ) { dlight_t *dl; shaderProgram_t *sp; vec4_t vector; vec4_t texMatrix; vec4_t texOffTurb; if ( !( tess.dlightBits & ( 1 << l ) ) ) { continue; // this surface definately doesn't have any of this light } dl = &backEnd.refdef.dlights[l]; //VectorCopy( dl->transformed, origin ); radius = dl->radius; //scale = 1.0f / radius; //if (pStage->glslShaderGroup == tr.lightallShader) { int index = pStage->glslShaderIndex; index &= ~LIGHTDEF_LIGHTTYPE_MASK; index |= LIGHTDEF_USE_LIGHT_VECTOR; sp = &tr.lightallShader[index]; } backEnd.pc.c_lightallDraws++; 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 ) { vec4_t fogColorMask; GLSL_SetUniformVec4(sp, UNIFORM_FOGDISTANCE, fogDistanceVector); GLSL_SetUniformVec4(sp, UNIFORM_FOGDEPTH, fogDepthVector); GLSL_SetUniformFloat(sp, UNIFORM_FOGEYET, eyeT); ComputeFogColorMask(pStage, fogColorMask); GLSL_SetUniformVec4(sp, UNIFORM_FOGCOLORMASK, fogColorMask); } { vec4_t baseColor; vec4_t vertColor; ComputeShaderColors(pStage, baseColor, vertColor, GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE); GLSL_SetUniformVec4(sp, UNIFORM_BASECOLOR, baseColor); GLSL_SetUniformVec4(sp, UNIFORM_VERTCOLOR, vertColor); } 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); GLSL_SetUniformVec3(sp, UNIFORM_DIRECTEDLIGHT, dl->color); VectorSet(vector, 0, 0, 0); GLSL_SetUniformVec3(sp, UNIFORM_AMBIENTLIGHT, vector); VectorCopy(dl->origin, vector); vector[3] = 1.0f; GLSL_SetUniformVec4(sp, UNIFORM_LIGHTORIGIN, vector); GLSL_SetUniformFloat(sp, UNIFORM_LIGHTRADIUS, radius); GLSL_SetUniformVec4(sp, UNIFORM_NORMALSCALE, pStage->normalScale); GLSL_SetUniformVec4(sp, UNIFORM_SPECULARSCALE, pStage->specularScale); // include GLS_DEPTHFUNC_EQUAL so alpha tested surfaces don't add light // where they aren't rendered GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHFUNC_EQUAL ); GLSL_SetUniformMat4(sp, UNIFORM_MODELMATRIX, backEnd.or.transformMatrix); if (pStage->bundle[TB_DIFFUSEMAP].image[0]) R_BindAnimatedImageToTMU( &pStage->bundle[TB_DIFFUSEMAP], TB_DIFFUSEMAP); // 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 (pStage->bundle[TB_NORMALMAP].image[0]) { R_BindAnimatedImageToTMU( &pStage->bundle[TB_NORMALMAP], TB_NORMALMAP); } else if (r_normalMapping->integer) GL_BindToTMU( tr.whiteImage, TB_NORMALMAP ); if (pStage->bundle[TB_SPECULARMAP].image[0]) { R_BindAnimatedImageToTMU( &pStage->bundle[TB_SPECULARMAP], TB_SPECULARMAP); } else if (r_specularMapping->integer) GL_BindToTMU( tr.whiteImage, TB_SPECULARMAP ); { vec4_t enableTextures; VectorSet4(enableTextures, 0.0f, 0.0f, 0.0f, 0.0f); GLSL_SetUniformVec4(sp, UNIFORM_ENABLETEXTURES, enableTextures); } if (r_dlightMode->integer >= 2) { GL_SelectTexture(TB_SHADOWMAP); GL_Bind(tr.shadowCubemaps[l]); GL_SelectTexture(0); } 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); // // 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); } backEnd.pc.c_totalIndexes += tess.numIndexes; backEnd.pc.c_dlightIndexes += tess.numIndexes; backEnd.pc.c_dlightVertexes += tess.numVertexes; } }
/* * RE_StretchRaw * * FIXME: not exactly backend * Stretches a raw 32 bit power of 2 bitmap image over the given screen rectangle. * Used for cinematics. */ void RE_StretchRaw(int x, int y, int w, int h, int cols, int rows, const byte *data, int client, qbool dirty) { int i, j; int start, end; shaderProgram_t *sp = &tr.textureColorShader; Vec4 color; if(!tr.registered){ return; } R_SyncRenderThread(); /* we definately want to sync every frame for the cinematics */ qglFinish(); start = 0; if(r_speeds->integer){ start = ri.Milliseconds(); } /* make sure rows and cols are powers of 2 */ for(i = 0; (1 << i) < cols; i++){ } for(j = 0; (1 << j) < rows; j++){ } if((1 << i) != cols || (1 << j) != rows){ ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows); } GL_Bind(tr.scratchImage[client]); /* if the scratchImage isn't in the format we want, specify it as a new texture */ if(cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height){ tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols; tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows; qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); }else{ if(dirty){ /* otherwise, just subimage upload it so that drivers can tell we are going to be changing * it and don't try and do a texture compression */ qglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data); } } if(r_speeds->integer){ end = ri.Milliseconds(); ri.Printf(PRINT_ALL, "qglTexSubImage2D %i, %i: %i msec\n", cols, rows, end - start); } /* FIXME: HUGE hack */ if(glRefConfig.framebufferObject && !glState.currentFBO){ if(backEnd.framePostProcessed){ FBO_Bind(tr.screenScratchFbo); }else{ FBO_Bind(tr.renderFbo); } } RB_SetGL2D(); tess.numIndexes = 0; tess.numVertexes = 0; tess.firstIndex = 0; tess.xyz[tess.numVertexes][0] = x; tess.xyz[tess.numVertexes][1] = y; tess.xyz[tess.numVertexes][2] = 0; tess.xyz[tess.numVertexes][3] = 1; tess.texCoords[tess.numVertexes][0][0] = 0.5f / cols; tess.texCoords[tess.numVertexes][0][1] = 0.5f / rows; tess.texCoords[tess.numVertexes][0][2] = 0; tess.texCoords[tess.numVertexes][0][3] = 1; tess.numVertexes++; tess.xyz[tess.numVertexes][0] = x + w; tess.xyz[tess.numVertexes][1] = y; tess.xyz[tess.numVertexes][2] = 0; tess.xyz[tess.numVertexes][3] = 1; tess.texCoords[tess.numVertexes][0][0] = (cols - 0.5f) / cols; tess.texCoords[tess.numVertexes][0][1] = 0.5f / rows; tess.texCoords[tess.numVertexes][0][2] = 0; tess.texCoords[tess.numVertexes][0][3] = 1; tess.numVertexes++; tess.xyz[tess.numVertexes][0] = x + w; tess.xyz[tess.numVertexes][1] = y + h; tess.xyz[tess.numVertexes][2] = 0; tess.xyz[tess.numVertexes][3] = 1; tess.texCoords[tess.numVertexes][0][0] = (cols - 0.5f) / cols; tess.texCoords[tess.numVertexes][0][1] = (rows - 0.5f) / rows; tess.texCoords[tess.numVertexes][0][2] = 0; tess.texCoords[tess.numVertexes][0][3] = 1; tess.numVertexes++; tess.xyz[tess.numVertexes][0] = x; tess.xyz[tess.numVertexes][1] = y + h; tess.xyz[tess.numVertexes][2] = 0; tess.xyz[tess.numVertexes][3] = 1; tess.texCoords[tess.numVertexes][0][0] = 0.5f / cols; tess.texCoords[tess.numVertexes][0][1] = (rows - 0.5f) / rows; tess.texCoords[tess.numVertexes][0][2] = 0; tess.texCoords[tess.numVertexes][0][3] = 1; tess.numVertexes++; tess.indexes[tess.numIndexes++] = 0; tess.indexes[tess.numIndexes++] = 1; tess.indexes[tess.numIndexes++] = 2; tess.indexes[tess.numIndexes++] = 0; tess.indexes[tess.numIndexes++] = 2; tess.indexes[tess.numIndexes++] = 3; /* FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function */ RB_UpdateVBOs(ATTR_POSITION | ATTR_TEXCOORD); sp = &tr.textureColorShader; GLSL_VertexAttribsState(ATTR_POSITION | ATTR_TEXCOORD); GLSL_BindProgram(sp); GLSL_SetUniformMatrix16(sp, TEXTURECOLOR_UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); setv34(color, 1, 1, 1, 1); GLSL_SetUniformVec4(sp, TEXTURECOLOR_UNIFORM_COLOR, color); qglDrawElements(GL_TRIANGLES, tess.numIndexes, GL_INDEX_TYPE, BUFFER_OFFSET(0)); /* R_BindNullVBO(); * R_BindNullIBO(); */ tess.numIndexes = 0; tess.numVertexes = 0; tess.firstIndex = 0; }
static void DrawSkySideInner( struct image_s *image, const int mins[2], const int maxs[2] ) { int s, t; int firstVertex = tess.numVertexes; //int firstIndex = tess.numIndexes; int minIndex = tess.minIndex; int maxIndex = tess.maxIndex; vec4_t color; //tess.numVertexes = 0; //tess.numIndexes = 0; tess.firstIndex = tess.numIndexes; GL_Bind( image ); GL_Cull( CT_TWO_SIDED ); for ( t = mins[1]+HALF_SKY_SUBDIVISIONS; t <= maxs[1]+HALF_SKY_SUBDIVISIONS; t++ ) { for ( s = mins[0]+HALF_SKY_SUBDIVISIONS; s <= maxs[0]+HALF_SKY_SUBDIVISIONS; s++ ) { tess.xyz[tess.numVertexes][0] = s_skyPoints[t][s][0]; tess.xyz[tess.numVertexes][1] = s_skyPoints[t][s][1]; tess.xyz[tess.numVertexes][2] = s_skyPoints[t][s][2]; tess.xyz[tess.numVertexes][3] = 1.0; tess.texCoords[tess.numVertexes][0][0] = s_skyTexCoords[t][s][0]; tess.texCoords[tess.numVertexes][0][1] = s_skyTexCoords[t][s][1]; tess.numVertexes++; if(tess.numVertexes >= SHADER_MAX_VERTEXES) { ri.Error(ERR_DROP, "SHADER_MAX_VERTEXES hit in DrawSkySideVBO()\n"); } } } for ( t = 0; t < maxs[1] - mins[1]; t++ ) { for ( s = 0; s < maxs[0] - mins[0]; s++ ) { if (tess.numIndexes + 6 >= SHADER_MAX_INDEXES) { ri.Error(ERR_DROP, "SHADER_MAX_INDEXES hit in DrawSkySideVBO()\n"); } tess.indexes[tess.numIndexes++] = s + t * (maxs[0] - mins[0] + 1) + firstVertex; tess.indexes[tess.numIndexes++] = s + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex; tess.indexes[tess.numIndexes++] = (s + 1) + t * (maxs[0] - mins[0] + 1) + firstVertex; tess.indexes[tess.numIndexes++] = (s + 1) + t * (maxs[0] - mins[0] + 1) + firstVertex; tess.indexes[tess.numIndexes++] = s + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex; tess.indexes[tess.numIndexes++] = (s + 1) + (t + 1) * (maxs[0] - mins[0] + 1) + firstVertex; } } tess.minIndex = firstVertex; tess.maxIndex = tess.numVertexes; // FIXME: A lot of this can probably be removed for speed, and refactored into a more convenient function RB_UpdateTessVao(ATTR_POSITION | ATTR_TEXCOORD); /* { shaderProgram_t *sp = &tr.textureColorShader; GLSL_BindProgram(sp); GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); color[0] = color[1] = color[2] = tr.identityLight; color[3] = 1.0f; GLSL_SetUniformVec4(sp, UNIFORM_COLOR, color); } */ { shaderProgram_t *sp = &tr.lightallShader[0]; vec4_t vector; GLSL_BindProgram(sp); GLSL_SetUniformMat4(sp, UNIFORM_MODELVIEWPROJECTIONMATRIX, glState.modelviewProjection); color[0] = color[1] = color[2] = backEnd.refdef.colorScale; color[3] = 1.0f; GLSL_SetUniformVec4(sp, UNIFORM_BASECOLOR, color); color[0] = color[1] = color[2] = color[3] = 0.0f; GLSL_SetUniformVec4(sp, UNIFORM_VERTCOLOR, color); VectorSet4(vector, 1.0, 0.0, 0.0, 1.0); GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXMATRIX, vector); VectorSet4(vector, 0.0, 0.0, 0.0, 0.0); GLSL_SetUniformVec4(sp, UNIFORM_DIFFUSETEXOFFTURB, vector); } R_DrawElementsVao(tess.numIndexes - tess.firstIndex, tess.firstIndex, tess.minIndex, tess.maxIndex); //qglDrawElements(GL_TRIANGLES, tess.numIndexes - tess.firstIndex, GL_INDEX_TYPE, BUFFER_OFFSET(tess.firstIndex * sizeof(glIndex_t))); //R_BindNullVBO(); //R_BindNullIBO(); tess.numIndexes = tess.firstIndex; tess.numVertexes = firstVertex; tess.firstIndex = 0; tess.minIndex = minIndex; tess.maxIndex = maxIndex; }