]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/COpenGLSLMaterialRenderer.cpp
Merging r6039 through r6072 from trunk to ogl-es branch.
[irrlicht.git] / source / Irrlicht / COpenGLSLMaterialRenderer.cpp
1 // Copyright (C) 2002-2012 Nikolaus Gebhardt\r
2 // This file is part of the "Irrlicht Engine".\r
3 // For conditions of distribution and use, see copyright notice in irrlicht.h\r
4 \r
5 // This file was originally written by William Finlayson.  I (Nikolaus\r
6 // Gebhardt) did some minor modifications and changes to it and integrated it\r
7 // into Irrlicht. Thanks a lot to William for his work on this and that he gave\r
8 // me his permission to add it into Irrlicht using the zlib license.\r
9 \r
10 // After Irrlicht 0.12, Michael Zoech did some improvements to this renderer, I\r
11 // merged this into Irrlicht 0.14, thanks to him for his work.\r
12 \r
13 #include "COpenGLSLMaterialRenderer.h"\r
14 \r
15 #ifdef _IRR_COMPILE_WITH_OPENGL_\r
16 \r
17 #include "IGPUProgrammingServices.h"\r
18 #include "IShaderConstantSetCallBack.h"\r
19 #include "IMaterialRendererServices.h"\r
20 #include "IVideoDriver.h"\r
21 #include "os.h"\r
22 \r
23 #include "COpenGLDriver.h"\r
24 #include "COpenGLCacheHandler.h"\r
25 #include "COpenGLMaterialRenderer.h"\r
26 \r
27 #include "COpenGLCoreFeature.h"\r
28 \r
29 namespace irr\r
30 {\r
31 namespace video\r
32 {\r
33 \r
34 \r
35 //! Constructor\r
36 COpenGLSLMaterialRenderer::COpenGLSLMaterialRenderer(video::COpenGLDriver* driver,\r
37                 s32& outMaterialTypeNr, const c8* vertexShaderProgram,\r
38                 const c8* vertexShaderEntryPointName,\r
39                 E_VERTEX_SHADER_TYPE vsCompileTarget,\r
40                 const c8* pixelShaderProgram,\r
41                 const c8* pixelShaderEntryPointName,\r
42                 E_PIXEL_SHADER_TYPE psCompileTarget,\r
43                 const c8* geometryShaderProgram,\r
44                 const c8* geometryShaderEntryPointName,\r
45                 E_GEOMETRY_SHADER_TYPE gsCompileTarget,\r
46                 scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,\r
47                 u32 verticesOut,\r
48                 IShaderConstantSetCallBack* callback,\r
49                 E_MATERIAL_TYPE baseMaterial,\r
50                 s32 userData)\r
51         : Driver(driver), CallBack(callback), Alpha(false), Blending(false), FixedBlending(false), AlphaTest(false), Program(0), Program2(0), UserData(userData)\r
52 {\r
53         #ifdef _DEBUG\r
54         setDebugName("COpenGLSLMaterialRenderer");\r
55         #endif\r
56 \r
57         switch (baseMaterial)\r
58         {\r
59         case EMT_TRANSPARENT_VERTEX_ALPHA:\r
60         case EMT_TRANSPARENT_ALPHA_CHANNEL:\r
61         case EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA:\r
62         case EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA:\r
63                 Alpha = true;\r
64                 break;\r
65         case EMT_TRANSPARENT_ADD_COLOR:\r
66         case EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR:\r
67         case EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR:\r
68                 FixedBlending = true;\r
69                 break;\r
70         case EMT_ONETEXTURE_BLEND:\r
71                 Blending = true;\r
72                 break;\r
73         case EMT_TRANSPARENT_ALPHA_CHANNEL_REF:\r
74                 AlphaTest = true;\r
75                 break;\r
76         default:\r
77                 break;\r
78         }\r
79 \r
80         if (CallBack)\r
81                 CallBack->grab();\r
82 \r
83         if (!Driver->queryFeature(EVDF_ARB_GLSL))\r
84                 return;\r
85 \r
86         init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram, geometryShaderProgram);\r
87 }\r
88 \r
89 \r
90 //! constructor only for use by derived classes who want to\r
91 //! create a fall back material for example.\r
92 COpenGLSLMaterialRenderer::COpenGLSLMaterialRenderer(COpenGLDriver* driver,\r
93                                         IShaderConstantSetCallBack* callback,\r
94                                         E_MATERIAL_TYPE baseMaterial, s32 userData)\r
95 : Driver(driver), CallBack(callback), Alpha(false), Blending(false), FixedBlending(false), AlphaTest(false), Program(0), Program2(0), UserData(userData)\r
96 {\r
97         switch (baseMaterial)\r
98         {\r
99         case EMT_TRANSPARENT_VERTEX_ALPHA:\r
100         case EMT_TRANSPARENT_ALPHA_CHANNEL:\r
101         case EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA:\r
102         case EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA:\r
103                 Alpha = true;\r
104                 break;\r
105         case EMT_TRANSPARENT_ADD_COLOR:\r
106         case EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR:\r
107         case EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR:\r
108                 FixedBlending = true;\r
109                 break;\r
110         case EMT_ONETEXTURE_BLEND:\r
111                 Blending = true;\r
112                 break;\r
113         case EMT_TRANSPARENT_ALPHA_CHANNEL_REF:\r
114                 AlphaTest = true;\r
115                 break;\r
116         default:\r
117                 break;\r
118         }\r
119 \r
120         if (CallBack)\r
121                 CallBack->grab();\r
122 }\r
123 \r
124 \r
125 //! Destructor\r
126 COpenGLSLMaterialRenderer::~COpenGLSLMaterialRenderer()\r
127 {\r
128         if (CallBack)\r
129                 CallBack->drop();\r
130 \r
131         if (Program)\r
132         {\r
133                 GLhandleARB shaders[8];\r
134                 GLint count;\r
135                 Driver->extGlGetAttachedObjects(Program, 8, &count, shaders);\r
136                 // avoid bugs in some drivers, which return larger numbers\r
137                 // use int variable to avoid compiler problems with template\r
138                 int mincount=core::min_((int)count,8);\r
139                 for (int i=0; i<mincount; ++i)\r
140                         Driver->extGlDeleteObject(shaders[i]);\r
141                 Driver->extGlDeleteObject(Program);\r
142                 Program = 0;\r
143         }\r
144 \r
145         if (Program2)\r
146         {\r
147                 GLuint shaders[8];\r
148                 GLint count;\r
149                 Driver->extGlGetAttachedShaders(Program2, 8, &count, shaders);\r
150                 // avoid bugs in some drivers, which return larger numbers\r
151                 // use int variable to avoid compiler problems with template\r
152                 int mincount=core::min_((int)count,8);\r
153                 for (int i=0; i<mincount; ++i)\r
154                         Driver->extGlDeleteShader(shaders[i]);\r
155                 Driver->extGlDeleteProgram(Program2);\r
156                 Program2 = 0;\r
157         }\r
158 \r
159         UniformInfo.clear();\r
160 }\r
161 \r
162 \r
163 void COpenGLSLMaterialRenderer::init(s32& outMaterialTypeNr,\r
164                 const c8* vertexShaderProgram,\r
165                 const c8* pixelShaderProgram,\r
166                 const c8* geometryShaderProgram,\r
167                 scene::E_PRIMITIVE_TYPE inType, scene::E_PRIMITIVE_TYPE outType,\r
168                 u32 verticesOut)\r
169 {\r
170         outMaterialTypeNr = -1;\r
171 \r
172         if (!createProgram())\r
173                 return;\r
174 \r
175 #if defined(GL_ARB_vertex_shader) && defined (GL_ARB_fragment_shader)\r
176         if (vertexShaderProgram)\r
177                 if (!createShader(GL_VERTEX_SHADER_ARB, vertexShaderProgram))\r
178                         return;\r
179 \r
180         if (pixelShaderProgram)\r
181                 if (!createShader(GL_FRAGMENT_SHADER_ARB, pixelShaderProgram))\r
182                         return;\r
183 #endif\r
184 \r
185 #if defined(GL_ARB_geometry_shader4) || defined(GL_EXT_geometry_shader4) || defined(GL_NV_geometry_program4) || defined(GL_NV_geometry_shader4)\r
186         if (geometryShaderProgram && Driver->queryFeature(EVDF_GEOMETRY_SHADER))\r
187         {\r
188                 if (!createShader(GL_GEOMETRY_SHADER_EXT, geometryShaderProgram))\r
189                         return;\r
190 #if defined(GL_ARB_geometry_shader4) || defined(GL_EXT_geometry_shader4) || defined(GL_NV_geometry_shader4)\r
191                 if (Program2) // Geometry shaders are supported only in OGL2.x+ drivers.\r
192                 {\r
193                         Driver->extGlProgramParameteri(Program2, GL_GEOMETRY_INPUT_TYPE_EXT, Driver->primitiveTypeToGL(inType));\r
194                         Driver->extGlProgramParameteri(Program2, GL_GEOMETRY_OUTPUT_TYPE_EXT, Driver->primitiveTypeToGL(outType));\r
195                         if (verticesOut==0)\r
196                                 Driver->extGlProgramParameteri(Program2, GL_GEOMETRY_VERTICES_OUT_EXT, Driver->MaxGeometryVerticesOut);\r
197                         else\r
198                                 Driver->extGlProgramParameteri(Program2, GL_GEOMETRY_VERTICES_OUT_EXT, core::min_(verticesOut, Driver->MaxGeometryVerticesOut));\r
199                 }\r
200 #elif defined(GL_NV_geometry_program4)\r
201                 if (verticesOut==0)\r
202                         Driver->extGlProgramVertexLimit(GL_GEOMETRY_PROGRAM_NV, Driver->MaxGeometryVerticesOut);\r
203                 else\r
204                         Driver->extGlProgramVertexLimit(GL_GEOMETRY_PROGRAM_NV, core::min_(verticesOut, Driver->MaxGeometryVerticesOut));\r
205 #endif\r
206         }\r
207 #endif\r
208 \r
209         if (!linkProgram())\r
210                 return;\r
211 \r
212         // register myself as new material\r
213         outMaterialTypeNr = Driver->addMaterialRenderer(this);\r
214 }\r
215 \r
216 \r
217 bool COpenGLSLMaterialRenderer::OnRender(IMaterialRendererServices* service,\r
218                                         E_VERTEX_TYPE vtxtype)\r
219 {\r
220         // call callback to set shader constants\r
221         if (CallBack && (Program||Program2))\r
222                 CallBack->OnSetConstants(this, UserData);\r
223 \r
224         return true;\r
225 }\r
226 \r
227 \r
228 void COpenGLSLMaterialRenderer::OnSetMaterial(const video::SMaterial& material,\r
229                                 const video::SMaterial& lastMaterial,\r
230                                 bool resetAllRenderstates,\r
231                                 video::IMaterialRendererServices* services)\r
232 {\r
233         if (Driver->getFixedPipelineState() == COpenGLDriver::EOFPS_ENABLE)\r
234                 Driver->setFixedPipelineState(COpenGLDriver::EOFPS_ENABLE_TO_DISABLE);\r
235         else\r
236                 Driver->setFixedPipelineState(COpenGLDriver::EOFPS_DISABLE);\r
237 \r
238         COpenGLCacheHandler* cacheHandler = Driver->getCacheHandler();\r
239 \r
240         if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)\r
241         {\r
242                 if (Program2)\r
243                         Driver->irrGlUseProgram(Program2);\r
244                 else if (Program)\r
245                         Driver->extGlUseProgramObject(Program);\r
246         }\r
247 \r
248         Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);\r
249 \r
250         if (Alpha)\r
251         {\r
252                 cacheHandler->setBlend(true);\r
253                 cacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
254         }\r
255         else if (FixedBlending)\r
256         {\r
257                 cacheHandler->setBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);\r
258                 cacheHandler->setBlend(true);\r
259         }\r
260         else if (Blending)\r
261         {\r
262                 E_BLEND_FACTOR srcRGBFact,dstRGBFact,srcAlphaFact,dstAlphaFact;\r
263                 E_MODULATE_FUNC modulate;\r
264                 u32 alphaSource;\r
265                 unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulate, alphaSource, material.MaterialTypeParam);\r
266 \r
267                 if (Driver->queryFeature(EVDF_BLEND_SEPARATE))\r
268         {\r
269                         cacheHandler->setBlendFuncSeparate(Driver->getGLBlend(srcRGBFact), Driver->getGLBlend(dstRGBFact),\r
270                 Driver->getGLBlend(srcAlphaFact), Driver->getGLBlend(dstAlphaFact));\r
271         }\r
272         else\r
273         {\r
274                         cacheHandler->setBlendFunc(Driver->getGLBlend(srcRGBFact), Driver->getGLBlend(dstRGBFact));\r
275         }\r
276 \r
277                 cacheHandler->setBlend(true);\r
278         }\r
279         else if (AlphaTest)\r
280         {\r
281                 cacheHandler->setAlphaTest(true);\r
282                 cacheHandler->setAlphaFunc(GL_GREATER, 0.5f);\r
283         }\r
284 \r
285         if (CallBack)\r
286                 CallBack->OnSetMaterial(material);\r
287 }\r
288 \r
289 \r
290 void COpenGLSLMaterialRenderer::OnUnsetMaterial()\r
291 {\r
292         if (Program)\r
293                 Driver->extGlUseProgramObject(0);\r
294         if (Program2)\r
295                 Driver->irrGlUseProgram(0);\r
296 \r
297         COpenGLCacheHandler* cacheHandler = Driver->getCacheHandler();\r
298         if (Alpha || FixedBlending || Blending)\r
299         {\r
300                 cacheHandler->setBlend(false);\r
301         }\r
302         else if (AlphaTest)\r
303         {\r
304                 cacheHandler->setAlphaTest(false);\r
305         }\r
306 }\r
307 \r
308 \r
309 //! Returns if the material is transparent.\r
310 bool COpenGLSLMaterialRenderer::isTransparent() const\r
311 {\r
312         return (Alpha || Blending || FixedBlending);\r
313 }\r
314 \r
315 \r
316 bool COpenGLSLMaterialRenderer::createProgram()\r
317 {\r
318         if (Driver->Version>=200)\r
319                 Program2 = Driver->extGlCreateProgram();\r
320         else\r
321                 Program = Driver->extGlCreateProgramObject();\r
322         return true;\r
323 }\r
324 \r
325 \r
326 bool COpenGLSLMaterialRenderer::createShader(GLenum shaderType, const char* shader)\r
327 {\r
328         if (Program2)\r
329         {\r
330                 GLuint shaderHandle = Driver->extGlCreateShader(shaderType);\r
331                 Driver->extGlShaderSource(shaderHandle, 1, &shader, NULL);\r
332                 Driver->extGlCompileShader(shaderHandle);\r
333 \r
334                 GLint status = 0;\r
335 \r
336 #ifdef GL_VERSION_2_0\r
337                 Driver->extGlGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &status);\r
338 #endif\r
339 \r
340                 if (status != GL_TRUE)\r
341                 {\r
342                         core::stringc typeInfo("shaderType: ");\r
343                         typeInfo += core::stringc((unsigned long)shaderType);\r
344                         os::Printer::log("GLSL (> 2.x) shader failed to compile", typeInfo.c_str(), ELL_ERROR);\r
345                         // check error message and log it\r
346                         GLint maxLength=0;\r
347                         GLint length;\r
348 #ifdef GL_VERSION_2_0\r
349                         Driver->extGlGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH,\r
350                                         &maxLength);\r
351 #endif\r
352                         if (maxLength)\r
353                         {\r
354                                 GLchar *infoLog = new GLchar[maxLength];\r
355                                 Driver->extGlGetShaderInfoLog(shaderHandle, maxLength, &length, infoLog);\r
356                                 os::Printer::log(reinterpret_cast<const c8*>(infoLog), ELL_ERROR);\r
357                                 delete [] infoLog;\r
358                         }\r
359 \r
360                         return false;\r
361                 }\r
362 \r
363                 Driver->extGlAttachShader(Program2, shaderHandle);\r
364         }\r
365         else\r
366         {\r
367                 GLhandleARB shaderHandle = Driver->extGlCreateShaderObject(shaderType);\r
368 \r
369                 Driver->extGlShaderSourceARB(shaderHandle, 1, &shader, NULL);\r
370                 Driver->extGlCompileShaderARB(shaderHandle);\r
371 \r
372                 GLint status = 0;\r
373 \r
374 #ifdef GL_ARB_shader_objects\r
375                 Driver->extGlGetObjectParameteriv(shaderHandle, GL_OBJECT_COMPILE_STATUS_ARB, &status);\r
376 #endif\r
377 \r
378                 if (!status)\r
379                 {\r
380                         core::stringc typeInfo("shaderType: ");\r
381                         typeInfo += core::stringc((unsigned long)shaderType);\r
382                         os::Printer::log("GLSL shader failed to compile", typeInfo.c_str(), ELL_ERROR);\r
383                         // check error message and log it\r
384                         GLint maxLength=0;\r
385                         GLsizei length;\r
386 #ifdef GL_ARB_shader_objects\r
387                         Driver->extGlGetObjectParameteriv(shaderHandle,\r
388                                         GL_OBJECT_INFO_LOG_LENGTH_ARB, &maxLength);\r
389 #endif\r
390                         if (maxLength)\r
391                         {\r
392                                 GLcharARB *infoLog = new GLcharARB[maxLength];\r
393                                 Driver->extGlGetInfoLog(shaderHandle, maxLength, &length, infoLog);\r
394                                 os::Printer::log(reinterpret_cast<const c8*>(infoLog), ELL_ERROR);\r
395                                 delete [] infoLog;\r
396                         }\r
397 \r
398                         return false;\r
399                 }\r
400 \r
401                 Driver->extGlAttachObject(Program, shaderHandle);\r
402         }\r
403         return true;\r
404 }\r
405 \r
406 \r
407 bool COpenGLSLMaterialRenderer::linkProgram()\r
408 {\r
409         if (Program2)\r
410         {\r
411                 Driver->extGlLinkProgram(Program2);\r
412 \r
413                 GLint status = 0;\r
414 \r
415 #ifdef GL_VERSION_2_0\r
416                 Driver->extGlGetProgramiv(Program2, GL_LINK_STATUS, &status);\r
417 #endif\r
418 \r
419                 if (!status)\r
420                 {\r
421                         os::Printer::log("GLSL (> 2.x) shader program failed to link", ELL_ERROR);\r
422                         // check error message and log it\r
423                         GLint maxLength=0;\r
424                         GLsizei length;\r
425 #ifdef GL_VERSION_2_0\r
426                         Driver->extGlGetProgramiv(Program2, GL_INFO_LOG_LENGTH, &maxLength);\r
427 #endif\r
428                         if (maxLength)\r
429                         {\r
430                                 GLchar *infoLog = new GLchar[maxLength];\r
431                                 Driver->extGlGetProgramInfoLog(Program2, maxLength, &length, infoLog);\r
432                                 os::Printer::log(reinterpret_cast<const c8*>(infoLog), ELL_ERROR);\r
433                                 delete [] infoLog;\r
434                         }\r
435 \r
436                         return false;\r
437                 }\r
438 \r
439                 // get uniforms information\r
440 \r
441                 GLint num = 0;\r
442 #ifdef GL_VERSION_2_0\r
443                 Driver->extGlGetProgramiv(Program2, GL_ACTIVE_UNIFORMS, &num);\r
444 #endif\r
445 \r
446                 if (num == 0)\r
447                 {\r
448                         // no uniforms\r
449                         return true;\r
450                 }\r
451 \r
452                 GLint maxlen = 0;\r
453 #ifdef GL_VERSION_2_0\r
454                 Driver->extGlGetProgramiv(Program2, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxlen);\r
455 #endif\r
456 \r
457                 if (maxlen == 0)\r
458                 {\r
459                         os::Printer::log("GLSL (> 2.x): failed to retrieve uniform information", ELL_ERROR);\r
460                         return false;\r
461                 }\r
462 \r
463                 // seems that some implementations use an extra null terminator\r
464                 ++maxlen;\r
465                 c8 *buf = new c8[maxlen];\r
466 \r
467                 UniformInfo.clear();\r
468                 UniformInfo.reallocate(num);\r
469 \r
470                 for (GLint i=0; i < num; ++i)\r
471                 {\r
472                         SUniformInfo ui;\r
473                         memset(buf, 0, maxlen);\r
474 \r
475                         GLint size;\r
476                         Driver->extGlGetActiveUniform(Program2, i, maxlen, 0, &size, &ui.type, reinterpret_cast<GLchar*>(buf));\r
477                         ui.name = buf;\r
478                         ui.location = Driver->extGlGetUniformLocation(Program2, buf);\r
479 \r
480                         UniformInfo.push_back(ui);\r
481                 }\r
482 \r
483                 delete [] buf;\r
484         }\r
485         else\r
486         {\r
487                 Driver->extGlLinkProgramARB(Program);\r
488 \r
489                 GLint status = 0;\r
490 \r
491 #ifdef GL_ARB_shader_objects\r
492                 Driver->extGlGetObjectParameteriv(Program, GL_OBJECT_LINK_STATUS_ARB, &status);\r
493 #endif\r
494 \r
495                 if (!status)\r
496                 {\r
497                         os::Printer::log("GLSL shader program failed to link", ELL_ERROR);\r
498                         // check error message and log it\r
499                         GLint maxLength=0;\r
500                         GLsizei length;\r
501 #ifdef GL_ARB_shader_objects\r
502                         Driver->extGlGetObjectParameteriv(Program,\r
503                                         GL_OBJECT_INFO_LOG_LENGTH_ARB, &maxLength);\r
504 #endif\r
505                         if (maxLength)\r
506                         {\r
507                                 GLcharARB *infoLog = new GLcharARB[maxLength];\r
508                                 Driver->extGlGetInfoLog(Program, maxLength, &length, infoLog);\r
509                                 os::Printer::log(reinterpret_cast<const c8*>(infoLog), ELL_ERROR);\r
510                                 delete [] infoLog;\r
511                         }\r
512 \r
513                         return false;\r
514                 }\r
515 \r
516                 // get uniforms information\r
517 \r
518                 GLint num = 0;\r
519         #ifdef GL_ARB_shader_objects\r
520                 Driver->extGlGetObjectParameteriv(Program, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &num);\r
521         #endif\r
522 \r
523                 if (num == 0)\r
524                 {\r
525                         // no uniforms\r
526                         return true;\r
527                 }\r
528 \r
529                 GLint maxlen = 0;\r
530         #ifdef GL_ARB_shader_objects\r
531                 Driver->extGlGetObjectParameteriv(Program, GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB, &maxlen);\r
532         #endif\r
533 \r
534                 if (maxlen == 0)\r
535                 {\r
536                         os::Printer::log("GLSL: failed to retrieve uniform information", ELL_ERROR);\r
537                         return false;\r
538                 }\r
539 \r
540                 // seems that some implementations use an extra null terminator\r
541                 ++maxlen;\r
542                 c8 *buf = new c8[maxlen];\r
543 \r
544                 UniformInfo.clear();\r
545                 UniformInfo.reallocate(num);\r
546 \r
547                 for (int i=0; i < num; ++i)\r
548                 {\r
549                         SUniformInfo ui;\r
550                         memset(buf, 0, maxlen);\r
551 \r
552                         GLint size;\r
553                         Driver->extGlGetActiveUniformARB(Program, i, maxlen, 0, &size, &ui.type, reinterpret_cast<GLcharARB*>(buf));\r
554                         ui.name = buf;\r
555                         ui.location = Driver->extGlGetUniformLocationARB(Program, buf);\r
556 \r
557                         UniformInfo.push_back(ui);\r
558                 }\r
559 \r
560                 delete [] buf;\r
561         }\r
562 \r
563         return true;\r
564 }\r
565 \r
566 \r
567 void COpenGLSLMaterialRenderer::setBasicRenderStates(const SMaterial& material,\r
568                                                 const SMaterial& lastMaterial,\r
569                                                 bool resetAllRenderstates)\r
570 {\r
571         // forward\r
572         Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);\r
573 }\r
574 \r
575 s32 COpenGLSLMaterialRenderer::getVertexShaderConstantID(const c8* name)\r
576 {\r
577         return getPixelShaderConstantID(name);\r
578 }\r
579 \r
580 s32 COpenGLSLMaterialRenderer::getPixelShaderConstantID(const c8* name)\r
581 {\r
582         for (u32 i = 0; i < UniformInfo.size(); ++i)\r
583         {\r
584                 if (UniformInfo[i].name == name)\r
585                         return i;\r
586         }\r
587 \r
588         return -1;\r
589 }\r
590 \r
591 void COpenGLSLMaterialRenderer::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)\r
592 {\r
593         os::Printer::log("Cannot set constant, please use high level shader call instead.", ELL_WARNING);\r
594 }\r
595 \r
596 void COpenGLSLMaterialRenderer::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)\r
597 {\r
598         os::Printer::log("Cannot set constant, use high level shader call.", ELL_WARNING);\r
599 }\r
600 \r
601 bool COpenGLSLMaterialRenderer::setVertexShaderConstant(s32 index, const f32* floats, int count)\r
602 {\r
603         return setPixelShaderConstant(index, floats, count);\r
604 }\r
605 \r
606 bool COpenGLSLMaterialRenderer::setVertexShaderConstant(s32 index, const s32* ints, int count)\r
607 {\r
608         return setPixelShaderConstant(index, ints, count);\r
609 }\r
610 \r
611 bool COpenGLSLMaterialRenderer::setPixelShaderConstant(s32 index, const f32* floats, int count)\r
612 {\r
613 #ifdef GL_ARB_shader_objects\r
614         if(index < 0 || UniformInfo[index].location < 0)\r
615                 return false;\r
616 \r
617         bool status = true;\r
618 \r
619         switch (UniformInfo[index].type)\r
620         {\r
621                 case GL_FLOAT:\r
622                         Driver->extGlUniform1fv(UniformInfo[index].location, count, floats);\r
623                         break;\r
624                 case GL_FLOAT_VEC2:\r
625                         Driver->extGlUniform2fv(UniformInfo[index].location, count/2, floats);\r
626                         break;\r
627                 case GL_FLOAT_VEC3:\r
628                         Driver->extGlUniform3fv(UniformInfo[index].location, count/3, floats);\r
629                         break;\r
630                 case GL_FLOAT_VEC4:\r
631                         Driver->extGlUniform4fv(UniformInfo[index].location, count/4, floats);\r
632                         break;\r
633                 case GL_FLOAT_MAT2:\r
634                         Driver->extGlUniformMatrix2fv(UniformInfo[index].location, count/4, false, floats);\r
635                         break;\r
636                 case GL_FLOAT_MAT2x3:\r
637                         Driver->extGlUniformMatrix2x3fv(UniformInfo[index].location, count/6, false, floats);\r
638                         break;\r
639                 case GL_FLOAT_MAT2x4:\r
640                         Driver->extGlUniformMatrix2x4fv(UniformInfo[index].location, count/8, false, floats);\r
641                         break;\r
642                 case GL_FLOAT_MAT3x2:\r
643                         Driver->extGlUniformMatrix3x2fv(UniformInfo[index].location, count/6, false, floats);\r
644                         break;\r
645                 case GL_FLOAT_MAT3:\r
646                         Driver->extGlUniformMatrix3fv(UniformInfo[index].location, count/9, false, floats);\r
647                         break;\r
648                 case GL_FLOAT_MAT3x4:\r
649                         Driver->extGlUniformMatrix3x4fv(UniformInfo[index].location, count/12, false, floats);\r
650                         break;\r
651                 case GL_FLOAT_MAT4x2:\r
652                         Driver->extGlUniformMatrix4x2fv(UniformInfo[index].location, count/8, false, floats);\r
653                         break;\r
654                 case GL_FLOAT_MAT4x3:\r
655                         Driver->extGlUniformMatrix4x3fv(UniformInfo[index].location, count/12, false, floats);\r
656                         break;\r
657                 case GL_FLOAT_MAT4:\r
658                         Driver->extGlUniformMatrix4fv(UniformInfo[index].location, count/16, false, floats);\r
659                         break;\r
660                 case GL_SAMPLER_1D:\r
661                 case GL_SAMPLER_2D:\r
662                 case GL_SAMPLER_3D:\r
663                 case GL_SAMPLER_CUBE:\r
664                 case GL_SAMPLER_1D_SHADOW:\r
665                 case GL_SAMPLER_2D_SHADOW:\r
666                         {\r
667                                 if(floats)\r
668                                 {\r
669                                         const GLint id = static_cast<GLint>(*floats);\r
670                                         Driver->extGlUniform1iv(UniformInfo[index].location, 1, &id);\r
671                                 }\r
672                                 else\r
673                                         status = false;\r
674                         }\r
675                         break;\r
676                 default:\r
677                         status = false;\r
678                         break;\r
679         }\r
680         return status;\r
681 #else\r
682         return false;\r
683 #endif\r
684 }\r
685 \r
686 bool COpenGLSLMaterialRenderer::setPixelShaderConstant(s32 index, const s32* ints, int count)\r
687 {\r
688 #ifdef GL_ARB_shader_objects\r
689         if(index < 0 || UniformInfo[index].location < 0)\r
690                 return false;\r
691 \r
692         bool status = true;\r
693 \r
694         switch (UniformInfo[index].type)\r
695         {\r
696                 case GL_INT:\r
697                 case GL_BOOL:\r
698                         Driver->extGlUniform1iv(UniformInfo[index].location, count, reinterpret_cast<const GLint*>(ints));\r
699                         break;\r
700                 case GL_INT_VEC2:\r
701                 case GL_BOOL_VEC2:\r
702                         Driver->extGlUniform2iv(UniformInfo[index].location, count/2, reinterpret_cast<const GLint*>(ints));\r
703                         break;\r
704                 case GL_INT_VEC3:\r
705                 case GL_BOOL_VEC3:\r
706                         Driver->extGlUniform3iv(UniformInfo[index].location, count/3, reinterpret_cast<const GLint*>(ints));\r
707                         break;\r
708                 case GL_INT_VEC4:\r
709                 case GL_BOOL_VEC4:\r
710                         Driver->extGlUniform4iv(UniformInfo[index].location, count/4, reinterpret_cast<const GLint*>(ints));\r
711                         break;\r
712                 case GL_SAMPLER_1D:\r
713                 case GL_SAMPLER_2D:\r
714                 case GL_SAMPLER_3D:\r
715                 case GL_SAMPLER_CUBE:\r
716                 case GL_SAMPLER_1D_SHADOW:\r
717                 case GL_SAMPLER_2D_SHADOW:\r
718                         Driver->extGlUniform1iv(UniformInfo[index].location, 1, reinterpret_cast<const GLint*>(ints));\r
719                         break;\r
720                 default:\r
721                         status = false;\r
722                         break;\r
723         }\r
724         return status;\r
725 #else\r
726         return false;\r
727 #endif\r
728 }\r
729 \r
730 IVideoDriver* COpenGLSLMaterialRenderer::getVideoDriver()\r
731 {\r
732         return Driver;\r
733 }\r
734 \r
735 } // end namespace video\r
736 } // end namespace irr\r
737 \r
738 \r
739 #endif\r
740 \r