I am writing an app for android in OpenGL ES 2.0 and I have a problem with some shader code. Here it is:
attribute vec4 vPosition;
vec4 tempPosition;
void main() {
tempPosition = vPosition;
tempPosition.x = 2 - tempPosition.x;
gl_Position = tempPosition.yxzw;
}
The line that causes the error is this one:
tempPosition.x = 2 - tempPosition.x;
I am enabling and disabling vertex atrrib arrays each time I want to draw something. Before i draw i call this: GLES20.glEnableVertexAttribArray(sPosition);
and after i drew i call this
GLES20.glDisableVertexAttribArray(sPosition);
What am I doing wrong? How to substract x from 2?
EDIT:
If I change the line that causes the error to this:
tempPosition.xz = vec2(2,0) - tempPosition.xz;
than it works, but why cant i substract with a single number?
In the GLSL version used with ES 2.0 (which somewhat mysteriously is version 1.00), there are no implicit type conversions. You can't add a value of type int
to a value of type float
, or a vector of floats.
This is specified in the introduction of chapter 4 "Variables and Types" of the spec:
The OpenGL ES Shading Language is type safe. There are no implicit conversions between types.
and in more detail for this case in section 5.9 "Expressions", where the +
operator is defined:
The two operands must be the same type, or one can be a scalar float and the other a float vector or matrix, or one can be a scalar integer and the other an integer vector.
Therefore, you need to use float constants when operating with floats:
tempPosition.x = 2.0 - tempPosition.x;
The more interesting case is why your second attempt worked, since you're also mixing different types:
tempPosition.xz = vec2(2,0) - tempPosition.xz;
This is legal because constructors can be used to convert types, and are the primary mechanism to do so. For example, you could have written your original expression as:
tempPosition.x = float(2) - tempPosition.x;
This looks awkward for a constant value, but would make much more sense if the integer value were in a variable:
int foo = ...;
tempPosition.x = float(foo) - tempPosition.x;
Back to the vector case, section 5.4.2 "Vector and Matrix Constructors" specifies:
If the basic type (bool, int, or float) of a parameter to a constructor does not match the basic type of the object being constructed, the scalar construction rules (above) are used to convert the parameters.
This means that you can use an int
value as the argument to a constructor of a vec2
, even though it contains float
values. In this case, the value is automatically converted. In other words, your second statement is equivalent to:
tempPosition.xz = vec2(float(2), float(0)) - tempPosition.xz;
IMHO, it's still much cleaner to not rely on implicit conversions, and write:
tempPosition.xz = vec2(2.0, 0.0) - tempPosition.xz;
Note that full OpenGL is different from OpenGL ES in this respect. In full GLSL, there are implicit type conversions. Which I personally find unfortunate, because I believe that type safety is a useful principle.