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