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