/* * R_ComputeShadowmapBounds */ static void R_ComputeShadowmapBounds( void ) { unsigned int i; vec3_t lightDir; vec4_t lightDiffuse; vec3_t mins, maxs; shadowGroup_t *group; for( i = 0; i < rsc.numShadowGroups; i++ ) { group = rsc.shadowGroups + i; // get projection dir from lightgrid R_LightForOrigin( group->origin, lightDir, group->lightAmbient, lightDiffuse, group->projDist * 0.5 ); // prevent light dir from going upwards VectorSet( lightDir, -lightDir[0], -lightDir[1], -fabs( lightDir[2] ) ); VectorNormalize2( lightDir, group->lightDir ); VectorScale( group->lightDir, group->projDist, lightDir ); VectorAdd( group->mins, lightDir, mins ); VectorAdd( group->maxs, lightDir, maxs ); AddPointToBounds( group->mins, group->visMins, group->visMaxs ); AddPointToBounds( group->maxs, group->visMins, group->visMaxs ); AddPointToBounds( mins, group->visMins, group->visMaxs ); AddPointToBounds( maxs, group->visMins, group->visMaxs ); } }
/* * R_RenderMeshGLSL_Material */ static void R_RenderMeshGLSL_Material( r_glslfeat_t programFeatures ) { int i; int tcgen, rgbgen; int state; int program, object; image_t *base, *normalmap, *glossmap, *decalmap, *entdecalmap; mat4x4_t unused; vec3_t lightDir = { 0.0f, 0.0f, 0.0f }; vec4_t ambient = { 0.0f, 0.0f, 0.0f, 0.0f }, diffuse = { 0.0f, 0.0f, 0.0f, 0.0f }; float offsetmappingScale, glossExponent; const superLightStyle_t *lightStyle = NULL; const mfog_t *fog = r_back.colorFog; shaderpass_t *pass = r_back.accumPasses[0]; qboolean applyDecal; // handy pointers base = pass->anim_frames[0]; normalmap = pass->anim_frames[1]; glossmap = pass->anim_frames[2]; decalmap = pass->anim_frames[3]; entdecalmap = pass->anim_frames[4]; tcgen = pass->tcgen; // store the original tcgen rgbgen = pass->rgbgen.type; // store the original rgbgen assert( normalmap ); if( normalmap->samples == 4 ) offsetmappingScale = r_offsetmapping_scale->value * r_back.currentShader->offsetmapping_scale; else // no alpha in normalmap, don't bother with offset mapping offsetmappingScale = 0; if( r_back.currentShader->gloss_exponent ) glossExponent = r_back.currentShader->gloss_exponent; else glossExponent = r_lighting_glossexponent->value; applyDecal = decalmap != NULL; if( ri.params & RP_CLIPPLANE ) programFeatures |= GLSL_COMMON_APPLY_CLIPPING; if( pass->flags & SHADERPASS_GRAYSCALE ) programFeatures |= GLSL_COMMON_APPLY_GRAYSCALE; if( fog ) { programFeatures |= GLSL_COMMON_APPLY_FOG; if( fog != ri.fog_eye ) programFeatures |= GLSL_COMMON_APPLY_FOG2; if( GL_IsAlphaBlending( pass->flags & GLSTATE_SRCBLEND_MASK, pass->flags & GLSTATE_DSTBLEND_MASK ) ) programFeatures |= GLSL_COMMON_APPLY_COLOR_FOG_ALPHA; } if( r_back.currentMeshBuffer->infokey > 0 && ( rgbgen != RGB_GEN_LIGHTING_DIFFUSE ) ) { if( !( r_offsetmapping->integer & 1 ) ) { offsetmappingScale = 0; } if( ri.params & RP_LIGHTMAP ) { programFeatures |= GLSL_MATERIAL_APPLY_BASETEX_ALPHA_ONLY; } if( ( ri.params & RP_DRAWFLAT ) && !( r_back.currentShader->flags & SHADER_NODRAWFLAT ) ) { programFeatures |= GLSL_COMMON_APPLY_DRAWFLAT|GLSL_MATERIAL_APPLY_BASETEX_ALPHA_ONLY; } } else if( ( r_back.currentMeshBuffer->sortkey & 3 ) == MB_POLY ) { // polys if( !( r_offsetmapping->integer & 2 ) ) offsetmappingScale = 0; R_BuildTangentVectors( r_backacc.numVerts, vertsArray, normalsArray, coordsArray, r_backacc.numElems/3, elemsArray, inSVectorsArray ); } else { // models and world lightingDiffuse materials if( r_back.currentMeshBuffer->infokey > 0 ) { if( !( r_offsetmapping->integer & 1 ) ) offsetmappingScale = 0; pass->rgbgen.type = RGB_GEN_VERTEX; } else { // models if( !( r_offsetmapping->integer & 4 ) ) offsetmappingScale = 0; #ifdef CELLSHADEDMATERIAL programFeatures |= GLSL_MATERIAL_APPLY_CELLSHADING; #endif #ifdef HALFLAMBERTLIGHTING programFeatures |= GLSL_MATERIAL_APPLY_HALFLAMBERT; #endif } } // add dynamic lights if( r_back.currentDlightBits ) { programFeatures |= R_DlightbitsToProgramFeatures(); } pass->tcgen = TC_GEN_BASE; R_BindShaderpass( pass, base, 0, &programFeatures ); // calculate vertex color R_ModifyColor( pass, applyDecal, r_back.currentMeshVBO != NULL ); // since R_ModifyColor has forcefully generated RGBA for the first vertex, // set the proper number of color elements here, so GL_COLOR_ARRAY will be enabled // before the DrawElements call if( !(pass->flags & SHADERPASS_NOCOLORARRAY) ) r_backacc.numColors = r_backacc.numVerts; // convert rgbgen and alphagen to GLSL feature defines programFeatures |= R_RGBAlphaGenToProgramFeatures( pass->rgbgen.type, pass->alphagen.type ); GL_TexEnv( GL_MODULATE ); // set shaderpass state (blending, depthwrite, etc) state = r_back.currentShaderState | ( pass->flags & r_back.currentShaderPassMask ) | GLSTATE_BLEND_MTEX; GL_SetState( state ); #if 1 // don't waste time on processing GLSL programs with zero colormask if( ( ri.params & RP_SHADOWMAPVIEW ) & !(programFeatures & GLSL_COMMON_APPLY_BONETRANSFORMS) ) { pass->tcgen = tcgen; // restore original tcgen R_FlushArrays(); return; } #endif // we only send S-vectors to GPU and recalc T-vectors as cross product // in vertex shader pass->tcgen = TC_GEN_SVECTORS; GL_Bind( 1, normalmap ); // normalmap GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY ); R_VertexTCBase( pass, 1, unused, NULL ); if( glossmap && r_lighting_glossintensity->value ) { programFeatures |= GLSL_MATERIAL_APPLY_SPECULAR; GL_Bind( 2, glossmap ); // gloss GL_SetTexCoordArrayMode( 0 ); } if( applyDecal ) { programFeatures |= GLSL_MATERIAL_APPLY_DECAL; if( ri.params & RP_LIGHTMAP ) { decalmap = r_blacktexture; programFeatures |= GLSL_MATERIAL_APPLY_DECAL_ADD; } else { // if no alpha, use additive blending if( decalmap->samples == 3 ) programFeatures |= GLSL_MATERIAL_APPLY_DECAL_ADD; } GL_Bind( 3, decalmap ); // decal GL_SetTexCoordArrayMode( 0 ); } if( entdecalmap ) { programFeatures |= GLSL_MATERIAL_APPLY_ENTITY_DECAL; // if no alpha, use additive blending if( entdecalmap->samples == 3 ) programFeatures |= GLSL_MATERIAL_APPLY_ENTITY_DECAL_ADD; GL_Bind( 4, entdecalmap ); // decal GL_SetTexCoordArrayMode( 0 ); } if( offsetmappingScale > 0 ) programFeatures |= r_offsetmapping_reliefmapping->integer ? GLSL_MATERIAL_APPLY_RELIEFMAPPING : GLSL_MATERIAL_APPLY_OFFSETMAPPING; if( r_back.currentMeshBuffer->infokey > 0 && ( rgbgen != RGB_GEN_LIGHTING_DIFFUSE ) ) { // world surface if( r_back.superLightStyle && r_back.superLightStyle->lightmapNum[0] >= 0 ) { lightStyle = r_back.superLightStyle; // bind lightmap textures and set program's features for lightstyles pass->tcgen = TC_GEN_LIGHTMAP; for( i = 0; i < MAX_LIGHTMAPS && lightStyle->lightmapStyles[i] != 255; i++ ) { r_back.lightmapStyleNum[i+4] = i; GL_Bind( i+4, r_worldbrushmodel->lightmapImages[lightStyle->lightmapNum[i]] ); // lightmap GL_SetTexCoordArrayMode( GL_TEXTURE_COORD_ARRAY ); R_VertexTCBase( pass, i+4, unused, NULL ); } programFeatures |= ( i * GLSL_MATERIAL_APPLY_LIGHTSTYLE0 ); if( i == 1 && !mapConfig.lightingIntensity ) { vec_t *rgb = r_lightStyles[lightStyle->lightmapStyles[0]].rgb; // GLSL_MATERIAL_APPLY_FB_LIGHTMAP indicates that there's no need to renormalize // the lighting vector for specular (saves 3 adds, 3 muls and 1 normalize per pixel) if( rgb[0] == 1 && rgb[1] == 1 && rgb[2] == 1 ) programFeatures |= GLSL_MATERIAL_APPLY_FB_LIGHTMAP; } if( !VectorCompare( mapConfig.ambient, vec3_origin ) ) { VectorCopy( mapConfig.ambient, ambient ); programFeatures |= GLSL_MATERIAL_APPLY_AMBIENT_COMPENSATION; } } } else { vec3_t temp; programFeatures |= GLSL_MATERIAL_APPLY_DIRECTIONAL_LIGHT; if( ( r_back.currentMeshBuffer->sortkey & 3 ) == MB_POLY ) { VectorCopy( r_polys[-r_back.currentMeshBuffer->infokey-1].normal, lightDir ); Vector4Set( ambient, 0, 0, 0, 0 ); Vector4Set( diffuse, 1, 1, 1, 1 ); } else if( ri.currententity ) { if( ri.currententity->flags & RF_FULLBRIGHT ) { Vector4Set( ambient, 1, 1, 1, 1 ); Vector4Set( diffuse, 1, 1, 1, 1 ); } else { if( r_back.currentMeshBuffer->infokey > 0 ) { programFeatures |= GLSL_MATERIAL_APPLY_DIRECTIONAL_LIGHT_MIX; if( r_back.overBrightBits ) programFeatures |= GLSL_COMMON_APPLY_OVERBRIGHT_SCALING; } if( ri.currententity->model && ri.currententity != r_worldent ) { // get weighted incoming direction of world and dynamic lights R_LightForOrigin( ri.currententity->lightingOrigin, temp, ambient, diffuse, ri.currententity->model->radius * ri.currententity->scale); } else { VectorSet( temp, 0.1f, 0.2f, 0.7f ); } if( ri.currententity->flags & RF_MINLIGHT ) { if( ambient[0] <= 0.1f || ambient[1] <= 0.1f || ambient[2] <= 0.1f ) VectorSet( ambient, 0.1f, 0.1f, 0.1f ); } // rotate direction Matrix_TransformVector( ri.currententity->axis, temp, lightDir ); } } } pass->tcgen = tcgen; // restore original tcgen pass->rgbgen.type = rgbgen; // restore original rgbgen program = R_RegisterGLSLProgram( pass->program_type, pass->program, NULL, r_back.currentShader->name, r_back.currentShader->deforms, r_back.currentShader->numdeforms, programFeatures ); object = R_GetProgramObject( program ); if( object ) { qglUseProgramObjectARB( object ); // update uniforms R_UpdateProgramUniforms( program, ri.viewOrigin, vec3_origin, lightDir, ambient, diffuse, lightStyle, qtrue, 0, 0, 0, offsetmappingScale, glossExponent, colorArrayCopy[0], r_back.overBrightBits, r_back.currentShaderTime, r_back.entityColor ); if( programFeatures & GLSL_COMMON_APPLY_FOG ) { cplane_t fogPlane, vpnPlane; R_TransformFogPlanes( fog, fogPlane.normal, &fogPlane.dist, vpnPlane.normal, &vpnPlane.dist ); R_UpdateProgramFogParams( program, fog->shader->fog_color, fog->shader->fog_clearDist, fog->shader->fog_dist, &fogPlane, &vpnPlane, ri.fog_dist_to_eye[fog-r_worldbrushmodel->fogs] ); } // submit animation data if( programFeatures & GLSL_COMMON_APPLY_BONETRANSFORMS ) { R_UpdateProgramBonesParams( program, r_back.currentAnimData->numBones, r_back.currentAnimData->dualQuats ); } // dynamic lights if( r_back.currentDlightBits ) { R_UpdateProgramLightsParams( program, ri.currententity->origin, ri.currententity->axis, r_back.currentDlightBits ); r_back.doDynamicLightsPass = qfalse; } // r_drawflat if( programFeatures & GLSL_COMMON_APPLY_DRAWFLAT ) { R_UpdateDrawFlatParams( program, r_front.wallColor, r_front.floorColor ); } R_FlushArrays(); qglUseProgramObjectARB( 0 ); } }
void RF_LightForOrigin( const vec3_t origin, vec3_t dir, vec4_t ambient, vec4_t diffuse, float radius ) { R_LightForOrigin( origin, dir, ambient, diffuse, radius, false ); }