Explicit vs Automatic attribute location binding for OpenGL shaders - opengl-es

When setting up attribute locations for an OpenGL shader program, you are faced with two options:
glBindAttribLocation() before linking to explicitly define an attribute location.
or
glGetAttribLocation() after linking to obtain an automatically assigned attribute location.
What is the utility for using one over the other?
And which one, if any, is preferred in practice?

I know one good reason to prefer explicit location definition.
Consider that you hold your geometry data in Vertex Array Objects. For a given object, you create a VAO in such way that the indices correspond to, for example:
index 0: positions,
index 1: normals,
index 2: texcoords
Now consider that you want to draw one object with two different shaders. One shader requires position and normal data as input, the other - positions and texture coords.
If you compile those shaders, you will notice that the first shader will expect the positions at attribute index 0 and normals at 1. The other would expect positions at 0 but texture coords at 1.
Quoting https://www.opengl.org/wiki/Vertex_Shader:
Automatic assignment
If neither of the prior two methods assign an input to an attribute index, then the index is automatically assigned by OpenGL when the program is linked. The index assigned is completely arbitrary and may be different for different programs that are linked, even if they use the exact same vertex shader code.
This means that you wouldn't be able to use your VAO with both shaders. Instead of having one VAO per, say, object, you'd need - in the worst case - a separate VAO per object per shader.
Forcing the shaders to use your own attribute numbering convention via glBindAttribLocation can solve this problem easily - all you need to do is to keep a consistent relation between attributes and their estabilished IDs, and force the shaders to use that convention when linking.
(That's not really a big issue if you don't use separate VAOs, but still might make your code clearer.)
BTW:
When setting up attribute locations for an OpenGL shader program, you are faced with two options
There's a third option in OpenGL/GLSL 3.3: Specify the location directly in shader code. It looks like this:
layout(location=0) in vec4 position;
But this is not present in GLSL ES shader language.

Another answer here is that glGetAttribLocation returns data to the caller, which means that it implicitly requires a pipeline flush. If you call it right after you compile your program, you're essentially forcing asynchronous compilation to occur synchronously.

The third option, ie layout(location=0) in vec4 position; in the shader code, is now available in OpenGL ES 3.0/GLSL 300 es. Only for vertex shader input variables though.

Related

Submitting integer to shader without using uniforms?

I plan to eliminate all glUniform calls from my GLSL shaders in order to save costs in state switching. For that purpose, I plan to use an UBO that is bound to the shader permanently. Different draw calls use different parts of the UBO (it's basically an array). In order to tell the draw call which entry to use, I have to submit an integer to the vertex/fragment shaders. The problem is, that on the system I have to use even casting a single glUniform call will cause an expensive state update, so I cannot use glUniform at all.
Do you know a solution that will work on GLES 3.1 and one that will work on GLES 2?
GLES doesn't have glMulti* calls yet and base vertex only from 3.2 upwards as far as I know. And adding another vertex attribute may be costly.

In opengl ES can I use a vertex buffer array buffer etc for shader shared matrices?

As OpenGL ES does not support shared "uniform blocks" I was wondering if there is a way I can put matrices that can be referenced by a number of different shaders, a simple example would be a worldToViewport or worldToEye which would not change for an entire frame and which all shaders would reference. I saw one post where one uses 3 or 4 dot calls on a vertex to transform it from 4 "column vectors", but wondering if there is a way to assign the buffer data to a "mat4" in the shader.
Ah yes the need for this is webGL which at the moment it seems only to support openGLES 2.0.
I wonder if it supports indexed attribute buffers as I assume they don't need to be any specified size relative to the size of the position vertex array.
Then if one can use a hard coded or calculated index into the attribute buffer ( in the shader ) and if one can bind more than one attribute buffer at a time, and access all "bound to the shader" buffers simultaneously in a shader ...
I see if all true might work. I need a good language/architecture reference on shaders as I am somewhat new to shader programming as I I'm trying to deign a wall without knowing the shapes of the bricks :)
Vertex attributes are per-vertex, so there is no way so share vertex attributes amongst multiple vertices.
OpenGL ES 2.0 upwards has CPU-side uniforms, which must be uploaded individually from the CPU at draw time. Uniforms belong to the program object, so for uniforms which are constant for a frame you only have to modify each program once, so the cost isn't necessarily proportional to draw count.
OpenGL ES 3.0 onwards has Uniform Buffer Objects (UBOs) which allow you to load uniforms from a buffer in memory.
I'm not sure what you mean by "doesn't support shared uniform blocks", as that's pretty much what a UBO is, albeit it won't work on older hardware which only supports OpenGL ES 2.x.

Variable number of lights in glsl-es shader

I'm working on a 3d engine, that should work for mobile platforms. Currently I just want to make a prototype that will work on iOS and use forward rendering. In the engine a scene can have a variable number of lights of different types (directional, spot etc). When rendering, for each object (mesh) an array of lights that affect this object is constructed. The array will always have 1 or more elements. I can pack the light source information into 1D texture and pass to the shader. The number of lights can be put into this texture or passed as a separate uniform (I did not try it yet, but these are my thoughts after googling).
The problem is that not all glsl-es implementation support for loops with variable limits. So I can't write a shader that will loop through light sources and expect it to work on a wide range on platforms. Are there any technics to support variable number of lights in a shader if for loops with variable limits are not supported?
The idea I have:
Implement some preprocessing of shader source to unroll loops manually for different number of lights.
So in that case if I would render all objects with one type of shader and if the number of lights limits are 1 to 3, I will end-up having 3 different shaders (generated automatically) for 1, 2 and 3 lights.
Is it a good idea?
Since the source code for a shader consists of strings that you pass in at runtime, there's nothing stopping you from building the source code dynamically, depending on the number of lights, or any other parameters that control what kind of shader you need.
If you're using a setup where the shader code is in separate text files, and you want to keep it that way, you can take advantage of the fact that you can use preprocessor directives in shader code. Say you use LIGHT_COUNT for the number of lights in your shader code. Then when compiling the shader code, you prepend it with a definition for the count you need, for example:
#define LIGHT_COUNT 4
Since glShaderSource() takes an array of strings, you don't even need any string operations to connect this to the shader code your read from the file. You simply pass it in as an additional string to glShaderSource().
Shader compilation is fairly expensive, so you'll probably want to cache the shader program for each light count.
Another option is what Andon suggested in a comment. You can write the shader for the upper limit of the light count you need, and then pass in uniforms that serve as multipliers for each light source. For the lights you don't need, you set the multiplier to 0. That's not very efficient since you're doing extra calculations for light sources you don't need, but it's simple, and might be fine if it meets your performance requirements.

GLSL 1.2: What are the default attributes for the different indexes used in glBindAttribLocation

GLuint index = 0;
glBindAttribLocation(mprogram, index, name);
For example, the '0' index is gl_position, but what about the other indexes like 1 and 2?
#Nicolas The problem is that when I set the index to zero, I noticed that the calls to glVertexAttrib(index...) would modify the vertex positions instead of the attribute I assigned it to...
First, gl_Position is the output position from the vertex shader, not the input. It's not a vertex attribute and it never has been. You're probably thinking about gl_Vertex.
Most importantly second, the built-in attributes like gl_Vertex, gl_Color, etc do not have generic attribute indices. gl_Vertex is not the same thing as generic attribute 0. The OpenGL specification explicitly forbids these two being the same. Generic attributes (things that have attribute indices) and built-in attributes do not "alias" with one another. They don't share the same resources or space.
Now, NVIDIA's OpenGL implementation allows aliasing, in direction contravention of the OpenGL specification. But such code is non-portable (and terrible). If you want to find exactly how NVIDIA does their mapping, I'm sure documentation on NVIDIA's site will spell it out somewhere.

GLSL PointSprite for particle system

I'm using an ParticleSystem with PointSprites (inspired by the Cocos2D Source). But I wonder how to rebuild the functionality for OpenGL ES 2.0
glEnable(GL_POINT_SPRITE_OES);
glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
glPointSizePointerOES(GL_FLOAT,sizeof(PointSprite),(GLvoid*) (sizeof(GL_FLOAT)*2));
glDisableClientState(GL_POINT_SIZE_ARRAY_OES);
glDisable(GL_POINT_SPRITE_OES);
these generate BAD_ACCESS when using an OpenGL ES 2.0 context.
Should I simply go with 2 TRIANGLES per PointSprite? But thats probably not very efficent (overhead for extra vertexes).
EDIT:
So, my new problem with the suggested solution from:
https://gamedev.stackexchange.com/questions/11095/opengl-es-2-0-point-sprites-size/15528#15528
is a possibility to pass many different sizes in an batch call. I thought of using an Attribute instead of an Uniform, but then I would need to pass always an PointSize to my shaders - even if I'm not drawing GL_POINTS. So, maybe a second shader (a shader only for GL_POINTS)?! I'm not aware of the overhead for switching shaders every frame in the draw routine (because if the particle system is used, I want naturally also render regular GL_TRIANGLES without an pointSize)... Any ideas on this?
So doing the thing here as I already commented here is what you need: https://gamedev.stackexchange.com/questions/11095/opengl-es-2-0-point-sprites-size/15528#15528
And for which approach to go, I can either tell you to use different shaders for different types of drawables in your application or just another boolean uniform in your shader and enable and disable changing the gl_PointSize through your shader code. It's usually up to you. What you need to keep in mind is changing the shader program is one of the most time costly operations so doing the drawing of same type of objects in a batch will be better in that case. I'm not really sure if using an if statement in your shader code will give a huge performance impact.

Resources