I've been searching for examples of shaders in OpenGL and I've seen some varying styles. Some shaders specifically use the built in types (ie. gl_Vertex) to transfer data to and from the application code and the shader.
Some shaders use the varying types to transfer data from vertex to fragment shader instead of gl_Position and gl_FragColor.
Some shaders use the prefixes 'in' and 'out' to specify data transfer:
in vec3 vertex;
void main() {
gl_Position = projection_matrix * modelview_matrix * vec4(vertex, 1.0);
}
... while others use attributes:
attribute vec4 vertex_attrib;
attribute vec4 tex_coord_attrib;
attribute vec4 color_attrib;
uniform mat4 mvp_matrix;
uniform mat4 texture_matrix;
varying vec4 frag_color;
varying vec2 tex_coord;
void main(void)
{
gl_Position = mvp_matrix * vertex_attrib;
vec4 transformed_tex_coord = texture_matrix * tex_coord_attrib;
tex_coord = transformed_tex_coord.st / transformed_tex_coord.q;
frag_color = color_attrib;
}
My question is, what is the preferred way in GLES 2.0 to write shaders? Is there a best practices guide? Can someone provide an example of a vertex & fragment shader that is a shining example of 'what to do'??
Thanks.
OpenGL runs on desktops/laptops etc. OpenGLES runs on embedded systems (duh, ES stands for embedded systems). So.. if you have a very good GPU on your embedded system (like a phone) and a very old GPU on your desktop, then OpenGL ES would run faster, as it would be running on a faster GPU.
Geometry shaders are typically associated with OpenGL on desktops, but with the AEP you can use them on Android devices with a Mali GPU. The following figure shows the position of geometry shaders in the graphics pipeline. Geometry shaders use a function that operates on input primitives.
However, even in OpenGL, using multiple shaders of the same type does not work they way you outline it in your question. Only one of the shaders can have a main() . The other shaders typically only contain functions. So your idea of chaining multiple shaders of the same type into a pipeline will not work in this form.
The OpenGL-required minimum is 1 for fragment shaders, 8 for compute shaders (note: possible spec typo), and again 0 for the rest. The maximum number of different shader storage blocks that a stage can use.
Finally, the best option for you would be to read OpenGL ES 2.0 Specification as suggested by Nicol Bolas. Rules first, best practices - later. Good luck!
Your biggest problem is that you're looking at desktop GLSL shaders and trying to figure out what that means for GLSL-ES.
Just as OpenGL ES is not the same thing as OpenGL, GLSL-ES is not the same thing as GLSL. GLSL has progressed rather far in the many years since GLSL-ES split off. Therefore, you cannot use desktop GLSL shaders as anything more than a rough guide for implementing GLSL-ES shaders. Any more than you could use C++ texts as a guide for C.
The languages are quite similar, but desktop GLSL had to abandon a lot of keywords that GLSL-ES has not ditched yet. Similarly, old-school GLSL (1.20) implemented a lot of things that GLSL-ES and later versions of GLSL removed, like built-in inputs and outputs. So you will see a lot of desktop GLSL shaders that will flat-out not work on GLSL-ES. Indeed, if you find some that do, it will only be by sheer accident.
I don't know much about guides to GLSL-ES, but the easiest to find and use is the ultimate source: The OpenGL ES Shading Language Specification (PDF). Extensions can pile on functionality, but that PDF defines the core language. Your next bet would be any material explicitly marked as OpenGL ES 2.0 specific.
Basically, while you can understand what a desktop GLSL shader is doing, it is best to look at the algorithm and not the syntax if you're writing an OpenGL ES 2.0 application.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With