Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenGL ES (2.0) Shading Language: How to input boolean into vertex shader and pass to fragment shader?

I'm trying to pass a boolean into my vertex shader for the first time; I've only been using floats until now.

The boolean in question is primitive-specific so cannot be passed as a uniform. However it has the same value for all vertices of any given primitive.

It seems from the Khronos spec that 'varying' is the only way to pass data into the fragment shader, but unsurprisingly declaring 'varying bool my_bool;' causes a parser error when defined in my vertex shader.

I'm passing the boolean into my vertex shader as:

attribute bool a_my_bool;

I define a varying in an attempt to pass to the fragment shader:

varying bool v_my_bool;
void main() {
    // ...
    v_my_bool = a_my_bool;
}

Could someone please tell me how I can achieve what I intend?

like image 318
KomodoDave Avatar asked Jan 14 '12 15:01

KomodoDave


People also ask

Can you send data from fragment shader to vertex shader?

All shader stages can pass data between them by using input and output variables. If in the vertex shader we create an output variable, we will be able to read it on the fragment shader as an input variable.

What happens between vertex and fragment shader?

The difference between vertex and fragment shaders is the process developed in the render pipeline. Vertex shaders could be define as the shader programs that modifies the geometry of the scene and made the 3D projection. Fragment shaders are related to the render window and define the color for each pixel.

Can textures be used in a vertex shader?

The most common way to read matrix in the vertex shader is by using textures. Although textures are most commonly used to store color information (albedo, roughness map, specular map, tint map, etc.) textures can also be used to store any kind of information (e.g. normal map).

What is OpenGL vertex shader?

The Vertex Shader is the programmable Shader stage in the rendering pipeline that handles the processing of individual vertices. Vertex shaders are fed Vertex Attribute data, as specified from a vertex array object by a drawing command.


2 Answers

I strongly advice you to not use the attribute and switch it to uniforms even though the boolean is attached to a given primitive. With Uniform you set it once and use many times, with attribute you increase a lot the memory bandwidth required in each draw. The only sense I see in this is if you perform an extreme batching of your primitives but, even in that case, the real benefits of this solution must be evaluated carefully since the risk is to achieve the opposite effect.

About varying variables, one common mistake is to not declare the varying in both Vertex and Fragment shaders and miss one of the 2.

This would raise a linking error and you would notice it anyway by checking the compile and linking results.

Another aspect I would check in your place is to make sure the variables are assigned and used in your code since compiler strips unused contents (dead code optimization) and this results in a very common issue.

like image 200
Maurizio Benedetti Avatar answered Oct 21 '22 01:10

Maurizio Benedetti


From §4.3.5 of The OpenGL® ES Shading Language version 1.0.17 (PDF):

The varying qualifier can be used only with the data types float, vec2, vec3, vec4, mat2, mat3, and mat4, or arrays of these.

And from §4.3.3:

The attribute qualifier can be used only with the data types float, vec2, vec3, vec4, mat2, mat3, and mat4. Attribute variables cannot be declared as arrays or structures.

So you can't have an attribute bool, let alone a varying bool, according to the spec.

If you really need a boolean value per vertex you could use 0.0 for false and 1.0 for true. When testing, check for x > 0.5. eg:

// vertex shader
attribute float a_my_bool;
varying float v_my_bool;
void main() {
    // ...
    v_my_bool = a_my_bool;
}

// fragment shader
varying float v_my_bool;
void main() {
    if (v_my_bool > 0.5) {
        // my_bool is true
        // ...
    } else {
        // my_bool is false
        // ...
    }
}

As long as all vertices in each triangle have the same value this should work. If they aren't consistent, then you'll end up with different fragments for the same triangle behaving differently. (If you stick to 0.0 and 1.0 the quarter of the triangle closest to the "odd" corner will behave differently from the rest.)

like image 24
Laurence Gonsalves Avatar answered Oct 20 '22 23:10

Laurence Gonsalves