1
\$\begingroup\$

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):

world

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.

\$\endgroup\$

1 Answer 1

0
\$\begingroup\$

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

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .