-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmaya_phong.cgfx
396 lines (329 loc) · 10.1 KB
/
maya_phong.cgfx
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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
// Copyright (C) 2012 Simon Otter
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// Loads into Maya using the bundled CGFX Shader Plugin.
//
// Some notes about variable naming.
// - dir = direction
// - pos = position
// - tsdir & tspos = same but in tangent space.
// - osdir & ospos = same but in object space.
// ######################################################################
// UNIFORM PARAMETERS.
// ######################################################################
// An additive ambient term, set to black for no ambient.
float3 ambient : DIFFUSE
<
string UIHelp = "Ambient";
> = {0.0, 0.0, 0.0};
texture diffuse_tex
<
string ResourceType = "2D";
string UIName = "Diffuse Texture";
>;
texture normalmap_tex : NormalTexture
<
string ResourceType = "2D";
string UIName = "Normal Map Texture";
>;
texture specular_tex
<
string ResourceType = "2D";
string UIName = "Normal Map Texture";
>;
texture gloss_tex
<
string ResourceType = "2D";
string UIName = "Gloss Map Texture";
>;
texture emissive_tex
<
string ResourceType = "2D";
string UIName = "Emissive Map Texture";
>;
texture alpha_tex
<
string ResourceType = "2D";
string UIName = "Alpha Map";
>;
// LIGHT 1
float3 light1_pos : Position
<
string UIHelp = "Light 1 Position";
> = {250, 250, -70};
float3 light1_color : DIFFUSE
<
string UIName = "Light 1 Colour";
string UIWidget = "Color";
> = {1.480, 1.470, 1.381};
// LIGHT 2
float3 light2_pos : POSITION
<
string UIHelp = "Light 2 Position";
> = {160, 0, 670};
float3 light2_color : DIFFUSE
<
string UIName = "Light 2 Colour";
string UIWidget = "Color";
> = {0.650, 0.8, 1.25};
// TEXTURES.
sampler2D diffuse_tex_sampler
<
string UIName = "Diffuse Map";
> =
sampler_state
{
Texture = <diffuse_tex>;
MinFilter = LinearMipMapLinear;
MagFilter = Linear;
};
sampler2D normalmap_tex_sampler
<
string UIName = "Normal Map";
> =
sampler_state
{
Texture = <normalmap_tex>;
MinFilter = LinearMipMapLinear;
MagFilter = Linear;
};
bool flip_y_normal
<
string UIHelp = "Flip Y Normal (UDK, CryEngine etc.)";
> = false;
sampler2D specular_tex_sampler
<
string UIName = "Specular Map";
> =
sampler_state
{
Texture = <specular_tex>;
MinFilter = LinearMipMapLinear;
MagFilter = Linear;
};
float gloss_multiplier
<
string UIHelp = "Spec. Exponent scale";
string UIWidget = "Slider";
float UIMin = 0.01;
float UIMax = 1.0;
> = 1;
sampler2D gloss_tex_sampler
<
string UIName = "Gloss Map";
> =
sampler_state
{
Texture = <gloss_tex>;
MinFilter = LinearMipMapLinear;
MagFilter = Linear;
};
sampler2D emissive_tex_sampler
<
string UIName = "Emissive Map";
> =
sampler_state
{
Texture = <emissive_tex>;
MinFilter = LinearMipMapLinear;
MagFilter = Linear;
};
sampler2D alpha_tex_sampler
<
string UIName = "Alpha Map";
> =
sampler_state
{
Texture = <alpha_tex>;
MinFilter = LinearMipMapLinear;
MagFilter = Linear;
};
//
// Provided by Maya for viewspace transform.
// object space -> clip space
//
float4x4 WorldViewProjXf : WorldViewProjection;
float4x4 WorldViewProjInverseXf : WorldViewProjectionInverse;
float4x4 WorldViewProjInverseTransposeXf : WorldViewProjectionInverseTranspose;
float4x4 WorldXf : World;
float4x4 WorldInverseXf : WorldInverse;
float4x4 ViewInverseXf : ViewInverse;
float4x4 WorldITXf : WorldInverseTranspose < string UIWidget="none";>;
float4x4 ViewITXf : ViewInverseTranspose < string UIWidget="none";>;
// These control how the gloss map is interpreted. The gloss map is
// averaged between the three channels and scaled to [0.0, 1.0]. The
// result is used to interpolate between these extremes.
#define GLOSS_MIN_EXPONENT 1
#define GLOSS_MAX_EXPONENT 200
// ######################################################################
// INPUT STRUCTURES.
// ######################################################################
//
// This is Maya's derp structure, it feeds the vertex shader with this.
//
struct appdata
{
float3 position : POSITION;
float4 normal : NORMAL;
float2 texCoord0 : TEXCOORD0;
float3 tangent : TEXCOORD1;
float3 binormal : TEXCOORD2;
};
// ######################################################################
// HELPER FUNCS.
// ######################################################################
// Schlick's Approximation (WIP)
//float get_fresnel(float refindex, float3 light_dir, float3 view_dir)
//{
// float f0 = pow((1 - refindex) / (1 + refindex), 2);
//
// return f0 + (1 - f0) * pow(1 - dot(light_dir, dot(light_dir, v) / 2)), 5);
//}
// Calculates a lambert term.
inline float lambert(float3 l_dir, float3 normal)
{
float l = dot(l_dir, normal);
return max(l, 0);
}
// Finds the unit direction of l_pos from pos.
inline float3 direction(float3 pos, float3 l_pos)
{
return normalize(l_pos - pos);
}
// ######################################################################
// PASS 1.
// ######################################################################
struct vertex_out
{
// Clip-space.
float4 position : POSITION;
float2 texCoord0 : TEXCOORD0;
// These are in object space.
float3 ospos;
// Tangent space.
float3 camera_tsdir;
float3 normal;
// Transforms object -> tangent space.
float3x3 tangent_transform;
};
vertex_out vertex_f(appdata IN)
{
vertex_out OUT;
OUT.position = mul(WorldViewProjXf, float4(IN.position, 1));
OUT.tangent_transform =
float3x3(
IN.tangent.xyz,
flip_y_normal? -IN.binormal.xyz : IN.binormal.xyz,
IN.normal.xyz
);
OUT.ospos = IN.position.xyz;
OUT.texCoord0 = IN.texCoord0;
OUT.camera_tsdir = normalize(mul(WorldViewProjInverseXf, float4(0, 0, 1, 1))).xyz;
OUT.camera_tsdir = mul(OUT.tangent_transform, OUT.camera_tsdir);
OUT.normal = mul(OUT.tangent_transform, IN.normal.xyz);
return OUT;
}
float3 calculate_light_contrib(float lamb_term, float3 diffuse_map_term, float3 light_color)
{
return (float3(lamb_term) * light_color.xyz) * diffuse_map_term;
}
float3 diffuse(float2 lamb_term, float2 texCoord)
{
// Add the ambient term here, might not be strictly kosher but
// gives a better looking ambient where the diffuse texture
// contributes.
float3 diffuse_map_term = tex2D(diffuse_tex_sampler, texCoord);
// light 1
float3 light_contrib = calculate_light_contrib(lamb_term.x, diffuse_map_term.rgb, light1_color);
// light 2
light_contrib += calculate_light_contrib(lamb_term.y, diffuse_map_term, light2_color);
float4 emissive = tex2D(emissive_tex_sampler, texCoord);
if (emissive.r == 1.0 && emissive.g == 1.0 && emissive.b == 1.0 && emissive.a == 1.0)
{
emissive.a = 0.0;
}
return (emissive.a * emissive.rgb) + light_contrib + (ambient * diffuse_map_term.rgb);
}
// Calculates a Phong specular term.
float3 phong(float3 light_dir, float3 light_col, float3 normal, float3 camera_dir, float2 texCoord)
{
float3 light_reflect = reflect(light_dir, normal);
// We use max here to remove highlights for surface points pointing away from the light.
float light_to_camera_ang = max(dot(light_reflect, camera_dir), 0);
float exponent = lerp(GLOSS_MIN_EXPONENT, GLOSS_MAX_EXPONENT, tex2D(gloss_tex_sampler, texCoord).r);
exponent *= gloss_multiplier;
// Technically, the light has a specular term too, but we don't care.
return pow(light_to_camera_ang, exponent) * tex2D(specular_tex_sampler, texCoord) * light_col;
}
float4 fragment_f(vertex_out IN) : COLOR
{
// ospos is interpolated by the GPU here between the vertices,
// so we must do the transform in the fragment shader.
float3 tspos = mul(IN.tangent_transform, IN.ospos);
float3 light1_tspos = mul(IN.tangent_transform, light1_pos);
float3 light2_tspos = mul(IN.tangent_transform, light2_pos);
float3 normal = IN.normal;
// Todo: might be more efficient as tex2D(normalmap_tex_sampler, IN.texCoord0) * 2 - 1
float3 mapped_normal =
lerp(
float4(-1.0),
float4( 1.0),
tex2D(normalmap_tex_sampler, IN.texCoord0));
float3 light1_tsdir = direction(tspos, light1_tspos);
float3 light2_tsdir = direction(tspos, light2_tspos);
if (mapped_normal.x != 1.0 && mapped_normal.y != 1.0 && mapped_normal.z != 1.0)
// mostly true if no nmap assigned.
{
normal = mapped_normal.xyz;
}
float3 diff_term = diffuse(
float2(
lambert(
light1_tsdir,
normal),
lambert(
light2_tsdir,
normal)
),
IN.texCoord0);
float3 spec_term1 = phong(light1_tsdir, light1_color, normal, IN.camera_tsdir, IN.texCoord0);
float3 spec_term2 = phong(light2_tsdir, light2_color, normal, IN.camera_tsdir, IN.texCoord0);
float4 alpha = tex2D(alpha_tex_sampler, IN.texCoord0);
return saturate(float4(diff_term + spec_term1 + spec_term2, alpha.r));
}
// ######################################################################
// TECHNIQUES.
// ######################################################################
technique main {
pass p1 {
VertexProgram = compile vs_3_0 vertex_f();
DepthTestEnable = true;
DepthMask = true;
CullFaceEnable = False;
CullFace = Back;
FragmentProgram = compile ps_3_0 fragment_f();
BlendEnable = true;
BlendFunc = int2(SrcAlpha, OneMinusSrcAlpha);
BlendFuncSeparate = int4( SrcAlpha, OneMinusSrcAlpha, One, OneMinusSrcAlpha);
BlendEquationSeparate = int2( Add, Add );
BlendColor = float4(1.0f,1.0f,1.0f,1.0f);
}
}