aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/COpenGLShaderMaterialRenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/COpenGLShaderMaterialRenderer.cpp')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/COpenGLShaderMaterialRenderer.cpp339
1 files changed, 339 insertions, 0 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/COpenGLShaderMaterialRenderer.cpp b/libraries/irrlicht-1.8/source/Irrlicht/COpenGLShaderMaterialRenderer.cpp
new file mode 100644
index 0000000..8921a51
--- /dev/null
+++ b/libraries/irrlicht-1.8/source/Irrlicht/COpenGLShaderMaterialRenderer.cpp
@@ -0,0 +1,339 @@
1// Copyright (C) 2002-2012 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
15namespace irr
16{
17namespace video
18{
19
20
21//! Constructor
22COpenGLShaderMaterialRenderer::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.
50COpenGLShaderMaterialRenderer::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
71COpenGLShaderMaterialRenderer::~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
88void 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
108bool 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
118void 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
175void 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.
200bool 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
207bool 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
239bool 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
298bool 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