Projective textures different in PS 2.0 than 1.1?

Started by
2 comments, last by Namethatnobodyelsetook 18 years, 1 month ago
I have written a shader that works fine in pixel shader version 1.1, but completely changes in pixel shader version 2.0. What I am doing is projecting the texture from the camera's view as to act as a sort of flashlight. When I switch to PS 2.0 however, the projected texture seems to always be in the top left corner of the screen, and gets larger as I get closer to what it is being projected upon. I was curious as to why it might be doing this. Here is the code for the shader:

float4x4 WorldViewProj; //World * View * Projection
float4x4 World;         //World
float4x4 TexTransform;  //Texture transformation matrix
float3 EyePos;          //World position of the camera
float Ambient = 0.0f;   //Amount of ambient light
float LightFalloff;

texture LightTex;
texture ColorTex;

//Must be clamped so the light texture shows up only once
sampler LightTexSampler = sampler_state
{
    Texture = <LightTex>;
    MinFilter = LINEAR;  
    MagFilter = LINEAR;
    MipFilter = LINEAR;
    AddressU  = Clamp;
    AddressV  = Clamp;
};

sampler ColorTexSampler = sampler_state
{
    Texture = <ColorTex>;
    MinFilter = LINEAR;  
    MagFilter = LINEAR;
    MipFilter = LINEAR;
    AddressU  = Wrap;
    AddressV  = Wrap;
};

////////////////////////////////////////////////////////////
// Structures
////////////////////////////////////////////////////////////
struct MainA2V{
    float4 Position : POSITION;
    float2 TexCoord0 : TEXCOORD0;
};

struct MainV2P{
    float4 Position  : POSITION;
    float2 TexCoord0 : TEXCOORD0;
    float4 TexCoord1 : TEXCOORD1;
    float  Attn      : TEXCOORD2;
};

////////////////////////////////////////////////////////////
// Vertex Shaders
////////////////////////////////////////////////////////////
void MainVS(in MainA2V IN, out MainV2P OUT)
{
    //Copy color texture coordinates through
    OUT.TexCoord0 = IN.TexCoord0;
    
    //First two are the projected texture coordinates
    OUT.TexCoord1 = mul(IN.Position, TexTransform);
    
    //Position to light vector
    float3 LightVec = mul(IN.Position.xyz, (float3x3)World) - EyePos;
    
    //Distance from position to light
    float Dist = dot(LightVec, LightVec);
    
    //Compute attenuation
    OUT.Attn = (LightFalloff * LightFalloff)/Dist;
    
    //Transform model-space vertex position to screen space:
    OUT.Position = mul(IN.Position, WorldViewProj);
}

////////////////////////////////////////////////////////////
// Pixel Shader
////////////////////////////////////////////////////////////
float4 MainPS(in MainV2P IN) : COLOR 
{
    //Read in values for shadow, light texture and color texture
    float4 Color    = tex2D(ColorTexSampler, IN.TexCoord0);
    float4 Light    = tex2D(LightTexSampler, IN.TexCoord1);
    
    //Compute lighting amount
    float4 I = (Light * IN.Attn) + Ambient;
    
    //Color of texture * lighting amount
    return I * Color;
}

////////////////////////////////////////////////////////////
// Techniques
////////////////////////////////////////////////////////////
technique ProjectiveTexture
{
    pass P0
    {
        VertexShader = compile vs_1_1 MainVS();
        PixelShader = compile ps_1_1 MainPS();
    
        TextureTransformFlags[0] = Projected;
        TextureTransformFlags[1] = Projected;
    }
}

Thanks for any help in advance, -Chris
Advertisement
I could be wrong, but im not sure that you are doing that right at all. You shouldn't really be passing in the texture coordinates for the projected texture, you should be calculating them in the vertex shader.

Here is my shader:
float4x4		matWorld;float4x4		matCameraWVP;float4x4		matLightWVP;texture			texLightTexture;sampler			sampLightTextureSampler	= sampler_state{	texture		=	( texLightTexture );	AddressU	=	CLAMP;	AddressV	=	CLAMP;};struct	VS_INPUT{	float4	position	:	POSITION;	float3	normal		:	NORMAL;};struct	VS_OUTPUT{	float4	position	:	POSITION;	float3	normal		:	TEXCOORD0;	float2	texcoord	:	TEXCOORD1;};float2		ClipToScreen( float4	clipPos ){	float2 homog	=	clipPos.xy	/	clipPos.w;		homog.xy	*=	0.5f;	homog.xy	+=	0.5f;	homog.y		= 1-homog.y;		return homog;}VS_OUTPUT	vs_main( VS_INPUT	input ){	VS_OUTPUT	output		=	( VS_OUTPUT )	0;		output.position			=	mul( input.position,	matCameraWVP );	output.normal			=	mul( input.normal,		matWorld);	output.texcoord			=	ClipToScreen( mul( input.position,	matLightWVP ) );		return		output;}float4		ps_main( VS_OUTPUT	input )	:	COLOR{	return	tex2D( sampLightTextureSampler, input.texcoord );}technique	ProjectedTexture{	pass P0	{		VertexShader	=	compile	vs_2_0	vs_main();		PixelShader		=	compile	ps_2_0	ps_main();	}}

Hope that helps,

Dave
I have not tried the code you have supplied there yet, but most of the projective texture samples I have looked at calculate the texture matrix in the app code, then send it to the shader. I assume this method would be quite a bit faster than having to calculate the texture matrix for every vertex. This may not be the case, that is just how it seems to me, is that incorrect?

-Chris
Shader 1.1 didn't have instructions for projective texture lookup, and relied on the fixed pipe flag being set. nVidia drivers also try to guess, though I'm not sure what the guess is based on. I know they look at your microcode, but I'm not sure what they're looking for.

Anyway, In shader 2.0, use tex2Dproj. I haven't tried projection in anything other than 1.1, but as far as I know, this is the only trick to it.

This topic is closed to new replies.

Advertisement