~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/COpenGLShaderMaterialRenderer.cpp

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (C) 2002-2011 Nikolaus Gebhardt
 
2
// This file is part of the "Irrlicht Engine".
 
3
// For conditions of distribution and use, see copyright notice in irrlicht.h
 
4
 
 
5
#include "IrrCompileConfig.h"
 
6
#ifdef _IRR_COMPILE_WITH_OPENGL_
 
7
 
 
8
#include "COpenGLShaderMaterialRenderer.h"
 
9
#include "IGPUProgrammingServices.h"
 
10
#include "IShaderConstantSetCallBack.h"
 
11
#include "IVideoDriver.h"
 
12
#include "os.h"
 
13
#include "COpenGLDriver.h"
 
14
 
 
15
namespace irr
 
16
{
 
17
namespace video
 
18
{
 
19
 
 
20
 
 
21
//! Constructor
 
22
COpenGLShaderMaterialRenderer::COpenGLShaderMaterialRenderer(video::COpenGLDriver* driver,
 
23
        s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
 
24
        IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData)
 
25
        : Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
 
26
                VertexShader(0), UserData(userData)
 
27
{
 
28
        #ifdef _DEBUG
 
29
        setDebugName("COpenGLShaderMaterialRenderer");
 
30
        #endif
 
31
 
 
32
        PixelShader.set_used(4);
 
33
        for (u32 i=0; i<4; ++i)
 
34
        {
 
35
                PixelShader[i]=0;
 
36
        }
 
37
 
 
38
        if (BaseMaterial)
 
39
                BaseMaterial->grab();
 
40
 
 
41
        if (CallBack)
 
42
                CallBack->grab();
 
43
 
 
44
        init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram, EVT_STANDARD);
 
45
}
 
46
 
 
47
 
 
48
//! constructor only for use by derived classes who want to
 
49
//! create a fall back material for example.
 
50
COpenGLShaderMaterialRenderer::COpenGLShaderMaterialRenderer(COpenGLDriver* driver,
 
51
                                IShaderConstantSetCallBack* callback,
 
52
                                IMaterialRenderer* baseMaterial, s32 userData)
 
53
: Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
 
54
                VertexShader(0), UserData(userData)
 
55
{
 
56
        PixelShader.set_used(4);
 
57
        for (u32 i=0; i<4; ++i)
 
58
        {
 
59
                PixelShader[i]=0;
 
60
        }
 
61
 
 
62
        if (BaseMaterial)
 
63
                BaseMaterial->grab();
 
64
 
 
65
        if (CallBack)
 
66
                CallBack->grab();
 
67
}
 
68
 
 
69
 
 
70
//! Destructor
 
71
COpenGLShaderMaterialRenderer::~COpenGLShaderMaterialRenderer()
 
72
{
 
73
        if (CallBack)
 
74
                CallBack->drop();
 
75
 
 
76
        if (VertexShader)
 
77
                Driver->extGlDeletePrograms(1, &VertexShader);
 
78
 
 
79
        for (u32 i=0; i<PixelShader.size(); ++i)
 
80
                if (PixelShader[i])
 
81
                        Driver->extGlDeletePrograms(1, &PixelShader[i]);
 
82
 
 
83
        if (BaseMaterial)
 
84
                BaseMaterial->drop();
 
85
}
 
86
 
 
87
 
 
88
void COpenGLShaderMaterialRenderer::init(s32& outMaterialTypeNr,
 
89
                const c8* vertexShaderProgram, const c8* pixelShaderProgram,
 
90
                E_VERTEX_TYPE type)
 
91
{
 
92
        outMaterialTypeNr = -1;
 
93
 
 
94
        bool success;
 
95
 
 
96
        // create vertex shader
 
97
        success=createVertexShader(vertexShaderProgram);
 
98
 
 
99
        // create pixel shader
 
100
        if (!createPixelShader(pixelShaderProgram) || !success)
 
101
                return;
 
102
 
 
103
        // register as a new material
 
104
        outMaterialTypeNr = Driver->addMaterialRenderer(this);
 
105
}
 
106
 
 
107
 
 
108
bool COpenGLShaderMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
 
109
{
 
110
        // call callback to set shader constants
 
111
        if (CallBack && (VertexShader || PixelShader[0]))
 
112
                CallBack->OnSetConstants(service, UserData);
 
113
 
 
114
        return true;
 
115
}
 
116
 
 
117
 
 
118
void COpenGLShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial,
 
119
        bool resetAllRenderstates, video::IMaterialRendererServices* services)
 
