Advertisement Jump to content
Sign in to follow this  
Juliean

OpenGL Bind sampler as uniform to all shaders

This topic is 1859 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello,

 

I've recently started to implemented the OpenGL4-renderer for my game engine. I've been using DirectX9 and 11 so far, and I've been used to binding textures/samplers globally to the device, and share them between shaders. Now it happens to be in my design that the texture bind commands are executed before actually binding the shader (that would be a bit more to explain, lets just say that for a good reason). Now in OpenGL this is a problem, since from what I understand I'd have to bind the shader program in order to set the sampler to the correct uniform location:

 

In my render queue, under normal circumstances these two command blocks

glUseProgram(shader);

....

glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, m_texture);
glUniform1i(slot, slot); // I'm already requiring the samplers to be at the first uniform locations not to make things even more complicated -.-

would be executed in reverse order, so the sampler would be bound to the wrong shader program. I could of course safe the currently bound shader and textures, and whenever a shader is switched bind them again, but this appears rather dirty and unnatural and would require a few precautions on my side. Is there any native way to avoid this? I've read about uniform buffers, but they seem not to work with samplers (thats just great), any other ideas?

Share this post


Link to post
Share on other sites
Advertisement
In my understanding the glUniform1i call doesn't have to happen every time you bind a texture. I would do all the glUniform1i calls after loading the program, then never again. You only need to call it once to tell the program which texture image unit each sampler uses. After you've done that all you need to do is bind textures to the right texture image units.

Share this post


Link to post
Share on other sites

+1 Samith, there is no need to constantly set the uniform value unless the texture is being switched to another texture unit. The binding can happen once at program creation..

Share this post


Link to post
Share on other sites

compile/link the shader

call glUseProgram(...)

get the uniform location for the tex unit

set the uniform.

 

when you want to use the texture call glActiveTexture(...) then glBindTexture(...).

 

This is what you normally would do. You can bind the texture objects to the texture units before the shaders are compiled, glUsed, etc ...and that shouldnt be affected by how you load the shaders and get the uniformlocations(later).

Share this post


Link to post
Share on other sites

Ah thanks all, thats certainly good to know, that in fact makes things very easy again.

 

Since on the topic, does this work the same for e.g. uniform buffer objects, and such?

 

EDIT: Also, is there a function for enumerating the number of samplers a shader program has? I already require a certain layout for my uniforms in order to apply to my API-independant interfaces, so I I could say

size_t numSampler = glGetNumSampler(program); // any equivalent to this call?
for(size_t i = 0; i < numSampler; i++)
{
      glUniform1i(i, i);
}

that would make things preferably easy.

Edited by Juliean

Share this post


Link to post
Share on other sites

Ah thanks all, thats certainly good to know, that in fact makes things very easy again.
 
Since on the topic, does this work the same for e.g. uniform buffer objects, and such?
 
EDIT: Also, is there a function for enumerating the number of samplers a shader program has? I already require a certain layout for my uniforms in order to apply to my API-independant interfaces, so I I could say

size_t numSampler = glGetNumSampler(program); // any equivalent to this call?
for(size_t i = 0; i < numSampler; i++)
{
      glUniform1i(i, i);
}
that would make things preferably easy.

With uniform buffer objects you set their bind point by calling glUniformBlockBinding, which can be done at program creation time along with the glUniform1i calls that you make to set up sampler bindings.

As for a glGetNumSamplers function: no such function exists that I am aware of. You just have to iterate through all the uniforms using glGetProgram with GL_ACTIVE_UNIFORMS to get the number of uniforms and then using glGetActiveUniform for each uniform to get its type. If the type is a sampler type (GL_SAMPLER_2D, GL_SAMPLER_3D, etc) then you know it's a sampler and you can set up its bind point with glUniform.

Share this post


Link to post
Share on other sites
With uniform buffer objects you set their bind point by calling glUniformBlockBinding, which can be done at program creation time along with the glUniform1i calls that you make to set up sampler bindings.

 

You can't put samplers into a uniform block - see the section on "opaque types" in the GLSL spec.

Share this post


Link to post
Share on other sites

 

With uniform buffer objects you set their bind point by calling glUniformBlockBinding, which can be done at program creation time along with the glUniform1i calls that you make to set up sampler bindings.

 

You can't put samplers into a uniform block - see the section on "opaque types" in the GLSL spec.

 

 

?? I didn't say you could put samplers inside a uniform block. Maybe I didn't write that post clearly. I was only trying to say that the binding for a uniform buffer object could be set up at program creation time by using glUniformBlockBinding.

Share this post


Link to post
Share on other sites

With uniform buffer objects you set their bind point by calling glUniformBlockBinding, which can be done at program creation time along with the glUniform1i calls that you make to set up sampler bindings.

 

Sweet, now that is for much less "Y u force me to rewrite high level abstraction OpenGL???"-than I thought I had before.

 

 

 


As for a glGetNumSamplers function: no such function exists that I am aware of. You just have to iterate through all the uniforms using glGetProgram with GL_ACTIVE_UNIFORMS to get the number of uniforms and then using glGetActiveUniform for each uniform to get its type. If the type is a sampler type (GL_SAMPLER_2D, GL_SAMPLER_3D, etc) then you know it's a sampler and you can set up its bind point with glUniform.

 

Well, that already helps - I've just implemented my own meta-language for shader, and therefore all uniforms I create are quaranted to be SAMPLER anyway, since I'm using uniform blocks due to my design for setting all other data anyway - having glGetProgram and glGetActiveUniform should do the job, thanks again.

 

@mhagain:

 

I also think you may have misread his post, at least I did get that he wanted to say how to bind the uniform blocks and not misinform me about being able to bind samplers to it... Thanks for the hint about opague types though, I still have so much fundamental stuff to understand about OGL.

Edited by Juliean

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!