~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/CSoftwareDriver2.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 / Thomas Alten
 
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
#include "CSoftwareDriver2.h"
 
7
 
 
8
#ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
 
9
 
 
10
#include "SoftwareDriver2_helper.h"
 
11
#include "CSoftwareTexture2.h"
 
12
#include "CSoftware2MaterialRenderer.h"
 
13
#include "S3DVertex.h"
 
14
#include "S4DVertex.h"
 
15
#include "CBlit.h"
 
16
 
 
17
 
 
18
#define MAT_TEXTURE(tex) ( (video::CSoftwareTexture2*) Material.org.getTexture ( tex ) )
 
19
 
 
20
 
 
21
namespace irr
 
22
{
 
23
namespace video
 
24
{
 
25
 
 
26
namespace glsl
 
27
{
 
28
 
 
29
typedef sVec4 vec4;
 
30
typedef sVec3 vec3;
 
31
typedef sVec2 vec2;
 
32
 
 
33
#define in
 
34
#define uniform
 
35
#define attribute
 
36
#define varying
 
37
 
 
38
#ifdef _MSC_VER
 
39
#pragma warning(disable:4244)
 
40
#endif
 
41
 
 
42
struct mat4{
 
43
   float m[4][4];
 
44
 
 
45
   vec4 operator* ( const vec4 &in ) const
 
46
   {
 
47
           vec4 out;
 
48
           return out;
 
49
   }
 
50
 
 
51
};
 
52
 
 
53
struct mat3{
 
54
   float m[3][3];
 
55
 
 
56
   vec3 operator* ( const vec3 &in ) const
 
57
   {
 
58
           vec3 out;
 
59
           return out;
 
60
   }
 
61
};
 
62
 
 
63
const int gl_MaxLights = 8;
 
64
 
 
65
 
 
66
inline float dot (float x, float y) { return x * y; }
 
67
inline float dot ( const vec2 &x, const vec2 &y) { return x.x * y.x + x.y * y.y; }
 
68
inline float dot ( const vec3 &x, const vec3 &y) { return x.x * y.x + x.y * y.y + x.z * y.z; }
 
69
inline float dot ( const vec4 &x, const vec4 &y) { return x.x * y.x + x.y * y.y + x.z * y.z + x.w * y.w; }
 
70
 
 
71
inline float reflect (float I, float N)                         { return I - 2.0 * dot (N, I) * N; }
 
72
inline vec2 reflect (const vec2 &I, const vec2 &N)      { return I - N * 2.0 * dot (N, I); }
 
73
inline vec3 reflect (const vec3 &I, const vec3 &N)      { return I - N * 2.0 * dot (N, I); }
 
74
inline vec4 reflect (const vec4 &I, const vec4 &N)      { return I - N * 2.0 * dot (N, I); }
 
75
 
 
76
 
 
77
inline float refract (float I, float N, float eta){
 
78
    const float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I));
 
79
    if (k < 0.0)
 
80
        return 0.0;
 
81
    return eta * I - (eta * dot (N, I) + sqrt (k)) * N;
 
82
}
 
83
 
 
84
inline vec2 refract (const vec2 &I, const vec2 &N, float eta){
 
85
    const float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I));
 
86
    if (k < 0.0)
 
87
        return vec2 (0.0);
 
88
    return I * eta - N * (eta * dot (N, I) + sqrt (k));
 
89
}
 
90
 
 
91
inline vec3 refract (const vec3 &I, const vec3 &N, float eta) {
 
92
    const float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I));
 
93
    if (k < 0.0)
 
94
        return vec3 (0.0);
 
95
    return I * eta - N * (eta * dot (N, I) + sqrt (k));
 
96
}
 
97
 
 
98
inline vec4 refract (const vec4 &I, const vec4 &N, float eta) {
 
99
    const float k = 1.0 - eta * eta * (1.0 - dot (N, I) * dot (N, I));
 
100
    if (k < 0.0)
 
101
        return vec4 (0.0);
 
102
    return I * eta - N * (eta * dot (N, I) + sqrt (k));
 
103
}
 
104
 
 
105
 
 
106
inline float length ( const vec3 &v ) { return sqrtf ( v.x * v.x + v.y * v.y + v.z * v.z ); }
 
107
vec3 normalize ( const vec3 &v ) {      float l = 1.f / length ( v ); return vec3 ( v.x * l, v.y * l, v.z * l ); }
 
108
float max ( float a, float b ) { return a > b ? a : b; }
 
109
float min ( float a, float b ) { return a < b ? a : b; }
 
110
vec4 clamp ( const vec4 &a, f32 low, f32 high ) { return vec4 ( min (max(a.x,low), high), min (max(a.y,low), high), min (max(a.z,low), high), min (max(a.w,low), high) ); }
 
111
 
 
112
 
 
113
 
 
114
typedef int sampler2D;
 
115
sampler2D texUnit0;
 
116
 
 
117
vec4 texture2D (sampler2D sampler, const vec2 &coord) { return vec4 (0.0); }
 
118
 
 
119
struct gl_LightSourceParameters {
 
120
        vec4 ambient;              // Acli
 
121
        vec4 diffuse;              // Dcli
 
122
        vec4 specular;             // Scli
 
123
        vec4 position;             // Ppli
 
124
        vec4 halfVector;           // Derived: Hi
 
125
        vec3 spotDirection;        // Sdli
 
126
        float spotExponent;        // Srli
 
127
        float spotCutoff;          // Crli
 
128
                                                        // (range: [0.0,90.0], 180.0)
 
129
        float spotCosCutoff;       // Derived: cos(Crli)
 
130
                                                        // (range: [1.0,0.0],-1.0)
 
131
        float constantAttenuation; // K0
 
132
        float linearAttenuation;   // K1
 
133
        float quadraticAttenuation;// K2
 
134
};
 
135
 
 
136
uniform gl_LightSourceParameters gl_LightSource[gl_MaxLights];
 
137
 
 
138
struct gl_LightModelParameters {
 
139
    vec4 ambient;
 
140
};
 
141
uniform gl_LightModelParameters gl_LightModel;
 
142
 
 
143
struct gl_LightModelProducts {
 
144
    vec4 sceneColor;
 
145
};
 
146
 
 
147
uniform gl_LightModelProducts gl_FrontLightModelProduct;
 
148
uniform gl_LightModelProducts gl_BackLightModelProduct;
 
149
 
 
150
struct gl_LightProducts {
 
151
    vec4 ambient;
 
152
    vec4 diffuse;
 
153
    vec4 specular;
 
154
};
 
155
 
 
156
uniform gl_LightProducts gl_FrontLightProduct[gl_MaxLights];
 
157
uniform gl_LightProducts gl_BackLightProduct[gl_MaxLights];
 
158
 
 
159
struct gl_MaterialParameters
 
160
{
 
161
        vec4 emission;    // Ecm
 
162
        vec4 ambient;     // Acm
 
163
        vec4 diffuse;     // Dcm
 
164
        vec4 specular;    // Scm
 
165
        float shininess;  // Srm
 
166
};
 
167
uniform gl_MaterialParameters gl_FrontMaterial;
 
168
uniform gl_MaterialParameters gl_BackMaterial;
 
169
 
 
170
// GLSL has some built-in attributes in a vertex shader:
 
171
attribute vec4 gl_Vertex;                       // 4D vector representing the vertex position
 
172
attribute vec3 gl_Normal;                       // 3D vector representing the vertex normal
 
173
attribute vec4 gl_Color;                        // 4D vector representing the vertex color
 
174
attribute vec4 gl_MultiTexCoord0;       // 4D vector representing the texture coordinate of texture unit X
 
175
attribute vec4 gl_MultiTexCoord1;       // 4D vector representing the texture coordinate of texture unit X
 
176
 
 
177
uniform mat4 gl_ModelViewMatrix;                        //4x4 Matrix representing the model-view matrix.
 
178
uniform mat4 gl_ModelViewProjectionMatrix;      //4x4 Matrix representing the model-view-projection matrix.
 
179
uniform mat3 gl_NormalMatrix;                           //3x3 Matrix representing the inverse transpose model-view matrix. This matrix is used for normal transformation.
 
180
 
 
181
 
 
182
varying vec4 gl_FrontColor;                             // 4D vector representing the primitives front color
 
183
varying vec4 gl_FrontSecondaryColor;    // 4D vector representing the primitives second front color
 
184
varying vec4 gl_BackColor;                              // 4D vector representing the primitives back color
 
185
varying vec4 gl_TexCoord[4];                    // 4D vector representing the Xth texture coordinate
 
186
 
 
187
// shader output
 
188
varying vec4 gl_Position;                               // 4D vector representing the final processed vertex position. Only  available in vertex shader.
 
189
varying vec4 gl_FragColor;                              // 4D vector representing the final color which is written in the frame buffer. Only available in fragment shader.
 
190
varying float gl_FragDepth;                             // float representing the depth which is written in the depth buffer. Only available in fragment shader.
 
191
 
 
192
varying vec4 gl_SecondaryColor;
 
193
varying float gl_FogFragCoord;
 
194
 
 
195
 
 
196
vec4 ftransform(void)
 
197
{
 
198
        return gl_ModelViewProjectionMatrix * gl_Vertex;
 
199
}
 
200
 
 
201
vec3 fnormal(void)
 
202
{
 
203
    //Compute the normal
 
204
    vec3 normal = gl_NormalMatrix * gl_Normal;
 
205
    normal = normalize(normal);
 
206
    return normal;
 
207
}
 
208
 
 
209
 
 
210
struct program1
 
211
{
 
212
        vec4 Ambient;
 
213
        vec4 Diffuse;
 
214
        vec4 Specular;
 
215
 
 
216
        void pointLight(in int i, in vec3 normal, in vec3 eye, in vec3 ecPosition3)
 
217
        {
 
218
           float nDotVP;       // normal . light direction
 
219
           float nDotHV;       // normal . light half vector
 
220
           float pf;           // power factor
 
221
           float attenuation;  // computed attenuation factor
 
222
           float d;            // distance from surface to light source
 
223
           vec3  VP;           // direction from surface to light position
 
224
           vec3  halfVector;   // direction of maximum highlights
 
225
 
 
226
           // Compute vector from surface to light position
 
227
           VP = vec3 (gl_LightSource[i].position) - ecPosition3;
 
228
 
 
229
           // Compute distance between surface and light position
 
230
           d = length(VP);
 
231
 
 
232
           // Normalize the vector from surface to light position
 
233
           VP = normalize(VP);
 
234
 
 
235
           // Compute attenuation
 
236
           attenuation = 1.0 / (gl_LightSource[i].constantAttenuation +
 
237
                   gl_LightSource[i].linearAttenuation * d +
 
238
                   gl_LightSource[i].quadraticAttenuation * d * d);
 
239
 
 
240
           halfVector = normalize(VP + eye);
 
241
 
 
242
           nDotVP = max(0.0, dot(normal, VP));
 
243
           nDotHV = max(0.0, dot(normal, halfVector));
 
244
 
 
245
           if (nDotVP == 0.0)
 
246
           {
 
247
                   pf = 0.0;
 
248
           }
 
249
           else
 
250
           {
 
251
                   pf = pow(nDotHV, gl_FrontMaterial.shininess);
 
252
 
 
253
           }
 
254
           Ambient  += gl_LightSource[i].ambient * attenuation;
 
255
           Diffuse  += gl_LightSource[i].diffuse * nDotVP * attenuation;
 
256
           Specular += gl_LightSource[i].specular * pf * attenuation;
 
257
        }
 
258
 
 
259
        vec3 fnormal(void)
 
260
        {
 
261
                //Compute the normal
 
262
                vec3 normal = gl_NormalMatrix * gl_Normal;
 
263
                normal = normalize(normal);
 
264
                return normal;
 
265
        }
 
266
 
 
267
        void ftexgen(in vec3 normal, in vec4 ecPosition)
 
268
        {
 
269
 
 
270
                gl_TexCoord[0] = gl_MultiTexCoord0;
 
271
        }
 
272
 
 
273
        void flight(in vec3 normal, in vec4 ecPosition, float alphaFade)
 
274
        {
 
275
                vec4 color;
 
276
                vec3 ecPosition3;
 
277
                vec3 eye;
 
278
 
 
279
                ecPosition3 = (vec3 (ecPosition)) / ecPosition.w;
 
280
                eye = vec3 (0.0, 0.0, 1.0);
 
281
 
 
282
                // Clear the light intensity accumulators
 
283
                Ambient  = vec4 (0.0);
 
284
                Diffuse  = vec4 (0.0);
 
285
                Specular = vec4 (0.0);
 
286
 
 
287
                pointLight(0, normal, eye, ecPosition3);
 
288
 
 
289
                pointLight(1, normal, eye, ecPosition3);
 
290
 
 
291
                color = gl_FrontLightModelProduct.sceneColor +
 
292
                  Ambient  * gl_FrontMaterial.ambient +
 
293
                  Diffuse  * gl_FrontMaterial.diffuse;
 
294
                gl_FrontSecondaryColor = Specular * gl_FrontMaterial.specular;
 
295
                color = clamp( color, 0.0, 1.0 );
 
296
                gl_FrontColor = color;
 
297
 
 
298
                gl_FrontColor.a *= alphaFade;
 
299
        }
 
300
 
 
301
 
 
302
        void vertexshader_main (void)
 
303
        {
 
304
                vec3  transformedNormal;
 
305
                float alphaFade = 1.0;
 
306
 
 
307
                // Eye-coordinate position of vertex, needed in various calculations
 
308
                vec4 ecPosition = gl_ModelViewMatrix * gl_Vertex;
 
309
 
 
310
                // Do fixed functionality vertex transform
 
311
                gl_Position = ftransform();
 
312
                transformedNormal = fnormal();
 
313
                flight(transformedNormal, ecPosition, alphaFade);
 
314
                ftexgen(transformedNormal, ecPosition);
 
315
        }
 
316
 
 
317
        void fragmentshader_main (void)
 
318
        {
 
319
                vec4 color;
 
320
 
 
321
                color = gl_Color;
 
322
 
 
323
                color *= texture2D(texUnit0, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y) );
 
324
 
 
325
                color += gl_SecondaryColor;
 
326
                color = clamp(color, 0.0, 1.0);
 
327
 
 
328
                gl_FragColor = color;
 
329
        }
 
330
};
 
331
 
 
332
}
 
333
 
 
334
//! constructor
 
335
CBurningVideoDriver::CBurningVideoDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, video::IImagePresenter* presenter)
 
336
: CNullDriver(io, params.WindowSize), BackBuffer(0), Presenter(presenter),
 
337
        WindowId(0), SceneSourceRect(0),
 
338
        RenderTargetTexture(0), RenderTargetSurface(0), CurrentShader(0),
 
339
         DepthBuffer(0), StencilBuffer ( 0 ),
 
340
         CurrentOut ( 12 * 2, 128 ), Temp ( 12 * 2, 128 )
 
341
{
 
342
        #ifdef _DEBUG
 
343
        setDebugName("CBurningVideoDriver");
 
344
        #endif
 
345
 
 
346
        // create backbuffer
 
347
        BackBuffer = new CImage(BURNINGSHADER_COLOR_FORMAT, params.WindowSize);
 
348
        if (BackBuffer)
 
349
        {
 
350
                BackBuffer->fill(SColor(0));
 
351
 
 
352
                // create z buffer
 
353
                if ( params.ZBufferBits )
 
354
                        DepthBuffer = video::createDepthBuffer(BackBuffer->getDimension());
 
355
 
 
356
                // create stencil buffer
 
357
                if ( params.Stencilbuffer )
 
358
                        StencilBuffer = video::createStencilBuffer(BackBuffer->getDimension());
 
359
        }
 
360
 
 
361
        DriverAttributes->setAttribute("MaxTextures", 2);
 
362
        DriverAttributes->setAttribute("MaxIndices", 1<<16);
 
363
        DriverAttributes->setAttribute("MaxTextureSize", 1024);
 
364
        DriverAttributes->setAttribute("MaxLights", glsl::gl_MaxLights);
 
365
        DriverAttributes->setAttribute("MaxTextureLODBias", 16.f);
 
366
        DriverAttributes->setAttribute("Version", 47);
 
367
 
 
368
        // create triangle renderers
 
369
 
 
370
        irr::memset32 ( BurningShader, 0, sizeof ( BurningShader ) );
 
371
        //BurningShader[ETR_FLAT] = createTRFlat2(DepthBuffer);
 
372
        //BurningShader[ETR_FLAT_WIRE] = createTRFlatWire2(DepthBuffer);
 
373
        BurningShader[ETR_GOURAUD] = createTriangleRendererGouraud2(this);
 
374
        BurningShader[ETR_GOURAUD_ALPHA] = createTriangleRendererGouraudAlpha2(this );
 
375
        BurningShader[ETR_GOURAUD_ALPHA_NOZ] = createTRGouraudAlphaNoZ2(this );
 
376
        //BurningShader[ETR_GOURAUD_WIRE] = createTriangleRendererGouraudWire2(DepthBuffer);
 
377
        //BurningShader[ETR_TEXTURE_FLAT] = createTriangleRendererTextureFlat2(DepthBuffer);
 
378
        //BurningShader[ETR_TEXTURE_FLAT_WIRE] = createTriangleRendererTextureFlatWire2(DepthBuffer);
 
379
        BurningShader[ETR_TEXTURE_GOURAUD] = createTriangleRendererTextureGouraud2(this);
 
380
        BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP_M1] = createTriangleRendererTextureLightMap2_M1(this);
 