120
{
 
121
        if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
 
122
        {
 
123
                if (VertexShader)
 
124
                {
 
125
                        // set new vertex shader
 
126
#ifdef GL_ARB_vertex_program
 
127
                        Driver->extGlBindProgram(GL_VERTEX_PROGRAM_ARB, VertexShader);
 
128
                        glEnable(GL_VERTEX_PROGRAM_ARB);
 
129
#elif defined(GL_NV_vertex_program)
 
130
                        Driver->extGlBindProgram(GL_VERTEX_PROGRAM_NV, VertexShader);
 
131
                        glEnable(GL_VERTEX_PROGRAM_NV);
 
132
#endif
 
133
                }
 
134
 
 
135
                // set new pixel shader
 
136
                if (PixelShader[0])
 
137
                {
 
138
                        GLuint nextShader=PixelShader[0];
 
139
                        if (material.FogEnable)
 
140
                        {
 
141
                                GLint curFogMode;
 
142
                                glGetIntegerv(GL_FOG_MODE, &curFogMode);
 
143
//                              if (Driver->LinearFog && PixelShader[1])
 
144
                                if (curFogMode==GL_LINEAR && PixelShader[1])
 
145
                                        nextShader=PixelShader[1];
 
146
//                              else if (!Driver->LinearFog && PixelShader[2])
 
147
                                else if (curFogMode==GL_EXP && PixelShader[2])
 
148
                                        nextShader=PixelShader[2];
 
149
                                else if (curFogMode==GL_EXP2 && PixelShader[3])
 
150
                                        nextShader=PixelShader[3];
 
151
                        }
 
152
#ifdef GL_ARB_fragment_program
 
153
                        Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, nextShader);
 
154
                        glEnable(GL_FRAGMENT_PROGRAM_ARB);
 
155
#elif defined(GL_NV_fragment_program)
 
156
                        Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_NV, nextShader);
 
157
                        glEnable(GL_FRAGMENT_PROGRAM_NV);
 
158
#endif
 
159
                }
 
160
 
 
161
                if (BaseMaterial)
 
162
                        BaseMaterial->OnSetMaterial(material, material, true, services);
 
163
        }
 
164
 
 
165
        //let callback know used material
 
166
        if (CallBack)
 
167
                CallBack->OnSetMaterial(material);
 
168
 
 
169
        for (u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
 
170
                Driver->setActiveTexture(i, material.getTexture(i));
 
171
        Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
 
172
}
 
173
 
 
174
 
 
175
void COpenGLShaderMaterialRenderer::OnUnsetMaterial()
 
176
{
 
177
        // disable vertex shader
 
178
#ifdef GL_ARB_vertex_program
 
179
        if (VertexShader)
 
180
                glDisable(GL_VERTEX_PROGRAM_ARB);
 
181
#elif defined(GL_NV_vertex_program)
 
182
        if (VertexShader)
 
183
                glDisable(GL_VERTEX_PROGRAM_NV);
 
184
#endif
 
185
 
 
186
#ifdef GL_ARB_fragment_program
 
187
        if (PixelShader[0])
 
188
                glDisable(GL_FRAGMENT_PROGRAM_ARB);
 
189
#elif defined(GL_NV_fragment_program)
 
190
        if (PixelShader[0])
 
191
                glDisable(GL_FRAGMENT_PROGRAM_NV);
 
192
#endif
 
193
 
 
194
        if (BaseMaterial)
 
195
                BaseMaterial->OnUnsetMaterial();
 
196
}
 
197
 
 
198
 
 
199
//! Returns if the material is transparent.
 
200
bool COpenGLShaderMaterialRenderer::isTransparent() const
 
201
{
 
202
        return BaseMaterial ? BaseMaterial->isTransparent() : false;
 
203
}
 
204
 
 
205
 
 
206
// This method needs a properly cleaned error state before the checked instruction is called
 
207
bool COpenGLShaderMaterialRenderer::checkError(const irr::c8* type)
 
208
{
 
209
#if defined(GL_ARB_vertex_program) || defined(GL_NV_vertex_program) || defined(GL_ARB_fragment_program) || defined(GL_NV_fragment_program)
 
210
        GLenum g = glGetError();
 
211
        if (g == GL_NO_ERROR)
 
212
                return false;
 
213
 
 
214
        core::stringc errString = type;
 
215
        errString += " compilation failed";
 
216
 
 
217
        errString += " at position ";
 
218
        GLint errPos=-1;
 
219
#if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program)
 
220
        glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
 
221
#else
 
222
        glGetIntegerv( GL_PROGRAM_ERROR_POSITION_NV, &errPos );
 
223
#endif
 
224
        errString += core::stringc(s32(errPos));
 
225
        errString += ":\n";
 
226
#if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program)
 
227
        errString += reinterpret_cast<const char*>(glGetString(GL_PROGRAM_ERROR_STRING_ARB));
 
228
#else
 
229
        errString += reinterpret_cast<const char*>(glGetString(GL_PROGRAM_ERROR_STRING_NV));
 
230
#endif
 
231
#else
 
232
        core::stringc errString("Shaders not supported.");
 
233
#endif
 
234
        os::Printer::log(errString.c_str(), ELL_ERROR);
 
235
        return true;
 
236
}
 
