~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CD3D9NormalMapRenderer.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_DIRECT3D_9_
 
7
 
 
8
#include "CD3D9NormalMapRenderer.h"
 
9
#include "IVideoDriver.h"
 
10
#include "IMaterialRendererServices.h"
 
11
#include "os.h"
 
12
#include "SLight.h"
 
13
 
 
14
namespace irr
 
15
{
 
16
namespace 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