Issues with rendering multiple textures

Hello all,

Thanks in advance for taking the time to read this.

I have come across an issue when trying to render multiple textures. The debugging process is slightly confounded by the fact that I am using haskell, so its not super straight forward to map, opengl calls to haskell functions. Still the below code should be pretty reminiscent of what you would expect:

      GL.activeTexture $= GL.TextureUnit 1
      wall <- either error id <$> GLUtil.readTexture "assets/wall.jpg"
      GL.textureFilter GL.Texture2D $= ((GL.Linear', Nothing), GL.Linear')
      GLUtil.texture2DWrap $= (GL.Repeated, GL.ClampToBorder)
      GL.textureBinding GL.Texture2D $= Just wall
      GL.texture GL.Texture2D $= GL.Enabled

      GL.activeTexture $= GL.TextureUnit 2
      smiley <- either error id <$> 
        readTexInfoFlipped "assets/awesomeface.png" GLUtil.loadTexture
      GL.textureFilter GL.Texture2D $= ((GL.Linear', Nothing), GL.Linear')
      GLUtil.texture2DWrap $= (GL.Repeated, GL.ClampToBorder)
      GL.textureBinding GL.Texture2D $= Just smiley
      GL.texture GL.Texture2D $= GL.Enabled

      texture1 <- GL.get $ GL.uniformLocation program "texture1"
      GL.uniform texture1 $= GL.TextureUnit 1

      texture2 <- GL.get $ GL.uniformLocation program "texture2"
      GL.uniform texture2 $= GL.TextureUnit 2

This code does not work, and in fact renders a black screen (I have tried just rendering one or the other texture and it only works if I use the default texture unit (0), so I suspect I am having issues communicating texture units to the shader)

The only way I can make it work is by doing this with the uniforms in my fragment shader:

...
layout(binding=1) uniform sampler2D texture1;
layout(binding=2) uniform sampler2D texture2;
...

Does anyone have any ideas why I am running into this? Could it be something with my gpu (NVIDIA GeForce RTX 3050 Mobile)? Any help is appreciated!

Here is some more information:

 GLFW C library:
        Version: 3.3.2
        Version string: Just "3.3.2 X11 GLX EGL OSMesa clock_gettime evdev"
    OpenGL context:
        Client API: ClientAPI'OpenGL
        Version: 4.6.0
        Robustness: ContextRobustness'NoResetNotification
        Forward compatibility: False
        Debug: False
        Profile: OpenGLProfile'Compat

I am on wayland if that confounds things even more

My guess is that you forgot to do the equivalent of glUseProgram(program) before calling GL.uniform. glUniform sets uniform variables in the default uniform block of the active program object; for this to work as intended, there has to actually be an active program object and it has to be the program object you intended to modify.

There isn’t an equivalent DSA (direct state access) function to set uniforms in some arbitrary program object referenced by name.

1 Like

Additionally, this looks like it is assigning the values of GL_TEXTURE1 and GL_TEXTURE2 as the uniforms’ values (I don’t know any haskell and what magic its OpenGL wrappers perform). IIRC in order to access the textures bound to units 1, 2 you assign the values 1 and 2 to the sampler uniforms respectively.

You may want to look into tools like RenderDoc or apitrace to capture the raw OpenGL calls made by your application - those would likely look more familiar to many folks here :wink:

1 Like

Oh my gosh, I can’t believe I missed this, I was binding the uniforms before I had activated my program object, such a silly mistake.

Thank you so much!

Okay, thank you so much for these resources. I was wondering if there was a way that I could get the raw OpenGL calls (for personal debugging AND so I don’t have to inflict haskell on you all). Will post with the raw opengl in the future!