381
        BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP_M2] = createTriangleRendererTextureLightMap2_M2(this);
 
382
        BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP_M4] = createTriangleRendererGTextureLightMap2_M4(this);
 
383
        BurningShader[ETR_TEXTURE_LIGHTMAP_M4] = createTriangleRendererTextureLightMap2_M4(this);
 
384
        BurningShader[ETR_TEXTURE_GOURAUD_LIGHTMAP_ADD] = createTriangleRendererTextureLightMap2_Add(this);
 
385
        BurningShader[ETR_TEXTURE_GOURAUD_DETAIL_MAP] = createTriangleRendererTextureDetailMap2(this);
 
386
 
 
387
        BurningShader[ETR_TEXTURE_GOURAUD_WIRE] = createTriangleRendererTextureGouraudWire2(this);
 
388
        BurningShader[ETR_TEXTURE_GOURAUD_NOZ] = createTRTextureGouraudNoZ2(this);
 
389
        BurningShader[ETR_TEXTURE_GOURAUD_ADD] = createTRTextureGouraudAdd2(this);
 
390
        BurningShader[ETR_TEXTURE_GOURAUD_ADD_NO_Z] = createTRTextureGouraudAddNoZ2(this);
 
391
        BurningShader[ETR_TEXTURE_GOURAUD_VERTEX_ALPHA] = createTriangleRendererTextureVertexAlpha2 ( this );
 
392
 
 
393
        BurningShader[ETR_TEXTURE_GOURAUD_ALPHA] = createTRTextureGouraudAlpha(this );
 
394
        BurningShader[ETR_TEXTURE_GOURAUD_ALPHA_NOZ] = createTRTextureGouraudAlphaNoZ( this );
 
395
 
 
396
        BurningShader[ETR_NORMAL_MAP_SOLID] = createTRNormalMap ( this );
 
397
        BurningShader[ETR_STENCIL_SHADOW] = createTRStencilShadow ( this );
 
398
        BurningShader[ETR_TEXTURE_BLEND] = createTRTextureBlend( this );
 
399
 
 
400
        BurningShader[ETR_REFERENCE] = createTriangleRendererReference ( this );
 
401
 
 
402
 
 
403
        // add the same renderer for all solid types
 
404
        CSoftware2MaterialRenderer_SOLID* smr = new CSoftware2MaterialRenderer_SOLID( this);
 
405
        CSoftware2MaterialRenderer_TRANSPARENT_ADD_COLOR* tmr = new CSoftware2MaterialRenderer_TRANSPARENT_ADD_COLOR( this);
 
406
        CSoftware2MaterialRenderer_UNSUPPORTED * umr = new CSoftware2MaterialRenderer_UNSUPPORTED ( this );
 
407
 
 
408
        //!TODO: addMaterialRenderer depends on pushing order....
 
409
        addMaterialRenderer ( smr ); // EMT_SOLID
 
410
        addMaterialRenderer ( smr ); // EMT_SOLID_2_LAYER,
 
411
        addMaterialRenderer ( smr ); // EMT_LIGHTMAP,
 
412
        addMaterialRenderer ( tmr ); // EMT_LIGHTMAP_ADD,
 
413
        addMaterialRenderer ( smr ); // EMT_LIGHTMAP_M2,
 
414
        addMaterialRenderer ( smr ); // EMT_LIGHTMAP_M4,
 
415
        addMaterialRenderer ( smr ); // EMT_LIGHTMAP_LIGHTING,
 
416
        addMaterialRenderer ( smr ); // EMT_LIGHTMAP_LIGHTING_M2,
 
417
        addMaterialRenderer ( smr ); // EMT_LIGHTMAP_LIGHTING_M4,
 
418
        addMaterialRenderer ( smr ); // EMT_DETAIL_MAP,
 
419
        addMaterialRenderer ( umr ); // EMT_SPHERE_MAP,
 
420
        addMaterialRenderer ( smr ); // EMT_REFLECTION_2_LAYER,
 
421
        addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_ADD_COLOR,
 
422
        addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_ALPHA_CHANNEL,
 
423
        addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_ALPHA_CHANNEL_REF,
 
424
        addMaterialRenderer ( tmr ); // EMT_TRANSPARENT_VERTEX_ALPHA,
 
425
        addMaterialRenderer ( smr ); // EMT_TRANSPARENT_REFLECTION_2_LAYER,
 
426
        addMaterialRenderer ( smr ); // EMT_NORMAL_MAP_SOLID,
 
427
        addMaterialRenderer ( umr ); // EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR,
 
428
        addMaterialRenderer ( tmr ); // EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA,
 
429
        addMaterialRenderer ( smr ); // EMT_PARALLAX_MAP_SOLID,
 
430
        addMaterialRenderer ( tmr ); // EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR,
 
431
        addMaterialRenderer ( tmr ); // EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA,
 
432
        addMaterialRenderer ( tmr ); // EMT_ONETEXTURE_BLEND
 
433
 
 
434
        smr->drop ();
 
435
        tmr->drop ();
 
436
        umr->drop ();
 
437
 
 
438
        // select render target
 
439
        setRenderTarget(BackBuffer);
 
440
 
 
441
        //reset Lightspace
 
442
        LightSpace.reset ();
 
443
 
 
444
        // select the right renderer
 
445
        setCurrentShader();
 
446
}
 
447
 
 
448
 
 
449
//! destructor
 
450
CBurningVideoDriver::~CBurningVideoDriver()
 
451
{
 
452
        // delete Backbuffer
 
453
        if (BackBuffer)
 
454
                BackBuffer->drop();
 
455
 
 
456
        // delete triangle renderers
 
457
 
 
458
        for (s32 i=0; i<ETR2_COUNT; ++i)
 
459
        {
 
460
                if (BurningShader[i])
 
461
                        BurningShader[i]->drop();
 
462
        }
 
463
 
 
464
        // delete Additional buffer
 
465
        if (StencilBuffer)
 
466
                StencilBuffer->drop();
 
467
 
 
468
        if (DepthBuffer)
 
469
                DepthBuffer->drop();
 
470
 
 
471
        if (RenderTargetTexture)
 
472
                RenderTargetTexture->drop();
 
473
 
 
474
        if (RenderTargetSurface)
 
475
                RenderTargetSurface->drop();
 
476
}
 
477
 
 
478
 
 
479
/*!
 
480
        selects the right triangle renderer based on the render states.
 
481
*/
 
482
void CBurningVideoDriver::setCurrentShader()
 
483
{
 
484
        ITexture *texture0 = Material.org.getTexture(0);
 
485
        ITexture *texture1 = Material.org.getTexture(1);
 
486
 
 
487
        bool zMaterialTest =    Material.org.ZBuffer != ECFN_NEVER &&
 
488
                                                        Material.org.ZWriteEnable &&
 
489
                                                        ( AllowZWriteOnTransparent || !Material.org.isTransparent() );
 
490
 
 
491
        EBurningFFShader shader = zMaterialTest ? ETR_TEXTURE_GOURAUD : ETR_TEXTURE_GOURAUD_NOZ;
 
492
 
 
493
        TransformationFlag[ ETS_TEXTURE_0] &= ~(ETF_TEXGEN_CAMERA_NORMAL|ETF_TEXGEN_CAMERA_REFLECTION);
 
494
        LightSpace.Flags &= ~VERTEXTRANSFORM;
 
495
 
 
496
        switch ( Material.org.MaterialType )
 
497
        {
 
498
                case EMT_ONETEXTURE_BLEND:
 
499
                        shader = ETR_TEXTURE_BLEND;
 
500
                        break;
 
501
 
 
502
                case EMT_TRANSPARENT_ALPHA_CHANNEL_REF:
 
503
                        Material.org.MaterialTypeParam = 0.5f;
 
504
                        // fall through
 
505
                case EMT_TRANSPARENT_ALPHA_CHANNEL:
 
506
                        if ( texture0 && texture0->hasAlpha () )
 
507
                        {
 
508
                                shader = zMaterialTest ? ETR_TEXTURE_GOURAUD_ALPHA : ETR_TEXTURE_GOURAUD_ALPHA_NOZ;
 
509
                                break;
 
510
                        }
 
511
                        // fall through
 
512
 
 
513
                case EMT_TRANSPARENT_ADD_COLOR:
 
514
                        shader = zMaterialTest ? ETR_TEXTURE_GOURAUD_ADD : ETR_TEXTURE_GOURAUD_ADD_NO_Z;
 
515
                        break;
 
516
 
 
517
                case EMT_TRANSPARENT_VERTEX_ALPHA:
 
518
                        shader = ETR_TEXTURE_GOURAUD_VERTEX_ALPHA;
 
519
                        break;
 
520
 
 
521
                case EMT_LIGHTMAP:
 
522
                case EMT_LIGHTMAP_LIGHTING:
 
523
                        shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M1;
 
524
                        break;
 
525
 
 
526
                case EMT_LIGHTMAP_M2:
 
527
                case EMT_LIGHTMAP_LIGHTING_M2:
 
528
                        shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M2;
 
529
                        break;
 
530
 
 
531
                case EMT_LIGHTMAP_LIGHTING_M4:
 
532
                        if ( texture1 )
 
533
                                shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M4;
 
534
                        break;
 
535
                case EMT_LIGHTMAP_M4:
 
536
                        if ( texture1 )
 
537
                                shader = ETR_TEXTURE_LIGHTMAP_M4;
 
538
                        break;
 
539
 
 
540
                case EMT_LIGHTMAP_ADD:
 
541
                        if ( texture1 )
 
542
                                shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_ADD;
 
543
                        break;
 
544
 
 
545
                case EMT_DETAIL_MAP:
 
546
                        shader = ETR_TEXTURE_GOURAUD_DETAIL_MAP;
 
547
                        break;
 
548
 
 
549
                case EMT_SPHERE_MAP:
 
550
                        TransformationFlag[ ETS_TEXTURE_0] |= ETF_TEXGEN_CAMERA_REFLECTION; // ETF_TEXGEN_CAMERA_NORMAL;
 
551
                        LightSpace.Flags |= VERTEXTRANSFORM;
 
552
                        break;
 
553
                case EMT_REFLECTION_2_LAYER:
 
554
                        shader = ETR_TEXTURE_GOURAUD_LIGHTMAP_M1;
 
555
                        TransformationFlag[ ETS_TEXTURE_1] |= ETF_TEXGEN_CAMERA_REFLECTION;
 
556
                        LightSpace.Flags |= VERTEXTRANSFORM;
 
557
                        break;
 
558
 
 
559
                case EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA:
 
560
                case EMT_NORMAL_MAP_SOLID:
 
561
                case EMT_PARALLAX_MAP_SOLID:
 
562
                case EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA:
 
563
                        shader = ETR_NORMAL_MAP_SOLID;
 
564
                        LightSpace.Flags |= VERTEXTRANSFORM;
 
565
                        break;
 
566
 
 
567
                default:
 
568
                        break;
 
569
 
 
570
        }
 
571
 
 
572
        if ( !texture0 )
 
573
        {
 
574
                shader = ETR_GOURAUD;
 
575
        }
 
576
 
 
577
        if ( Material.org.Wireframe )
 
578
        {
 
579
                shader = ETR_TEXTURE_GOURAUD_WIRE;
 
580
        }
 
581
 
 
582
        //shader = ETR_REFERENCE;
 
583
 
 
584
        // switchToTriangleRenderer
 
585
        CurrentShader = BurningShader[shader];
 
586
        if ( CurrentShader )
 
587
        {
 
588
                CurrentShader->setZCompareFunc ( Material.org.ZBuffer );
 
589
                CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort);
 
590
                CurrentShader->setMaterial ( Material );
 
591
 
 
592
                switch ( shader )
 
593
                {
 
594
                        case ETR_TEXTURE_GOURAUD_ALPHA:
 
595
                        case ETR_TEXTURE_GOURAUD_ALPHA_NOZ:
 
596
                        case ETR_TEXTURE_BLEND:
 
597
                                CurrentShader->setParam ( 0, Material.org.MaterialTypeParam );
 
598
                                break;
 
599
                        default:
 
600
                        break;
 
601
                }
 
602
        }
 
603
 
 
604
}
 
605
 
 
606
 
 
607
 
 
608
//! queries the features of the driver, returns true if feature is available
 
609
bool CBurningVideoDriver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const
 
610
{
 
611
        if (!FeatureEnabled[feature])
 
612
                return false;
 
613
 
 
614
        switch (feature)
 
615
        {
 
616
#ifdef SOFTWARE_DRIVER_2_BILINEAR
 
617
        case EVDF_BILINEAR_FILTER:
 
618
                return true;
 
619
#endif
 
620
#ifdef SOFTWARE_DRIVER_2_MIPMAPPING
 
621
        case EVDF_MIP_MAP:
 
622
                return true;
 
623
#endif
 
624
        case EVDF_STENCIL_BUFFER:
 
625
        case EVDF_RENDER_TO_TARGET:
 
626
        case EVDF_MULTITEXTURE:
 
627
        case EVDF_HARDWARE_TL:
 
628
        case EVDF_TEXTURE_NSQUARE:
 
629
                return true;
 
630
 
 
631
        default:
 
632
                return false;
 
633
        }
 
634
}
 
635
 
 
636
 
 
637
 
 
638
//! sets transformation
 
639
void CBurningVideoDriver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat)
 
640
{
 
641
        Transformation[state] = mat;
 
642
        core::setbit_cond ( TransformationFlag[state], mat.isIdentity(), ETF_IDENTITY );
 
643
 
 
644
        switch ( state )
 
645
        {
 
646
                case ETS_VIEW:
 
647
                        Transformation[ETS_VIEW_PROJECTION].setbyproduct_nocheck (
 
648
                                Transformation[ETS_PROJECTION],
 
649
                                Transformation[ETS_VIEW]
 
650
                        );
 
651
                        getCameraPosWorldSpace ();
 
652
                        break;
 
653
 
 
654
                case ETS_WORLD:
 
655
                        if ( TransformationFlag[state] & ETF_IDENTITY )
 
656
                        {
 
657
                                Transformation[ETS_WORLD_INVERSE] = Transformation[ETS_WORLD];
 
658
                                TransformationFlag[ETS_WORLD_INVERSE] |= ETF_IDENTITY;
 
659
                                Transformation[ETS_CURRENT] = Transformation[ETS_VIEW_PROJECTION];
 
660
                        }
 
661
                        else
 
662
                        {
 
663
                                //Transformation[ETS_WORLD].getInversePrimitive ( Transformation[ETS_WORLD_INVERSE] );
 
664
                                Transformation[ETS_CURRENT].setbyproduct_nocheck (
 
665
                                        Transformation[ETS_VIEW_PROJECTION],
 
666
                                        Transformation[ETS_WORLD]
 
667
                                );
 
668
                        }
 
669
                        TransformationFlag[ETS_CURRENT] = 0;
 
670
                        //getLightPosObjectSpace ();
 
671
                        break;
 
672
                case ETS_TEXTURE_0:
 
673
                case ETS_TEXTURE_1:
 
674
                case ETS_TEXTURE_2:
 
675
                case ETS_TEXTURE_3:
 
676
                        if ( 0 == (TransformationFlag[state] & ETF_IDENTITY ) )
 
677
                                LightSpace.Flags |= VERTEXTRANSFORM;
 
678
                default:
 
679
                        break;
 
680
        }
 
681
}
 
682
 
 
683
 
 
684
//! clears the zbuffer
 
685
bool CBurningVideoDriver::beginScene(bool backBuffer, bool zBuffer,
 
686
                SColor color, const SExposedVideoData& videoData,
 
687
                core::rect<s32>* sourceRect)
 
688
{
 
689
        CNullDriver::beginScene(backBuffer, zBuffer, color, videoData, sourceRect);
 
690
        WindowId = videoData.D3D9.HWnd;
 
691
        SceneSourceRect = sourceRect;
 
692
 
 
693
        if (backBuffer && BackBuffer)
 
694
                BackBuffer->fill(color);
 
695
 
 
696
        if (zBuffer && DepthBuffer)
 
697
                DepthBuffer->clear();
 
698
 
 
699
        memset ( TransformationFlag, 0, sizeof ( TransformationFlag ) );
 
700
        return true;
 
701
}
 
