aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/others/irrlicht-1.8.1/source/Irrlicht/COpenGLNormalMapRenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/others/irrlicht-1.8.1/source/Irrlicht/COpenGLNormalMapRenderer.cpp')
-rw-r--r--src/others/irrlicht-1.8.1/source/Irrlicht/COpenGLNormalMapRenderer.cpp291
1 files changed, 291 insertions, 0 deletions
diff --git a/src/others/irrlicht-1.8.1/source/Irrlicht/COpenGLNormalMapRenderer.cpp b/src/others/irrlicht-1.8.1/source/Irrlicht/COpenGLNormalMapRenderer.cpp
new file mode 100644
index 0000000..875fe63
--- /dev/null
+++ b/src/others/irrlicht-1.8.1/source/Irrlicht/COpenGLNormalMapRenderer.cpp
@@ -0,0 +1,291 @@
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_OPENGL_
7
8#include "COpenGLNormalMapRenderer.h"
9#include "IGPUProgrammingServices.h"
10#include "IShaderConstantSetCallBack.h"
11#include "IVideoDriver.h"
12#include "os.h"
13#include "COpenGLDriver.h"
14
15namespace irr
16{
17namespace video
18{
19
20// Irrlicht Engine OpenGL render path normal map vertex shader
21// I guess it could be optimized a lot, because I wrote it in D3D ASM and
22// transferred it 1:1 to OpenGL
23const char OPENGL_NORMAL_MAP_VSH[] =
24 "!!ARBvp1.0\n"\
25 "#input\n"\
26 "# 0-3: transposed world matrix;\n"\
27 "#;12: Light01 position \n"\
28 "#;13: x,y,z: Light01 color; .w: 1/LightRadius^2 \n"\
29 "#;14: Light02 position \n"\
30 "#;15: x,y,z: Light02 color; .w: 1/LightRadius^2 \n"\
31 "\n"\
32 "ATTRIB InPos = vertex.position;\n"\
33 "ATTRIB InColor = vertex.color;\n"\
34 "ATTRIB InNormal = vertex.normal;\n"\
35 "ATTRIB InTexCoord = vertex.texcoord[0];\n"\
36 "ATTRIB InTangent = vertex.texcoord[1];\n"\
37 "ATTRIB InBinormal = vertex.texcoord[2];\n"\
38 "\n"\
39 "#output\n"\
40 "OUTPUT OutPos = result.position;\n"\
41 "OUTPUT OutLightColor1 = result.color.primary;\n"\
42 "OUTPUT OutLightColor2 = result.color.secondary;\n"\
43 "OUTPUT OutTexCoord = result.texcoord[0];\n"\
44 "OUTPUT OutLightVector1 = result.texcoord[1];\n"\
45 "OUTPUT OutLightVector2 = result.texcoord[2];\n"\
46 "\n"\
47 "PARAM MVP[4] = { state.matrix.mvp }; # modelViewProjection matrix.\n"\
48 "TEMP Temp;\n"\
49 "TEMP TempColor;\n"\
50 "TEMP TempLightVector1;\n"\
51 "TEMP TempLightVector2;\n"\
52 "TEMP TempTransLightV1;\n"\
53 "TEMP TempTransLightV2;\n"\
54 "\n"\
55 "# transform position to clip space \n"\
56 "DP4 OutPos.x, MVP[0], InPos;\n"\
57 "DP4 OutPos.y, MVP[1], InPos;\n"\
58 "DP4 Temp.z, MVP[2], InPos;\n"\
59 "DP4 OutPos.w, MVP[3], InPos;\n"\
60 "MOV OutPos.z, Temp.z;\n"\
61 "MOV result.fogcoord.x, Temp.z;\n"\
62 "\n"\
63 "# vertex - lightpositions \n"\
64 "SUB TempLightVector1, program.local[12], InPos; \n"\
65 "SUB TempLightVector2, program.local[14], InPos; \n"\
66 "\n"\
67 "# transform the light vector 1 with U, V, W \n"\
68 "DP3 TempTransLightV1.x, InTangent, TempLightVector1; \n"\
69 "DP3 TempTransLightV1.y, InBinormal, TempLightVector1; \n"\
70 "DP3 TempTransLightV1.z, InNormal, TempLightVector1; \n"\
71 "\n"\
72 "# transform the light vector 2 with U, V, W \n"\
73 "DP3 TempTransLightV2.x, InTangent, TempLightVector2; \n"\
74 "DP3 TempTransLightV2.y, InBinormal, TempLightVector2; \n"\
75 "DP3 TempTransLightV2.z, InNormal, TempLightVector2; \n"\
76 "\n"\
77 "# normalize light vector 1 \n"\
78 "DP3 TempTransLightV1.w, TempTransLightV1, TempTransLightV1; \n"\
79 "RSQ TempTransLightV1.w, TempTransLightV1.w; \n"\
80 "MUL TempTransLightV1, TempTransLightV1, TempTransLightV1.w;\n"\
81 "\n"\
82 "# normalize light vector 2 \n"\
83 "DP3 TempTransLightV2.w, TempTransLightV2, TempTransLightV2; \n"\
84 "RSQ TempTransLightV2.w, TempTransLightV2.w; \n"\
85 "MUL TempTransLightV2, TempTransLightV2, TempTransLightV2.w;\n"\
86 "\n"\
87 "\n"\
88 "# move light vectors out\n"\
89 "MAD OutLightVector1, TempTransLightV1, {0.5,0.5,0.5,0.5}, {0.5,0.5,0.5,0.5}; \n"\
90 "MAD OutLightVector2, TempTransLightV2, {0.5,0.5,0.5,0.5}, {0.5,0.5,0.5,0.5}; \n"\
91 "\n"\
92 "# calculate attenuation of light 1\n"\
93 "MOV TempLightVector1.w, {0,0,0,0}; \n"\
94 "DP3 TempLightVector1.x, TempLightVector1, TempLightVector1; \n"\
95 "MUL TempLightVector1.x, TempLightVector1.x, program.local[13].w; \n"\
96 "RSQ TempLightVector1, TempLightVector1.x; \n"\
97 "MUL OutLightColor1, TempLightVector1, program.local[13]; # resulting light color = lightcolor * attenuation \n"\
98 "\n"\
99 "# calculate attenuation of light 2\n"\
100 "MOV TempLightVector2.w, {0,0,0,0}; \n"\
101 "DP3 TempLightVector2.x, TempLightVector2, TempLightVector2; \n"\
102 "MUL TempLightVector2.x, TempLightVector2.x, program.local[15].w; \n"\
103 "RSQ TempLightVector2, TempLightVector2.x; \n"\
104 "MUL OutLightColor2, TempLightVector2, program.local[15]; # resulting light color = lightcolor * attenuation \n"\
105 "\n"\
106 "# move out texture coordinates and original alpha value\n"\
107 "MOV OutTexCoord, InTexCoord; \n"\
108 "MOV OutLightColor1.w, InColor.w; \n"\
109 "\n"\
110 "END\n";
111
112// Irrlicht Engine OpenGL render path normal map pixel shader
113// I guess it could be optimized a bit, because I wrote it in D3D ASM and
114// transfered it 1:1 to OpenGL
115const char OPENGL_NORMAL_MAP_PSH[] =
116 "!!ARBfp1.0\n"\
117 "#_IRR_FOG_MODE_\n"\
118 "\n"\
119 "#Input\n"\
120 "ATTRIB inTexCoord = fragment.texcoord[0]; \n"\
121 "ATTRIB light1Vector = fragment.texcoord[1]; \n"\
122 "ATTRIB light2Vector = fragment.texcoord[2]; \n"\
123 "ATTRIB light1Color = fragment.color.primary; \n"\
124 "ATTRIB light2Color = fragment.color.secondary; \n"\
125 "\n"\
126 "#Output\n"\
127 "OUTPUT outColor = result.color;\n"\
128 "TEMP temp;\n"\
129 "TEMP temp2;\n"\
130 "TEMP colorMapColor;\n"\
131 "TEMP normalMapColor;\n"\
132 "\n"\
133 "# fetch color and normal map; \n"\
134 "TXP colorMapColor, inTexCoord, texture[0], 2D; \n"\
135 "TXP normalMapColor, inTexCoord, texture[1], 2D; \n"\
136 "\n"\
137 "# calculate color of light1; \n"\
138 "MAD normalMapColor, normalMapColor, {2,2,2,2}, {-1,-1,-1,-1}; \n"\
139 "MAD temp, light1Vector, {2,2,2,2}, {-1,-1,-1,-1}; \n"\
140 "DP3_SAT temp, normalMapColor, temp; \n"\
141 "MUL temp, light1Color, temp; \n"\
142 "\n"\
143 "# calculate color of light2; \n"\
144 "MAD temp2, light2Vector, {2,2,2,2}, {-1,-1,-1,-1}; \n"\
145 "DP3_SAT temp2, normalMapColor, temp2; \n"\
146 "MAD temp, light2Color, temp2, temp; \n"\
147 "\n"\
148 "# luminance * base color; \n"\
149 "MUL outColor, temp, colorMapColor; \n"\
150 "MOV outColor.a, light1Color.a; #write interpolated vertex alpha value\n"\
151 "\n"\
152 "END\n";
153
154//! Constructor
155COpenGLNormalMapRenderer::COpenGLNormalMapRenderer(video::COpenGLDriver* driver,
156 s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
157 : COpenGLShaderMaterialRenderer(driver, 0, baseMaterial), CompiledShaders(true)
158{
159
160 #ifdef _DEBUG
161 setDebugName("COpenGLNormalMapRenderer");
162 #endif
163
164 // set this as callback. We could have done this in
165 // the initialization list, but some compilers don't like it.
166
167 CallBack = this;
168
169 // basically, this thing simply compiles the hardcoded shaders if the
170 // hardware is able to do them, otherwise it maps to the base material
171
172 if (!driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1) ||
173 !driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1))
174 {
175 // this hardware is not able to do shaders. Fall back to
176 // base material.
177 outMaterialTypeNr = driver->addMaterialRenderer(this);
178 return;
179 }
180
181 // check if already compiled normal map shaders are there.
182
183 video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_NORMAL_MAP_SOLID);
184
185 if (renderer)
186 {
187 // use the already compiled shaders
188 video::COpenGLNormalMapRenderer* nmr = reinterpret_cast<video::COpenGLNormalMapRenderer*>(renderer);
189 CompiledShaders = false;
190
191 VertexShader = nmr->VertexShader;
192 PixelShader = nmr->PixelShader;
193
194 outMaterialTypeNr = driver->addMaterialRenderer(this);
195 }
196 else
197 {
198 // compile shaders on our own
199 init(outMaterialTypeNr, OPENGL_NORMAL_MAP_VSH, OPENGL_NORMAL_MAP_PSH, EVT_TANGENTS);
200 }
201
202 // fallback if compilation has failed
203 if (-1==outMaterialTypeNr)
204 outMaterialTypeNr = driver->addMaterialRenderer(this);
205}
206
207
208//! Destructor
209COpenGLNormalMapRenderer::~COpenGLNormalMapRenderer()
210{
211 if (CallBack == this)
212 CallBack = 0;
213
214 if (!CompiledShaders)
215 {
216 // prevent this from deleting shaders we did not create
217 VertexShader = 0;
218 PixelShader.clear();
219 }
220}
221
222
223//! Returns the render capability of the material.
224s32 COpenGLNormalMapRenderer::getRenderCapability() const
225{
226 if (Driver->queryFeature(video::EVDF_ARB_FRAGMENT_PROGRAM_1) &&
227 Driver->queryFeature(video::EVDF_ARB_VERTEX_PROGRAM_1))
228 return 0;
229
230 return 1;
231}
232
233
234//! Called by the engine when the vertex and/or pixel shader constants for an
235//! material renderer should be set.
236void COpenGLNormalMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
237{
238 video::IVideoDriver* driver = services->getVideoDriver();
239
240 // set transposed world matrix
241 const core::matrix4& tWorld = driver->getTransform(video::ETS_WORLD).getTransposed();
242 services->setVertexShaderConstant(tWorld.pointer(), 0, 4);
243
244 // set transposed worldViewProj matrix
245 core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
246 worldViewProj *= driver->getTransform(video::ETS_VIEW);
247 worldViewProj *= driver->getTransform(video::ETS_WORLD);
248 core::matrix4 tr(worldViewProj.getTransposed());
249 services->setVertexShaderConstant(tr.pointer(), 8, 4);
250
251 // here we fetch the fixed function lights from the driver
252 // and set them as constants
253
254 u32 cnt = driver->getDynamicLightCount();
255
256 // Load the inverse world matrix.
257 core::matrix4 invWorldMat;
258 driver->getTransform(video::ETS_WORLD).getInverse(invWorldMat);
259
260 for (u32 i=0; i<2; ++i)
261 {
262 video::SLight light;
263
264 if (i<cnt)
265 light = driver->getDynamicLight(i);
266 else
267 {
268 light.DiffuseColor.set(0,0,0); // make light dark
269 light.Radius = 1.0f;
270 }
271
272 light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation
273
274 // Transform the light by the inverse world matrix to get it into object space.
275 invWorldMat.transformVect(light.Position);
276
277 services->setVertexShaderConstant(
278 reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);
279
280 services->setVertexShaderConstant(
281 reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
282 }
283}
284
285
286} // end namespace video
287} // end namespace irr
288
289
290#endif
291