I'm having a hard time understanding why this code doesn't end up displaying the container_specular image rather than the diffuse. I'm explicitly setting fragColor to be specular, so why would it show the diffuse instead? Thanks.
#Can't display two textures OpenGL
1 messages · Page 1 of 1 (latest)
it seems to be resolved by doing two things. First is setting the uniforms with gl.Uniform1i and not gl.Uniform1ui.
set_uniform(cube_shader, "material.diffuse", i32(container_texture))
set_uniform(cube_shader, "material.specular", i32(container_specular))
the second is to set the active textures as 1 and 2, not 0 and 1. I don't know why this is, if anyone has more info I'd appreciate it!
gl.ActiveTexture(gl.TEXTURE1);
gl.BindTexture(gl.TEXTURE_2D, container_texture)
gl.ActiveTexture(gl.TEXTURE2);
gl.BindTexture(gl.TEXTURE_2D, container_specular)
i think i know
but im gonna vomit some ideas in because im not entirely sure if they are correct
so this part here is correct, you bind texture handlers to the texture units in the shader
this one isn't correct
and the reason that setting the active textures to 1 and 2 works makes sense, do check the values for container_texture and container_specular and I'm gonna assume they match 1 and 2 respectively
so the main problem is that you misunderstood how you use glUniform1i to point towards a texture
you first do this, so you can bind your textures to the units in the shader
then you just set material.diffuse/specular to point to that unit in your shader
so
gl.ActiveTexture(gl.TEXTURE0)
gl.BindTexture(gl.TEXTURE_2D, container_texture)
gl.ActiveTexture(gl.TEXTURE1)
gl.BindTexture(gl.TEXTURE_2D, container_specular)
set_uniform(cube_shader, "material.diffuse", i32(0)) // gl.TEXTURE0
set_uniform(cube_shader, "material.specular", i32(1)) // gl.TEXTURE1
if you could just (sanely) set the uniforms directly to the handle of the texture, then those activetexture calls wouldn't make sense would they?
another think i would recommend you to do is have a look at DSA (direct state access), there might be some calls around there to simplify your opengl and worry less about state machine fiascos
even though this problem isn't related to the state machine, so this recommendation is off topic
also, from what you saw in this 1ui vs 1i problem, I'd personally advise against parapoly-ing the shader stuff. Have it be explicit via set_uint_uniform set_int_uniform. It will remove a lot of pain in the future
@lime coral thanks for mentioning DSA, I didn't know about that. It seems I won't be able to use it since ogl on macOS is capped at 4.1 😕
Using your snippet does work indeed, but I'm confused about something. I thought that the value we pass to gl.Uniform1i was supposed to be the texture id returned from gl.GenTextures (in my case that's what's returned from load_texture). Based on your comment I guess that's not true, and instead we need to hardcode the value to match the TEXTURE0 TEXTURE1 etc? Appreciate your help in this very much 🙂
and also, why does my texture loading return 1 and 2 when I haven't loaded any more textures prior to those? shouldn't it be 0 and 1?
0 is not a valid handle. You can use 0 to check for errors
Yeah, not necesarly hardcode, but you specify the texture unit as opposed to the texture handle. The texture handle is specified in the bindtexture
Thats why you bind them with activetexture in the first place
Why would that be needed ifyou could just specify the handle
I see. Is there a less hardcode-y way to do it or is it just done this way everywhere?
Maybe with dsa, but im not sure what you mean hardcoded
If you want to make it less hardcody, gl.TEXTUREx are in order