GLSL - setting samplers
Posted: Thu Apr 13, 2006 1:38 pm
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 -
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 :
In COpenGLDriver.cpp - add :
to the ctor initialization list, add :
for the windows portion of the exetension loading code and
for the linux portion of the extension loading code. And then add this function to COpenGLDriver.cpp also -
Then, in IMaterialRenderer.h, add :
In D3D8Driver.h and D3D9Driver.h, add :
In COpenGLDriver.h, add :
And then add this function to COpenGLDriver.cpp :
Finally, add this -
to COpenGLSLMaterialRenderer.h, and this
to COpenGLSLMaterialRenderer.cpp
So, for fragment program, I use this node -
and in my IShaderConstantSetCallBack, I do this -
And voila, now I can access more than just the 1st texture stage in GLSL!!!
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 COpenGLDirver.h - add :
Code: Select all
void extGlUniform1iARB (GLint loc, GLint v0);
PFNGLUNIFORM1IARBPROC pGlUniform1iARB;
In COpenGLDriver.cpp - add :
Code: Select all
pGlUniform1iARB(0)
Code: Select all
pGlUniform1iARB = (PFNGLUNIFORM1IARBPROC) wglGetProcAddress("glUniform1iARB");
Code: Select all
pGlUniform1iARB = (PFNGLUNIFORM1IARBPROC)
IRR_OGL_LOAD_EXTENSION(reinterpret_cast<const GLubyte*>("glUniform1iARB"));
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
}
Code: Select all
//! Used for GLSL to link textures to samplers
virtual void setGLSLSampler(const c8* name, u8 textureStage) = 0;
Code: Select all
//! NOT USED for this video driver
virtual void setGLSLSampler(const c8* name, u8 textureStage) {}
Code: Select all
//! Used for GLSL to link textures to samplers
virtual void setGLSLSampler(const c8* name, u8 textureStage);
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().");
}
Code: Select all
virtual void setGLSLSampler(const c8* name, u8 textureStage);
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 );
}
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);
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 );
}