-// Copyright (C) 2014 Patryk Nadrowski\r
-// This file is part of the "Irrlicht Engine".\r
-// For conditions of distribution and use, see copyright notice in irrlicht.h\r
-\r
-#include "MaterialRenderer.h"\r
-\r
-#include "EVertexAttributes.h"\r
-#include "IGPUProgrammingServices.h"\r
-#include "IShaderConstantSetCallBack.h"\r
-#include "IVideoDriver.h"\r
-#include "os.h"\r
-\r
-#include "Driver.h"\r
-\r
-#include "COpenGLCoreTexture.h"\r
-#include "COpenGLCoreCacheHandler.h"\r
-\r
-namespace irr\r
-{\r
-namespace video\r
-{\r
-\r
-\r
-COpenGL3MaterialRenderer::COpenGL3MaterialRenderer(COpenGL3DriverBase* driver,\r
- s32& outMaterialTypeNr,\r
- const c8* vertexShaderProgram,\r
- const c8* pixelShaderProgram,\r
- IShaderConstantSetCallBack* callback,\r
- E_MATERIAL_TYPE baseMaterial,\r
- s32 userData)\r
- : Driver(driver), CallBack(callback), Alpha(false), Blending(false), FixedBlending(false), Program(0), UserData(userData)\r
-{\r
-#ifdef _DEBUG\r
- setDebugName("MaterialRenderer");\r
-#endif\r
-\r
- switch (baseMaterial)\r
- {\r
- case EMT_TRANSPARENT_VERTEX_ALPHA:\r
- case EMT_TRANSPARENT_ALPHA_CHANNEL:\r
- Alpha = true;\r
- break;\r
- case EMT_TRANSPARENT_ADD_COLOR:\r
- FixedBlending = true;\r
- break;\r
- case EMT_ONETEXTURE_BLEND:\r
- Blending = true;\r
- break;\r
- default:\r
- break;\r
- }\r
-\r
- if (CallBack)\r
- CallBack->grab();\r
-\r
- init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram);\r
-}\r
-\r
-\r
-COpenGL3MaterialRenderer::COpenGL3MaterialRenderer(COpenGL3DriverBase* driver,\r
- IShaderConstantSetCallBack* callback,\r
- E_MATERIAL_TYPE baseMaterial, s32 userData)\r
-: Driver(driver), CallBack(callback), Alpha(false), Blending(false), FixedBlending(false), Program(0), UserData(userData)\r
-{\r
- switch (baseMaterial)\r
- {\r
- case EMT_TRANSPARENT_VERTEX_ALPHA:\r
- case EMT_TRANSPARENT_ALPHA_CHANNEL:\r
- Alpha = true;\r
- break;\r
- case EMT_TRANSPARENT_ADD_COLOR:\r
- FixedBlending = true;\r
- break;\r
- case EMT_ONETEXTURE_BLEND:\r
- Blending = true;\r
- break;\r
- default:\r
- break;\r
- }\r
-\r
- if (CallBack)\r
- CallBack->grab();\r
-}\r
-\r
-\r
-COpenGL3MaterialRenderer::~COpenGL3MaterialRenderer()\r
-{\r
- if (CallBack)\r
- CallBack->drop();\r
-\r
- if (Program)\r
- {\r
- GLuint shaders[8];\r
- GLint count;\r
- glGetAttachedShaders(Program, 8, &count, shaders);\r
-\r
- count=core::min_(count,8);\r
- for (GLint i=0; i<count; ++i)\r
- glDeleteShader(shaders[i]);\r
- glDeleteProgram(Program);\r
- Program = 0;\r
- }\r
-\r
- UniformInfo.clear();\r
-}\r
-\r
-GLuint COpenGL3MaterialRenderer::getProgram() const\r
-{\r
- return Program;\r
-}\r
-\r
-void COpenGL3MaterialRenderer::init(s32& outMaterialTypeNr,\r
- const c8* vertexShaderProgram,\r
- const c8* pixelShaderProgram,\r
- bool addMaterial)\r
-{\r
- outMaterialTypeNr = -1;\r
-\r
- Program = glCreateProgram();\r
-\r
- if (!Program)\r
- return;\r
-\r
- if (vertexShaderProgram)\r
- if (!createShader(GL_VERTEX_SHADER, vertexShaderProgram))\r
- return;\r
-\r
- if (pixelShaderProgram)\r
- if (!createShader(GL_FRAGMENT_SHADER, pixelShaderProgram))\r
- return;\r
-\r
- for ( size_t i = 0; i < EVA_COUNT; ++i )\r
- glBindAttribLocation( Program, i, sBuiltInVertexAttributeNames[i]);\r
-\r
- if (!linkProgram())\r
- return;\r
-\r
- if (addMaterial)\r
- outMaterialTypeNr = Driver->addMaterialRenderer(this);\r
-}\r
-\r
-\r
-bool COpenGL3MaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)\r
-{\r
- if (CallBack && Program)\r
- CallBack->OnSetConstants(this, UserData);\r
-\r
- return true;\r
-}\r
-\r
-\r
-void COpenGL3MaterialRenderer::OnSetMaterial(const video::SMaterial& material,\r
- const video::SMaterial& lastMaterial,\r
- bool resetAllRenderstates,\r
- video::IMaterialRendererServices* services)\r
-{\r
- COpenGL3CacheHandler* cacheHandler = Driver->getCacheHandler();\r
-\r
- cacheHandler->setProgram(Program);\r
-\r
- Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);\r
-\r
- if (Alpha)\r
- {\r
- cacheHandler->setBlend(true);\r
- cacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
- }\r
- else if (FixedBlending)\r
- {\r
- cacheHandler->setBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);\r
- cacheHandler->setBlend(true);\r
- }\r
- else if (Blending)\r
- {\r
- E_BLEND_FACTOR srcRGBFact,dstRGBFact,srcAlphaFact,dstAlphaFact;\r
- E_MODULATE_FUNC modulate;\r
- u32 alphaSource;\r
- unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulate, alphaSource, material.MaterialTypeParam);\r
-\r
- cacheHandler->setBlendFuncSeparate(Driver->getGLBlend(srcRGBFact), Driver->getGLBlend(dstRGBFact),\r
- Driver->getGLBlend(srcAlphaFact), Driver->getGLBlend(dstAlphaFact));\r
-\r
- cacheHandler->setBlend(true);\r
- }\r
-\r
- if (CallBack)\r
- CallBack->OnSetMaterial(material);\r
-}\r
-\r
-\r
-void COpenGL3MaterialRenderer::OnUnsetMaterial()\r
-{\r
-}\r
-\r
-\r
-bool COpenGL3MaterialRenderer::isTransparent() const\r
-{\r
- return (Alpha || Blending || FixedBlending);\r
-}\r
-\r
-\r
-s32 COpenGL3MaterialRenderer::getRenderCapability() const\r
-{\r
- return 0;\r
-}\r
-\r
-\r
-bool COpenGL3MaterialRenderer::createShader(GLenum shaderType, const char* shader)\r
-{\r
- if (Program)\r
- {\r
- GLuint shaderHandle = glCreateShader(shaderType);\r
- glShaderSource(shaderHandle, 1, &shader, NULL);\r
- glCompileShader(shaderHandle);\r
-\r
- GLint status = 0;\r
-\r
- glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &status);\r
-\r
- if (status != GL_TRUE)\r
- {\r
- os::Printer::log("GLSL shader failed to compile", ELL_ERROR);\r
-\r
- GLint maxLength=0;\r
- GLint length;\r
-\r
- glGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH,\r
- &maxLength);\r
-\r
- if (maxLength)\r
- {\r
- GLchar *infoLog = new GLchar[maxLength];\r
- glGetShaderInfoLog(shaderHandle, maxLength, &length, infoLog);\r
- os::Printer::log(reinterpret_cast<const c8*>(infoLog), ELL_ERROR);\r
- delete [] infoLog;\r
- }\r
-\r
- return false;\r
- }\r
-\r
- glAttachShader(Program, shaderHandle);\r
- }\r
-\r
- return true;\r
-}\r
-\r
-\r
-bool COpenGL3MaterialRenderer::linkProgram()\r
-{\r
- if (Program)\r
- {\r
- glLinkProgram(Program);\r
-\r
- GLint status = 0;\r
-\r
- glGetProgramiv(Program, GL_LINK_STATUS, &status);\r
-\r
- if (!status)\r
- {\r
- os::Printer::log("GLSL shader program failed to link", ELL_ERROR);\r
-\r
- GLint maxLength=0;\r
- GLsizei length;\r
-\r
- glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &maxLength);\r
-\r
- if (maxLength)\r
- {\r
- GLchar *infoLog = new GLchar[maxLength];\r
- glGetProgramInfoLog(Program, maxLength, &length, infoLog);\r
- os::Printer::log(reinterpret_cast<const c8*>(infoLog), ELL_ERROR);\r
- delete [] infoLog;\r
- }\r
-\r
- return false;\r
- }\r
-\r
- GLint num = 0;\r
-\r
- glGetProgramiv(Program, GL_ACTIVE_UNIFORMS, &num);\r
-\r
- if (num == 0)\r
- return true;\r
-\r
- GLint maxlen = 0;\r
-\r
- glGetProgramiv(Program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxlen);\r
-\r
- if (maxlen == 0)\r
- {\r
- os::Printer::log("GLSL: failed to retrieve uniform information", ELL_ERROR);\r
- return false;\r
- }\r
-\r
- // seems that some implementations use an extra null terminator.\r
- ++maxlen;\r
- c8 *buf = new c8[maxlen];\r
-\r
- UniformInfo.clear();\r
- UniformInfo.reallocate(num);\r
-\r
- for (GLint i=0; i < num; ++i)\r
- {\r
- SUniformInfo ui;\r
- memset(buf, 0, maxlen);\r
-\r
- GLint size;\r
- glGetActiveUniform(Program, i, maxlen, 0, &size, &ui.type, reinterpret_cast<GLchar*>(buf));\r
-\r
- core::stringc name = "";\r
-\r
- // array support, workaround for some bugged drivers.\r
- for (s32 i = 0; i < maxlen; ++i)\r
- {\r
- if (buf[i] == '[' || buf[i] == '\0')\r
- break;\r
-\r
- name += buf[i];\r
- }\r
-\r
- ui.name = name;\r
- ui.location = glGetUniformLocation(Program, buf);\r
-\r
- UniformInfo.push_back(ui);\r
- }\r
-\r
- delete [] buf;\r
- }\r
-\r
- return true;\r
-}\r
-\r
-\r
-void COpenGL3MaterialRenderer::setBasicRenderStates(const SMaterial& material,\r
- const SMaterial& lastMaterial,\r
- bool resetAllRenderstates)\r
-{\r
- Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);\r
-}\r
-\r
-s32 COpenGL3MaterialRenderer::getVertexShaderConstantID(const c8* name)\r
-{\r
- return getPixelShaderConstantID(name);\r
-}\r
-\r
-s32 COpenGL3MaterialRenderer::getPixelShaderConstantID(const c8* name)\r
-{\r
- for (u32 i = 0; i < UniformInfo.size(); ++i)\r
- {\r
- if (UniformInfo[i].name == name)\r
- return i;\r
- }\r
-\r
- return -1;\r
-}\r
-\r
-void COpenGL3MaterialRenderer::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)\r
-{\r
- os::Printer::log("Cannot set constant, please use high level shader call instead.", ELL_WARNING);\r
-}\r
-\r
-void COpenGL3MaterialRenderer::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)\r
-{\r
- os::Printer::log("Cannot set constant, use high level shader call.", ELL_WARNING);\r
-}\r
-\r
-bool COpenGL3MaterialRenderer::setVertexShaderConstant(s32 index, const f32* floats, int count)\r
-{\r
- return setPixelShaderConstant(index, floats, count);\r
-}\r
-\r
-bool COpenGL3MaterialRenderer::setVertexShaderConstant(s32 index, const s32* ints, int count)\r
-{\r
- return setPixelShaderConstant(index, ints, count);\r
-}\r
-\r
-bool COpenGL3MaterialRenderer::setVertexShaderConstant(s32 index, const u32* ints, int count)\r
-{\r
- return setPixelShaderConstant(index, ints, count);\r
-}\r
-\r
-bool COpenGL3MaterialRenderer::setPixelShaderConstant(s32 index, const f32* floats, int count)\r
-{\r
- if(index < 0 || UniformInfo[index].location < 0)\r
- return false;\r
-\r
- bool status = true;\r
-\r
- switch (UniformInfo[index].type)\r
- {\r
- case GL_FLOAT:\r
- glUniform1fv(UniformInfo[index].location, count, floats);\r
- break;\r
- case GL_FLOAT_VEC2:\r
- glUniform2fv(UniformInfo[index].location, count/2, floats);\r
- break;\r
- case GL_FLOAT_VEC3:\r
- glUniform3fv(UniformInfo[index].location, count/3, floats);\r
- break;\r
- case GL_FLOAT_VEC4:\r
- glUniform4fv(UniformInfo[index].location, count/4, floats);\r
- break;\r
- case GL_FLOAT_MAT2:\r
- glUniformMatrix2fv(UniformInfo[index].location, count/4, false, floats);\r
- break;\r
- case GL_FLOAT_MAT3:\r
- glUniformMatrix3fv(UniformInfo[index].location, count/9, false, floats);\r
- break;\r
- case GL_FLOAT_MAT4:\r
- glUniformMatrix4fv(UniformInfo[index].location, count/16, false, floats);\r
- break;\r
- case GL_SAMPLER_2D:\r
- case GL_SAMPLER_CUBE:\r
- {\r
- if(floats)\r
- {\r
- const GLint id = (GLint)(*floats);\r
- glUniform1iv(UniformInfo[index].location, 1, &id);\r
- }\r
- else\r
- status = false;\r
- }\r
- break;\r
- default:\r
- status = false;\r
- break;\r
- }\r
-\r
- return status;\r
-}\r
-\r
-bool COpenGL3MaterialRenderer::setPixelShaderConstant(s32 index, const s32* ints, int count)\r
-{\r
- if(index < 0 || UniformInfo[index].location < 0)\r
- return false;\r
-\r
- bool status = true;\r
-\r
- switch (UniformInfo[index].type)\r
- {\r
- case GL_INT:\r
- case GL_BOOL:\r
- glUniform1iv(UniformInfo[index].location, count, ints);\r
- break;\r
- case GL_INT_VEC2:\r
- case GL_BOOL_VEC2:\r
- glUniform2iv(UniformInfo[index].location, count/2, ints);\r
- break;\r
- case GL_INT_VEC3:\r
- case GL_BOOL_VEC3:\r
- glUniform3iv(UniformInfo[index].location, count/3, ints);\r
- break;\r
- case GL_INT_VEC4:\r
- case GL_BOOL_VEC4:\r
- glUniform4iv(UniformInfo[index].location, count/4, ints);\r
- break;\r
- case GL_SAMPLER_2D:\r
- case GL_SAMPLER_CUBE:\r
- glUniform1iv(UniformInfo[index].location, 1, ints);\r
- break;\r
- default:\r
- status = false;\r
- break;\r
- }\r
-\r
- return status;\r
-}\r
-\r
-bool COpenGL3MaterialRenderer::setPixelShaderConstant(s32 index, const u32* ints, int count)\r
-{\r
- os::Printer::log("Unsigned int support needs at least GLES 3.0", ELL_WARNING);\r
- return false;\r
-}\r
-\r
-IVideoDriver* COpenGL3MaterialRenderer::getVideoDriver()\r
-{\r
- return Driver;\r
-}\r
-\r
-}\r
-}\r
+// Copyright (C) 2014 Patryk Nadrowski
+// This file is part of the "Irrlicht Engine".
+// For conditions of distribution and use, see copyright notice in irrlicht.h
+
+#include "MaterialRenderer.h"
+
+#include "EVertexAttributes.h"
+#include "IGPUProgrammingServices.h"
+#include "IShaderConstantSetCallBack.h"
+#include "IVideoDriver.h"
+#include "os.h"
+
+#include "Driver.h"
+
+#include "COpenGLCoreTexture.h"
+#include "COpenGLCoreCacheHandler.h"
+
+namespace irr
+{
+namespace video
+{
+
+
+COpenGL3MaterialRenderer::COpenGL3MaterialRenderer(COpenGL3DriverBase* driver,
+ s32& outMaterialTypeNr,
+ const c8* vertexShaderProgram,
+ const c8* pixelShaderProgram,
+ IShaderConstantSetCallBack* callback,
+ E_MATERIAL_TYPE baseMaterial,
+ s32 userData)
+ : Driver(driver), CallBack(callback), Alpha(false), Blending(false), FixedBlending(false), Program(0), UserData(userData)
+{
+#ifdef _DEBUG
+ setDebugName("MaterialRenderer");
+#endif
+
+ switch (baseMaterial)
+ {
+ case EMT_TRANSPARENT_VERTEX_ALPHA:
+ case EMT_TRANSPARENT_ALPHA_CHANNEL:
+ Alpha = true;
+ break;
+ case EMT_TRANSPARENT_ADD_COLOR:
+ FixedBlending = true;
+ break;
+ case EMT_ONETEXTURE_BLEND:
+ Blending = true;
+ break;
+ default:
+ break;
+ }
+
+ if (CallBack)
+ CallBack->grab();
+
+ init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram);
+}
+
+
+COpenGL3MaterialRenderer::COpenGL3MaterialRenderer(COpenGL3DriverBase* driver,
+ IShaderConstantSetCallBack* callback,
+ E_MATERIAL_TYPE baseMaterial, s32 userData)
+: Driver(driver), CallBack(callback), Alpha(false), Blending(false), FixedBlending(false), Program(0), UserData(userData)
+{
+ switch (baseMaterial)
+ {
+ case EMT_TRANSPARENT_VERTEX_ALPHA:
+ case EMT_TRANSPARENT_ALPHA_CHANNEL:
+ Alpha = true;
+ break;
+ case EMT_TRANSPARENT_ADD_COLOR:
+ FixedBlending = true;
+ break;
+ case EMT_ONETEXTURE_BLEND:
+ Blending = true;
+ break;
+ default:
+ break;
+ }
+
+ if (CallBack)
+ CallBack->grab();
+}
+
+
+COpenGL3MaterialRenderer::~COpenGL3MaterialRenderer()
+{
+ if (CallBack)
+ CallBack->drop();
+
+ if (Program)
+ {
+ GLuint shaders[8];
+ GLint count;
+ glGetAttachedShaders(Program, 8, &count, shaders);
+
+ count=core::min_(count,8);
+ for (GLint i=0; i<count; ++i)
+ glDeleteShader(shaders[i]);
+ glDeleteProgram(Program);
+ Program = 0;
+ }
+
+ UniformInfo.clear();
+}
+
+GLuint COpenGL3MaterialRenderer::getProgram() const
+{
+ return Program;
+}
+
+void COpenGL3MaterialRenderer::init(s32& outMaterialTypeNr,
+ const c8* vertexShaderProgram,
+ const c8* pixelShaderProgram,
+ bool addMaterial)
+{
+ outMaterialTypeNr = -1;
+
+ Program = glCreateProgram();
+
+ if (!Program)
+ return;
+
+ if (vertexShaderProgram)
+ if (!createShader(GL_VERTEX_SHADER, vertexShaderProgram))
+ return;
+
+ if (pixelShaderProgram)
+ if (!createShader(GL_FRAGMENT_SHADER, pixelShaderProgram))
+ return;
+
+ for ( size_t i = 0; i < EVA_COUNT; ++i )
+ glBindAttribLocation( Program, i, sBuiltInVertexAttributeNames[i]);
+
+ if (!linkProgram())
+ return;
+
+ if (addMaterial)
+ outMaterialTypeNr = Driver->addMaterialRenderer(this);
+}
+
+
+bool COpenGL3MaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
+{
+ if (CallBack && Program)
+ CallBack->OnSetConstants(this, UserData);
+
+ return true;
+}
+
+
+void COpenGL3MaterialRenderer::OnSetMaterial(const video::SMaterial& material,
+ const video::SMaterial& lastMaterial,
+ bool resetAllRenderstates,
+ video::IMaterialRendererServices* services)
+{
+ COpenGL3CacheHandler* cacheHandler = Driver->getCacheHandler();
+
+ cacheHandler->setProgram(Program);
+
+ Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
+
+ if (Alpha)
+ {
+ cacheHandler->setBlend(true);
+ cacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ }
+ else if (FixedBlending)
+ {
+ cacheHandler->setBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_COLOR);
+ cacheHandler->setBlend(true);
+ }
+ else if (Blending)
+ {
+ E_BLEND_FACTOR srcRGBFact,dstRGBFact,srcAlphaFact,dstAlphaFact;
+ E_MODULATE_FUNC modulate;
+ u32 alphaSource;
+ unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulate, alphaSource, material.MaterialTypeParam);
+
+ cacheHandler->setBlendFuncSeparate(Driver->getGLBlend(srcRGBFact), Driver->getGLBlend(dstRGBFact),
+ Driver->getGLBlend(srcAlphaFact), Driver->getGLBlend(dstAlphaFact));
+
+ cacheHandler->setBlend(true);
+ }
+
+ if (CallBack)
+ CallBack->OnSetMaterial(material);
+}
+
+
+void COpenGL3MaterialRenderer::OnUnsetMaterial()
+{
+}
+
+
+bool COpenGL3MaterialRenderer::isTransparent() const
+{
+ return (Alpha || Blending || FixedBlending);
+}
+
+
+s32 COpenGL3MaterialRenderer::getRenderCapability() const
+{
+ return 0;
+}
+
+
+bool COpenGL3MaterialRenderer::createShader(GLenum shaderType, const char* shader)
+{
+ if (Program)
+ {
+ GLuint shaderHandle = glCreateShader(shaderType);
+ glShaderSource(shaderHandle, 1, &shader, NULL);
+ glCompileShader(shaderHandle);
+
+ GLint status = 0;
+
+ glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &status);
+
+ if (status != GL_TRUE)
+ {
+ os::Printer::log("GLSL shader failed to compile", ELL_ERROR);
+
+ GLint maxLength=0;
+ GLint length;
+
+ glGetShaderiv(shaderHandle, GL_INFO_LOG_LENGTH,
+ &maxLength);
+
+ if (maxLength)
+ {
+ GLchar *infoLog = new GLchar[maxLength];
+ glGetShaderInfoLog(shaderHandle, maxLength, &length, infoLog);
+ os::Printer::log(reinterpret_cast<const c8*>(infoLog), ELL_ERROR);
+ delete [] infoLog;
+ }
+
+ return false;
+ }
+
+ glAttachShader(Program, shaderHandle);
+ }
+
+ return true;
+}
+
+
+bool COpenGL3MaterialRenderer::linkProgram()
+{
+ if (Program)
+ {
+ glLinkProgram(Program);
+
+ GLint status = 0;
+
+ glGetProgramiv(Program, GL_LINK_STATUS, &status);
+
+ if (!status)
+ {
+ os::Printer::log("GLSL shader program failed to link", ELL_ERROR);
+
+ GLint maxLength=0;
+ GLsizei length;
+
+ glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &maxLength);
+
+ if (maxLength)
+ {
+ GLchar *infoLog = new GLchar[maxLength];
+ glGetProgramInfoLog(Program, maxLength, &length, infoLog);
+ os::Printer::log(reinterpret_cast<const c8*>(infoLog), ELL_ERROR);
+ delete [] infoLog;
+ }
+
+ return false;
+ }
+
+ GLint num = 0;
+
+ glGetProgramiv(Program, GL_ACTIVE_UNIFORMS, &num);
+
+ if (num == 0)
+ return true;
+
+ GLint maxlen = 0;
+
+ glGetProgramiv(Program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxlen);
+
+ if (maxlen == 0)
+ {
+ os::Printer::log("GLSL: failed to retrieve uniform information", ELL_ERROR);
+ return false;
+ }
+
+ // seems that some implementations use an extra null terminator.
+ ++maxlen;
+ c8 *buf = new c8[maxlen];
+
+ UniformInfo.clear();
+ UniformInfo.reallocate(num);
+
+ for (GLint i=0; i < num; ++i)
+ {
+ SUniformInfo ui;
+ memset(buf, 0, maxlen);
+
+ GLint size;
+ glGetActiveUniform(Program, i, maxlen, 0, &size, &ui.type, reinterpret_cast<GLchar*>(buf));
+
+ core::stringc name = "";
+
+ // array support, workaround for some bugged drivers.
+ for (s32 i = 0; i < maxlen; ++i)
+ {
+ if (buf[i] == '[' || buf[i] == '\0')
+ break;
+
+ name += buf[i];
+ }
+
+ ui.name = name;
+ ui.location = glGetUniformLocation(Program, buf);
+
+ UniformInfo.push_back(ui);
+ }
+
+ delete [] buf;
+ }
+
+ return true;
+}
+
+
+void COpenGL3MaterialRenderer::setBasicRenderStates(const SMaterial& material,
+ const SMaterial& lastMaterial,
+ bool resetAllRenderstates)
+{
+ Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
+}
+
+s32 COpenGL3MaterialRenderer::getVertexShaderConstantID(const c8* name)
+{
+ return getPixelShaderConstantID(name);
+}
+
+s32 COpenGL3MaterialRenderer::getPixelShaderConstantID(const c8* name)
+{
+ for (u32 i = 0; i < UniformInfo.size(); ++i)
+ {
+ if (UniformInfo[i].name == name)
+ return i;
+ }
+
+ return -1;
+}
+
+void COpenGL3MaterialRenderer::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)
+{
+ os::Printer::log("Cannot set constant, please use high level shader call instead.", ELL_WARNING);
+}
+
+void COpenGL3MaterialRenderer::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)
+{
+ os::Printer::log("Cannot set constant, use high level shader call.", ELL_WARNING);
+}
+
+bool COpenGL3MaterialRenderer::setVertexShaderConstant(s32 index, const f32* floats, int count)
+{
+ return setPixelShaderConstant(index, floats, count);
+}
+
+bool COpenGL3MaterialRenderer::setVertexShaderConstant(s32 index, const s32* ints, int count)
+{
+ return setPixelShaderConstant(index, ints, count);
+}
+
+bool COpenGL3MaterialRenderer::setVertexShaderConstant(s32 index, const u32* ints, int count)
+{
+ return setPixelShaderConstant(index, ints, count);
+}
+
+bool COpenGL3MaterialRenderer::setPixelShaderConstant(s32 index, const f32* floats, int count)
+{
+ if(index < 0 || UniformInfo[index].location < 0)
+ return false;
+
+ bool status = true;
+
+ switch (UniformInfo[index].type)
+ {
+ case GL_FLOAT:
+ glUniform1fv(UniformInfo[index].location, count, floats);
+ break;
+ case GL_FLOAT_VEC2:
+ glUniform2fv(UniformInfo[index].location, count/2, floats);
+ break;
+ case GL_FLOAT_VEC3:
+ glUniform3fv(UniformInfo[index].location, count/3, floats);
+ break;
+ case GL_FLOAT_VEC4:
+ glUniform4fv(UniformInfo[index].location, count/4, floats);
+ break;
+ case GL_FLOAT_MAT2:
+ glUniformMatrix2fv(UniformInfo[index].location, count/4, false, floats);
+ break;
+ case GL_FLOAT_MAT3:
+ glUniformMatrix3fv(UniformInfo[index].location, count/9, false, floats);
+ break;
+ case GL_FLOAT_MAT4:
+ glUniformMatrix4fv(UniformInfo[index].location, count/16, false, floats);
+ break;
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_CUBE:
+ {
+ if(floats)
+ {
+ const GLint id = (GLint)(*floats);
+ glUniform1iv(UniformInfo[index].location, 1, &id);
+ }
+ else
+ status = false;
+ }
+ break;
+ default:
+ status = false;
+ break;
+ }
+
+ return status;
+}
+
+bool COpenGL3MaterialRenderer::setPixelShaderConstant(s32 index, const s32* ints, int count)
+{
+ if(index < 0 || UniformInfo[index].location < 0)
+ return false;
+
+ bool status = true;
+
+ switch (UniformInfo[index].type)
+ {
+ case GL_INT:
+ case GL_BOOL:
+ glUniform1iv(UniformInfo[index].location, count, ints);
+ break;
+ case GL_INT_VEC2:
+ case GL_BOOL_VEC2:
+ glUniform2iv(UniformInfo[index].location, count/2, ints);
+ break;
+ case GL_INT_VEC3:
+ case GL_BOOL_VEC3:
+ glUniform3iv(UniformInfo[index].location, count/3, ints);
+ break;
+ case GL_INT_VEC4:
+ case GL_BOOL_VEC4:
+ glUniform4iv(UniformInfo[index].location, count/4, ints);
+ break;
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_CUBE:
+ glUniform1iv(UniformInfo[index].location, 1, ints);
+ break;
+ default:
+ status = false;
+ break;
+ }
+
+ return status;
+}
+
+bool COpenGL3MaterialRenderer::setPixelShaderConstant(s32 index, const u32* ints, int count)
+{
+ os::Printer::log("Unsigned int support needs at least GLES 3.0", ELL_WARNING);
+ return false;
+}
+
+IVideoDriver* COpenGL3MaterialRenderer::getVideoDriver()
+{
+ return Driver;
+}
+
+}
+}