Here's my (well, mostly borrowed) shader code:
#SelectExpand
1float4x4 World
;
2float4x4 View
;
3float4x4 Projection
;
4
5texture DiffuseTexture
;
6texture BumpTexture
;
7texture NormalTexture
;
8float3 CameraPos
;
9float3 LightPosition
;
10float3 LightDiffuseColor
; // intensity multiplier
11float3 LightSpecularColor
; // intensity multiplier
12float LightDistanceSquared
;
13float3 DiffuseColor
;
14float3 AmbientLightColor
;
15float3 EmissiveColor
;
16float3 SpecularColor
;
17float SpecularPower
;
18bool BumpMapping
= true;
19
20sampler texsampler
= sampler_state
21{
22 Texture
= <DiffuseTexture>
;
23};
24
25sampler bumpsampler
= sampler_state
26{
27 Texture
= <BumpTexture>
;
28};
29
30sampler normalsampler
= sampler_state
31{
32 Texture
= <NormalTexture>
;
33};
34
35struct VertexShaderInput
36{
37 float4 Position
: POSITION0
;
38 float2 TexCoords
: TEXCOORD0
;
39};
40
41struct VertexShaderOutput
42{
43 float4 Position
: POSITION0
;
44 float2 TexCoords
: TEXCOORD0
;
45 float3 WorldPos
: TEXCOORD1
;
46};
47
48VertexShaderOutput VertexShaderFunction
(VertexShaderInput input
)
49{
50 VertexShaderOutput output
;
51
52 // "Multiplication will be done in the pre-shader - so no cost per vertex"
53 float4x4 viewprojection
= mul
(View, Projection
);
54 float4 posWorld
= mul
(input.Position, World
);
55 output.Position
= mul
(posWorld, viewprojection
);
56 output.TexCoords
= input.TexCoords
;
57
58 // Passing information on to do both specular AND diffuse calculation in pixel shader
59 output.WorldPos
= posWorld
;
60
61 return output
;
62}
63
64float4 PixelShaderFunctionWithTex
(VertexShaderOutput input
) : COLOR0
65{
66 // Get light direction for this fragment
67 float3 lightDir
= normalize
(input.WorldPos
- LightPosition
); // per pixel diffuse lighting
68 float3 Normal
= tex2D
(normalsampler, input.TexCoords
);
69
70 // Note: Non-uniform scaling not supported
71 float diffuseLighting
= saturate
(dot
(Normal,
-lightDir
));
72
73 // Introduce fall-off of light intensity
74 diffuseLighting
*= (LightDistanceSquared
/ dot
(LightPosition
- input.WorldPos, LightPosition
- input.WorldPos
));
75
76 // Using Blinn half angle modification for perofrmance over correctness
77 float3 h
= normalize
(normalize
(CameraPos
- input.WorldPos
) - lightDir
);
78 float specLighting
= pow(saturate
(dot
(h, Normal
)), SpecularPower
);
79 float4 texel
= tex2D
(texsampler, input.TexCoords
);
80 float4 bump
= tex2D
(bumpsampler, input.TexCoords
);
81
82 if (!BumpMapping
)
83 {
84 bump
= float4
(1,
1,
1,
1);
85 }
86
87 return float4
(saturate
(
88 AmbientLightColor
+
89 (texel.xyz
* DiffuseColor
* LightDiffuseColor
* diffuseLighting
* 0.
6 * bump
) + // Use light diffuse vector as intensity multiplier
90 (SpecularColor
* LightSpecularColor
* specLighting
* 0.
5 * bump
) // Use light specular vector as intensity multiplier
91 ), texel.w
);
92 }
93
94technique TechniqueWithTexture
95{
96 pass Pass1
97 {
98 VertexShader
= compile vs_2_0 VertexShaderFunction
();
99 PixelShader
= compile ps_2_0 PixelShaderFunctionWithTex
();
100 }
101}
I'm using a point light (its center is more or less in the middle of the image). Here's what happens:
{"name":"603774","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/7\/a762dc61dd86ec552182359a45e849ac.png","w":712,"h":714,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/7\/a762dc61dd86ec552182359a45e849ac"}
So, everything seems to be working perfectly for the top left part of the screen, but the other side of the light is completely black.
I isolated the fault to the float diffuseLighting = saturate(dot(Normal, -lightDir)); line, but I don't know why it doesn't work and how to fix it.
Any help in making it work like it's supposed to would be appreciated.
It would be fairly easy if I were to use directional lights, but I need point lights for this. Heck, directional lights wouldn't even require a vertex shader, because it's 2D anyway.