protected void RenderTextureLighting( Light light )
{
if ( !( light is TextureLight ) )
return;
TextureLight texLight = (TextureLight)light;
if ( !texLight.IsTextureLight )
return;
if ( texLight.Type == LightType.Spotlight )
spotlightFrustum.Spotlight = texLight;
// no world transform required
targetRenderSystem.WorldMatrix = Matrix4.Identity;
// Set view / proj
targetRenderSystem.ViewMatrix = cameraInProgress.ViewMatrix;
targetRenderSystem.ProjectionMatrix = cameraInProgress.ProjectionMatrix;
TextureUnitState lightTex = textureLightPass.GetTextureUnitState( 0 );
TextureUnitState normalTex = textureLightPass.GetTextureUnitState( 1 );
switch ( texLight.Intensity )
{
case LightIntensity.Normal:
normalTex.ColorBlendMode.operation = LayerBlendOperationEx.Modulate;
break;
case LightIntensity.ModulateX2:
normalTex.ColorBlendMode.operation = LayerBlendOperationEx.ModulateX2;
break;
case LightIntensity.ModulateX4:
normalTex.ColorBlendMode.operation = LayerBlendOperationEx.ModulateX4;
break;
}
if ( texLight.Type == LightType.Spotlight )
{
spotlightFrustum.Spotlight = texLight;
lightTex.SetProjectiveTexturing( true, spotlightFrustum );
}
else
{
lightTex.SetProjectiveTexturing( false, null );
}
if ( texLight.Type == LightType.Directional )
{
// light it using only diffuse color and alpha
normalTex.ColorBlendMode.source2 = LayerBlendSource.Diffuse;
normalTex.AlphaBlendMode.source2 = LayerBlendSource.Diffuse;
}
else
{
// light it using the texture light
normalTex.ColorBlendMode.source2 = LayerBlendSource.Current;
normalTex.AlphaBlendMode.source2 = LayerBlendSource.Current;
}
SetPass( textureLightPass );
if ( texLight.Type == LightType.Directional )
{
// Disable the light texture
targetRenderSystem.SetTexture( 0, true, lightTex.TextureName );
}
// For each material in turn, cache rendering data & render
IEnumerator mapEnu = matFaceGroupMap.Keys.GetEnumerator();
while ( mapEnu.MoveNext() )
{
// Get Material
Material thisMaterial = (Material)mapEnu.Current;
List<BspStaticFaceGroup> faceGrp = matFaceGroupMap[ thisMaterial ];
// if one face group is a quake shader then the material is a quake shader
if ( faceGrp[ 0 ].isQuakeShader )
continue;
ManualCullingMode cullMode = thisMaterial.GetTechnique( 0 ).GetPass( 0 ).ManualCullingMode;
// Empty existing cache
renderOp.indexData.indexCount = 0;
HardwareVertexBuffer bspVertexBuffer = level.VertexData.vertexBufferBinding.GetBuffer( 0 );
HardwareVertexBuffer lightTexCoordBuffer = level.VertexData.vertexBufferBinding.GetBuffer( 1 );
// lock index buffer ready to receive data
unsafe
{
BspVertex* pVertices = (BspVertex*)bspVertexBuffer.Lock( BufferLocking.ReadOnly );
TextureLightMap* pTexLightMap = (TextureLightMap*)lightTexCoordBuffer.Lock( BufferLocking.Discard );
uint* pIdx = (uint*)renderOp.indexData.indexBuffer.Lock( BufferLocking.Discard );
for ( int i = 0; i < faceGrp.Count; i++ )
{
if ( faceGrp[ i ].type != FaceGroup.Patch &&
texLight.AffectsFaceGroup( faceGrp[ i ], cullMode ) )
{
// Cache each
int numElems = CacheLightGeometry( texLight, pIdx, pTexLightMap, pVertices, faceGrp[ i ] );
renderOp.indexData.indexCount += numElems;
pIdx += numElems;
}
}
// Unlock the buffers
renderOp.indexData.indexBuffer.Unlock();
lightTexCoordBuffer.Unlock();
bspVertexBuffer.Unlock();
}
// Skip if no faces to process
if ( renderOp.indexData.indexCount == 0 )
continue;
// Get the plain geometry texture
TextureUnitState geometryTex = thisMaterial.GetTechnique( 0 ).GetPass( 0 ).GetTextureUnitState( 0 );
if ( geometryTex.IsBlank )
continue;
targetRenderSystem.SetTexture( 1, true, geometryTex.TextureName );
// OpenGL requires the addressing mode to be set before every render operation
targetRenderSystem.SetTextureAddressingMode( 0, new UVWAddressing( TextureAddressing.Clamp ) );
targetRenderSystem.Render( renderOp );
}
}