GLSL - setting samplers

You discovered a bug in the engine, and you are sure that it is not a problem of your code? Just post it in here. Please read the bug posting guidelines first.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

GLSL - setting samplers

Post by Spintz »

GLSL requires you to set the values of the samplers in your fragment shader to a texture stage from the engine. Take this GLSL fragment program as an example -

Code: Select all

uniform vec3 distortion_amount;
uniform vec2 height_attenuation;

uniform sampler2D fire_base;
uniform sampler2D fire_distortion;
uniform sampler2D fire_opacity;

varying vec2  vTexCoord0;
varying vec2  vTexCoord1;
varying vec2  vTexCoord2;
varying vec2  vTexCoord3;

void main(void)
{
...
In the current Irrlicht, fire_base, fire_distortion and fire_opacity all will be set to texture stage 0( the default ). Here are the code changes to be able to set these samplers to specific textures -

In COpenGLDirver.h - add :

Code: Select all

void extGlUniform1iARB  (GLint loc, GLint v0);
PFNGLUNIFORM1IARBPROC pGlUniform1iARB;

In COpenGLDriver.cpp - add :

Code: Select all

pGlUniform1iARB(0)
to the ctor initialization list, add :

Code: Select all

pGlUniform1iARB = (PFNGLUNIFORM1IARBPROC) wglGetProcAddress("glUniform1iARB");
for the windows portion of the exetension loading code and

Code: Select all

pGlUniform1iARB = (PFNGLUNIFORM1IARBPROC)
	IRR_OGL_LOAD_EXTENSION(reinterpret_cast<const GLubyte*>("glUniform1iARB"));
for the linux portion of the extension loading code. And then add this function to COpenGLDriver.cpp also -

Code: Select all

void COpenGLDriver::extGlUniform1iARB  (GLint loc, GLint v0)
{
#if defined(_IRR_WINDOWS_) || defined(_IRR_LINUX_OPENGL_USE_EXTENSIONS_) 
    if (pGlUniform1iARB)
        pGlUniform1iARB(loc, v0);
#endif
}
Then, in IMaterialRenderer.h, add :

Code: Select all

//! Used for GLSL to link textures to samplers
virtual void setGLSLSampler(const c8* name, u8 textureStage) = 0;
In D3D8Driver.h and D3D9Driver.h, add :

Code: Select all

//! NOT USED for this video driver
virtual void setGLSLSampler(const c8* name, u8 textureStage) {}
In COpenGLDriver.h, add :

Code: Select all

//! Used for GLSL to link textures to samplers
virtual void setGLSLSampler(const c8* name, u8 textureStage);
And then add this function to COpenGLDriver.cpp :

Code: Select all

//! Used for GLSL to link textures to samplers
void COpenGLDriver::setGLSLSampler(const c8* name, u8 textureStage)
{
	os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant().");
}
Finally, add this -

Code: Select all

virtual void setGLSLSampler(const c8* name, u8 textureStage);
to COpenGLSLMaterialRenderer.h, and this

Code: Select all

//! Used for GLSL to link textures to samplers
void COpenGLSLMaterialRenderer::setGLSLSampler(const c8* name, u8 textureStage)
{
    s32 i = 0, num = (s32)UniformInfo.size();

    for (; i < num; i++)
	{
        if (UniformInfo[i].name == name) 
			break;
    }

    if (i == num) 
		return;

	Driver->extGlUniform1iARB( i, textureStage );
}
to COpenGLSLMaterialRenderer.cpp

So, for fragment program, I use this node -

Code: Select all

// FLAME 
billboardNode = smgr->addBillboardSceneNode( 0, billboardSize );
billboardNode->setMaterialTexture( 0, firebase );
billboardNode->setMaterialTexture( 1, tex2Dnoise );
billboardNode->setMaterialTexture( 2, fireopacity );
billboardNode->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType1);
and in my IShaderConstantSetCallBack, I do this -

Code: Select all

if( driver->getDriverType() == video::EDT_OPENGL )
{
			// GLSL requires us to set texture uniforms
			services->setGLSLSampler("fire_base", 0 );
			services->setGLSLSampler("fire_distortion", 1 );
			services->setGLSLSampler("fire_opacity", 2 );
}
And voila, now I can access more than just the 1st texture stage in GLSL!!!
Image
chromdragon
Posts: 101
Joined: Wed Feb 15, 2006 4:22 pm
Location: RO

Post by chromdragon »

Great! Very nice!
chromdragon
Posts: 101
Joined: Wed Feb 15, 2006 4:22 pm
Location: RO

Post by chromdragon »

a little trick: (no more setGLSLSampler())

Code: Select all


