Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to learn OpenGL ES 2.0 and I'm wondering what is the most common practice to "manage" shaders.
I'm asking this question because in the examples I've found (like the one included in the API Demo provided with the android sdk), I usually see everything inside the GLRenderer class and I'd rather separate things so I can have, for example, a GLImage object that I can reuse whenever I want to draw a textured quad (I'm focusing on 2D only at the moment), just like I had in my OpenGL ES 1.0 code. In almost every example I've found, shaders are just defined as class attributes. For example:

public class Square {

public final String vertexShader =
        "uniform mat4 uMVPMatrix;\n" +
        "attribute vec4 aPosition;\n" +
        "attribute vec4 aColor;\n" +
        "varying vec4 vColor;\n" +
        "void main() {\n" +
        "  gl_Position = uMVPMatrix * aPosition;\n" +
        "  vColor = aColor;\n" +
        "}\n";

public final String fragmentShader =
        "precision mediump float;\n" +
        "varying vec4 vColor;\n" +
        "void main() {\n" +
        "  gl_FragColor = vColor;\n" +
        "}\n";
// ...
}

I apologize in advance if some of these questions are dumb, but I've never worked with shaders before.

1) Is the above code the common way to define shaders (public final class properties)?
2) Should I have a separate Shader class?
3) If shaders are defined outside the class that uses them, how would I know the names of their attributes (e.g. "aColor" in the following piece of code) so I can bind them?

colorHandle = GLES20.glGetAttribLocation(program, "aColor");
share|improve this question
add comment

2 Answers

up vote 13 down vote accepted

I've always disliked that way of defining shaders (in a string). I prefer to do mine in a text file and read it in when loading. Defining it in a string is annoying for debugging and it just looks messy to me. It's just so much easier to be able to type it out and see it formatted like it should be, instead of inside a string.

I also have a separate class that has common shader functionality, like reading in shaders and printing logging info for shader debugging.

Where ever the shaders are defined, you can access the names just like you do in your example. Using the string literal is acceptable for shaders since those values are unlikely to change once you've implemented them.

However, in the end it's up to you. The way you're currently doing it works great, if it's not causing you any troubles.

share|improve this answer
2  
Having your shaders in separate files also means that you can use your handy-dandy shader editors and have full syntax highlighting, and even preview them before testing them in your program, if your supports that. –  Raceimaztion Dec 11 '12 at 5:33
6  
The only real reason for having shaders in a string is for quick tests and tutorials.. where file handling adds bulk of "unnecessary code". –  Jari Komppa Dec 11 '12 at 6:42
2  
You can also implement hot-reload on shader files - allowing you to debug changes without relaunching the game. Productivity++ –  Liosan Dec 11 '12 at 9:24
    
I like the idea of reading them form a file and having a separate Shader class. Seeing them always in a String was confusing me beacause I didn't know if that was the way they are usually defined or just for learning purposes. Thanks! –  miviclin Dec 11 '12 at 13:19
add comment

Shader (and thus material) management is a rather tricky problem you run into when your graphics system gets more complex and you notice hard coding every shader would lead into massive code duplication. Here's a few alternative ways to solve it:

  • Small examples where there are only a couple of shaders tend to hard-code them as strings to avoid file handling as Jari Komppa commented
  • Better is to use separate files where you can have syntax highlighting and proper formatting. You can also code a simple debug system which watches changes in those files and apply the modified shader on-the-fly while your game is running.
  • When the material count increases, a shader generator becomes almost a necessity. Basically you define common snippets like "fragment shader normal mapping snippet" and compose your complete shaders by including the desired components.
    • You could use hard-coded string snippets, but that gets really messy fast, so once again files are a good idea.
    • You can either have bits of code in separate files (or same) or alternatively use ubershader / supershader where you use the preprocessor (or uniform flags) to enable/disable stuff.

As for the attribute and uniform names and such, you just use a consistent naming across all the shaders.

share|improve this answer
    
I will definitely move my shaders to a separate file. Thanks! –  miviclin Dec 11 '12 at 13:33
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.