aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8.1/source/Irrlicht/CD3D9NormalMapRenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libraries/irrlicht-1.8.1/source/Irrlicht/CD3D9NormalMapRenderer.cpp306
1 files changed, 306 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8.1/source/Irrlicht/CD3D9NormalMapRenderer.cpp b/libraries/irrlicht-1.8.1/source/Irrlicht/CD3D9NormalMapRenderer.cpp
new file mode 100644
index 0000000..eb6f732
--- /dev/null
+++ b/libraries/irrlicht-1.8.1/source/Irrlicht/CD3D9NormalMapRenderer.cpp
@@ -0,0 +1,306 @@
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine".
3// For conditions of distribution and use, see copyright notice in irrlicht.h
4
5#include "IrrCompileConfig.h"
6#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
7
8#include "CD3D9NormalMapRenderer.h"
9#include "IVideoDriver.h"
10#include "IMaterialRendererServices.h"
11#include "os.h"
12#include "SLight.h"
13
14namespace irr
15{
16namespace video
17{
18
19 // 1.1 Shaders with two lights and vertex based attenuation
20
21 // Irrlicht Engine D3D9 render path normal map vertex shader
22 const char D3D9_NORMAL_MAP_VSH[] =
23 ";Irrlicht Engine 0.8 D3D9 render path normal map vertex shader\n"\
24 "; c0-3: Transposed world matrix \n"\
25 "; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\
26 "; c12: Light01 position \n"\
27 "; c13: x,y,z: Light01 color; .w: 1/LightRadius˛ \n"\
28 "; c14: Light02 position \n"\
29 "; c15: x,y,z: Light02 color; .w: 1/LightRadius˛ \n"\
30 "vs.1.1\n"\
31 "dcl_position v0 ; position \n"\
32 "dcl_normal v1 ; normal \n"\
33 "dcl_color v2 ; color \n"\
34 "dcl_texcoord0 v3 ; texture coord \n"\
35 "dcl_texcoord1 v4 ; tangent \n"\
36 "dcl_texcoord2 v5 ; binormal \n"\
37 "\n"\
38 "def c95, 0.5, 0.5, 0.5, 0.5 ; used for moving light vector to ps \n"\
39 "\n"\
40 "m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\
41 "\n"\
42 "m3x3 r5, v4, c0 ; transform tangent U\n"\
43 "m3x3 r7, v1, c0 ; transform normal W\n"\
44 "m3x3 r6, v5, c0 ; transform binormal V\n"\
45 "\n"\
46 "m4x4 r4, v0, c0 ; vertex into world position\n"\
47 "add r2, c12, -r4 ; vtxpos - lightpos1\n"\
48 "add r3, c14, -r4 ; vtxpos - lightpos2\n"\
49 "\n"\
50 "dp3 r8.x, r5, r2 ; transform the light vector 1 with U, V, W\n"\
51 "dp3 r8.y, r6, r2 \n"\
52 "dp3 r8.z, r7, r2 \n"\
53 "dp3 r9.x, r5, r3 ; transform the light vector 2 with U, V, W\n"\
54 "dp3 r9.y, r6, r3 \n"\
55 "dp3 r9.z, r7, r3 \n"\
56 "\n"\
57 "dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\
58 "rsq r8.w, r8.w \n"\
59 "mul r8, r8, r8.w \n"\
60 "dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\
61 "rsq r9.w, r9.w \n"\
62 "mul r9, r9, r9.w \n"\
63 "\n"\
64 "mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\
65 "mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\
66 "\n"\
67 " ; calculate attenuation of light 1 \n"\
68 "dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x˛ + r2.y˛ + r2.z˛ \n"\
69 "mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\
70 "rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
71 "mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\
72 "\n"\
73 " ; calculate attenuation of light 2 \n"\
74 "dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x˛ + r3.y˛ + r3.z˛ \n"\
75 "mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\
76 "rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
77 "mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\
78 "\n"\
79 "mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\
80 "mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\
81 "mov oD0.a, v2.a ; move out original alpha value \n"\
82 "\n";
83
84 // Irrlicht Engine D3D9 render path normal map pixel shader
85 const char D3D9_NORMAL_MAP_PSH_1_1[] =
86 ";Irrlicht Engine 0.8 D3D9 render path normal map pixel shader\n"\
87 ";Input: \n"\
88 ";t0: color map texture coord \n"\
89 ";t1: normal map texture coords \n"\
90 ";t2: light 1 vector in tangent space \n"\
91 ";v0: light 1 color \n"\
92 ";t3: light 2 vector in tangent space \n"\
93 ";v1: light 2 color \n"\
94 ";v0.a: vertex alpha value \n"\
95 "ps.1.1 \n"\
96 "tex t0 ; sample color map \n"\
97 "tex t1 ; sample normal map\n"\
98 "texcoord t2 ; fetch light vector 1\n"\
99 "texcoord t3 ; fetch light vector 2\n"\
100 "\n"\
101 "dp3_sat r0, t1_bx2, t2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1)\n"\
102 "mul r0, r0, v0 ; luminance1 * light color 1 \n"\
103 "\n"\
104 "dp3_sat r1, t1_bx2, t3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1)\n"\
105 "mad r0, r1, v1, r0 ; (luminance2 * light color 2) + luminance 1 \n"\
106 "\n"\
107 "mul r0.xyz, t0, r0 ; total luminance * base color\n"\
108 "+mov r0.a, v0.a ; write interpolated vertex alpha value \n"\
109 "\n"\
110 "";
111
112 // Higher-quality normal map pixel shader (requires PS 2.0)
113 // uses per-pixel normalization for improved accuracy
114 const char D3D9_NORMAL_MAP_PSH_2_0[] =
115 ";Irrlicht Engine 0.8 D3D9 render path normal map pixel shader\n"\
116 ";Input: \n"\
117 ";t0: color map texture coord \n"\
118 ";t1: normal map texture coords \n"\
119 ";t2: light 1 vector in tangent space \n"\
120 ";v0: light 1 color \n"\
121 ";t3: light 2 vector in tangent space \n"\
122 ";v1: light 2 color \n"\
123 ";v0.a: vertex alpha value \n"\
124
125 "ps_2_0 \n"\
126 "def c0, 0, 0, 0, 0\n"\
127 "def c1, 1.0, 1.0, 1.0, 1.0\n"\
128 "def c2, 2.0, 2.0, 2.0, 2.0\n"\
129 "def c3, -.5, -.5, -.5, -.5\n"\
130 "dcl t0\n"\
131 "dcl t1\n"\
132 "dcl t2\n"\
133 "dcl t3\n"\
134 "dcl v1\n"\
135 "dcl v0\n"\
136 "dcl_2d s0\n"\
137 "dcl_2d s1\n"\
138
139 "texld r0, t0, s0 ; sample color map into r0 \n"\
140 "texld r4, t0, s1 ; sample normal map into r4\n"\
141 "add r4, r4, c3 ; bias the normal vector\n"\
142 "add r5, t2, c3 ; bias the light 1 vector into r5\n"\
143 "add r6, t3, c3 ; bias the light 2 vector into r6\n"\
144
145 "nrm r1, r4 ; normalize the normal vector into r1\n"\
146 "nrm r2, r5 ; normalize the light1 vector into r2\n"\
147 "nrm r3, r6 ; normalize the light2 vector into r3\n"\
148
149 "dp3 r2, r2, r1 ; let r2 = normal DOT light 1 vector\n"\
150 "max r2, r2, c0 ; clamp result to positive numbers\n"\
151 "mul r2, r2, v0 ; let r2 = luminance1 * light color 1 \n"\
152
153 "dp3 r3, r3, r1 ; let r3 = normal DOT light 2 vector\n"\
154 "max r3, r3, c0 ; clamp result to positive numbers\n"\
155
156 "mad r2, r3, v1, r2 ; let r2 = (luminance2 * light color 2) + (luminance2 * light color 1) \n"\
157
158 "mul r2, r2, r0 ; let r2 = total luminance * base color\n"\
159 "mov r2.w, v0.w ; write interpolated vertex alpha value \n"\
160
161 "mov oC0, r2 ; copy r2 to the output register \n"\
162
163 "\n"\
164 "";
165
166 CD3D9NormalMapRenderer::CD3D9NormalMapRenderer(
167 IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
168 s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
169 : CD3D9ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial)
170 {
171 #ifdef _DEBUG
172 setDebugName("CD3D9NormalMapRenderer");
173 #endif
174
175 // set this as callback. We could have done this in
176 // the initialization list, but some compilers don't like it.
177
178 CallBack = this;
179
180 // basically, this thing simply compiles the hardcoded shaders
181 // if the hardware is able to do them, otherwise it maps to the
182 // base material
183
184 if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) ||
185 !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
186 {
187 // this hardware is not able to do shaders. Fall back to
188 // base material.
189 outMaterialTypeNr = driver->addMaterialRenderer(this);
190 return;
191 }
192
193 // check if already compiled normal map shaders are there.
194
195 video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_NORMAL_MAP_SOLID);
196 if (renderer)
197 {
198 // use the already compiled shaders
199 video::CD3D9NormalMapRenderer* nmr = (video::CD3D9NormalMapRenderer*)renderer;
200 VertexShader = nmr->VertexShader;
201 if (VertexShader)
202 VertexShader->AddRef();
203
204 PixelShader = nmr->PixelShader;
205 if (PixelShader)
206 PixelShader->AddRef();
207
208 outMaterialTypeNr = driver->addMaterialRenderer(this);
209 }
210 else
211 {
212 // compile shaders on our own
213 if (driver->queryFeature(video::EVDF_PIXEL_SHADER_2_0))
214 {
215 init(outMaterialTypeNr, D3D9_NORMAL_MAP_VSH, D3D9_NORMAL_MAP_PSH_2_0);
216 }
217 else
218 {
219 init(outMaterialTypeNr, D3D9_NORMAL_MAP_VSH, D3D9_NORMAL_MAP_PSH_1_1);
220 }
221 }
222 // something failed, use base material
223 if (-1==outMaterialTypeNr)
224 driver->addMaterialRenderer(this);
225 }
226
227
228 CD3D9NormalMapRenderer::~CD3D9NormalMapRenderer()
229 {
230 if (CallBack == this)
231 CallBack = 0;
232 }
233
234
235 bool CD3D9NormalMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
236 {
237 if (vtxtype != video::EVT_TANGENTS)
238 {
239 os::Printer::log("Error: Normal map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR);
240 return false;
241 }
242
243 return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype);
244 }
245
246
247 //! Returns the render capability of the material.
248 s32 CD3D9NormalMapRenderer::getRenderCapability() const
249 {
250 if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
251 Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
252 return 0;
253
254 return 1;
255 }
256
257
258 //! Called by the engine when the vertex and/or pixel shader constants
259 //! for an material renderer should be set.
260 void CD3D9NormalMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
261 {
262 video::IVideoDriver* driver = services->getVideoDriver();
263
264 // set transposed world matrix
265 services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4);
266
267 // set transposed worldViewProj matrix
268 core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
269 worldViewProj *= driver->getTransform(video::ETS_VIEW);
270 worldViewProj *= driver->getTransform(video::ETS_WORLD);
271 services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4);
272
273 // here we've got to fetch the fixed function lights from the
274 // driver and set them as constants
275
276 u32 cnt = driver->getDynamicLightCount();
277
278 for (u32 i=0; i<2; ++i)
279 {
280 SLight light;
281
282 if (i<cnt)
283 light = driver->getDynamicLight(i);
284 else
285 {
286 light.DiffuseColor.set(0,0,0); // make light dark
287 light.Radius = 1.0f;
288 }
289
290 light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation
291
292 services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);
293 services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
294 }
295
296 // this is not really necessary in d3d9 (used a def instruction), but to be sure:
297 f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f};
298 services->setVertexShaderConstant(c95, 95, 1);
299 }
300
301
302} // end namespace video
303} // end namespace irr
304
305#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
306