Projective texture and deferred lighting

In my previous question, I asked whether it is possible to do projective texturing with deferred lighting. Now (more than half a year later) I have a problem with my implementation of the same thing. I am trying to apply this technique in light pass. (my projector doesn't affect albedo). I have this projector View a Projection matrix:

``````Matrix projection = Matrix.CreateOrthographicOffCenter(-halfWidth * Scale, halfWidth * Scale, -halfHeight * Scale, halfHeight * Scale, 1, 100000);
Matrix view       = Matrix.CreateLookAt(Position, Target, Vector3.Up);
``````

Where `halfWidth` and `halfHeight` is are half of the texture's width and height, `Position` is the Projector's position and `target` is the projector's target. This seems to be ok. I am drawing full screen quad with this shader:

``````float4x4 InvViewProjection;

texture2D DepthTexture;
texture2D NormalTexture;
texture2D ProjectorTexture;

float4x4 ProjectorViewProjection;

sampler2D depthSampler = sampler_state {
texture = <DepthTexture>;
minfilter = point;
magfilter = point;
mipfilter = point;
};

sampler2D normalSampler = sampler_state {
texture = <NormalTexture>;
minfilter = point;
magfilter = point;
mipfilter = point;
};

sampler2D projectorSampler = sampler_state {
texture = <ProjectorTexture>;
};

float viewportWidth;
float viewportHeight;

// Calculate the 2D screen position of a 3D position
float2 postProjToScreen(float4 position) {
float2 screenPos = position.xy / position.w;
return 0.5f * (float2(screenPos.x, -screenPos.y) + 1);
}

// Calculate the size of one half of a pixel, to convert
// between texels and pixels
float2 halfPixel() {
return 0.5f / float2(viewportWidth, viewportHeight);
}

float4 Position : POSITION0;
};

float4 Position :POSITION0;
float4 PositionCopy : TEXCOORD1;
};

output.Position = input.Position;
output.PositionCopy=output.Position;
return output;
}

float2 texCoord =postProjToScreen(input.PositionCopy) + halfPixel();

// Extract the depth for this pixel from the depth map
float4 depth = tex2D(depthSampler, texCoord);
//return float4(depth.r,0,0,1);
// Recreate the position with the UV coordinates and depth value
float4 position;
position.x = texCoord.x * 2 - 1;
position.y = (1 - texCoord.y) * 2 - 1;
position.z = depth.r;
position.w = 1.0f;

// Transform position from screen space to world space
position = mul(position, InvViewProjection);
position.xyz /= position.w;
//compute projection
float3 projection=tex2D(projectorSampler,postProjToScreen(mul(position,ProjectorViewProjection)) + halfPixel());
return float4(projection,1);
}
``````

In first part of pixel shader is recovered position from G-buffer (this code I am using in other shaders without any problem) and then is tranformed to projector viewprojection space. Problem is that projection doesn't appear. Here is an image of my situation:

The green lines are the rendered projector frustum. Where is my mistake hidden? I am using XNA 4. Thanks for advice and sorry for my English.

EDIT:

Shader above is working but projection was too small. When I changed the Scale property to a large value (e.g. 100), the projection appears. But when the camera moves toward the projection, the projection expands, as can bee seen on this YouTube video.

-

In your shader, you'll need to remove the `position.xyz /= w;` as this is what is causing your resizing issue:

``````// Transform position from screen space to world space
position = mul(position, InvViewProjection);
position.xyz /= position.w;  <<-- Comment this out
``````

That should do the trick.

-
thank's!! it works! – Vodáček Mar 22 '12 at 15:29

If you get results that are too small and get to that size it might be because the frustum is still in 1 to -1 space or 0 to 1 or the like? Is that your origo that the frustum is based around?

-