Click here to Skip to main content
15,867,686 members
Articles / Multimedia / OpenGL

GLSL Shader for Interpolating Two Textures

Rate me:
Please Sign up or sign in to vote.
4.60/5 (5 votes)
24 Jun 2010CPOL2 min read 50.6K   2.4K   10   7
A simple shader developed in GLSL for interpolating two textures

Introduction

This sample application demonstrates a simple shader for interpolating two textures.

The screenshot of Interpolation of two bitmaps Kerala.bmp and Shrine.bmp.

Screenshot.jpg

Background

Shaders are an very interesting feature in OpenGL. This article shows a simple pixel shader for interpolating two textures.

There are three types of shaders:

  • Fragment or Pixel shader
  • Vertex Shader
  • Geometry Shader

A Pixel Shader is a program which will be processed (executed) for each pixel of a rendering. The output color of each pixel is determined by the shader program.

From GLSL spec,

The fragment processor is a programmable unit that operates on fragment values and their associated data. Compilation units written in the OpenGL Shading Language to run on this processor are called fragment shaders.

Using the Code

First time I created a shader program in CG. At runtime, it requires cg.dll and CGGL.dll. When I deployed my binaries, installation of Cg is necessary for running my application. If we are using GLSL, we can avoid this dependency with Cg.dll and CgGl.dll. Only dependency is that the PC should have shader support.

opengl32.dll exposes functions for basic opengl functionalities, others (GPU dependent functionalities) are implemented as opengl extensions. Opengl provides GL_ARB_fragment_shader extension for pixel shader programs.

GLExtension class handles all opengl extension operations. This class exposes the following functions (the required functions for GLSL pixels shader with texturing).

C++
// This Singleton class hold all function pointers of opengl Extensions.
// Functions similar to opengl extension are provided in this class. 
// All function will call corresponding function pointer.
class GLExtension
{
public:

    GLhandleARB glCreateProgramObjectARB();
    GLhandleARB glCreateShaderObjectARB(GLenum shaderType);
    void glShaderSourceARB( GLhandleARB shader, GLuint number_strings,
                            const GLcharARB** strings, GLint * length);
    void glAttachObjectARB(GLhandleARB program, GLhandleARB shader);
    void glLinkProgramARB(GLhandleARB program);
    void glCompileShader(GLhandleARB program);
    void glUseProgramObjectARB(GLhandleARB program);
    void glDeleteObjectARB(GLhandleARB object);
    void glGetInfoLogARB(GLhandleARB object, GLsizei maxLenght, GLsizei *length, 
	GLbyte*infoLog);
    GLint glGetUniformLocationARB(GLhandleARB program, const GLbyte* name);
    GLint glGetAttribLocationARB(GLhandleARB program, const GLbyte* name);
    void glUniform1iARB(GLuint index, int val);
    void glUniform1fARB(GLuint index, float fval);
    void glActiveTexture(GLenum Texture);

public:

    static GLExtension* GetInstance();
    // pFailedFunction Return NULL is all wglGetProcAddress are success.
    // Else return the name of failed function. Application should delete this buffer.
    bool GetWglProcAddress( TCHAR*& pFailedFunction );

private:

    // Constructor and destructor defined in private section for Singleton behaviour.
    GLExtension(void);
    ~GLExtension(void);
};

GLSLShader class is created to create a GLSL shader with opengl extensions. CreateProgram can create a shader with the help of GLExtension class.

C++
// Shader class handles creating of a Shader, and parameter setting to the 
// GLSL Shader. This class uses GLExtension for calling opengl extension functions.
class GLSLShader
{
public:
    GLSLShader(void);
    // nProgramID_i is the resource ID of Shader.
    // glSlShaderType_i should be GL_FRAGMENT_PROGRAM_ARB, GL_VERTEX_PROGRAM_ARB
    bool CreateProgram( const int nProgramID_i, GLenum glSlShaderType_i );
    bool DeleteShader();
    bool EnableShader();
    bool DisableShader();
    // This function attach a texture to shader parameter.
    // pParamName_i is parameter name given in shader.
    bool SetTexture( const CHAR* pParamName_i, const int nTextureID_i, int nIndex = 0 );
    // This function passes a float value to Shader float parameter.
    bool SetParam( const CHAR* pParamName_i, const float fValue_i );
    ~GLSLShader(void);

private:
   static GLhandleARB m_hProgramObject;
   GLhandleARB m_hShaderHandle;
}; 

Finally, I’ll show interpolation pixel shader, which can interpolate two textures based on an interpolation value.

C++
uniform sampler2D texture1;
uniform sampler2D texture2;
uniform float fInterpValue;
void main()
{
	vec4 Color2 = texture2D(texture2,gl_TexCoord[0].st);
	vec4 Color1 = texture2D(texture1,gl_TexCoord[0].st);
	gl_FragColor = ( 1.0 - fInterpValue )* Color1 + fInterpValue * Color2;
}  

