I'm an amateur, trying to learn HLSL techniques. I'm currently trying to implement texture projection (making a movie projector) in a DX9 environment.
I'm running my vertices through an alternate view and projection and using that as UV coordinates on a texture. However, I find that the coordinates are very different depending on whether I convert them from screen coordinates to texture coordinates in the vertex shader or the pixel shader and I don't know why. I suspect it may have something to do with some kind of automatic conversions going on between the vertex shader and the pixel shader?
I don't care much about performance, but I really want to use the vertex shader for this calculation so that I can shadow the projection, shadow-buffer style. But there are artifacts and clones that I can't live with.
I'm attaching two pics, one showing the artifacts when calculating UV coordinates in the vertex shader, one when calculating the UV coordinates in the pixel shader (which, other than shadowing, I'm happy with.)
Here is the almost-complete code (I'm leaving out the wide variety of technique calls that all look the same). I'm never sure whether to whittle this down to what's relevant in order to save you some effort in understanding, or to leave it complete in case I turn out unqualified to be the one-that-whittles. Here, there is a single line in the pixel shader that I'm uncommenting in order to replace the UV coordinates with those computed in the vertex shader.
I'm certain that there are a lot of other things that I'm doing poorly as well, and appreciate any extra recommendations. I don't have access to the main executable, just the HLSL.
I greatly appreciate any help anyone is willing to offer. Thanks for looking.
#define MOVIETEX "b.png"
//#define MOVIETEX "test.gif"
//#define MOVIETEX "NT.gif"
#define VSVRS vs_2_0
#define PSVRS ps_2_0 //animated textures don't work in v3.0
#define PI 3.14159265f
#define IDENTITYMATRIX {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0, 0, 0, 1}}
#define BLACK float4(0,0,0,1)
#define CONT_MODEL_INSTANCE "Projector.pmx"
float4x4 cProjector : CONTROLOBJECT < string name = CONT_MODEL_INSTANCE; string item = "Projector"; >;
float4 cFOV : CONTROLOBJECT < string name = CONT_MODEL_INSTANCE; string item = "FOV"; >;
float4 cBrightness : CONTROLOBJECT < string name = CONT_MODEL_INSTANCE; string item = "Brightness"; >;
float4 cCol : CONTROLOBJECT < string name = CONT_MODEL_INSTANCE; string item = "Color"; >;
float4 cNearFar : CONTROLOBJECT < string name = CONT_MODEL_INSTANCE; string item = "NearFar"; >;
float3 cZVec : CONTROLOBJECT < string name = CONT_MODEL_INSTANCE; string item = "NearFar"; >;
static float3 projWPos = float3(cProjector._41, cProjector._42, cProjector._43);
float4x4 WorldMatrix : WORLD;
float4x4 ViewMatrix : VIEW;
float4x4 ViewProjMatrix : VIEWPROJECTION;
float4x4 WorldViewProjMatrix : WORLDVIEWPROJECTION;
float4x4 ProjMatrix : PROJECTION;
float4 MaterialDiffuse : DIFFUSE < string Object = "Geometry"; >;
float3 MaterialAmbient : AMBIENT < string Object = "Geometry"; >;
float4 TextureAddValue : ADDINGTEXTURE;
float4 TextureMulValue : MULTIPLYINGTEXTURE;
texture MovieTex : ANIMATEDTEXTURE <
string ResourceName = MOVIETEX;
>;
sampler MovieSamp = sampler_state {
texture = <MovieTex>;
MINFILTER = LINEAR;
MAGFILTER = LINEAR;
MIPFILTER = LINEAR;
ADDRESSU = BORDER;
ADDRESSV = BORDER;
BORDERCOLOR = BLACK;
};
texture ObjectTexture: MATERIALTEXTURE;
sampler ObjTexSampler = sampler_state {
texture = <ObjectTexture>;
MINFILTER = LINEAR;
MAGFILTER = LINEAR;
MIPFILTER = LINEAR;
ADDRESSU = WRAP;
ADDRESSV = WRAP;
};
technique EdgeTec < string MMDPass = "edge"; > { //disable
}
technique ShadowTec < string MMDPass = "shadow"; > { //disable
}
technique ZplotTec <string MMDPass = "zplot";> { //disable
}
float4x4 mat3tomat4 (float3x3 inpM) {
float4x4 outp = IDENTITYMATRIX;
outp._11 = inpM._11; outp._12 = inpM._12; outp._13 = inpM._13;
outp._21 = inpM._21; outp._22 = inpM._22; outp._23 = inpM._23;
outp._31 = inpM._31; outp._32 = inpM._32; outp._33 = inpM._33;
outp._41 = 0.0f; outp._42 = 0.0f; outp._43 = 0.0f;
outp._14 = 0.0f; outp._24 = 0.0f; outp._34 = 0.0f;
return outp;
}
float4x4 invertTR4x4 (float4x4 inpM) {
//inverts a typical 4x4 matrix composed of only translations and rotations
float4x4 invTr = IDENTITYMATRIX;
invTr._41 = -inpM._41; invTr._42 = -inpM._42; invTr._43 = -inpM._43;
float3x3 invRot3x3 = transpose((float3x3)inpM);
float4x4 invRot4x4 = mat3tomat4(invRot3x3);
float4x4 outpM = mul(invTr, invRot4x4);
return outpM;
}
float4x4 getPerspProj (float2 Fov, float near, float far) {
//http://www.codinglabs.net/article_world_view_projection_matrix.aspx
//receives FOV in degrees
Fov *= PI / 180.0f;
Fov = 1.0f/Fov;
float4x4 outp = IDENTITYMATRIX;
outp._11 = atan(Fov.x/2.0f);
outp._22 = atan(Fov.y/2.0f);
outp._33 = -(far+near)/(far-near);
outp._43 = (-2.0f*near*far)/(far-near);
outp._34 = -1.0f;
outp._44 = 0.0f;
return outp;
}
struct BufferShadow_OUTPUT {
float4 Pos : POSITION;
float4 PTex : TEXCOORD0; //texture coordinates in alternate projection
float4 UV : TEXCOORD1;
float3 Normal : TEXCOORD2;
float3 PEye : TEXCOORD3;
float2 Tex : TEXCOORD4;
float4 wPos : TEXCOORD5;
float4 Color : COLOR0;
};
BufferShadow_OUTPUT BufferShadow_VS(float4 Pos : POSITION, float3 Normal : NORMAL, float2 Tex : TEXCOORD0, float2 Tex2 : TEXCOORD1, uniform bool useTexture, uniform bool useSphereMap, uniform bool useToon)
{
BufferShadow_OUTPUT Out = (BufferShadow_OUTPUT)0;
Pos = mul( Pos, WorldMatrix );
Out.PEye = cZVec - projWPos.xyz; //easier than transforming Zvec
Out.wPos = Pos;
Out.Pos = mul(Pos, ViewProjMatrix);
float4x4 invTR = invertTR4x4(cProjector);
Out.PTex = mul(Pos, invTR);
float4x4 altProj = getPerspProj((cFOV.xy)*cFOV.z, cNearFar.x, cNearFar.y);
Out.PTex = mul(Out.PTex, altProj);
Out.UV = Out.PTex;
Out.UV.xyz /= Out.UV.w;
Out.UV.x = (Out.UV.x + 0.5f)*2.0f;
Out.UV.y = (-Out.UV.y + 0.5f)*2.0f;
Out.UV.xy -= 0.5f; //texture is centered on 0,0
Out.Normal = normalize( mul( Normal, (float3x3)WorldMatrix ) );
Out.Tex = Tex;
Out.Color.rgb = MaterialAmbient;
Out.Color.a = MaterialDiffuse.a;
return Out;
}
float4 BufferShadow_PS(BufferShadow_OUTPUT IN, uniform bool useTexture, uniform bool useSphereMap, uniform bool useToon) : COLOR
{
float4 Color = IN.Color;
float3 PEn = normalize(IN.PEye); float3 Nn = normalize(IN.Normal);
if ( useTexture ) {
float4 TexColor = tex2D( ObjTexSampler, IN.Tex );
TexColor.rgb = lerp(1, TexColor * TextureMulValue + TextureAddValue, TextureMulValue.a + TextureAddValue.a).rgb;
Color *= TexColor;
}
float4 UV = IN.PTex;
UV.xyz /= UV.w;
UV.x = (UV.x + 0.5f) *2.0f;
UV.y = (-UV.y+0.5f) * 2.0f;
UV.xy -= 0.5f;
//uncommenting seems like it should provide same output yet doesn't
//UV = IN.UV;
float4 projTex = tex2D(MovieSamp, UV.xy);
Color *= projTex;
Color = projTex;
Color.rgb *= pow(dot(Nn, PEn), 0.6f);
Color.rgb *= cCol.rgb;
Color.rgb *= cBrightness.x;
if ((UV.z < 0.0f) || (UV.z > 1.0f) || (UV.x < 0.0f) || (UV.x > 1.0f) || (UV.y < 0.0f) || (UV.y > 1.0f)){
return BLACK;
//outside range; using border mode giving me artifacts i don't understand
}
else {return Color;}
}
technique MainTecBS0 < string MMDPass = "object_ss"; bool UseTexture = false; bool UseSphereMap = false; bool UseToon = false; > {
pass DrawObject {
VertexShader = compile vs_3_0 BufferShadow_VS(false, false, false);
PixelShader = compile ps_3_0 BufferShadow_PS(false, false, false);
}
}
↧