paj777
paj777

Reputation: 255

Problem Loading multiple textures using multiple shaders with GLSL

I am trying to use multiple textures in the same scene but no matter what I try the same texture is loaded for each object. So this what I am doing at the moment, I initialise each shader:

rightWall.SendShaders("wall.vert","wall.frag","brick3.bmp", "wallTex", 0);      
demoFloor.SendShaders("floor.vert","floor.frag","dirt1.bmp", "floorTex", 1);

The code in SendShaders is:

            GLuint vert,frag;
            glEnable(GL_DEPTH_TEST);
            glEnable(GL_TEXTURE_2D);

            char *vs = NULL,*fs = NULL;

            vert = glCreateShader(GL_VERTEX_SHADER);
            frag = glCreateShader(GL_FRAGMENT_SHADER);

            vs = textFileRead(vertFile);
            fs = textFileRead(fragFile);
            const char * ff = fs;
            const char * vv = vs;

            glShaderSource(vert, 1, &vv, NULL);
            glShaderSource(frag, 1, &ff, NULL);

            free(vs); free(fs);

            glCompileShader(vert);
            glCompileShader(frag);

            program = glCreateProgram();
            glAttachShader(program, frag);
            glAttachShader(program, vert);

            glLinkProgram(program);
            glUseProgram(program);

        LoadGLTexture(textureImage, texture);

And then in the main loop:

rightWall.UseShader("wallTex");
rightWall.Draw();   

demoFloor.UseShader("floorTex");
demoFloor.Draw();

The code in UseShader:

void GraphicsObject::UseShader(char textureName []){

glUseProgram(program);  
GLint location = glGetUniformLocation(program, textureName);
glUniform1i(location, 0); 
glActiveTexture(GL_TEXTURE0);           
glBindTexture(GL_TEXTURE_2D, texture);

}

And finally, the texture load methods:

int GraphicsObject::LoadGLTexture(const char fileName []){

AUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture
memset(TextureImage,0,sizeof(void *)*1); // Set The Pointer To NULL
int arraySize = strlen(fileName); 
arraySize += 1;
 if (TextureImage[0]=LoadBMP(fileName, arraySize))
{
              glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TextureImage[0]->sizeX, 
    TextureImage[0]->sizeY, 0, GL_RGB,         
     GL_UNSIGNED_BYTE, TextureImage[0]->data);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);       
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);       
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);        
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);        
 }
if (TextureImage[0])
{
        if (TextureImage[0]->data)
    {
            free(TextureImage[0]->data);    
                }
    free(TextureImage[0]);              
}   

return 1;

}

AUX_RGBImageRec* GraphicsObject::LoadBMP(const char fileName[], int arraySize){

FILE *File=NULL; 
LPWSTR pwszFileName;
int lenW;
BSTR unicodestr;

lenW = MultiByteToWideChar(CP_ACP, 0, fileName, arraySize, 0,0);

DWORD bottom = GetLastError();
unicodestr = SysAllocStringLen(0, lenW);

MultiByteToWideChar(CP_ACP,0, fileName, arraySize,
    unicodestr,lenW);
SysFreeString(unicodestr);
DWORD tit = GetLastError();

if (!fileName) 
{
    return NULL; 
}

File=fopen(fileName,"r"); 

if (File) 
{
    fclose(File);
    return auxDIBImageLoad((LPCWSTR)unicodestr);
}
return NULL;

}

Which ever shader is initialised last is the texture which is used for both objects. Thank you for your time and I appreciate any comments.

Upvotes: 1

Views: 2582

Answers (2)

Jose
Jose

Reputation: 311

I'm going to point out the obvious just to make sure you can rule it out.

Is your texture image data actually different? Have you checked your texture loading code to make sure you are getting different files for the texture?

Upvotes: 1

Danvil
Danvil

Reputation: 22991

Like you have to call glUseProgram(program) before using the shader for rendering, you also have to bind the right texture directly before rendering.

The code should look like this:

glUseProgram(program1);
glBindTexture(GL_TEXTURE_2D, texture1);
// render calls for object 1

glUseProgram(program2);
glBindTexture(GL_TEXTURE_2D, texture2);
// render calls for object 2

Moreover also Uniforms must be set directly before rendering, and not at shader intialization.

So in your case the part

GLint location = glGetUniformLocation(program, textureName);
glUniform1i(location, 0);
glActiveTexture(GL_TEXTURE0);           
glBindTexture(GL_TEXTURE_2D, texture);

does not belong in the function SendShaders, but in UseShader!

Upvotes: 3

Related Questions