The value of fInterpValue determines the contribution of texture1 and texture2. If fInterpValue is 0, then color1(texture1) will be output and if fInterpValue is 1, then colro2( texture2 ) will be the output.

A scrollbar is created to change the interpolation value. Whenever scrollbar changes its position, it will be updated to shader.

CInterpolationDlg calls GLSetup::InitGL(), GLSetup wraps opengl initialisation and deletion of opengl rendering context. Most of the opengl function calls are avoided from Dialog class.

CInterpolationDlg::OnInitDialog() creates a Timer for displaying 60 frames in a second.

Points of Interest

If we are creating shader from a file, the shader file is also required with binary. Here I'm creating shader from resource. I just added the shader file pixelshader.cg into the resource. GLSLShader::CreateProgram() receives the resource id of pixelshader.cg. Then calls LoadResource() and LockResource() for getting the data from resource. And Interpolation.exe can run without pixelshader.cg, because it's already embedded in Interpolation.exe as a resource.

MC++
bool GLSLShader::CreateProgram( const int nProgramID_i, GLenum glSlShaderType_i )
{
    HRSRC hrResInfo = FindResource( 0, MAKEINTRESOURCE( nProgramID_i ),
	TEXT("IDR_DATA"));
    if( 0 == hrResInfo )
    {
        return false;
    }
    HGLOBAL hRcResource =  LoadResource(0, hrResInfo  );
    const CHAR* pBufferResData = (CHAR* )LockResource( hRcResource );
    m_hShaderHandle = GLExtension::GetInstance()->
	glCreateShaderObjectARB( GL_FRAGMENT_PROGRAM_ARB );
} 

And textures are also created from two bitmaps. Here also bitmap files are hidden as resource and avoided dependency with a bitmap file.

C++
  // Macro for getting function pointers of Extension functions.
#define GET_PROC_ADDRESS(fname, failedFunName)\
{\
    Obj_##fname = (FPTR_##fname)wglGetProcAddress( #fname ); \
    if( 0 == Obj_##fname ) \
    { \
        failedFunName = new TCHAR[strlen(#fname)+1]; \
        wcscpy( failedFunName, L#fname ); \
        return false; \
    } \
}\ 

History

  • Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralUse integrated GLSL functions Pin
Agnius Vasiliauskas10-Jul-10 4:41
Agnius Vasiliauskas10-Jul-10 4:41 
GeneralRe: Use integrated GLSL functions Pin
Santhosh G_2-Aug-10 2:09
Santhosh G_2-Aug-10 2:09 
GeneralShader creation failed Pin
Adrian Pasik24-Jun-10 1:35
Adrian Pasik24-Jun-10 1:35 
GeneralRe: Shader creation failed Pin
Santhosh G_24-Jun-10 2:32
Santhosh G_24-Jun-10 2:32 
GeneralRe: Shader creation failed - [solved] Pin
enhzflep24-Jun-11 22:41
enhzflep24-Jun-11 22:41 
I get the same message.

EDIT: I tried to change the shader's code, to check that it wasn't using features my hardware doesn't support by substituting it with the following:
void main()
{
	gl_FragColor = vec4(0.4,0.4,0.8,1.0);
}

This also failed. Don't know why this is yet, I'm stil trying to get any glsl hello-work app working right now, since they seem to commonly rely on glaux.

Hardware:
Renderer: Intel(R) Graphics Media Accelerator HD
Vendor: Intel
Memory: 1755 MB
Version: 2.1.0 - Build 8.15.10.2057
Shading language version: 1.20 - Intel Build 8.15.10.2057


Otherwise, thank-you for the articles and for the example code of how to go about loading the extensions, without resorting to glut, glaux or any of the other libs. While glut & glaux seem great, I want the ability to use a window of my choosing to host the GL content - be it dialog-control, window or full-screen. - couldn't seem to do that with glut, and I don't seem to have glaux

I'd love to give it a 4, though struggle to since the compiled program won't work nor give me a strong enough indication of why not. We'll see. Wink | ;)


[EDIT #2]: I managed to track the source of the problem.. It seems that GLSLShader::CreateProgram would exit with an error. This was happening after the shader source had be assigned and compiled. Looking closer, found that the reason for this exit was that the infoLog created when the shader was compiled had a non-zero length. Investigating further, I discovered the log to contain the text
"No errors."

I.e because the infolog contained the text "No errors." GLSLShader::CreateProgram was returning false, indicating failure. :oops:.
I'm a happy camper now. I'll be sending you my 4. Smile | :)

modified on Sunday, June 26, 2011 12:28 AM

GeneralRe: Shader creation failed - [solved] Pin
Santhosh G_30-Jun-11 6:43
Santhosh G_30-Jun-11 6:43 
GeneralRe: Shader creation failed - [solved] Pin
enhzflep30-Jun-11 6:59
enhzflep30-Jun-11 6:59 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.