702
 
 
703
 
 
704
//! presents the rendered scene on the screen, returns false if failed
 
705
bool CBurningVideoDriver::endScene()
 
706
{
 
707
        CNullDriver::endScene();
 
708
 
 
709
        return Presenter->present(BackBuffer, WindowId, SceneSourceRect);
 
710
}
 
711
 
 
712
 
 
713
//! sets a render target
 
714
bool CBurningVideoDriver::setRenderTarget(video::ITexture* texture, bool clearBackBuffer,
 
715
                                                                 bool clearZBuffer, SColor color)
 
716
{
 
717
        if (texture && texture->getDriverType() != EDT_BURNINGSVIDEO)
 
718
        {
 
719
                os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR);
 
720
                return false;
 
721
        }
 
722
 
 
723
        if (RenderTargetTexture)
 
724
                RenderTargetTexture->drop();
 
725
 
 
726
        RenderTargetTexture = texture;
 
727
 
 
728
        if (RenderTargetTexture)
 
729
        {
 
730
                RenderTargetTexture->grab();
 
731
                setRenderTarget(((CSoftwareTexture2*)RenderTargetTexture)->getTexture());
 
732
        }
 
733
        else
 
734
        {
 
735
                setRenderTarget(BackBuffer);
 
736
        }
 
737
 
 
738
        if (RenderTargetSurface && (clearBackBuffer || clearZBuffer))
 
739
        {
 
740
                if (clearZBuffer)
 
741
                        DepthBuffer->clear();
 
742
 
 
743
                if (clearBackBuffer)
 
744
                        RenderTargetSurface->fill( color );
 
745
        }
 
746
 
 
747
        return true;
 
748
}
 
749
 
 
750
 
 
751
//! sets a render target
 
752
void CBurningVideoDriver::setRenderTarget(video::CImage* image)
 
753
{
 
754
        if (RenderTargetSurface)
 
755
                RenderTargetSurface->drop();
 
756
 
 
757
        RenderTargetSurface = image;
 
758
        RenderTargetSize.Width = 0;
 
759
        RenderTargetSize.Height = 0;
 
760
 
 
761
        if (RenderTargetSurface)
 
762
        {
 
763
                RenderTargetSurface->grab();
 
764
                RenderTargetSize = RenderTargetSurface->getDimension();
 
765
        }
 
766
 
 
767
        setViewPort(core::rect<s32>(0,0,RenderTargetSize.Width,RenderTargetSize.Height));
 
768
 
 
769
        if (DepthBuffer)
 
770
                DepthBuffer->setSize(RenderTargetSize);
 
771
 
 
772
        if (StencilBuffer)
 
773
                StencilBuffer->setSize(RenderTargetSize);
 
774
}
 
775
 
 
776
 
 
777
 
 
778
//! sets a viewport
 
779
void CBurningVideoDriver::setViewPort(const core::rect<s32>& area)
 
780
{
 
781
        ViewPort = area;
 
782
 
 
783
        core::rect<s32> rendert(0,0,RenderTargetSize.Width,RenderTargetSize.Height);
 
784
        ViewPort.clipAgainst(rendert);
 
785
 
 
786
        Transformation [ ETS_CLIPSCALE ].buildNDCToDCMatrix ( ViewPort, 1 );
 
787
 
 
788
        if (CurrentShader)
 
789
                CurrentShader->setRenderTarget(RenderTargetSurface, ViewPort);
 
790
}
 
791
 
 
792
/*
 
793
        generic plane clipping in homogenous coordinates
 
794
        special case ndc frustum <-w,w>,<-w,w>,<-w,w>
 
795
        can be rewritten with compares e.q near plane, a.z < -a.w and b.z < -b.w
 
796
*/
 
797
 
 
798
const sVec4 CBurningVideoDriver::NDCPlane[6] =
 
799
{
 
800
        sVec4(  0.f,  0.f, -1.f, -1.f ),        // near
 
801
        sVec4(  0.f,  0.f,  1.f, -1.f ),        // far
 
802
        sVec4(  1.f,  0.f,  0.f, -1.f ),        // left
 
803
        sVec4( -1.f,  0.f,  0.f, -1.f ),        // right
 
804
        sVec4(  0.f,  1.f,  0.f, -1.f ),        // bottom
 
805
        sVec4(  0.f, -1.f,  0.f, -1.f )         // top
 
806
};
 
807
 
 
808
 
 
809
 
 
810
/*
 
811
        test a vertex if it's inside the standard frustum
 
812
 
 
813
        this is the generic one..
 
814
 
 
815
        f32 dotPlane;
 
816
        for ( u32 i = 0; i!= 6; ++i )
 
817
        {
 
818
                dotPlane = v->Pos.dotProduct ( NDCPlane[i] );
 
819
                core::setbit_cond( flag, dotPlane <= 0.f, 1 << i );
 
820
        }
 
821
 
 
822
        // this is the base for ndc frustum <-w,w>,<-w,w>,<-w,w>
 
823
        core::setbit_cond( flag, ( v->Pos.z - v->Pos.w ) <= 0.f, 1 );
 
824
        core::setbit_cond( flag, (-v->Pos.z - v->Pos.w ) <= 0.f, 2 );
 
825
        core::setbit_cond( flag, ( v->Pos.x - v->Pos.w ) <= 0.f, 4 );
 
826
        core::setbit_cond( flag, (-v->Pos.x - v->Pos.w ) <= 0.f, 8 );
 
827
        core::setbit_cond( flag, ( v->Pos.y - v->Pos.w ) <= 0.f, 16 );
 
828
        core::setbit_cond( flag, (-v->Pos.y - v->Pos.w ) <= 0.f, 32 );
 
829
 
 
830
*/
 
831
#ifdef IRRLICHT_FAST_MATH
 
832
 
 
833
REALINLINE u32 CBurningVideoDriver::clipToFrustumTest ( const s4DVertex * v  ) const
 
834
{
 
835
        f32 test[6];
 
836
        u32 flag;
 
837
        const f32 w = - v->Pos.w;
 
838
 
 
839
        // a conditional move is needed....FCOMI ( but we don't have it )
 
840
        // so let the fpu calculate and write it back.
 
841
        // cpu makes the compare, interleaving
 
842
 
 
843
        test[0] =  v->Pos.z + w;
 
844
        test[1] = -v->Pos.z + w;
 
845
        test[2] =  v->Pos.x + w;
 
846
        test[3] = -v->Pos.x + w;
 
847
        test[4] =  v->Pos.y + w;
 
848
        test[5] = -v->Pos.y + w;
 
849
 
 
850
        flag  = (IR ( test[0] )              ) >> 31;
 
851
        flag |= (IR ( test[1] ) & 0x80000000 ) >> 30;
 
852
        flag |= (IR ( test[2] ) & 0x80000000 ) >> 29;
 
853
        flag |= (IR ( test[3] ) & 0x80000000 ) >> 28;
 
854
        flag |= (IR ( test[4] ) & 0x80000000 ) >> 27;
 
855
        flag |= (IR ( test[5] ) & 0x80000000 ) >> 26;
 
856
 
 
857
/*
 
858
        flag  = F32_LOWER_EQUAL_0 ( test[0] );
 
859
        flag |= F32_LOWER_EQUAL_0 ( test[1] ) << 1;
 
860
        flag |= F32_LOWER_EQUAL_0 ( test[2] ) << 2;
 
861
        flag |= F32_LOWER_EQUAL_0 ( test[3] ) << 3;
 
862
        flag |= F32_LOWER_EQUAL_0 ( test[4] ) << 4;
 
863
        flag |= F32_LOWER_EQUAL_0 ( test[5] ) << 5;
 
864
*/
 
865
        return flag;
 
866
}
 
867
 
 
868
#else
 
869
 
 
870
 
 
871
REALINLINE u32 CBurningVideoDriver::clipToFrustumTest ( const s4DVertex * v  ) const
 
872
{
 
873
        u32 flag = 0;
 
874
 
 
875
        if ( v->Pos.z <= v->Pos.w ) flag |= 1;
 
876
        if (-v->Pos.z <= v->Pos.w ) flag |= 2;
 
877
 
 
878
        if ( v->Pos.x <= v->Pos.w ) flag |= 4;
 
879
        if (-v->Pos.x <= v->Pos.w ) flag |= 8;
 
880
 
 
881
        if ( v->Pos.y <= v->Pos.w ) flag |= 16;
 
882
        if (-v->Pos.y <= v->Pos.w ) flag |= 32;
 
883
 
 
884
/*
 
885
        for ( u32 i = 0; i!= 6; ++i )
 
886
        {
 
887
                core::setbit_cond( flag, v->Pos.dotProduct ( NDCPlane[i] ) <= 0.f, 1 << i );
 
888
        }
 
889
*/
 
890
        return flag;
 
891
}
 
892
 
 
893
#endif // _MSC_VER
 
894
 
 
895
u32 CBurningVideoDriver::clipToHyperPlane ( s4DVertex * dest, const s4DVertex * source, u32 inCount, const sVec4 &plane )
 
896
{
 
897
        u32 outCount = 0;
 
898
        s4DVertex * out = dest;
 
899
 
 
900
        const s4DVertex * a;
 
901
        const s4DVertex * b = source;
 
902
 
 
903
        f32 bDotPlane;
 
904
 
 
905
        bDotPlane = b->Pos.dotProduct ( plane );
 
906
 
 
907
        for( u32 i = 1; i < inCount + 1; ++i)
 
908
        {
 
909
                const s32 condition = i - inCount;
 
910
                const s32 index = (( ( condition >> 31 ) & ( i ^ condition ) ) ^ condition ) << 1;
 
911
 
 
912
                a = &source[ index ];
 
913
 
 
914
                // current point inside
 
915
                if ( a->Pos.dotProduct ( plane ) <= 0.f )
 
916
                {
 
917
                        // last point outside
 
918
                        if ( F32_GREATER_0 ( bDotPlane ) )
 
919
                        {
 
920
                                // intersect line segment with plane
 
921
                                out->interpolate ( *b, *a, bDotPlane / (b->Pos - a->Pos).dotProduct ( plane ) );
 
922
                                out += 2;
 
923
                                outCount += 1;
 
924
                        }
 
925
 
 
926
                        // copy current to out
 
927
                        //*out = *a;
 
928
                        irr::memcpy32_small ( out, a, SIZEOF_SVERTEX * 2 );
 
929
                        b = out;
 
930
 
 
931
                        out += 2;
 
932
                        outCount += 1;
 
933
                }
 
934
                else
 
935
                {
 
936
                        // current point outside
 
937
 
 
938
                        if ( F32_LOWER_EQUAL_0 (  bDotPlane ) )
 
939
                        {
 
940
                                // previous was inside
 
941
                                // intersect line segment with plane
 
942
                                out->interpolate ( *b, *a, bDotPlane / (b->Pos - a->Pos).dotProduct ( plane ) );
 
943
                                out += 2;
 
944
                                outCount += 1;
 
945
                        }
 
946
                        // pointer
 
947
                        b = a;
 
948
                }
 
949
 
 
950
                bDotPlane = b->Pos.dotProduct ( plane );
 
951
 
 
952
        }
 
953
 
 
954
        return outCount;
 
955
}
 
956
 
 
957
 
 
958
u32 CBurningVideoDriver::clipToFrustum ( s4DVertex *v0, s4DVertex * v1, const u32 vIn )
 
959
{
 
960
        u32 vOut = vIn;
 
961
 
 
962
        vOut = clipToHyperPlane ( v1, v0, vOut, NDCPlane[0] ); if ( vOut < vIn ) return vOut;
 
963
        vOut = clipToHyperPlane ( v0, v1, vOut, NDCPlane[1] ); if ( vOut < vIn ) return vOut;
 
964
        vOut = clipToHyperPlane ( v1, v0, vOut, NDCPlane[2] ); if ( vOut < vIn ) return vOut;
 
965
        vOut = clipToHyperPlane ( v0, v1, vOut, NDCPlane[3] ); if ( vOut < vIn ) return vOut;
 
966
        vOut = clipToHyperPlane ( v1, v0, vOut, NDCPlane[4] ); if ( vOut < vIn ) return vOut;
 
967
        vOut = clipToHyperPlane ( v0, v1, vOut, NDCPlane[5] );
 
968
        return vOut;
 
969
}
 
970
 
 
971
/*!
 
972
 Part I:
 
973
        apply Clip Scale matrix
 
974
        From Normalized Device Coordiante ( NDC ) Space to Device Coordinate Space ( DC )
 
975
 
 
976
 Part II:
 
977
        Project homogeneous vector
 
978
        homogeneous to non-homogenous coordinates ( dividebyW )
 
979
 
 
980
        Incoming: ( xw, yw, zw, w, u, v, 1, R, G, B, A )
 
981
        Outgoing: ( xw/w, yw/w, zw/w, w/w, u/w, v/w, 1/w, R/w, G/w, B/w, A/w )
 
982
 
 
983
 
 
984
        replace w/w by 1/w
 
985
*/
 
986
inline void CBurningVideoDriver::ndc_2_dc_and_project ( s4DVertex *dest,s4DVertex *source, u32 vIn ) const
 
987
{
 
988
        u32 g;
 
989
 
 
990
        for ( g = 0; g != vIn; g += 2 )
 
991
        {
 
992
                if ( (dest[g].flag & VERTEX4D_PROJECTED ) == VERTEX4D_PROJECTED )
 
993
                        continue;
 
994
 
 
995
                dest[g].flag = source[g].flag | VERTEX4D_PROJECTED;
 
996
 
 
997
                const f32 w = source[g].Pos.w;
 
998
                const f32 iw = core::reciprocal ( w );
 
999
 
 
1000
                // to device coordinates
 
1001
                dest[g].Pos.x = iw * ( source[g].Pos.x * Transformation [ ETS_CLIPSCALE ][ 0] + w * Transformation [ ETS_CLIPSCALE ][12] );
 
1002
                dest[g].Pos.y = iw * ( source[g].Pos.y * Transformation [ ETS_CLIPSCALE ][ 5] + w * Transformation [ ETS_CLIPSCALE ][13] );
 
1003
 
 
1004
#ifndef SOFTWARE_DRIVER_2_USE_WBUFFER
 
1005
                dest[g].Pos.z = iw * source[g].Pos.z;
 
1006
#endif
 
1007
 
 
1008
        #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR
 
1009
                #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
 
1010
                        dest[g].Color[0] = source[g].Color[0] * iw;
 
1011
                #else
 
1012
                        dest[g].Color[0] = source[g].Color[0];
 
1013
                #endif
 
1014
 
 
1015
        #endif
 
1016
                dest[g].LightTangent[0] = source[g].LightTangent[0] * iw;
 
1017
                dest[g].Pos.w = iw;
 
1018
        }
 
1019
}
 
1020
 
 
1021
 
 
1022
inline void CBurningVideoDriver::ndc_2_dc_and_project2 ( const s4DVertex **v, const u32 size ) const
 
1023
{
 
1024
        u32 g;
 
1025
 
 
1026
        for ( g = 0; g != size; g += 1 )
 
1027
        {
 
1028
                s4DVertex * a = (s4DVertex*) v[g];
 
1029
 
 
1030
                if ( (a[1].flag & VERTEX4D_PROJECTED ) == VERTEX4D_PROJECTED )
 
1031
                        continue;
 
1032
 
 
1033
                a[1].flag = a->flag | VERTEX4D_PROJECTED;
 
1034
 
 
1035
                // project homogenous vertex, store 1/w
 
1036
                const f32 w = a->Pos.w;
 
1037
                const f32 iw = core::reciprocal ( w );
 
1038
 
 
1039
                // to device coordinates
 
1040
                const f32 * p = Transformation [ ETS_CLIPSCALE ].pointer();
 
1041
                a[1].Pos.x = iw * ( a->Pos.x * p[ 0] + w * p[12] );
 
1042
                a[1].Pos.y = iw * ( a->Pos.y * p[ 5] + w * p[13] );
 
1043
 
 
1044
#ifndef SOFTWARE_DRIVER_2_USE_WBUFFER
 
1045
                a[1].Pos.z = a->Pos.z * iw;
 
1046
#endif
 
1047
 
 
1048
        #ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR
 
1049
                #ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
 
1050
                        a[1].Color[0] = a->Color[0] * iw;
 
1051
                #else
 
1052
                        a[1].Color[0] = a->Color[0];
 
1053
                #endif
 
1054
        #endif
 
1055
 
 
1056
                a[1].LightTangent[0] = a[0].LightTangent[0] * iw;
 
1057
                a[1].Pos.w = iw;
 
1058
 
 
1059
        }
 
1060
 
 
1061
}
 
