12
votes

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?

2

2 Answers

23
votes

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.)

5
votes

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.