bool COpenGLSLMaterialRenderer::setPixelShaderConstant(const c8* name, const f32* floats, int count)
{
    int i = 0, num = (int)UniformInfo.size();

    for (; i < num; i++)
	{
        if (UniformInfo[i].name == name) 
			break;
    }

    if (i == num) return false;

    switch (UniformInfo[i].type) 
	{
		case GL_INT:
		case GL_SAMPLER_1D_ARB:
		case GL_SAMPLER_2D_ARB:
		case GL_SAMPLER_3D_ARB:
		case GL_SAMPLER_CUBE_ARB:
			Driver->extGlUniform1iARB(i, (s32) *floats);
			break;
	
		case GL_FLOAT:          
			Driver->extGlUniform1fvARB(i, count, floats); 
			break;
        case GL_FLOAT_VEC2_ARB: 
			Driver->extGlUniform2fvARB(i, count/2, floats); 
			break;
        case GL_FLOAT_VEC3_ARB: 
			Driver->extGlUniform3fvARB(i, count/3, floats); 
			break;
        case GL_FLOAT_VEC4_ARB: 
			Driver->extGlUniform4fvARB(i, count/4, floats); 
			break;
        case GL_FLOAT_MAT2_ARB: 
			Driver->extGlUniformMatrix2fvARB(i, count/4, false, floats); 
			break;
        case GL_FLOAT_MAT3_ARB: 
			Driver->extGlUniformMatrix3fvARB(i, count/9, false, floats); 
			break;
        case GL_FLOAT_MAT4_ARB: 
			Driver->extGlUniformMatrix4fvARB(i, count/16, false, floats); 
			break;
        default: 
			return false;
    }

    return true;
}

gfxstyler
Posts: 222
Joined: Tue Apr 18, 2006 11:47 pm

Post by gfxstyler »

erm... does this allow us to use more than 1 texture with glsl? im no shader experienced :D
chromdragon
Posts: 101
Joined: Wed Feb 15, 2006 4:22 pm
Location: RO

Post by chromdragon »

yup!
casty
Posts: 11
Joined: Sun Aug 27, 2006 10:40 am

Post by casty »

I expected to see that change in 1.1, what are they waiting for?
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Money 8)
Or warm and friendly words :wink:
Oh, it's already in :shock: Maybe you can send money nonetheless :?:
casty
Posts: 11
Joined: Sun Aug 27, 2006 10:40 am

Post by casty »

My words cannot be more friendly, I didn´t say "the hell". 8)

Really?

I haven't seen the difference in 1.1.

'setPixelShaderConstat' still not have GL_SAMPLER_xD_ARB options. Maybe I downloaded the wrong file. But I cannot either find it in changes.txt.
Eternl Knight
Posts: 313
Joined: Tue Nov 01, 2005 5:01 am

Post by Eternl Knight »

I'd give you a warm and friendly hug hybrid, but the last guy I did that too gave me a black eye :P

--EK
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Oh thank you :D I promise I won't :wink:
BTW: The code by chromdragon is at least in the SVN version of Irrlicht, I don't have 1.1 on this system right now. But it shoudl be easy to check for anyone :wink:
casty
Posts: 11
Joined: Sun Aug 27, 2006 10:40 am

Post by casty »

Yes, sorry it is in 1.1.

I expected to see it in the same way chromdragon wrote it.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

:D That's art :wink:
DeusXL
Posts: 114
Joined: Sun Mar 14, 2004 9:37 am
Contact:

Post by DeusXL »

Just looked to Irrlicht 1.1, chromdragon's work is actually here but it does not seem to work...

Here's my fragment program :

Code: Select all

uniform sampler2D myTexture1;
uniform sampler2D myTexture2;

void main (void)
{
   vec4 texval1 = texture2D(myTexture1, vec2(gl_TexCoord[0]));
   vec4 texval2 = texture2D(myTexture2, vec2(gl_TexCoord[1]));
   
   gl_FragColor = 0.5*(texval1 + texval2);
}
And the shader set callback :

Code: Select all

static void OnShaderSet(MaterialRendererServices services, int userData)
        {
            services.SetPixelShaderConstant("myTexture1", new float[] { 0 }, 1);
            services.SetPixelShaderConstant("myTexture2", new float[] { 1 }, 1);
        }
As you may see, it should just perform a basic multitexturing but the color returned seems to be nothing at all (it is transparent).
I tried by modifying the callback's second line and setting "new float[] { 0 }" instead and the multitexturing worked perfectly...

The code that is missing :
In COpenGLSLMaterialRenderer.cpp :

Code: Select all

		  case GL_INT:
		  case GL_SAMPLER_1D_ARB:
		  case GL_SAMPLER_2D_ARB:
		  case GL_SAMPLER_3D_ARB:
		  case GL_SAMPLER_CUBE_ARB:				
			Driver->extGlUniform1iARB(i, (s32) *floats);
			break; 
(on switch (UniformInfo.type))

And then create the function extGlUniform1iARB as Spintz described it.

For now it is late but tommorow I'll try to modify Irrlicht and if I can do it, I'll send you the code :)
Irrlicht .NET complete and Cross Platform Wrapper
The kid on my avatar wrote:A painless lesson is one without any meaning
DeusXL
Posts: 114
Joined: Sun Mar 14, 2004 9:37 am
Contact:

Post by DeusXL »

Just added chromdragon's code and Spintz's code (until Then, in IMaterialRenderer.h, add : ) and it works perfectly !
Irrlicht .NET complete and Cross Platform Wrapper
The kid on my avatar wrote:A painless lesson is one without any meaning
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Hmm, shouldn't Uniform1iv perform the same as Uniform1i if count is 1 (and of course passing int or pointer)?! Maybe the missing return false might make some errors harder to recognize, but the basic functionality should be there.
Post Reply