1062
 
 
1063
 
 
1064
/*!
 
1065
        crossproduct in projected 2D -> screen area triangle
 
1066
*/
 
1067
inline f32 CBurningVideoDriver::screenarea ( const s4DVertex *v ) const
 
1068
{
 
1069
        return  ( ( v[3].Pos.x - v[1].Pos.x ) * ( v[5].Pos.y - v[1].Pos.y ) ) -
 
1070
                        ( ( v[3].Pos.y - v[1].Pos.y ) * ( v[5].Pos.x - v[1].Pos.x ) );
 
1071
}
 
1072
 
 
1073
 
 
1074
/*!
 
1075
*/
 
1076
inline f32 CBurningVideoDriver::texelarea ( const s4DVertex *v, int tex ) const
 
1077
{
 
1078
        f32 z;
 
1079
 
 
1080
        z =             ( (v[2].Tex[tex].x - v[0].Tex[tex].x ) * (v[4].Tex[tex].y - v[0].Tex[tex].y ) )
 
1081
                 -      ( (v[4].Tex[tex].x - v[0].Tex[tex].x ) * (v[2].Tex[tex].y - v[0].Tex[tex].y ) );
 
1082
 
 
1083
        return MAT_TEXTURE ( tex )->getLODFactor ( z );
 
1084
}
 
1085
 
 
1086
/*!
 
1087
        crossproduct in projected 2D
 
1088
*/
 
1089
inline f32 CBurningVideoDriver::screenarea2 ( const s4DVertex **v ) const
 
1090
{
 
1091
        return  ( (( v[1] + 1 )->Pos.x - (v[0] + 1 )->Pos.x ) * ( (v[2] + 1 )->Pos.y - (v[0] + 1 )->Pos.y ) ) -
 
1092
                        ( (( v[1] + 1 )->Pos.y - (v[0] + 1 )->Pos.y ) * ( (v[2] + 1 )->Pos.x - (v[0] + 1 )->Pos.x ) );
 
1093
}
 
1094
 
 
1095
/*!
 
1096
*/
 
1097
inline f32 CBurningVideoDriver::texelarea2 ( const s4DVertex **v, s32 tex ) const
 
1098
{
 
1099
        f32 z;
 
1100
        z =             ( (v[1]->Tex[tex].x - v[0]->Tex[tex].x ) * (v[2]->Tex[tex].y - v[0]->Tex[tex].y ) )
 
1101
                 -      ( (v[2]->Tex[tex].x - v[0]->Tex[tex].x ) * (v[1]->Tex[tex].y - v[0]->Tex[tex].y ) );
 
1102
 
 
1103
        return MAT_TEXTURE ( tex )->getLODFactor ( z );
 
1104
}
 
1105
 
 
1106
 
 
1107
/*!
 
1108
*/
 
1109
inline void CBurningVideoDriver::select_polygon_mipmap ( s4DVertex *v, u32 vIn, u32 tex, const core::dimension2du& texSize ) const
 
1110
{
 
1111
        f32 f[2];
 
1112
 
 
1113
        f[0] = (f32) texSize.Width - 0.25f;
 
1114
        f[1] = (f32) texSize.Height - 0.25f;
 
1115
 
 
1116
#ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
 
1117
        for ( u32 g = 0; g != vIn; g += 2 )
 
1118
        {
 
1119
                (v + g + 1 )->Tex[tex].x        = (v + g + 0)->Tex[tex].x * ( v + g + 1 )->Pos.w * f[0];
 
1120
                (v + g + 1 )->Tex[tex].y        = (v + g + 0)->Tex[tex].y * ( v + g + 1 )->Pos.w * f[1];
 
1121
        }
 
1122
#else
 
1123
        for ( u32 g = 0; g != vIn; g += 2 )
 
1124
        {
 
1125
                (v + g + 1 )->Tex[tex].x        = (v + g + 0)->Tex[tex].x * f[0];
 
1126
                (v + g + 1 )->Tex[tex].y        = (v + g + 0)->Tex[tex].y * f[1];
 
1127
        }
 
1128
#endif
 
1129
}
 
1130
 
 
1131
inline void CBurningVideoDriver::select_polygon_mipmap2 ( s4DVertex **v, u32 tex, const core::dimension2du& texSize ) const
 
1132
{
 
1133
        f32 f[2];
 
1134
 
 
1135
        f[0] = (f32) texSize.Width - 0.25f;
 
1136
        f[1] = (f32) texSize.Height - 0.25f;
 
1137
 
 
1138
#ifdef SOFTWARE_DRIVER_2_PERSPECTIVE_CORRECT
 
1139
        (v[0] + 1 )->Tex[tex].x = v[0]->Tex[tex].x * ( v[0] + 1 )->Pos.w * f[0];
 
1140
        (v[0] + 1 )->Tex[tex].y = v[0]->Tex[tex].y * ( v[0] + 1 )->Pos.w * f[1];
 
1141
 
 
1142
        (v[1] + 1 )->Tex[tex].x = v[1]->Tex[tex].x * ( v[1] + 1 )->Pos.w * f[0];
 
1143
        (v[1] + 1 )->Tex[tex].y = v[1]->Tex[tex].y * ( v[1] + 1 )->Pos.w * f[1];
 
1144
 
 
1145
        (v[2] + 1 )->Tex[tex].x = v[2]->Tex[tex].x * ( v[2] + 1 )->Pos.w * f[0];
 
1146
        (v[2] + 1 )->Tex[tex].y = v[2]->Tex[tex].y * ( v[2] + 1 )->Pos.w * f[1];
 
1147
 
 
1148
#else
 
1149
        (v[0] + 1 )->Tex[tex].x = v[0]->Tex[tex].x * f[0];
 
1150
        (v[0] + 1 )->Tex[tex].y = v[0]->Tex[tex].y * f[1];
 
1151
 
 
1152
        (v[1] + 1 )->Tex[tex].x = v[1]->Tex[tex].x * f[0];
 
1153
        (v[1] + 1 )->Tex[tex].y = v[1]->Tex[tex].y * f[1];
 
1154
 
 
1155
        (v[2] + 1 )->Tex[tex].x = v[2]->Tex[tex].x * f[0];
 
1156
        (v[2] + 1 )->Tex[tex].y = v[2]->Tex[tex].y * f[1];
 
1157
#endif
 
1158
}
 
1159
 
 
1160
// Vertex Cache
 
1161
const SVSize CBurningVideoDriver::vSize[] =
 
1162
{
 
1163
        { VERTEX4D_FORMAT_TEXTURE_1 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex), 1 },
 
1164
        { VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex2TCoords),2 },
 
1165
        { VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1 | VERTEX4D_FORMAT_BUMP_DOT3, sizeof(S3DVertexTangents),2 },
 
1166
        { VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex), 2 },  // reflection map
 
1167
        { 0, sizeof(f32) * 3, 0 },      // core::vector3df*
 
1168
};
 
1169
 
 
1170
 
 
1171
 
 
1172
/*!
 
1173
        fill a cache line with transformed, light and clipp test triangles
 
1174
*/
 
1175
void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 destIndex)
 
1176
{
 
1177
        u8 * source;
 
1178
        s4DVertex *dest;
 
1179
 
 
1180
        source = (u8*) VertexCache.vertices + ( sourceIndex * vSize[VertexCache.vType].Pitch );
 
1181
 
 
1182
        // it's a look ahead so we never hit it..
 
1183
        // but give priority...
 
1184
        //VertexCache.info[ destIndex ].hit = hitCount;
 
1185
 
 
1186
        // store info
 
1187
        VertexCache.info[ destIndex ].index = sourceIndex;
 
1188
        VertexCache.info[ destIndex ].hit = 0;
 
1189
 
 
1190
        // destination Vertex
 
1191
        dest = (s4DVertex *) ( (u8*) VertexCache.mem.data + ( destIndex << ( SIZEOF_SVERTEX_LOG2 + 1  ) ) );
 
1192
 
 
1193
        // transform Model * World * Camera * Projection * NDCSpace matrix
 
1194
        const S3DVertex *base = ((S3DVertex*) source );
 
1195
        Transformation [ ETS_CURRENT].transformVect ( &dest->Pos.x, base->Pos );
 
1196
 
 
1197
        //mhm ;-) maybe no goto
 
1198
        if ( VertexCache.vType == 4 ) goto clipandproject;
 
1199
 
 
1200
 
 
1201
#if defined (SOFTWARE_DRIVER_2_LIGHTING) || defined ( SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM )
 
1202
 
 
1203
        // vertex normal in light space
 
1204
        if ( Material.org.Lighting || (LightSpace.Flags & VERTEXTRANSFORM) )
 
1205
        {
 
1206
                if ( TransformationFlag[ETS_WORLD] & ETF_IDENTITY )
 
1207
                {
 
1208
                        LightSpace.normal.set ( base->Normal.X, base->Normal.Y, base->Normal.Z, 1.f );
 
1209
                        LightSpace.vertex.set ( base->Pos.X, base->Pos.Y, base->Pos.Z, 1.f );
 
1210
                }
 
1211
                else
 
1212
                {
 
1213
                        Transformation[ETS_WORLD].rotateVect ( &LightSpace.normal.x, base->Normal );
 
1214
 
 
1215
                        // vertex in light space
 
1216
                        if ( LightSpace.Flags & ( POINTLIGHT | FOG | SPECULAR | VERTEXTRANSFORM) )
 
1217
                                Transformation[ETS_WORLD].transformVect ( &LightSpace.vertex.x, base->Pos );
 
1218
                }
 
1219
 
 
1220
                if ( LightSpace.Flags & NORMALIZE )
 
1221
                        LightSpace.normal.normalize_xyz();
 
1222
 
 
1223
        }
 
1224
 
 
1225
#endif
 
1226
 
 
1227
#if defined ( SOFTWARE_DRIVER_2_USE_VERTEX_COLOR )
 
1228
        // apply lighting model
 
1229
        #if defined (SOFTWARE_DRIVER_2_LIGHTING)
 
1230
                if ( Material.org.Lighting )
 
1231
                {
 
1232
                        lightVertex ( dest, base->Color.color );
 
1233
                }
 
1234
                else
 
1235
                {
 
1236
                        dest->Color[0].setA8R8G8B8 ( base->Color.color );
 
1237
                }
 
1238
        #else
 
1239
                dest->Color[0].setA8R8G8B8 ( base->Color.color );
 
1240
        #endif
 
1241
#endif
 
1242
 
 
1243
        // Texture Transform
 
1244
#if !defined ( SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM )
 
1245
        irr::memcpy32_small ( &dest->Tex[0],&base->TCoords,
 
1246
                                        vSize[VertexCache.vType].TexSize << 3 //  * ( sizeof ( f32 ) * 2 )
 
1247
                                );
 
1248
#else
 
1249
 
 
1250
        if ( 0 == (LightSpace.Flags & VERTEXTRANSFORM) )
 
1251
        {
 
1252
                irr::memcpy32_small ( &dest->Tex[0],&base->TCoords,
 
1253
                                                vSize[VertexCache.vType].TexSize << 3 //  * ( sizeof ( f32 ) * 2 )
 
1254
                                        );
 
1255
        }
 
1256
        else
 
1257
        {
 
1258
        /*
 
1259
                        Generate texture coordinates as linear functions so that:
 
1260
                                u = Ux*x + Uy*y + Uz*z + Uw
 
1261
                                v = Vx*x + Vy*y + Vz*z + Vw
 
1262
                        The matrix M for this case is:
 
1263
                                Ux  Vx  0  0
 
1264
                                Uy  Vy  0  0
 
1265
                                Uz  Vz  0  0
 
1266
                                Uw  Vw  0  0
 
1267
        */
 
1268
 
 
1269
                u32 t;
 
1270
                sVec4 n;
 
1271
                sVec2 srcT;
 
1272
 
 
1273
                for ( t = 0; t != vSize[VertexCache.vType].TexSize; ++t )
 
1274
                {
 
1275
                        const core::matrix4& M = Transformation [ ETS_TEXTURE_0 + t ];
 
1276
 
 
1277
                        // texgen
 
1278
                        if ( TransformationFlag [ ETS_TEXTURE_0 + t ] & (ETF_TEXGEN_CAMERA_NORMAL|ETF_TEXGEN_CAMERA_REFLECTION) )
 
1279
                        {
 
1280
                                n.x = LightSpace.campos.x - LightSpace.vertex.x;
 
1281
                                n.y = LightSpace.campos.x - LightSpace.vertex.y;
 
1282
                                n.z = LightSpace.campos.x - LightSpace.vertex.z;
 
1283
                                n.normalize_xyz();
 
1284
                                n.x += LightSpace.normal.x;
 
1285
                                n.y += LightSpace.normal.y;
 
1286
                                n.z += LightSpace.normal.z;
 
1287
                                n.normalize_xyz();
 
1288
 
 
1289
                                const f32 *view = Transformation[ETS_VIEW].pointer();
 
1290
 
 
1291
                                if ( TransformationFlag [ ETS_TEXTURE_0 + t ] & ETF_TEXGEN_CAMERA_REFLECTION )
 
1292
                                {
 
1293
                                        srcT.x = 0.5f * ( 1.f + (n.x * view[0] + n.y * view[4] + n.z * view[8] ));
 
1294
                                        srcT.y = 0.5f * ( 1.f + (n.x * view[1] + n.y * view[5] + n.z * view[9] ));
 
1295
                                }
 
1296
                                else
 
1297
                                {
 
1298
                                        srcT.x = 0.5f * ( 1.f + (n.x * view[0] + n.y * view[1] + n.z * view[2] ));
 
1299
                                        srcT.y = 0.5f * ( 1.f + (n.x * view[4] + n.y * view[5] + n.z * view[6] ));
 
1300
                                }
 
1301
                        }
 
1302
                        else
 
1303
                        {
 
1304
                                irr::memcpy32_small ( &srcT,(&base->TCoords) + t,
 
1305
                                        sizeof ( f32 ) * 2 );
 
1306
                        }
 
1307
 
 
1308
                        switch ( Material.org.TextureLayer[t].TextureWrapU )
 
1309
                        {
 
1310
                                case ETC_CLAMP:
 
1311
                                case ETC_CLAMP_TO_EDGE:
 
1312
                                case ETC_CLAMP_TO_BORDER:
 
1313
                                        dest->Tex[t].x = core::clamp ( (f32) ( M[0] * srcT.x + M[4] * srcT.y + M[8] ), 0.f, 1.f );
 
1314
                                        break;
 
1315
                                case ETC_MIRROR:
 
1316
                                        dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8];
 
1317
                                        if (core::fract(dest->Tex[t].x)>0.5f)
 
1318
                                                dest->Tex[t].x=1.f-dest->Tex[t].x;
 
1319
                                break;
 
1320
                                case ETC_MIRROR_CLAMP:
 
1321
                                case ETC_MIRROR_CLAMP_TO_EDGE:
 
1322
                                case ETC_MIRROR_CLAMP_TO_BORDER:
 
1323
                                        dest->Tex[t].x = core::clamp ( (f32) ( M[0] * srcT.x + M[4] * srcT.y + M[8] ), 0.f, 1.f );
 
1324
                                        if (core::fract(dest->Tex[t].x)>0.5f)
 
1325
                                                dest->Tex[t].x=1.f-dest->Tex[t].x;
 
1326
                                break;
 
1327
                                case ETC_REPEAT:
 
1328
                                default:
 
1329
                                        dest->Tex[t].x = M[0] * srcT.x + M[4] * srcT.y + M[8];
 
1330
                                        break;
 
1331
                        }
 
1332
                        switch ( Material.org.TextureLayer[t].TextureWrapV )
 
1333
                        {
 
1334
                                case ETC_CLAMP:
 
1335
                                case ETC_CLAMP_TO_EDGE:
 
1336
                                case ETC_CLAMP_TO_BORDER:
 
1337
                                        dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f );
 
1338
                                        break;
 
1339
                                case ETC_MIRROR:
 
1340
                                        dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9];
 
1341
                                        if (core::fract(dest->Tex[t].y)>0.5f)
 
1342
                                                dest->Tex[t].y=1.f-dest->Tex[t].y;
 
1343
                                break;
 
1344
                                case ETC_MIRROR_CLAMP:
 
1345
                                case ETC_MIRROR_CLAMP_TO_EDGE:
 
1346
                                case ETC_MIRROR_CLAMP_TO_BORDER:
 
1347
                                        dest->Tex[t].y = core::clamp ( (f32) ( M[1] * srcT.x + M[5] * srcT.y + M[9] ), 0.f, 1.f );
 
1348
                                        if (core::fract(dest->Tex[t].y)>0.5f)
 
1349
                                                dest->Tex[t].y=1.f-dest->Tex[t].y;
 
1350
                                break;
 
1351
                                case ETC_REPEAT:
 
1352
                                default:
 
1353
                                        dest->Tex[t].y = M[1] * srcT.x + M[5] * srcT.y + M[9];
 
1354
                                        break;
 
1355
                        }
 
