Search code examples
c++openglrenderingglewfreeglut

How to use more than one shader program?


Using one shader program my code looks something like this:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
InitFunctions();
glUseProgram(ShaderProgram);

//render objects

glutSwapBuffers();

But I wanted to add another shader program but it seems to clear the screen. Even just putting this after rendering the objects clears the screen:

glUseProgram(ShaderProgramNew);

The only time the screen it doesn't clear the screen is when I use the same shader in both uses of glUseProgram()

To load the shaders i use this function:

GLuint ShaderProgramManager::loadProgram(char* VertexShaderFileLocation, char*     FragmentShaderFileLocation){

cout << "Creating Shader...\n";
cout << "Initalizing Variables\n";
GLuint ShaderProgram = glCreateProgram();
GLuint VertexShader = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

string VString = loadShader(VertexShaderFileLocation);
string FString = loadShader(FragmentShaderFileLocation);

const GLchar* VText = (const GLchar*)VString.c_str();
const GLchar* FText = (const GLchar*)FString.c_str();

cout << "Load VertexShader and FragmentShader\n";

const GLchar* pp[1];
pp[0] = FText;
GLint Lengthss[1];
Lengthss[0] = strlen(FText);
glShaderSource(FragmentShader, 1, (const GLchar**)&pp, Lengthss);
glCompileShader(FragmentShader);

const GLchar* p[1];
p[0] = VText;
GLint Lengths[1];
Lengths[0] = strlen(VText);
glShaderSource(VertexShader, 1, (const GLchar**)&p, Lengths);
glCompileShader(VertexShader);

GLint success;
glGetShaderiv(FragmentShader, GL_COMPILE_STATUS, &success);
if (!success) {
    GLchar InfoLog[1024];
    glGetShaderInfoLog(FragmentShader, sizeof(InfoLog), NULL, InfoLog);
    fprintf(stderr, "Error compiling shader type %d: '%s'\n", GL_FRAGMENT_SHADER, InfoLog);
}


glGetShaderiv(VertexShader, GL_COMPILE_STATUS, &success);
if (!success) {
    GLchar InfoLog[1024];
    glGetShaderInfoLog(VertexShader, sizeof(InfoLog), NULL, InfoLog);
    fprintf(stderr, "Error compiling shader type %d: '%s'\n", GL_VERTEX_SHADER, InfoLog);
}

cout << "Shaders Compiled.\n";



cout << "Attach Shaders\n";
glAttachShader(ShaderProgram, VertexShader);
glAttachShader(ShaderProgram, FragmentShader);

cout << "Link Program\n";
glLinkProgram(ShaderProgram);

cout << "Validate Program\n";
glValidateProgram(ShaderProgram);
cout << "Complete.\n";
return ShaderProgram;

}

And this:

string ShaderProgramManager::loadShader(char* location){

string textS = "";
string line;
ifstream myfile(location);

cout << "Start of shader tex:\n" << "\n";

    while (getline(myfile, line))
    {
        //cout << line << "\n\n";
        textS = textS + line + "\n";
    }

    cout << "End of shader text" << "\n";

    //text = new char[sizeOfCharArray];
    //strcat(text, textS.c_str());
    myfile.close();

    cout << "Shader Finished Loading.\n";


    return  textS;
}

At the start of the program i run this

ShaderProgramManager spm;

    ShaderProgram = spm.loadProgram("data/Shaders/VertexShader.txt", "data/Shaders/FragmentShader.txt");

        gWorldLocation = glGetUniformLocation(ShaderProgram, "gWorld");
        rotmLocation = glGetUniformLocation(ShaderProgram, "rotm");
        PermLocation = glGetUniformLocation(ShaderProgram, "persm");

Solution

  • This solutions works perfectly for me, when I want to use 2 different shader during one render pass.

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glUseProgram(shaderProgram01);
    
    // Do Modelview and projection matrix stuff and uniforms
    
    // Render objects with fstshaderProgram
    
    glUseProgram(shaderProgram02);
    // Do Modelview and projection matrix stuff and uniforms
    
    // Render objects with 2nd shaderProgram
    
    glutSwapBuffers();
    

    Very important is that you have to reupload all the needed uniforms. For this approach I assume that you are loading the shaders correctly and that they are working without problems. Using glut you only call glutSwapBuffers() one per iteration.