aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/CD3D8NormalMapRenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/CD3D8NormalMapRenderer.cpp248
1 files changed, 248 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/CD3D8NormalMapRenderer.cpp b/libraries/irrlicht-1.8/source/Irrlicht/CD3D8NormalMapRenderer.cpp
new file mode 100644
index 0000000..c5e039d
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/CD3D8NormalMapRenderer.cpp
@@ -0,0 +1,248 @@
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_8_
7
8#include "CD3D8NormalMapRenderer.h"
9#include "IMaterialRendererServices.h"
10#include "IVideoDriver.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 D3D8 render path normal map vertex shader
22 const char D3D8_NORMAL_MAP_VSH[] =
23 ";Irrlicht Engine 0.8 D3D8 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 "\n"\
31 "; v0 - position \n"\
32 "; v1 - normal \n"\
33 "; v2 - color \n"\
34 "; v3 - texture coord \n"\
35 "; v4 - tangent \n"\
36 "; v5 - binormal \n"\
37 "\n"\
38 "vs.1.1\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 D3D8 render path normal map pixel shader
85 const char D3D8_NORMAL_MAP_PSH[] =
86 ";Irrlicht Engine 0.8 D3D8 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, t0, r0 ; total luminance * base color\n"\
108 "mov r0.a, v0.a ; write interpolated vertex alpha value \n"\
109 "\n"\
110 "";
111
112 CD3D8NormalMapRenderer::CD3D8NormalMapRenderer(
113 IDirect3DDevice8* d3ddev, video::IVideoDriver* driver,
114 s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
115 : CD3D8ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial),
116 CompiledShaders(true)
117 {
118
119 #ifdef _DEBUG
120 setDebugName("CD3D8NormalMapRenderer");
121 #endif
122
123 // set this as callback. We could have done this in
124 // the initialization list, but some compilers don't like it.
125
126 CallBack = this;
127
128 // basicly, this thing simply compiles these hardcoded shaders if the
129 // hardware is able to do them, otherwise it maps to the base material
130
131 if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) ||
132 !driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
133 {
134 // this hardware is not able to do shaders. Fall back to
135 // base material.
136 outMaterialTypeNr = driver->addMaterialRenderer(this);
137 return;
138 }
139
140 // check if already compiled normal map shaders are there.
141
142 video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_NORMAL_MAP_SOLID);
143 if (renderer)
144 {
145 // use the already compiled shaders
146 video::CD3D8NormalMapRenderer* nmr = (video::CD3D8NormalMapRenderer*)renderer;
147 CompiledShaders = false;
148
149 VertexShader = nmr->VertexShader;
150 PixelShader = nmr->PixelShader;
151
152 outMaterialTypeNr = driver->addMaterialRenderer(this);
153 }
154 else
155 {
156 // compile shaders on our own
157 init(outMaterialTypeNr, D3D8_NORMAL_MAP_VSH, D3D8_NORMAL_MAP_PSH, EVT_TANGENTS);
158 }
159 // something failed, use base material
160 if (-1==outMaterialTypeNr)
161 driver->addMaterialRenderer(this);
162 }
163
164
165 CD3D8NormalMapRenderer::~CD3D8NormalMapRenderer()
166 {
167 if (CallBack == this)
168 CallBack = 0;
169
170 if (!CompiledShaders)
171 {
172 // prevent this from deleting shaders we did not create
173 VertexShader = 0;
174 PixelShader = 0;
175 }
176 }
177
178
179 bool CD3D8NormalMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
180 {
181 if (vtxtype != video::EVT_TANGENTS)
182 {
183 os::Printer::log("Error: Normal map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR);
184 return false;
185 }
186
187 return CD3D8ShaderMaterialRenderer::OnRender(service, vtxtype);
188 }
189
190 //! Returns the render capability of the material.
191 s32 CD3D8NormalMapRenderer::getRenderCapability() const
192 {
193 if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
194 Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
195 return 0;
196
197 return 1;
198 }
199
200
201 //! Called by the engine when the vertex and/or pixel shader constants for an
202 //! material renderer should be set.
203 void CD3D8NormalMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
204 {
205 video::IVideoDriver* driver = services->getVideoDriver();
206
207 // set transposed world matrix
208 services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4);
209
210 // set transposed worldViewProj matrix
211 core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
212 worldViewProj *= driver->getTransform(video::ETS_VIEW);
213 worldViewProj *= driver->getTransform(video::ETS_WORLD);
214 services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4);
215
216 // here we've got to fetch the fixed function lights from the
217 // driver and set them as constants
218
219 u32 cnt = driver->getDynamicLightCount();
220
221 for (u32 i=0; i<2; ++i)
222 {
223 SLight light;
224
225 if (i<cnt)
226 light = driver->getDynamicLight(i);
227 else
228 {
229 light.DiffuseColor.set(0,0,0); // make light dark
230 light.Radius = 1.0f;
231 }
232
233 light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation
234
235 services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);
236 services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
237 }
238
239 f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f};
240 services->setVertexShaderConstant(c95, 95, 1);
241 }
242
243
244} // end namespace video
245} // end namespace irr
246
247#endif // _IRR_COMPILE_WITH_DIRECT3D_8_
248