Hi!
I tried to make a vertex shader for a single point that is only controlled by uniforms. It doesn’t really need any attributes. In order to avoid any problems I’m binding attributes and a VBO (which is bound anyways). Here is my vertex shader (the fragment shader may just set a constant color; I’m drawing GL_POINTS):
attribute vec4 a_Position;
attribute vec4 a_TexCoord;
uniform vec2 u_Position;
uniform float u_PointSize;
void main(void)
{
gl_Position = vec4(u_Position.x, u_Position.y, 0.0, 1.0);
gl_PointSize = u_PointSize;
}
It works fine in the simulator but it doesn’t work on an iPod touch with iOS 4.1 (3rd and 4th generation). However, this version works:
attribute vec4 a_Position;
attribute vec4 a_TexCoord;
uniform vec2 u_Position;
uniform float u_PointSize;
void main(void)
{
gl_Position = vec4(u_Position.x, u_Position.y, 0.0, 1.0);
gl_PointSize = u_PointSize + a_Position.x - a_Position.x;
}
Apparently, the driver/compiler/whoever just has to believe that at least one attribute is being used.
Is this a known bug? How would one write a vertex shader that doesn’t require attributes?
Thanks!
Hi Martin,
This sounds like a very strange issue. I’ve put the example code you have given into our UniSCoEditor utility, and both versions give the same cycle count (6 cycles). I’ve looked into the disassembly for each shader, and the output is identical (which means the use of the attribute is getting optimised out in the second case as the calculation is redundant).
I’ve never personally written a shader that doesn’t use attributes so I don’t know how well other platforms would deal with this use case. Have you tried running your application on any SGX platforms that are not running iOS?
I think you should contact Apple to discuss this issue (as they write their own drivers and compilers for their platforms), but it sounds like your workaround should be acceptable for now.
As all shaders require geometry to operate on, you will have to submit geometric data to render your points. The best way to do this is to create a VBO of a single vertex at the lowest precision you can (i.e. GL_BYTE) as it wont be used anyway and you want to minimise storage requirements. You then need to create an index array the size of the number of points your need, and get each index to reference the single dummy vertex you have stored in your VBO. Unless you need texture coordinates (your a_TexCoord attribute is currently unused), you shouldn’t bother to store information for this. When you come to render all of the points, you should use a workaround similar to the one you have used above to ensure an attribute is used at least once in your vertex shader. Also, you should remove any redundant uniforms, attributes or varyings from your shader/s (e.g. the a_TexCoord your not using).
Joe
I’ve just discussed this with a colleague, and the VBO approach may not be the most suitable for your use case. If the position information is likely to change on a frame by frame basis (which sounds likely based on what your trying to do), a better approach would be to avoid VBOs entirely (as you would be constantly updating positions, so you would negate any benefits they could give) and instead create an array of all of the points you need to submit and update the array on a per frame basis, and then using glVertexAttribPointer() to submit the data and glDrawArrays() to render it.
This should be much faster than trying to use uniforms to determine the position
Thanks Joe! Sorry, I'm not able to run the code on other SGX devices. I'll post the problem in the Apple developer forums. Anyways, thanks for the performance tips!
Martin Kraus2010-11-08 15:49:40
Hi!
I just ran into almost the same problem with the OpenGL ES 2.0 PC emulation on Windows.
However, my previous work-around doesn’t work, thus, I’m now actually using an attribute:
gl_PointSize = u_PointSize + a_Position.x * 0.00001;
Also, I think it did show a one-pixel sized point when it didn’t work.
Cheers,
Martin
Is there a particular reason why you want to pass position and point size as a uniform instead of an attribute?
It’s an academic exercise: I’m writing an assignment for students and try to keep the source code as short and simple as possible. Being able to avoid another vertex array would help but it’s certainly not necessary. Actually I was inspired by one of the examples in the PowerVR SDK training course which rendered a textured triangle strip and specified the position of the strip by uniforms. I’m doing the same thing but render a point sprite.
By the way, it would be really cool if the shader compiler would report an error instead of silently rejecting the code.