237
 
 
238
 
 
239
bool COpenGLShaderMaterialRenderer::createPixelShader(const c8* pxsh)
 
240
{
 
241
        if (!pxsh)
 
242
                return true;
 
243
 
 
244
        const core::stringc inshdr(pxsh);
 
245
        core::stringc shdr;
 
246
        const s32 pos = inshdr.find("#_IRR_FOG_MODE_");
 
247
        const u32 numShaders = (-1 != pos)?4:1;
 
248
 
 
249
        for (u32 i=0; i<numShaders; ++i)
 
250
        {
 
251
                if (i==0)
 
252
                {
 
253
                        shdr=inshdr;
 
254
                }
 
255
                else
 
256
                {
 
257
                        shdr = inshdr.subString(0, pos);
 
258
                        switch (i) {
 
259
                                case 1: shdr += "OPTION ARB_fog_linear;"; break;
 
260
                                case 2: shdr += "OPTION ARB_fog_exp;"; break;
 
261
                                case 3: shdr += "OPTION ARB_fog_exp2;"; break;
 
262
                        }
 
263
                        shdr += inshdr.subString(pos+16, inshdr.size()-pos-16);
 
264
                }
 
265
                Driver->extGlGenPrograms(1, &PixelShader[i]);
 
266
#ifdef GL_ARB_fragment_program
 
267
                Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, PixelShader[i]);
 
268
#elif defined GL_NV_fragment_program
 
269
                Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_NV, PixelShader[i]);
 
270
#endif
 
271
 
 
272
                // clear error buffer
 
273
                while(glGetError() != GL_NO_ERROR)
 
274
                        {}
 
275
 
 
276
#ifdef GL_ARB_fragment_program
 
277
                // compile
 
278
                Driver->extGlProgramString(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
 
279
                                shdr.size(), shdr.c_str());
 
280
#elif defined GL_NV_fragment_program
 
281
                Driver->extGlLoadProgram(GL_FRAGMENT_PROGRAM_NV, PixelShader[i],
 
282
                                shdr.size(), shdr.c_str());
 
283
#endif
 
284
 
 
285
                if (checkError("Pixel shader"))
 
286
                {
 
287
                        Driver->extGlDeletePrograms(1, &PixelShader[i]);
 
288
                        PixelShader[i]=0;
 
289
 
 
290
                        return false;
 
291
                }
 
292
        }
 
293
 
 
294
        return true;
 
295
}
 
296
 
 
297
 
 
298
bool COpenGLShaderMaterialRenderer::createVertexShader(const c8* vtxsh)
 
299
{
 
300
        if (!vtxsh)
 
301
                return true;
 
302
 
 
303
        Driver->extGlGenPrograms(1, &VertexShader);
 
304
#ifdef GL_ARB_vertex_program
 
305
        Driver->extGlBindProgram(GL_VERTEX_PROGRAM_ARB, VertexShader);
 
306
#elif defined GL_NV_vertex_program
 
307
        Driver->extGlBindProgram(GL_VERTEX_PROGRAM_NV, VertexShader);
 
308
#endif
 
309
 
 
310
        // clear error buffer
 
311
        while(glGetError() != GL_NO_ERROR)
 
312
        {}
 
313
 
 
314
        // compile
 
315
#ifdef GL_ARB_vertex_program
 
316
        Driver->extGlProgramString(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
 
317
                        (GLsizei)strlen(vtxsh), vtxsh);
 
318
#elif defined GL_NV_vertex_program
 
319
        Driver->extGlLoadProgram(GL_VERTEX_PROGRAM_NV, VertexShader,
 
320
                        (GLsizei)strlen(vtxsh), vtxsh);
 
321
#endif
 
322
 
 
323
        if (checkError("Vertex shader"))
 
324
        {
 
325
                Driver->extGlDeletePrograms(1, &VertexShader);
 
326
                VertexShader=0;
 
327
 
 
328
                return false;
 
329
        }
 
330
 
 
331
        return true;
 
332
}
 
333
 
 
334
 
 
335
} // end namespace video
 
336
} // end namespace irr
 
337
 
 
338
#endif
 
339