I recently implemented a prelighting renderer for my XNA voxel engine, but there is now a weird alpha blending glitch. When I render to the light map, I set the graphics device's blend state to additive (though in the pixel shaders for each light I output an opaque color). When I finally render the world, I set the device's blend state to opaque, I only deal with the RGB components of colors in the shaders, and I again output an opaque color. However, the light map and the final rendering both somehow have transparency.

Edit: I believe the problem with the final rendering is caused by the light map's transparency issues. If a pixel appears to be semi-transparent in the light map, then it will appear as so in the final rendering because of how the final color is calculated.

Here is a picture of the rendered world (there is a blue directional light and a red point light at the player's position):


Here is a picture of the light map (different seed, but you get the idea):

light map

Here is my directional light pixel shader (the point light one is similar, but [obviously] with point light calculations):

float4 PSFunc( VSOutput input ) : COLOR0
    // extract information
    float2 coords = GetTexCoords( input.LPosition );
    float4 normal = ( tex2D( normalSampler, coords ) - 0.5 ) * 2.0;

    // calculate the lighting value
    float3 lighting = clamp( -dot( normalize( lightDirection ), normal.xyz ), 0.0, 1.0 ) * lightColor;
    return float4( lighting, 1.0 );

Finally, here is my pixel shader that combines texture and lighting values:

float4 PSFunc( VSOutput input ) : COLOR0
    // extract lighting info (TPosition is the world position in the TEXCOORD0 channel)
    float2 coords = ProjectToScreen( input.TPosition ) + GetHalfPixel();
    float3 light = tex2D( lightSampler, coords );
    light += ambientColor; // ambientColor is a float3

    // calculate final color
    float3 tex = tex2D( spriteSampler, input.UV ).rgb;
    return float4( tex * diffuseColor * light, 1.0 );

Note: I do use the sprite batch to render the text, but I have a graphics state class that allows me to push and pop states (rasterizer, blend, depth-stencil, etc.), so I use that to preserve states when drawing with the sprite batch.


I've found the error. When I render point lights, I use a light mesh placed where the light is. When I render directional lights, I cannot do this because there is no position so I need to render the entire world. For some reason having the blend state set to additive when doing this caused the transparency issues, so when I draw the directional lights I use an opaque blend state then switch back to additive. This works for now because I only have one directional light (the sun) and I only plan to use that one.

Here is a picture of the result now:

new world

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.