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