~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CD3D8NormalMapRenderer.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_8_
 
7
 
 
8
#include "CD3D8NormalMapRenderer.h"
 
9
#include "IMaterialRendererServices.h"
 
10
#include "IVideoDriver.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 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