-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathLightShaders.fx
240 lines (203 loc) · 6.06 KB
/
LightShaders.fx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
cbuffer ConstantBuffer
{
matrix World;
matrix View;
matrix Projection;
float4 EyePosition;
}
cbuffer MaterialBuffer
{
float4 MatAmbient;
float4 MatDiffuse;
float4 MatSpecular;
float MatPower;
bool textureOn = false;
}
Texture2D Texture;
SamplerState Sampler
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};
cbuffer LightBuffer
{
int type;
float4 LightPos;
float4 LightDir;
float4 LightAmb;
float4 LightDiff;
float4 LightSpe;
float LightAtt0;
float LightAtt1;
float LightAtt2;
float LightAlpha;
float LightBeta;
float LightFallOff;
}
struct VS_INPUT
{
float4 Pos : POSITION;
float4 Norm : NORMAL;
float4 Tan : TANGENT;
float2 Tex : TEXCOORD;
};
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float4 Norm : TEXCOORD0;
float4 ViewDirection : TEXCOORD1;
float4 LightVector : TEXCOORD2; //对点光源和聚光灯有效,前3各分量记录“光照向量”,最后一个分量记录光照距离
float2 Tex : TEXCOORD3;
};
//顶点着色器
PS_INPUT VS( VS_INPUT input )
{
PS_INPUT output = (PS_INPUT)0;
output.Pos = mul(input.Pos, World);
output.Pos = mul(output.Pos, View);
output.Pos = mul(output.Pos, Projection);
output.Norm = mul(input.Norm, World);
output.Norm = normalize(output.Norm);
float4 worldPosition = mul(input.Pos, World); //一定要非常慎重世界坐标!
output.ViewDirection = EyePosition - worldPosition; //一切的计算都是世界坐标里面!
output.ViewDirection = normalize(output.ViewDirection); //所以千万不能用视图投影之后的坐标!
output.LightVector = LightPos - worldPosition;
output.LightVector = normalize(output.LightVector);
output.LightVector.w = length(LightPos - worldPosition);
output.Tex = input.Tex;
return output;
}
//平行光像素着色器
float4 PSDirectionalLight(PS_INPUT input) : SV_Target
{
float4 textureColor;
float4 finalColor;
float4 ambientColor, diffuseColor, specularColor;
//光照方向,和光线照射方向相反
float4 lightVector = -LightDir;
ambientColor = MatAmbient * LightAmb;
float diffuseFactor = dot(lightVector, input.Norm);
if(diffuseFactor > 0.0f)
{
diffuseColor = MatDiffuse * LightDiff * diffuseFactor;
float4 reflection = reflect(-lightVector, input.Norm);
float specularFactor = pow(max(dot(reflection, input.ViewDirection), 0.0f), MatPower);
specularColor = MatSpecular * LightSpe * specularFactor;
}
finalColor = ambientColor + diffuseColor;
if(textureOn)
{
textureColor = Texture.Sample(Sampler, input.Tex);
finalColor = finalColor * textureColor;
}
finalColor = saturate(finalColor + specularColor);
return finalColor;
}
//点光源着色器
float4 PSPointLight(PS_INPUT input) : SV_Target
{
float4 textureColor;
float4 finalColor;
float4 ambientColor, diffuseColor, specularColor;
float4 lightVector = input.LightVector;
ambientColor = MatAmbient * LightAmb;
float diffuseFactor = dot(lightVector, input.Norm);
if(diffuseFactor > 0.0f)
{
diffuseColor = MatDiffuse * LightDiff * diffuseFactor;
float4 reflection = reflect(-lightVector, input.Norm);
float specularFactor = pow(max(dot(reflection, input.ViewDirection), 0.0f), MatPower);
specularColor = MatSpecular * LightSpe * specularFactor;
}
//距离衰减因子
float d = input.LightVector.w;
float att = LightAtt0 + LightAtt1 * d + LightAtt2 * d * d;
finalColor = ambientColor + diffuseColor;
if(textureOn)
{
textureColor = Texture.Sample(Sampler, input.Tex);
finalColor = finalColor * textureColor;
}
finalColor = saturate(finalColor + specularColor)/att;
return finalColor;
}
//聚光光源着色器
float4 PSSpotLight(PS_INPUT input) : SV_Target
{
float4 textureColor;
float4 finalColor = 0;
float4 ambientColor = 0, diffuseColor = 0, specularColor = 0;
float4 lightVector = input.LightVector;
float3 lightDir = LightDir.xyz;
lightDir = normalize(lightDir);
//判断光照区域
float cosTheta = dot(-lightVector.xyz, lightDir);
if(cosTheta < cos(LightBeta/2))
return float4(0.0f, 0.0f, 0.0f, 1.0f);
//环境光
ambientColor = LightAmb * MatAmbient;
//漫反射光
float diffuseFactor = dot(input.Norm, lightVector);
if(diffuseFactor > 0)
{
diffuseColor = MatDiffuse * LightDiff * diffuseFactor;
}
//镜面光
float4 reflection = reflect(-lightVector, input.Norm);
reflection = normalize(reflection);
float specularFactor = pow(max(dot(reflection, input.ViewDirection), 0.0f), MatPower);
specularColor = MatSpecular * LightSpe * specularFactor;
//距离衰减因子
float d = input.LightVector.w;
float att = LightAtt0 + LightAtt1 * d + LightAtt2 * d * d;
if(cosTheta > cos(LightAlpha/2))
{
finalColor = ambientColor + diffuseColor;
if(textureOn)
{
textureColor = Texture.Sample(Sampler, input.Tex);
finalColor = finalColor * textureColor;
}
finalColor = saturate(finalColor + specularColor);
}
else
{
float spotFactor = pow((cosTheta - cos(LightBeta / 2)) / (cos(LightAlpha / 2) - cos(LightBeta / 2)), 1);
finalColor = ambientColor + diffuseColor;
if(textureOn)
{
textureColor = Texture.Sample(Sampler, input.Tex);
finalColor = finalColor * textureColor;
}
finalColor = spotFactor * saturate(finalColor + specularColor)/att;
}
return finalColor;
}
technique11 T_DirLight
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_5_0, PSDirectionalLight() ) );
}
}
technique11 T_PointLight
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_5_0, PSPointLight() ) );
}
}
technique11 T_SpotLight
{
pass P0
{
SetVertexShader( CompileShader( vs_5_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_5_0, PSSpotLight() ) );
}
}