1356
                }
 
1357
        }
 
1358
 
 
1359
#if 0
 
1360
        // tangent space light vector, emboss
 
1361
        if ( Lights.size () && ( vSize[VertexCache.vType].Format & VERTEX4D_FORMAT_BUMP_DOT3 ) )
 
1362
        {
 
1363
                const S3DVertexTangents *tangent = ((S3DVertexTangents*) source );
 
1364
                const SBurningShaderLight &light = LightSpace.Light[0];
 
1365
 
 
1366
                sVec4 vp;
 
1367
 
 
1368
                vp.x = light.pos.x - LightSpace.vertex.x;
 
1369
                vp.y = light.pos.y - LightSpace.vertex.y;
 
1370
                vp.z = light.pos.z - LightSpace.vertex.z;
 
1371
 
 
1372
                vp.normalize_xyz();
 
1373
 
 
1374
                LightSpace.tangent.x = vp.x * tangent->Tangent.X + vp.y * tangent->Tangent.Y + vp.z * tangent->Tangent.Z;
 
1375
                LightSpace.tangent.y = vp.x * tangent->Binormal.X + vp.y * tangent->Binormal.Y + vp.z * tangent->Binormal.Z;
 
1376
                //LightSpace.tangent.z = vp.x * tangent->Normal.X + vp.y * tangent->Normal.Y + vp.z * tangent->Normal.Z;
 
1377
                LightSpace.tangent.z = 0.f;
 
1378
                LightSpace.tangent.normalize_xyz();
 
1379
 
 
1380
                f32 scale = 1.f / 128.f;
 
1381
                if ( Material.org.MaterialTypeParam > 0.f )
 
1382
                        scale = Material.org.MaterialTypeParam;
 
1383
 
 
1384
                // emboss, shift coordinates
 
1385
                dest->Tex[1].x = dest->Tex[0].x + LightSpace.tangent.x * scale;
 
1386
                dest->Tex[1].y = dest->Tex[0].y + LightSpace.tangent.y * scale;
 
1387
                //dest->Tex[1].z = LightSpace.tangent.z * scale;
 
1388
        }
 
1389
#endif
 
1390
 
 
1391
        if ( LightSpace.Light.size () && ( vSize[VertexCache.vType].Format & VERTEX4D_FORMAT_BUMP_DOT3 ) )
 
1392
        {
 
1393
                const S3DVertexTangents *tangent = ((S3DVertexTangents*) source );
 
1394
 
 
1395
                sVec4 vp;
 
1396
 
 
1397
                dest->LightTangent[0].x = 0.f;
 
1398
                dest->LightTangent[0].y = 0.f;
 
1399
                dest->LightTangent[0].z = 0.f;
 
1400
                for ( u32 i = 0; i < 2 && i < LightSpace.Light.size (); ++i )
 
1401
                {
 
1402
                        const SBurningShaderLight &light = LightSpace.Light[i];
 
1403
 
 
1404
                        if ( !light.LightIsOn )
 
1405
                                continue;
 
1406
 
 
1407
                        vp.x = light.pos.x - LightSpace.vertex.x;
 
1408
                        vp.y = light.pos.y - LightSpace.vertex.y;
 
1409
                        vp.z = light.pos.z - LightSpace.vertex.z;
 
1410
 
 
1411
        /*
 
1412
                        vp.x = light.pos_objectspace.x - base->Pos.X;
 
1413
                        vp.y = light.pos_objectspace.y - base->Pos.Y;
 
1414
                        vp.z = light.pos_objectspace.z - base->Pos.Z;
 
1415
        */
 
1416
 
 
1417
                        vp.normalize_xyz();
 
1418
 
 
1419
 
 
1420
                        // transform by tangent matrix
 
1421
                        sVec3 l;
 
1422
        #if 1
 
1423
                        l.x = (vp.x * tangent->Tangent.X + vp.y * tangent->Tangent.Y + vp.z * tangent->Tangent.Z );
 
1424
                        l.y = (vp.x * tangent->Binormal.X + vp.y * tangent->Binormal.Y + vp.z * tangent->Binormal.Z );
 
1425
                        l.z = (vp.x * tangent->Normal.X + vp.y * tangent->Normal.Y + vp.z * tangent->Normal.Z );
 
1426
        #else
 
1427
                        l.x = (vp.x * tangent->Tangent.X + vp.y * tangent->Binormal.X + vp.z * tangent->Normal.X );
 
1428
                        l.y = (vp.x * tangent->Tangent.Y + vp.y * tangent->Binormal.Y + vp.z * tangent->Normal.Y );
 
1429
                        l.z = (vp.x * tangent->Tangent.Z + vp.y * tangent->Binormal.Z + vp.z * tangent->Normal.Z );
 
1430
        #endif
 
1431
 
 
1432
 
 
1433
        /*
 
1434
                        f32 scale = 1.f / 128.f;
 
1435
                        scale /= dest->LightTangent[0].b;
 
1436
 
 
1437
                        // emboss, shift coordinates
 
1438
                        dest->Tex[1].x = dest->Tex[0].x + l.r * scale;
 
1439
                        dest->Tex[1].y = dest->Tex[0].y + l.g * scale;
 
1440
        */
 
1441
                        dest->Tex[1].x = dest->Tex[0].x;
 
1442
                        dest->Tex[1].y = dest->Tex[0].y;
 
1443
 
 
1444
                        // scale bias
 
1445
                        dest->LightTangent[0].x += l.x;
 
1446
                        dest->LightTangent[0].y += l.y;
 
1447
                        dest->LightTangent[0].z += l.z;
 
1448
                }
 
1449
                dest->LightTangent[0].setLength ( 0.5f );
 
1450
                dest->LightTangent[0].x += 0.5f;
 
1451
                dest->LightTangent[0].y += 0.5f;
 
1452
                dest->LightTangent[0].z += 0.5f;
 
1453
        }
 
1454
 
 
1455
 
 
1456
#endif
 
1457
 
 
1458
clipandproject:
 
1459
        dest[0].flag = dest[1].flag = vSize[VertexCache.vType].Format;
 
1460
 
 
1461
        // test vertex
 
1462
        dest[0].flag |= clipToFrustumTest ( dest);
 
1463
 
 
1464
        // to DC Space, project homogenous vertex
 
1465
        if ( (dest[0].flag & VERTEX4D_CLIPMASK ) == VERTEX4D_INSIDE )
 
1466
        {
 
1467
                ndc_2_dc_and_project2 ( (const s4DVertex**) &dest, 1 );
 
1468
        }
 
1469
 
 
1470
        //return dest;
 
1471
}
 
1472
 
 
1473
//
 
1474
 
 
1475
REALINLINE s4DVertex * CBurningVideoDriver::VertexCache_getVertex ( const u32 sourceIndex )
 
1476
{
 
1477
        for ( s32 i = 0; i < VERTEXCACHE_ELEMENT; ++i )
 
1478
        {
 
1479
                if ( VertexCache.info[ i ].index == sourceIndex )
 
1480
                {
 
1481
                        return (s4DVertex *) ( (u8*) VertexCache.mem.data + ( i << ( SIZEOF_SVERTEX_LOG2 + 1  ) ) );
 
1482
                }
 
1483
        }
 
1484
        return 0;
 
1485
}
 
1486
 
 
1487
 
 
1488
/*
 
1489
        Cache based on linear walk indices
 
1490
        fill blockwise on the next 16(Cache_Size) unique vertices in indexlist
 
1491
        merge the next 16 vertices with the current
 
1492
*/
 
1493
REALINLINE void CBurningVideoDriver::VertexCache_get ( s4DVertex ** face )
 
1494
{
 
1495
        SCacheInfo info[VERTEXCACHE_ELEMENT];
 
1496
 
 
1497
        // next primitive must be complete in cache
 
1498
        if (    VertexCache.indicesIndex - VertexCache.indicesRun < 3 &&
 
1499
                        VertexCache.indicesIndex < VertexCache.indexCount
 
1500
                )
 
1501
        {
 
1502
                // rewind to start of primitive
 
1503
                VertexCache.indicesIndex = VertexCache.indicesRun;
 
1504
 
 
1505
                irr::memset32 ( info, VERTEXCACHE_MISS, sizeof ( info ) );
 
1506
 
 
1507
                // get the next unique vertices cache line
 
1508
                u32 fillIndex = 0;
 
1509
                u32 dIndex;
 
1510
                u32 i;
 
1511
                u32 sourceIndex;
 
1512
 
 
1513
                while ( VertexCache.indicesIndex < VertexCache.indexCount &&
 
1514
                                fillIndex < VERTEXCACHE_ELEMENT
 
1515
                                )
 
1516
                {
 
1517
                        switch ( VertexCache.iType )
 
1518
                        {
 
1519
                                case 1:
 
1520
                                        sourceIndex =  ((u16*)VertexCache.indices) [ VertexCache.indicesIndex ];
 
1521
                                        break;
 
1522
                                case 2:
 
1523
                                        sourceIndex =  ((u32*)VertexCache.indices) [ VertexCache.indicesIndex ];
 
1524
                                        break;
 
1525
                                case 4:
 
1526
                                        sourceIndex = VertexCache.indicesIndex;
 
1527
                                        break;
 
1528
                        }
 
1529
 
 
1530
                        VertexCache.indicesIndex += 1;
 
1531
 
 
1532
                        // if not exist, push back
 
1533
                        s32 exist = 0;
 
1534
                        for ( dIndex = 0;  dIndex < fillIndex; ++dIndex )
 
1535
                        {
 
1536
                                if ( info[ dIndex ].index == sourceIndex )
 
1537
                                {
 
1538
                                        exist = 1;
 
1539
                                        break;
 
1540
                                }
 
1541
                        }
 
1542
 
 
1543
                        if ( 0 == exist )
 
1544
                        {
 
1545
                                info[fillIndex++].index = sourceIndex;
 
1546
                        }
 
1547
                }
 
1548
 
 
1549
                // clear marks
 
1550
                for ( i = 0; i!= VERTEXCACHE_ELEMENT; ++i )
 
1551
                {
 
1552
                        VertexCache.info[i].hit = 0;
 
1553
                }
 
1554
 
 
1555
                // mark all existing
 
1556
                for ( i = 0; i!= fillIndex; ++i )
 
1557
                {
 
1558
                        for ( dIndex = 0;  dIndex < VERTEXCACHE_ELEMENT; ++dIndex )
 
1559
                        {
 
1560
                                if ( VertexCache.info[ dIndex ].index == info[i].index )
 
1561
                                {
 
1562
                                        info[i].hit = dIndex;
 
1563
                                        VertexCache.info[ dIndex ].hit = 1;
 
1564
                                        break;
 
1565
                                }
 
1566
                        }
 
1567
                }
 
1568
 
 
1569
                // fill new
 
1570
                for ( i = 0; i!= fillIndex; ++i )
 
1571
                {
 
1572
                        if ( info[i].hit != VERTEXCACHE_MISS )
 
1573
                                continue;
 
1574
 
 
1575
                        for ( dIndex = 0;  dIndex < VERTEXCACHE_ELEMENT; ++dIndex )
 
1576
                        {
 
1577
                                if ( 0 == VertexCache.info[dIndex].hit )
 
1578
                                {
 
1579
                                        VertexCache_fill ( info[i].index, dIndex );
 
1580
                                        VertexCache.info[dIndex].hit += 1;
 
1581
                                        info[i].hit = dIndex;
 
1582
                                        break;
 
1583
                                }
 
1584
                        }
 
1585
                }
 
1586
        }
 
1587
 
 
1588
        const u32 i0 = core::if_c_a_else_0 ( VertexCache.pType != scene::EPT_TRIANGLE_FAN, VertexCache.indicesRun );
 
1589
 
 
1590
        switch ( VertexCache.iType )
 
1591
        {
 
1592
                case 1:
 
1593
                {
 
1594
                        const u16 *p = (const u16 *) VertexCache.indices;
 
1595
                        face[0] = VertexCache_getVertex ( p[ i0    ] );
 
1596
                        face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] );
 
1597
                        face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] );
 
1598
                } break;
 
1599
 
 
1600
                case 2:
 
1601
                {
 
1602
                        const u32 *p = (const u32 *) VertexCache.indices;
 
1603
                        face[0] = VertexCache_getVertex ( p[ i0    ] );
 
1604
                        face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] );
 
1605
                        face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] );
 
1606
                } break;
 
1607
                case 4:
 
1608
                        face[0] = VertexCache_getVertex ( VertexCache.indicesRun + 0 );
 
1609
                        face[1] = VertexCache_getVertex ( VertexCache.indicesRun + 1 );
 
1610
                        face[2] = VertexCache_getVertex ( VertexCache.indicesRun + 2 );
 
1611
                        break;
 
1612
        }
 
1613
 
 
1614
        VertexCache.indicesRun += VertexCache.primitivePitch;
 
1615
}
 
1616
 
 
1617
/*!
 
1618
*/
 
1619
REALINLINE void CBurningVideoDriver::VertexCache_getbypass ( s4DVertex ** face )
 
1620
{
 
1621
        const u32 i0 = core::if_c_a_else_0 ( VertexCache.pType != scene::EPT_TRIANGLE_FAN, VertexCache.indicesRun );
 
1622
 
 
1623
        if ( VertexCache.iType == 1 )
 
1624
        {
 
1625
                const u16 *p = (const u16 *) VertexCache.indices;
 
1626
                VertexCache_fill ( p[ i0    ], 0 );
 
1627
                VertexCache_fill ( p[ VertexCache.indicesRun + 1], 1 );
 
1628
                VertexCache_fill ( p[ VertexCache.indicesRun + 2], 2 );
 
1629
        }
 
1630
        else
 
1631
        {
 
1632
                const u32 *p = (const u32 *) VertexCache.indices;
 
1633
                VertexCache_fill ( p[ i0    ], 0 );
 
1634
                VertexCache_fill ( p[ VertexCache.indicesRun + 1], 1 );
 
1635
                VertexCache_fill ( p[ VertexCache.indicesRun + 2], 2 );
 
1636
        }
 
1637
 
 
1638
        VertexCache.indicesRun += VertexCache.primitivePitch;
 
1639
 
 
1640
        face[0] = (s4DVertex *) ( (u8*) VertexCache.mem.data + ( 0 << ( SIZEOF_SVERTEX_LOG2 + 1  ) ) );
 
1641
        face[1] = (s4DVertex *) ( (u8*) VertexCache.mem.data + ( 1 << ( SIZEOF_SVERTEX_LOG2 + 1  ) ) );
 
1642
        face[2] = (s4DVertex *) ( (u8*) VertexCache.mem.data + ( 2 << ( SIZEOF_SVERTEX_LOG2 + 1  ) ) );
 
1643
 
 
1644
}
 
1645
 
 
1646
/*!
 
1647
*/
 
1648
void CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCount,
 
1649
                                                                                        const void* indices, u32 primitiveCount,
 
1650
                                                                                        E_VERTEX_TYPE vType,
 
1651
                                                                                        scene::E_PRIMITIVE_TYPE pType,
 
1652
                                                                                        E_INDEX_TYPE iType)
 
