~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/COpenGLParallaxMapRenderer.cpp

  • Committer: Mantas Kriaučiūnas
  • Date: 2011-07-18 13:06:25 UTC
  • Revision ID: mantas@akl.lt-20110718130625-c5pvifp61e7kj1ol
Included whole irrlicht SVN libraries to work around launchpad recipe issue with quilt, see https://answers.launchpad.net/launchpad/+question/165193

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2002-2011 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
 
 
15
namespace irr
 
16
{
 
17
namespace 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
 
23
const 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
 
133
const 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
 
189
COpenGLParallaxMapRenderer::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
 
243
COpenGLParallaxMapRenderer::~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
 
 
257
void 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.
 
270
s32 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.
 
282
void 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