1653
{
 
1654
        VertexCache.vertices = vertices;
 
1655
        VertexCache.vertexCount = vertexCount;
 
1656
 
 
1657
        VertexCache.indices = indices;
 
1658
        VertexCache.indicesIndex = 0;
 
1659
        VertexCache.indicesRun = 0;
 
1660
 
 
1661
        if ( Material.org.MaterialType == video::EMT_REFLECTION_2_LAYER )
 
1662
                VertexCache.vType = 3;
 
1663
        else
 
1664
                VertexCache.vType = vType;
 
1665
        VertexCache.pType = pType;
 
1666
 
 
1667
        switch ( iType )
 
1668
        {
 
1669
                case EIT_16BIT: VertexCache.iType = 1; break;
 
1670
                case EIT_32BIT: VertexCache.iType = 2; break;
 
1671
                default:
 
1672
                        VertexCache.iType = iType; break;
 
1673
        }
 
1674
 
 
1675
        switch ( VertexCache.pType )
 
1676
        {
 
1677
                // most types here will not work as expected, only triangles/triangle_fan
 
1678
                // is known to work.
 
1679
                case scene::EPT_POINTS:
 
1680
                        VertexCache.indexCount = primitiveCount;
 
1681
                        VertexCache.primitivePitch = 1;
 
1682
                        break;
 
1683
                case scene::EPT_LINE_STRIP:
 
1684
                        VertexCache.indexCount = primitiveCount+1;
 
1685
                        VertexCache.primitivePitch = 1;
 
1686
                        break;
 
1687
                case scene::EPT_LINE_LOOP:
 
1688
                        VertexCache.indexCount = primitiveCount+1;
 
1689
                        VertexCache.primitivePitch = 1;
 
1690
                        break;
 
1691
                case scene::EPT_LINES:
 
1692
                        VertexCache.indexCount = 2*primitiveCount;
 
1693
                        VertexCache.primitivePitch = 2;
 
1694
                        break;
 
1695
                case scene::EPT_TRIANGLE_STRIP:
 
1696
                        VertexCache.indexCount = primitiveCount+2;
 
1697
                        VertexCache.primitivePitch = 1;
 
1698
                        break;
 
1699
                case scene::EPT_TRIANGLES:
 
1700
                        VertexCache.indexCount = primitiveCount + primitiveCount + primitiveCount;
 
1701
                        VertexCache.primitivePitch = 3;
 
1702
                        break;
 
1703
                case scene::EPT_TRIANGLE_FAN:
 
1704
                        VertexCache.indexCount = primitiveCount + 2;
 
1705
                        VertexCache.primitivePitch = 1;
 
1706
                        break;
 
1707
                case scene::EPT_QUAD_STRIP:
 
1708
                        VertexCache.indexCount = 2*primitiveCount + 2;
 
1709
                        VertexCache.primitivePitch = 2;
 
1710
                        break;
 
1711
                case scene::EPT_QUADS:
 
1712
                        VertexCache.indexCount = 4*primitiveCount;
 
1713
                        VertexCache.primitivePitch = 4;
 
1714
                        break;
 
1715
                case scene::EPT_POLYGON:
 
1716
                        VertexCache.indexCount = primitiveCount+1;
 
1717
                        VertexCache.primitivePitch = 1;
 
1718
                        break;
 
1719
                case scene::EPT_POINT_SPRITES:
 
1720
                        VertexCache.indexCount = primitiveCount;
 
1721
                        VertexCache.primitivePitch = 1;
 
1722
                        break;
 
1723
        }
 
1724
 
 
1725
        irr::memset32 ( VertexCache.info, VERTEXCACHE_MISS, sizeof ( VertexCache.info ) );
 
1726
}
 
1727
 
 
1728
 
 
1729
void CBurningVideoDriver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount,
 
1730
                                const void* indexList, u32 primitiveCount,
 
1731
                                E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType)
 
1732
 
 
1733
{
 
1734
        if (!checkPrimitiveCount(primitiveCount))
 
1735
                return;
 
1736
 
 
1737
        CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType);
 
1738
 
 
1739
        if ( 0 == CurrentShader )
 
1740
                return;
 
1741
 
 
1742
        VertexCache_reset ( vertices, vertexCount, indexList, primitiveCount, vType, pType, iType );
 
1743
 
 
1744
        const s4DVertex * face[3];
 
1745
 
 
1746
        f32 dc_area;
 
1747
        s32 lodLevel;
 
1748
        u32 i;
 
1749
        u32 g;
 
1750
        u32 m;
 
1751
        video::CSoftwareTexture2* tex;
 
1752
 
 
1753
        for ( i = 0; i < (u32) primitiveCount; ++i )
 
1754
        {
 
1755
                VertexCache_get ( (s4DVertex**) face );
 
1756
 
 
1757
                // if fully outside or outside on same side
 
1758
                if ( ( (face[0]->flag | face[1]->flag | face[2]->flag) & VERTEX4D_CLIPMASK )
 
1759
                                != VERTEX4D_INSIDE
 
1760
                        )
 
1761
                        continue;
 
1762
 
 
1763
                // if fully inside
 
1764
                if ( ( face[0]->flag & face[1]->flag & face[2]->flag & VERTEX4D_CLIPMASK ) == VERTEX4D_INSIDE )
 
1765
                {
 
1766
                        dc_area = screenarea2 ( face );
 
1767
                        if ( Material.org.BackfaceCulling && F32_LOWER_EQUAL_0( dc_area ) )
 
1768
                                continue;
 
1769
                        else
 
1770
                        if ( Material.org.FrontfaceCulling && F32_GREATER_EQUAL_0( dc_area ) )
 
1771
                                continue;
 
1772
 
 
1773
                        // select mipmap
 
1774
                        dc_area = core::reciprocal ( dc_area );
 
1775
                        for ( m = 0; m != vSize[VertexCache.vType].TexSize; ++m )
 
1776
                        {
 
1777
                                if ( 0 == (tex = MAT_TEXTURE ( m )) )
 
1778
                                {
 
1779
                                        CurrentShader->setTextureParam(m, 0, 0);
 
1780
                                        continue;
 
1781
                                }
 
1782
 
 
1783
                                lodLevel = s32_log2_f32 ( texelarea2 ( face, m ) * dc_area  );
 
1784
                                CurrentShader->setTextureParam(m, tex, lodLevel );
 
1785
                                select_polygon_mipmap2 ( (s4DVertex**) face, m, tex->getSize() );
 
1786
                        }
 
1787
 
 
1788
                        // rasterize
 
1789
                        CurrentShader->drawTriangle ( face[0] + 1, face[1] + 1, face[2] + 1 );
 
1790
                        continue;
 
1791
                }
 
1792
 
 
1793
                // else if not complete inside clipping necessary
 
1794
                irr::memcpy32_small ( ( (u8*) CurrentOut.data + ( 0 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ), face[0], SIZEOF_SVERTEX * 2 );
 
1795
                irr::memcpy32_small ( ( (u8*) CurrentOut.data + ( 1 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ), face[1], SIZEOF_SVERTEX * 2 );
 
1796
                irr::memcpy32_small ( ( (u8*) CurrentOut.data + ( 2 << ( SIZEOF_SVERTEX_LOG2 + 1 ) ) ), face[2], SIZEOF_SVERTEX * 2 );
 
1797
 
 
1798
                const u32 flag = CurrentOut.data->flag & VERTEX4D_FORMAT_MASK;
 
1799
 
 
1800
                for ( g = 0; g != CurrentOut.ElementSize; ++g )
 
1801
                {
 
1802
                        CurrentOut.data[g].flag = flag;
 
1803
                        Temp.data[g].flag = flag;
 
1804
                }
 
1805
 
 
1806
                u32 vOut;
 
1807
                vOut = clipToFrustum ( CurrentOut.data, Temp.data, 3 );
 
1808
/*
 
1809
                if ( vOut < 3 )
 
1810
                {
 
1811
                        char buf[256];
 
1812
                        struct SCheck
 
1813
                        {
 
1814
                                u32 flag;
 
1815
                                const char * name;
 
1816
                        };
 
1817
 
 
1818
                        SCheck check[5];
 
1819
                        check[0].flag = face[0]->flag;
 
1820
                        check[0].name = "face0";
 
1821
                        check[1].flag = face[1]->flag;
 
1822
                        check[1].name = "face1";
 
1823
                        check[2].flag = face[2]->flag;
 
1824
                        check[2].name = "face2";
 
1825
                        check[3].flag = (face[0]->flag & face[1]->flag & face[2]->flag);
 
1826
                        check[3].name = "AND  ";
 
1827
                        check[4].flag = (face[0]->flag | face[1]->flag | face[2]->flag);
 
1828
                        check[4].name = "OR   ";
 
1829
 
 
1830
                        for ( s32 h = 0; h!= 5; ++h )
 
1831
                        {
 
1832
                                sprintf ( buf, "%s: %d %d %d %d %d %d",
 
1833
                                                                check[h].name,
 
1834
                                                                ( check[h].flag & 1 ),
 
1835
                                                                ( check[h].flag & 2 ) >> 1,
 
1836
                                                                ( check[h].flag & 4 ) >> 2,
 
1837
                                                                ( check[h].flag & 8 ) >> 3,
 
1838
                                                                ( check[h].flag & 16 ) >> 4,
 
1839
                                                                ( check[h].flag & 32 ) >> 5
 
1840
                                                        );
 
1841
                                os::Printer::log( buf );
 
1842
                        }
 
1843
 
 
1844
                        sprintf ( buf, "Vout: %d\n", vOut );
 
1845
                        os::Printer::log( buf );
 
1846
 
 
1847
                        int hold = 1;
 
1848
                }
 
1849
*/
 
1850
                if ( vOut < 3 )
 
1851
                        continue;
 
1852
 
 
1853
                vOut <<= 1;
 
1854
 
 
1855
                // to DC Space, project homogenous vertex
 
1856
                ndc_2_dc_and_project ( CurrentOut.data + 1, CurrentOut.data, vOut );
 
1857
 
 
1858
/*
 
1859
                // TODO: don't stick on 32 Bit Pointer
 
1860
                #define PointerAsValue(x) ( (u32) (u32*) (x) )
 
1861
 
 
1862
                // if not complete inside clipping necessary
 
1863
                if ( ( test & VERTEX4D_INSIDE ) != VERTEX4D_INSIDE )
 
1864
                {
 
1865
                        u32 v[2] = { PointerAsValue ( Temp ) , PointerAsValue ( CurrentOut ) };
 
1866
                        for ( g = 0; g != 6; ++g )
 
1867
                        {
 
1868
                                vOut = clipToHyperPlane ( (s4DVertex*) v[0], (s4DVertex*) v[1], vOut, NDCPlane[g] );
 
1869
                                if ( vOut < 3 )
 
1870
                                        break;
 
1871
 
 
1872
                                v[0] ^= v[1];
 
1873
                                v[1] ^= v[0];
 
1874
                                v[0] ^= v[1];
 
1875
                        }
 
1876
 
 
1877
                        if ( vOut < 3 )
 
1878
                                continue;
 
1879
 
 
1880
                }
 
1881
*/
 
1882
 
 
1883
                // check 2d backface culling on first
 
1884
                dc_area = screenarea ( CurrentOut.data );
 
1885
                if ( Material.org.BackfaceCulling && F32_LOWER_EQUAL_0 ( dc_area ) )
 
1886
                        continue;
 
1887
                else
 
1888
                if ( Material.org.FrontfaceCulling && F32_GREATER_EQUAL_0( dc_area ) )
 
1889
                        continue;
 
1890
 
 
1891
                // select mipmap
 
1892
                dc_area = core::reciprocal ( dc_area );
 
1893
                for ( m = 0; m != vSize[VertexCache.vType].TexSize; ++m )
 
1894
                {
 
1895
                        if ( 0 == (tex = MAT_TEXTURE ( m )) )
 
1896
                        {
 
1897
                                CurrentShader->setTextureParam(m, 0, 0);
 
1898
                                continue;
 
1899
                        }
 
1900
 
 
1901
                        lodLevel = s32_log2_f32 ( texelarea ( CurrentOut.data, m ) * dc_area );
 
1902
                        CurrentShader->setTextureParam(m, tex, lodLevel );
 
1903
                        select_polygon_mipmap ( CurrentOut.data, vOut, m, tex->getSize() );
 
1904
                }
 
1905
 
 
1906
 
 
1907
                // re-tesselate ( triangle-fan, 0-1-2,0-2-3.. )
 
1908
                for ( g = 0; g <= vOut - 6; g += 2 )
 
1909
                {
 
1910
                        // rasterize
 
1911
                        CurrentShader->drawTriangle ( CurrentOut.data + 0 + 1,
 
1912
                                                        CurrentOut.data + g + 3,
 
1913
                                                        CurrentOut.data + g + 5);
 
1914
                }
 
1915
 
 
1916
        }
 
1917
 
 
1918
        // dump statistics
 
1919
/*
 
1920
        char buf [64];
 
1921
        sprintf ( buf,"VCount:%d PCount:%d CacheMiss: %d",
 
1922
                                        vertexCount, primitiveCount,
 
1923
                                        VertexCache.CacheMiss
 
1924
                                );
 
1925
        os::Printer::log( buf );
 
1926
*/
 
1927
 
 
1928
}
 
1929
 
 
1930
 
 
1931
//! Sets the dynamic ambient light color. The default color is
 
1932
//! (0,0,0,0) which means it is dark.
 
1933
//! \param color: New color of the ambient light.
 
1934
void CBurningVideoDriver::setAmbientLight(const SColorf& color)
 
1935
{
 
1936
        LightSpace.Global_AmbientLight.setColorf ( color );
 
1937
}
 
1938
 
 
1939
 
 
1940
//! adds a dynamic light
 
1941
s32 CBurningVideoDriver::addDynamicLight(const SLight& dl)
 
1942
{
 
1943
        (void) CNullDriver::addDynamicLight( dl );
 
1944
 
 
1945
        SBurningShaderLight l;
 
1946
//      l.org = dl;
 
1947
        l.Type = dl.Type;
 
1948
        l.LightIsOn = true;
 
1949
 
 
1950
        l.AmbientColor.setColorf ( dl.AmbientColor );
 
1951
        l.DiffuseColor.setColorf ( dl.DiffuseColor );
 
1952
        l.SpecularColor.setColorf ( dl.SpecularColor );
 
1953
 
 
1954
        switch ( dl.Type )
 
1955
        {
 
1956
                case video::ELT_DIRECTIONAL:
 
1957
                        l.pos.x = -dl.Direction.X;
 
1958
                        l.pos.y = -dl.Direction.Y;
 
1959
                        l.pos.z = -dl.Direction.Z;
 
1960
                        l.pos.w = 1.f;
 
1961
                        break;
 
1962
                case ELT_POINT:
 
1963
                case ELT_SPOT:
 
1964
                        LightSpace.Flags |= POINTLIGHT;
 
1965
                        l.pos.x = dl.Position.X;
 
1966
                        l.pos.y = dl.Position.Y;
 
1967
                        l.pos.z = dl.Position.Z;
 
1968
                        l.pos.w = 1.f;
 
1969
/*
 
1970
                        l.radius = (1.f / dl.Attenuation.Y) * (1.f / dl.Attenuation.Y);
 
1971
                        l.constantAttenuation = dl.Attenuation.X;
 
1972
                        l.linearAttenuation = dl.Attenuation.Y;
 
1973
                        l.quadraticAttenuation = dl.Attenuation.Z;
 
1974
*/
 
1975
                        l.radius = dl.Radius * dl.Radius;
 
1976
                        l.constantAttenuation = dl.Attenuation.X;
 
1977
                        l.linearAttenuation = 1.f / dl.Radius;
 
1978
                        l.quadraticAttenuation = dl.Attenuation.Z;
 
1979
 
 
1980
                        break;
 
1981
        }
 
1982
 
 
1983
        LightSpace.Light.push_back ( l );
 
1984
        return LightSpace.Light.size() - 1;
 
1985
}
 
1986
 
 
1987
//! Turns a dynamic light on or off
 
1988
void CBurningVideoDriver::turnLightOn(s32 lightIndex, bool turnOn)
 
1989
{
 
1990
        if(lightIndex > -1 && lightIndex < (s32)LightSpace.Light.size())
 
1991
        {
 
1992
                LightSpace.Light[lightIndex].LightIsOn = turnOn;
 
1993
        }
 
1994
}
 
1995
 
 
1996
//! deletes all dynamic lights there are
 
1997
void CBurningVideoDriver::deleteAllDynamicLights()
 
1998
{
 
1999
        LightSpace.reset ();
 
2000
        CNullDriver::deleteAllDynamicLights();
 
2001
 
 
2002
}
 
2003
 
 
2004
//! returns the maximal amount of dynamic lights the device can handle
 
2005
u32 CBurningVideoDriver::getMaximalDynamicLightAmount() const
 
2006
{
 
2007
        return 8;
 
2008
}
 
2009
 
 
2010
 
 
2011
//! sets a material
 
2012
void CBurningVideoDriver::setMaterial(const SMaterial& material)
 
2013
{
 
2014
        Material.org = material;
 
2015
 
 
2016
#ifdef SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM
 
2017
        for (u32 i = 0; i < 2; ++i)
 
2018
        {
 
2019
                setTransform((E_TRANSFORMATION_STATE) (ETS_TEXTURE_0 + i),
 
2020
                                material.getTextureMatrix(i));
 
2021
        }
 
2022
#endif
 
2023
 
 
2024
#ifdef SOFTWARE_DRIVER_2_LIGHTING
 
2025
        Material.AmbientColor.setR8G8B8 ( Material.org.AmbientColor.color );
 
2026
        Material.DiffuseColor.setR8G8B8 ( Material.org.DiffuseColor.color );
 
2027
        Material.EmissiveColor.setR8G8B8 ( Material.org.EmissiveColor.color );
 
2028
        Material.SpecularColor.setR8G8B8 ( Material.org.SpecularColor.color );
 
2029
 
 
2030
        core::setbit_cond ( LightSpace.Flags, Material.org.Shininess != 0.f, SPECULAR );
 
2031
        core::setbit_cond ( LightSpace.Flags, Material.org.FogEnable, FOG );
 
2032
        core::setbit_cond ( LightSpace.Flags, Material.org.NormalizeNormals, NORMALIZE );
 
2033
#endif
 
2034
 
 
2035
        setCurrentShader();
 
2036
}
 
2037
 
 
2038
 
 
2039
/*!
 
2040
        Camera Position in World Space
 
2041
*/
 
2042
void CBurningVideoDriver::getCameraPosWorldSpace ()
 
2043
{
 
2044
        Transformation[ETS_VIEW_INVERSE] = Transformation[ ETS_VIEW ];
 
2045
        Transformation[ETS_VIEW_INVERSE].makeInverse ();
 
2046
        TransformationFlag[ETS_VIEW_INVERSE] = 0;
 
2047
 
 
2048
        const f32 *M = Transformation[ETS_VIEW_INVERSE].pointer ();
 
2049
 
 
2050
        /*      The  viewpoint is at (0., 0., 0.) in eye space.
 
2051
                Turning this into a vector [0 0 0 1] and multiply it by
 
2052
                the inverse of the view matrix, the resulting vector is the
 
2053
                object space location of the camera.
 
2054
        */
 
2055
 
 
2056
        LightSpace.campos.x = M[12];
 
2057
        LightSpace.campos.y = M[13];
 
2058
        LightSpace.campos.z = M[14];
 
2059
        LightSpace.campos.w = 1.f;
 
2060
}
 
2061
 
 
2062
void CBurningVideoDriver::getLightPosObjectSpace ()
 
2063
{
 
2064
        if ( TransformationFlag[ETS_WORLD] & ETF_IDENTITY )
 
2065
        {
 
2066
                Transformation[ETS_WORLD_INVERSE] = Transformation[ETS_WORLD];
 
2067
                TransformationFlag[ETS_WORLD_INVERSE] |= ETF_IDENTITY;
 
2068
        }
 
2069
        else
 
2070
        {
 
2071
                Transformation[ETS_WORLD].getInverse ( Transformation[ETS_WORLD_INVERSE] );
 
2072
                TransformationFlag[ETS_WORLD_INVERSE] &= ~ETF_IDENTITY;
 
2073
        }
 
2074
 
 
2075
        for ( u32 i = 0; i < 1 && i < LightSpace.Light.size(); ++i )
 
2076
        {
 
2077
                SBurningShaderLight &l = LightSpace.Light[i];
 
2078
 
 
2079
                Transformation[ETS_WORLD_INVERSE].transformVec3 ( &l.pos_objectspace.x, &l.pos.x );
 
2080
        }
 
2081
}
 
2082
 
 
2083
 
 
2084
#ifdef SOFTWARE_DRIVER_2_LIGHTING
 
2085
 
 
2086
//! Sets the fog mode.
 
2087
void CBurningVideoDriver::setFog(SColor color, E_FOG_TYPE fogType, f32 start,
 
2088
        f32 end, f32 density, bool pixelFog, bool rangeFog)
 
2089
{
 
2090
        CNullDriver::setFog(color, fogType, start, end, density, pixelFog, rangeFog);
 
2091
        LightSpace.FogColor.setA8R8G8B8 ( color.color );
 
2092
}
 
2093
 
 
2094
/*!
 
2095
        applies lighting model
 
2096
*/
 
2097
void CBurningVideoDriver::lightVertex ( s4DVertex *dest, u32 vertexargb )
 
2098
{
 
2099
        sVec3 dColor;
 
2100
 
 
2101
        dColor = LightSpace.Global_AmbientLight;
 
2102
        dColor.add ( Material.EmissiveColor );
 
2103
 
 
2104
        if ( Lights.size () == 0 )
 
2105
        {
 
2106
                dColor.saturate( dest->Color[0], vertexargb);
 
2107
                return;
 
2108
        }
 
2109
 
 
2110
        sVec3 ambient;
 
2111
        sVec3 diffuse;
 
2112
        sVec3 specular;
 
2113
 
 
2114
 
 
2115
        // the universe started in darkness..
 
2116
        ambient.set ( 0.f, 0.f, 0.f );
 
2117
        diffuse.set ( 0.f, 0.f, 0.f );
 
2118
        specular.set ( 0.f, 0.f, 0.f );
 
2119
 
 
2120
 
 
2121
        u32 i;
 
2122
        f32 dot;
 
2123
        f32 len;
 
2124
        f32 attenuation;
 
2125
        sVec4 vp;                       // unit vector vertex to light
 
2126
        sVec4 lightHalf;        // blinn-phong reflection
 
2127
 
 
2128
        for ( i = 0; i!= LightSpace.Light.size (); ++i )
 
2129
        {
 
2130
                const SBurningShaderLight &light = LightSpace.Light[i];
 
2131
 
 
2132
                if ( !light.LightIsOn )
 
2133
                        continue;
 
2134
 
 
2135
                // accumulate ambient
 
2136
                ambient.add ( light.AmbientColor );
 
2137
 
 
2138
                switch ( light.Type )
 
2139
                {
 
2140
                        case video::ELT_SPOT:
 
2141
                        case video::ELT_POINT:
 
2142
                                // surface to light
 
2143
                                vp.x = light.pos.x - LightSpace.vertex.x;
 
2144
                                vp.y = light.pos.y - LightSpace.vertex.y;
 
2145
                                vp.z = light.pos.z - LightSpace.vertex.z;
 
2146
                                //vp.x = light.pos_objectspace.x - LightSpace.vertex.x;
 
2147
                                //vp.y = light.pos_objectspace.y - LightSpace.vertex.x;
 
2148
                                //vp.z = light.pos_objectspace.z - LightSpace.vertex.x;
 
2149
 
 
2150
                                len = vp.get_length_xyz_square();
 
2151
                                if ( light.radius < len )
 
2152
                                        continue;
 
2153
 
 
2154
                                len = core::reciprocal_squareroot ( len );
 
2155
 
 
2156
                                // build diffuse reflection
 
2157
 
 
2158
                                //angle between normal and light vector
 
2159
                                vp.mul ( len );
 
2160
                                dot = LightSpace.normal.dot_xyz ( vp );
 
2161
                                if ( dot < 0.f )
 
2162
                                        continue;
 
2163
 
 
2164
                                attenuation = light.constantAttenuation + ( 1.f - ( len * light.linearAttenuation ) );
 
2165
 
 
2166
                                // diffuse component
 
2167
                                diffuse.mulAdd ( light.DiffuseColor, 3.f * dot * attenuation );
 
2168
 
 
2169
                                if ( !(LightSpace.Flags & SPECULAR) )
 
2170
                                        continue;
 
2171
 
 
2172
                                // build specular
 
2173
                                // surface to view
 
2174
                                lightHalf.x = LightSpace.campos.x - LightSpace.vertex.x;
 
2175
                                lightHalf.y = LightSpace.campos.y - LightSpace.vertex.y;
 
2176
                                lightHalf.z = LightSpace.campos.z - LightSpace.vertex.z;
 
2177
                                lightHalf.normalize_xyz();
 
2178
                                lightHalf += vp;
 
2179
                                lightHalf.normalize_xyz();
 
2180
 
 
2181
                                // specular
 
2182
                                dot = LightSpace.normal.dot_xyz ( lightHalf );
 
2183
                                if ( dot < 0.f )
 
2184
                                        continue;
 
2185
 
 
2186
                                //specular += light.SpecularColor * ( powf ( Material.org.Shininess ,dot ) * attenuation );
 
2187
                                specular.mulAdd ( light.SpecularColor, dot * attenuation );
 
2188
                                break;
 
2189
 
 
2190
                        case video::ELT_DIRECTIONAL:
 
2191
 
 
2192
                                //angle between normal and light vector
 
2193
                                dot = LightSpace.normal.dot_xyz ( light.pos );
 
2194
                                if ( dot < 0.f )
 
2195
                                        continue;
 
2196
 
 
2197
                                // diffuse component
 
2198
                                diffuse.mulAdd ( light.DiffuseColor, dot );
 
2199
                                break;
 
2200
                }
 
2201
 
 
2202
        }
 
2203
 
 
2204
        // sum up lights
 
2205
        dColor.mulAdd (ambient, Material.AmbientColor );
 
2206
        dColor.mulAdd (diffuse, Material.DiffuseColor);
 
2207
        dColor.mulAdd (specular, Material.SpecularColor);
 
2208
 
 
2209
        dColor.saturate ( dest->Color[0], vertexargb );
 
2210
}
 
2211
 
 
2212
#endif
 
2213
 
 
2214
 
 
2215
//! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted.
 
2216
void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
 
2217
                                         const core::rect<s32>& sourceRect,
 
2218
                                         const core::rect<s32>* clipRect, SColor color,
 
2219
                                         bool useAlphaChannelOfTexture)
 
2220
{
 
2221
        if (texture)
 
2222
        {
 
2223
                if (texture->getDriverType() != EDT_BURNINGSVIDEO)
 
2224
                {
 
2225
                        os::Printer::log("Fatal Error: Tried to copy from a surface not owned by this driver.", ELL_ERROR);
 
2226
                        return;
 
2227
                }
 
2228
 
 
2229
#if 0
 
2230
                // 2d methods don't use viewPort
 
2231
                core::position2di dest = destPos;
 
2232
                core::recti clip=ViewPort;
 
2233
                if (ViewPort.getSize().Width != ScreenSize.Width)
 
2234
                {
 
2235
                        dest.X=ViewPort.UpperLeftCorner.X+core::round32(destPos.X*ViewPort.getWidth()/(f32)ScreenSize.Width);
 
2236
                        dest.Y=ViewPort.UpperLeftCorner.Y+core::round32(destPos.Y*ViewPort.getHeight()/(f32)ScreenSize.Height);
 
2237
                        if (clipRect)
 
2238
                        {
 
2239
                                clip.constrainTo(*clipRect);
 
2240
                        }
 
2241
                        clipRect = &clip;
 
2242
                }
 
2243
#endif
 
2244
                if (useAlphaChannelOfTexture)
 
2245
                        ((CSoftwareTexture2*)texture)->getImage()->copyToWithAlpha(
 
2246
                        RenderTargetSurface, destPos, sourceRect, color, clipRect);
 
2247
                else
 
2248
                        ((CSoftwareTexture2*)texture)->getImage()->copyTo(
 
2249
                                RenderTargetSurface, destPos, sourceRect, clipRect);
 
2250
        }
 
2251
}
 
2252
 
 
2253
 
 
2254
//! Draws a part of the texture into the rectangle.
 
2255
void CBurningVideoDriver::draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
 
2256
                const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,
 
2257
                const video::SColor* const colors, bool useAlphaChannelOfTexture)
 
2258
{
 
2259
        if (texture)
 
2260
        {
 
2261
                if (texture->getDriverType() != EDT_BURNINGSVIDEO)
 
2262
                {
 
2263
                        os::Printer::log("Fatal Error: Tried to copy from a surface not owned by this driver.", ELL_ERROR);
 
2264
                        return;
 
2265
                }
 
2266
        
 
2267
        if (useAlphaChannelOfTexture)
 
2268
                StretchBlit(BLITTER_TEXTURE_ALPHA_BLEND, RenderTargetSurface, &destRect, &sourceRect,
 
2269
                            ((CSoftwareTexture2*)texture)->getImage(), (colors ? colors[0].color : 0));
 
2270
        else
 
2271
                StretchBlit(BLITTER_TEXTURE, RenderTargetSurface, &destRect, &sourceRect,
 
2272
                            ((CSoftwareTexture2*)texture)->getImage(), (colors ? colors[0].color : 0));
 
2273
        }
 
2274
}
 
2275
    
 
2276
//! Draws a 2d line.
 
2277
void CBurningVideoDriver::draw2DLine(const core::position2d<s32>& start,
 
2278
                                        const core::position2d<s32>& end,
 
2279
                                        SColor color)
 
2280
{
 
2281
        drawLine(BackBuffer, start, end, color );
 
2282
}
 
2283
 
 
2284
 
 
2285
//! Draws a pixel
 
2286
void CBurningVideoDriver::drawPixel(u32 x, u32 y, const SColor & color)
 
2287
{
 
2288
        BackBuffer->setPixel(x, y, color, true);
 
2289
}
 
2290
 
 
2291
 
 
2292
//! draw an 2d rectangle
 
2293
void CBurningVideoDriver::draw2DRectangle(SColor color, const core::rect<s32>& pos,
 
2294
                                                                         const core::rect<s32>* clip)
 
2295
{
 
2296
        if (clip)
 
2297
        {
 
2298
                core::rect<s32> p(pos);
 
2299
 
 
2300
                p.clipAgainst(*clip);
 
2301
 
 
2302
                if(!p.isValid())
 
2303
                        return;
 
2304
 
 
2305
                drawRectangle(BackBuffer, p, color);
 
2306
        }
 
2307
        else
 
2308
        {
 
2309
                if(!pos.isValid())
 
2310
                        return;
 
2311
 
 
2312
                drawRectangle(BackBuffer, pos, color);
 
2313
        }
 
2314
}
 
2315
 
 
2316
 
 
2317
//! Only used by the internal engine. Used to notify the driver that
 
2318
//! the window was resized.
 
2319
void CBurningVideoDriver::OnResize(const core::dimension2d<u32>& size)
 
2320
{
 
2321
        // make sure width and height are multiples of 2
 
2322
        core::dimension2d<u32> realSize(size);
 
2323
 
 
2324
        if (realSize.Width % 2)
 
2325
                realSize.Width += 1;
 
2326
 
 
2327
        if (realSize.Height % 2)
 
2328
                realSize.Height += 1;
 
2329
 
 
2330
        if (ScreenSize != realSize)
 
2331
        {
 
2332
                if (ViewPort.getWidth() == (s32)ScreenSize.Width &&
 
2333
                        ViewPort.getHeight() == (s32)ScreenSize.Height)
 
2334
                {
 
2335
                        ViewPort.UpperLeftCorner.X = 0;
 
2336
                        ViewPort.UpperLeftCorner.Y = 0;
 
2337
                        ViewPort.LowerRightCorner.X = realSize.Width;
 
2338
                        ViewPort.LowerRightCorner.X = realSize.Height;
 
2339
                }
 
2340
 
 
2341
                ScreenSize = realSize;
 
2342
 
 
2343
                bool resetRT = (RenderTargetSurface == BackBuffer);
 
2344
 
 
2345
                if (BackBuffer)
 
2346
                        BackBuffer->drop();
 
2347
                BackBuffer = new CImage(BURNINGSHADER_COLOR_FORMAT, realSize);
 
2348
 
 
2349
                if (resetRT)
 
2350
                        setRenderTarget(BackBuffer);
 
2351
        }
 
2352
}
 
2353
 
 
2354
 
 
2355
//! returns the current render target size
 
2356
const core::dimension2d<u32>& CBurningVideoDriver::getCurrentRenderTargetSize() const
 
2357
{
 
2358
        return RenderTargetSize;
 
2359
}
 
2360
 
 
2361
 
 
2362
//!Draws an 2d rectangle with a gradient.
 
2363
void CBurningVideoDriver::draw2DRectangle(const core::rect<s32>& position,
 
2364
        SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,
 
2365
        const core::rect<s32>* clip)
 
2366
{
 
2367
#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR
 
2368
 
 
2369
        core::rect<s32> pos = position;
 
2370
 
 
2371
        if (clip)
 
2372
                pos.clipAgainst(*clip);
 
2373
 
 
2374
        if (!pos.isValid())
 
2375
                return;
 
2376
 
 
2377
        const core::dimension2d<s32> renderTargetSize ( ViewPort.getSize() );
 
2378
 
 
2379
        const s32 xPlus = -(renderTargetSize.Width>>1);
 
2380
        const f32 xFact = 1.0f / (renderTargetSize.Width>>1);
 
2381
 
 
2382
        const s32 yPlus = renderTargetSize.Height-(renderTargetSize.Height>>1);
 
2383
        const f32 yFact = 1.0f / (renderTargetSize.Height>>1);
 
2384
 
 
2385
        // fill VertexCache direct
 
2386
        s4DVertex *v;
 
2387
 
 
2388
        VertexCache.vertexCount = 4;
 
2389
 
 
2390
        VertexCache.info[0].index = 0;
 
2391
        VertexCache.info[1].index = 1;
 
2392
        VertexCache.info[2].index = 2;
 
2393
        VertexCache.info[3].index = 3;
 
2394
 
 
2395
        v = &VertexCache.mem.data [ 0 ];
 
2396
 
 
2397
        v[0].Pos.set ( (f32)(pos.UpperLeftCorner.X+xPlus) * xFact, (f32)(yPlus-pos.UpperLeftCorner.Y) * yFact, 0.f, 1.f );
 
2398
        v[0].Color[0].setA8R8G8B8 ( colorLeftUp.color );
 
2399
 
 
2400
        v[2].Pos.set ( (f32)(pos.LowerRightCorner.X+xPlus) * xFact, (f32)(yPlus- pos.UpperLeftCorner.Y) * yFact, 0.f, 1.f );
 
2401
        v[2].Color[0].setA8R8G8B8 ( colorRightUp.color );
 
2402
 
 
2403
        v[4].Pos.set ( (f32)(pos.LowerRightCorner.X+xPlus) * xFact, (f32)(yPlus-pos.LowerRightCorner.Y) * yFact, 0.f ,1.f );
 
2404
        v[4].Color[0].setA8R8G8B8 ( colorRightDown.color );
 
2405
 
 
2406
        v[6].Pos.set ( (f32)(pos.UpperLeftCorner.X+xPlus) * xFact, (f32)(yPlus-pos.LowerRightCorner.Y) * yFact, 0.f, 1.f );
 
2407
        v[6].Color[0].setA8R8G8B8 ( colorLeftDown.color );
 
2408
 
 
2409
        s32 i;
 
2410
        u32 g;
 
2411
 
 
2412
        for ( i = 0; i!= 8; i += 2 )
 
2413
        {
 
2414
                v[i + 0].flag = clipToFrustumTest ( v + i );
 
2415
                v[i + 1].flag = 0;
 
2416
                if ( (v[i].flag & VERTEX4D_INSIDE ) == VERTEX4D_INSIDE )
 
2417
                {
 
2418
                        ndc_2_dc_and_project ( v + i + 1, v + i, 2 );
 
2419
                }
 
2420
        }
 
2421
 
 
2422
 
 
2423
        IBurningShader * render;
 
2424
 
 
2425
        render = BurningShader [ ETR_GOURAUD_ALPHA_NOZ ];
 
2426
        render->setRenderTarget(RenderTargetSurface, ViewPort);
 
2427
 
 
2428
        static const s16 indexList[6] = {0,1,2,0,2,3};
 
2429
 
 
2430
        s4DVertex * face[3];
 
2431
 
 
2432
        for ( i = 0; i!= 6; i += 3 )
 
2433
        {
 
2434
                face[0] = VertexCache_getVertex ( indexList [ i + 0 ] );
 
2435
                face[1] = VertexCache_getVertex ( indexList [ i + 1 ] );
 
2436
                face[2] = VertexCache_getVertex ( indexList [ i + 2 ] );
 
2437
 
 
2438
                // test clipping
 
2439
                u32 test = face[0]->flag & face[1]->flag & face[2]->flag & VERTEX4D_INSIDE;
 
2440
 
 
2441
                if ( test == VERTEX4D_INSIDE )
 
2442
                {
 
2443
                        render->drawTriangle ( face[0] + 1, face[1] + 1, face[2] + 1 );
 
2444
                        continue;
 
2445
                }
 
2446
                // Todo: all vertices are clipped in 2d..
 
2447
                // is this true ?
 
2448
                u32 vOut = 6;
 
2449
                memcpy ( CurrentOut.data + 0, face[0], sizeof ( s4DVertex ) * 2 );
 
2450
                memcpy ( CurrentOut.data + 2, face[1], sizeof ( s4DVertex ) * 2 );
 
2451
                memcpy ( CurrentOut.data + 4, face[2], sizeof ( s4DVertex ) * 2 );
 
2452
 
 
2453
                vOut = clipToFrustum ( CurrentOut.data, Temp.data, 3 );
 
2454
                if ( vOut < 3 )
 
2455
                        continue;
 
2456
 
 
2457
                vOut <<= 1;
 
2458
                // to DC Space, project homogenous vertex
 
2459
                ndc_2_dc_and_project ( CurrentOut.data + 1, CurrentOut.data, vOut );
 
2460
 
 
2461
                // re-tesselate ( triangle-fan, 0-1-2,0-2-3.. )
 
2462
                for ( g = 0; g <= vOut - 6; g += 2 )
 
2463
                {
 
2464
                        // rasterize
 
2465
                        render->drawTriangle ( CurrentOut.data + 1, &CurrentOut.data[g + 3], &CurrentOut.data[g + 5] );
 
2466
                }
 
2467
 
 
2468
        }
 
2469
#else
 
2470
        draw2DRectangle ( colorLeftUp, position, clip );
 
2471
#endif
 
2472
}
 
2473
 
 
2474
 
 
2475
//! Draws a 3d line.
 
2476
void CBurningVideoDriver::draw3DLine(const core::vector3df& start,
 
2477
        const core::vector3df& end, SColor color)
 
2478
{
 
2479
        Transformation [ ETS_CURRENT].transformVect ( &CurrentOut.data[0].Pos.x, start );
 
2480
        Transformation [ ETS_CURRENT].transformVect ( &CurrentOut.data[2].Pos.x, end );
 
2481
 
 
2482
        u32 g;
 
2483
        u32 vOut;
 
2484
 
 
2485
        // no clipping flags
 
2486
        for ( g = 0; g != CurrentOut.ElementSize; ++g )
 
2487
        {
 
2488
                CurrentOut.data[g].flag = 0;
 
2489
                Temp.data[g].flag = 0;
 
2490
        }
 
2491
 
 
2492
        // vertices count per line
 
2493
        vOut = clipToFrustum ( CurrentOut.data, Temp.data, 2 );
 
2494
        if ( vOut < 2 )
 
2495
                return;
 
2496
 
 
2497
        vOut <<= 1;
 
2498
 
 
2499
        IBurningShader * line;
 
2500
        line = BurningShader [ ETR_TEXTURE_GOURAUD_WIRE ];
 
2501
        line->setRenderTarget(RenderTargetSurface, ViewPort);
 
2502
 
 
2503
        // to DC Space, project homogenous vertex
 
2504
        ndc_2_dc_and_project ( CurrentOut.data + 1, CurrentOut.data, vOut );
 
2505
 
 
2506
        // unproject vertex color
 
2507
#ifdef SOFTWARE_DRIVER_2_USE_VERTEX_COLOR
 
2508
        for ( g = 0; g != vOut; g+= 2 )
 
2509
        {
 
2510
                CurrentOut.data[ g + 1].Color[0].setA8R8G8B8 ( color.color );
 
2511
        }
 
2512
#endif
 
2513
 
 
2514
 
 
2515
        for ( g = 0; g <= vOut - 4; g += 2 )
 
2516
        {
 
2517
                // rasterize
 
2518
                line->drawLine ( CurrentOut.data + 1, CurrentOut.data + g + 3 );
 
2519
        }
 
2520
}
 
2521
 
 
2522
 
 
2523
//! \return Returns the name of the video driver. Example: In case of the DirectX8
 
2524
//! driver, it would return "Direct3D8.1".
 
2525
const wchar_t* CBurningVideoDriver::getName() const
 
2526
{
 
2527
#ifdef BURNINGVIDEO_RENDERER_BEAUTIFUL
 
2528
        return L"Burning's Video 0.47 beautiful";
 
2529
#elif defined ( BURNINGVIDEO_RENDERER_ULTRA_FAST )
 
2530
        return L"Burning's Video 0.47 ultra fast";
 
2531
#elif defined ( BURNINGVIDEO_RENDERER_FAST )
 
2532
        return L"Burning's Video 0.47 fast";
 
2533
#else
 
2534
        return L"Burning's Video 0.47";
 
2535
#endif
 
2536
}
 
2537
 
 
2538
//! Returns the graphics card vendor name.
 
2539
core::stringc CBurningVideoDriver::getVendorInfo()
 
2540
{
 
2541
        return "Burning's Video: Ing. Thomas Alten (c) 2006-2011";
 
2542
}
 
2543
 
 
2544
 
 
2545
//! Returns type of video driver
 
2546
E_DRIVER_TYPE CBurningVideoDriver::getDriverType() const
 
2547
{
 
2548
        return EDT_BURNINGSVIDEO;
 
2549
}
 
2550
 
 
2551
 
 
2552
//! returns color format
 
2553
ECOLOR_FORMAT CBurningVideoDriver::getColorFormat() const
 
2554
{
 
2555
        return BURNINGSHADER_COLOR_FORMAT;
 
2556
}
 
2557
 
 
2558
 
 
2559
//! Returns the transformation set by setTransform
 
2560
const core::matrix4& CBurningVideoDriver::getTransform(E_TRANSFORMATION_STATE state) const
 
2561
{
 
2562
        return Transformation[state];
 
2563
}
 
2564
 
 
2565
 
 
2566
//! Creates a render target texture.
 
2567
ITexture* CBurningVideoDriver::addRenderTargetTexture(const core::dimension2d<u32>& size,
 
2568
                const io::path& name, const ECOLOR_FORMAT format)
 
2569
{
 
2570
        IImage* img = createImage(BURNINGSHADER_COLOR_FORMAT, size);
 
2571
        ITexture* tex = new CSoftwareTexture2(img, name, CSoftwareTexture2::IS_RENDERTARGET );
 
2572
        img->drop();
 
2573
        addTexture(tex);
 
2574
        tex->drop();
 
2575
        return tex;
 
2576
}
 
2577
 
 
2578
 
 
2579
//! Clears the DepthBuffer.
 
2580
void CBurningVideoDriver::clearZBuffer()
 
2581
{
 
2582
        if (DepthBuffer)
 
2583
                DepthBuffer->clear();
 
2584
}
 
2585
 
 
2586
 
 
2587
//! Returns an image created from the last rendered frame.
 
2588
IImage* CBurningVideoDriver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)
 
2589
{
 
2590
        if (target != video::ERT_FRAME_BUFFER)
 
2591
                return 0;
 
2592
 
 
2593
        if (BackBuffer)
 
2594
        {
 
2595
                IImage* tmp = createImage(BackBuffer->getColorFormat(), BackBuffer->getDimension());
 
2596
                BackBuffer->copyTo(tmp);
 
2597
                return tmp;
 
2598
        }
 
2599
        else
 
2600
                return 0;
 
2601
}
 
2602
 
 
2603
 
 
2604
//! returns a device dependent texture from a software surface (IImage)
 
2605
//! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES
 
2606
ITexture* CBurningVideoDriver::createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData)
 
2607
{
 
2608
        return new CSoftwareTexture2(
 
2609
                surface, name,
 
2610
                (getTextureCreationFlag(ETCF_CREATE_MIP_MAPS) ? CSoftwareTexture2::GEN_MIPMAP : 0 ) |
 
2611
                (getTextureCreationFlag(ETCF_ALLOW_NON_POWER_2) ? 0 : CSoftwareTexture2::NP2_SIZE ), mipmapData);
 
2612
 
 
2613
}
 
2614
 
 
2615
 
 
2616
//! Returns the maximum amount of primitives (mostly vertices) which
 
2617
//! the device is able to render with one drawIndexedTriangleList
 
2618
//! call.
 
2619
u32 CBurningVideoDriver::getMaximalPrimitiveCount() const
 
2620
{
 
2621
        return 0xFFFFFFFF;
 
2622
}
 
2623
 
 
2624
 
 
2625
//! Draws a shadow volume into the stencil buffer. To draw a stencil shadow, do
 
2626
//! this: First, draw all geometry. Then use this method, to draw the shadow
 
2627
//! volume. Next use IVideoDriver::drawStencilShadow() to visualize the shadow.
 
2628
void CBurningVideoDriver::drawStencilShadowVolume(const core::vector3df* triangles, s32 count, bool zfail)
 
2629
{
 
2630
        IBurningShader *shader = BurningShader [ ETR_STENCIL_SHADOW ];
 
2631
 
 
2632
        CurrentShader = shader;
 
2633
        shader->setRenderTarget(RenderTargetSurface, ViewPort);
 
2634
 
 
2635
        Material.org.MaterialType = video::EMT_SOLID;
 
2636
        Material.org.Lighting = false;
 
2637
        Material.org.ZWriteEnable = false;
 
2638
        Material.org.ZBuffer = ECFN_LESSEQUAL;
 
2639
        LightSpace.Flags &= ~VERTEXTRANSFORM;
 
2640
 
 
2641
        //glStencilMask(~0);
 
2642
        //glStencilFunc(GL_ALWAYS, 0, ~0);
 
2643
 
 
2644
        if (zfail)
 
2645
        {
 
2646
                Material.org.BackfaceCulling = true;
 
2647
                Material.org.FrontfaceCulling = false;
 
2648
                shader->setParam ( 0, 0 );
 
2649
                shader->setParam ( 1, 1 );
 
2650
                shader->setParam ( 2, 0 );
 
2651
                drawVertexPrimitiveList ( triangles, count, 0, count/3, (video::E_VERTEX_TYPE) 4, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) 4 );
 
2652
                //glStencilOp(GL_KEEP, incr, GL_KEEP);
 
2653
                //glDrawArrays(GL_TRIANGLES,0,count);
 
2654
 
 
2655
                Material.org.BackfaceCulling = false;
 
2656
                Material.org.FrontfaceCulling = true;
 
2657
                shader->setParam ( 0, 0 );
 
2658
                shader->setParam ( 1, 2 );
 
2659
                shader->setParam ( 2, 0 );
 
2660
                drawVertexPrimitiveList ( triangles, count, 0, count/3, (video::E_VERTEX_TYPE) 4, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) 4 );
 
2661
                //glStencilOp(GL_KEEP, decr, GL_KEEP);
 
2662
                //glDrawArrays(GL_TRIANGLES,0,count);
 
2663
        }
 
2664
        else // zpass
 
2665
        {
 
2666
                Material.org.BackfaceCulling = true;
 
2667
                Material.org.FrontfaceCulling = false;
 
2668
                shader->setParam ( 0, 0 );
 
2669
                shader->setParam ( 1, 0 );
 
2670
                shader->setParam ( 2, 1 );
 
2671
                //glStencilOp(GL_KEEP, GL_KEEP, incr);
 
2672
                //glDrawArrays(GL_TRIANGLES,0,count);
 
2673
 
 
2674
                Material.org.BackfaceCulling = false;
 
2675
                Material.org.FrontfaceCulling = true;
 
2676
                shader->setParam ( 0, 0 );
 
2677
                shader->setParam ( 1, 0 );
 
2678
                shader->setParam ( 2, 2 );
 
2679
                //glStencilOp(GL_KEEP, GL_KEEP, decr);
 
2680
                //glDrawArrays(GL_TRIANGLES,0,count);
 
2681
        }
 
2682
 
 
2683
 
 
2684
}
 
2685
 
 
2686
//! Fills the stencil shadow with color. After the shadow volume has been drawn
 
2687
//! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this
 
2688
//! to draw the color of the shadow.
 
2689
void CBurningVideoDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge,
 
2690
        video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge)
 
2691
{
 
2692
        if (!StencilBuffer)
 
2693
                return;
 
2694
        // draw a shadow rectangle covering the entire screen using stencil buffer
 
2695
        const u32 h = RenderTargetSurface->getDimension().Height;
 
2696
        const u32 w = RenderTargetSurface->getDimension().Width;
 
2697
        tVideoSample *dst;
 
2698
        u32 *stencil;
 
2699
        u32* const stencilBase=(u32*) StencilBuffer->lock();
 
2700
 
 
2701
        for ( u32 y = 0; y < h; ++y )
 
2702
        {
 
2703
                dst = (tVideoSample*)RenderTargetSurface->lock() + ( y * w );
 
2704
                stencil =  stencilBase + ( y * w );
 
2705
 
 
2706
                for ( u32 x = 0; x < w; ++x )
 
2707
                {
 
2708
                        if ( stencil[x] > 1 )
 
2709
                        {
 
2710
                                dst[x] = PixelBlend32 ( dst[x], leftUpEdge.color );
 
2711
                        }
 
2712
                }
 
2713
        }
 
2714
 
 
2715
        StencilBuffer->clear();
 
2716
}
 
2717
 
 
2718
 
 
2719
core::dimension2du CBurningVideoDriver::getMaxTextureSize() const
 
2720
{
 
2721
        return core::dimension2du(SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE, SOFTWARE_DRIVER_2_TEXTURE_MAXSIZE);
 
2722
}
 
2723
 
 
2724
 
 
2725
} // end namespace video
 
2726
} // end namespace irr
 
2727
 
 
2728
#endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
 
2729
 
 
2730
namespace irr
 
2731
{
 
2732
namespace video
 
2733
{
 
2734
 
 
2735
//! creates a video driver
 
2736
IVideoDriver* createBurningVideoDriver(const irr::SIrrlichtCreationParameters& params, io::IFileSystem* io, video::IImagePresenter* presenter)
 
2737
{
 
2738
        #ifdef _IRR_COMPILE_WITH_BURNINGSVIDEO_
 
2739
        return new CBurningVideoDriver(params, io, presenter);
 
2740
        #else
 
2741
        return 0;
 
2742
        #endif // _IRR_COMPILE_WITH_BURNINGSVIDEO_
 
2743
}
 
2744
 
 
2745
 
 
2746
 
 
2747
} // end namespace video
 
2748
} // end namespace irr
 
2749