iOS: How does one write shaders for OpenGL ES 2.0 ?

I am looking at trying to get up to speed with shaders for OpenGL ES 2.0 (Programmable shaders) for the iPad 2. I’m having difficulty separating out what is Unity specific and what is a part of the OpenGL ES spec. I get the impression that Shaderlab wraps CG/HLSL. Is this the case?

Are there any good resources/tutorial/examples for understanding this? I have read wiki stuff (The iPhone examples are limited and the non-iPhone examples have a lot of graphic card specific complexity that I’m hoping to avoid having to sort out). I’ve looked at examples and I’ve read some of the forums but I’m still not getting it.

How useful is it for me to read about generic shader info? Can I play with Apple’s shader tools and it be applicable to writing shaders in shaderlab?

Is there a “Shaders for Dummies” that would be relevant? I’m reasonably well versed in C/C++ and I’ve got years of programming experience but this is first time I’m really looking at shaders themselves and I’m probably still somewhat weak on generic shader concepts.

The FAQ for this forum is somewhat sparse. I’m hoping people have a better understanding out. It seems clear that the iPad is very capable for someone who understands shaders. Any help would be great.

Thanks.

Here’s where I got started with GLSL: TyphoonLabs

You can give my tutorial videos a look, but there’s a lot of fixed function information in there, which would only be useful on older iOS hardware. I learned a lot from, and based those videos around, the ShaderLab documentation. However, Unity’s GLSL documentation is nil, so if you come up with anything good, please show us, if you can.

Here’s a basic vertex lighting/Beäst-utilizing shader I wrote that’s aimed at performance, which may help. It also represents about the extent of what I know how to do, given the aforementioned lack of help. :stuck_out_tongue:

(Here are more simple examples.)

573358–20447–$Diffuse (1 directional light).shader (2.48 KB)

1 Like

Hi. My knowledge on shaders is pretty limited, but I 'll try to share some things I’ve found out.

Reference

  1. There are two types of shaders that GLSL ES 2.0 supports : Vertex and Fragment. Other types ( e.g Geometry shaders ) are not supported.
  2. The Vertex shader might get some input (more on that later) and should output at least gl_Position. A minimum Vertex shader is
void main() 
{
    // Each vertex position in screen ( window ) space ( = gl_Position ) is calculated
    //   by multiplying the vertex position in the World space ( = gl_Vertex ) ( It is either World or Object space, not sure ) 
    //   with the MVP matrix ( = gl_ModelViewProjectionMatrix ).     
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
  1. The Fragment shader might get some input and should output at least gl_FragColor. A minimum Fragment shader is
void main() 
{
    // For every pixel on the screen that belongs to this object
    //   paint the pixel red.         
    gl_FragColor = vec4 (1.0, 0.0, 0.0, 1.0);
}

To use the above shaders in a unity shader, the template is

Shader "Shader name" 
{     
        Properties 
        {         
             //Fill any properties      
        }
          SubShader 
          { 
                 Tags { "Queue" = "Geometry" }
                 Pass 
                  {             
                     GLSLPROGRAM                          
                     #ifdef VERTEX             
                         // Add Vertex shader code here
                     #endif  

                     #ifdef FRAGMENT
                         // Add Fragment shader code here    
                     #endif                          
                     ENDGLSL        
                   }
           } 
}

So a simple shader that displays the object in red is

Shader "simple_Red_Shader" 
{     
    Properties 
    {         
                
    }
    SubShader 
    { 
        Tags { "Queue" = "Geometry" }
        Pass 
            {             
                GLSLPROGRAM                          
                #ifdef VERTEX  
                void main() 
                {           
                   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
                } 
                #endif  
            
                #ifdef FRAGMENT
                void main() 
                {           
                   gl_FragColor = vec4 (1.0, 0.0, 0.0, 1.0);
                } 
                #endif                          
                ENDGLSL        
            }
     } 
}

You can create and access shader’s properties ( ie color, texture, etc ) and access Unity’s built-in values from UnityCG.glslinc. I plan to create some posts in my blog regarding those aspects.
Also, keep an eye on any WebGl tutorial that contains Vertex or Fragment shader code, place them as shown above and the code should work.

I have uploaded a new shader tutorial and I intend on making a few more. If you want, you can watch them in
http://unity.ippomed.com

Please continue with this :slight_smile:

Currently I have posted four GLSL tutorials. I prepare a tutorial series for Cg as well.
I will start publishing them in mid-September.
I have to admit that seeing nobody is interested for them until now has weakened my interest on publishing them.

I guess it’s just because it’s not easy to find it.

Also, Unity appears to strongly discourage the use of GLSL.

I just spend some hours yesterday trying to get surface shaders to work with GLSL code (why doesn’t that work although you can use Cg code?) or to get the Unity 2.x shaders with GLSL to run (well, I guess it’s understandable that those shaders no longer work). However, both points would be nice to easily use shadows and cookies etc. with custom-maded GLSL shaders. Otherwise, it quickly gets very difficult to use even the basic features of Unity’s light sources.

Surface Shaders are cg only.

There are multiple reasons behind that:

  1. Surface shaders are crossplatform as is cg (glsl isn’t, its mac - mobile only)
  2. Surface shaders do a lot automatic which cuts the possibility to optimize it - thats something you don’t want to do for mobile or better if you want it you can just as well go with cg as there is no gain in glsl anymore due to how well the cg → glsl crosscompiler and optimizer works

And I fail to see the point on shadows cause shadows aren’t supported on mobile at all.

I’m sure this was just a typo, but glsl is cross platform, it’s part of opengl, which is obviously cross-platform itself :wink:

Funny you mention, considering Martin has a wikibook that teaches GLSL with Unity, on Windows! :smile:

@dreamora: OK. I get your point. :slight_smile: The thing is: I want to teach GLSL (on Windows and Mac). If Unity wouldn’t support GLSL, I wouldn’t use Unity for teaching GLSL. Makes sense, doesn’t it? That said, I’m just saying that it would be nice to use surface shaders with GLSL in order to make it easier to program GLSL shaders that use shadows.

You can’t use GLSL on windows without the -opengl enforce flag (is standalone and unity opengl force on windows does not feature the full set of capabilities, from what I recall deferred does not work and a few other things don’t work either. Its more a reminder of Unity 2 than a real thing, thats why there is no editor setting for it either), cause DirectX does not support GLSL and thats what is being used on windows. Also for windows shader programmers GLSL is really of no interest, as hard as it sounds. CG is much more important cause its very very close to HLSL which unlike GLSL is the major player (aside of cases where CG or FX / CGFX are used themself)

@dreamora: unityversum.com doesn’t show on my Windows machine with Firefox version 3.6.18. (Just in case you care. :wink:

Ok I see what you are saying, but you should have qualified that you are talking about GLSL in Unity as otherwise your comments make no sense. Even then the stuff about window developers is way of the mark, of course they use glsl if using opengl and plenty of them do, otherwise nvidia and ATI/AMD would simply stop supporting it.

I’d love to see them if that counts for anything

The differences between HLSL/CG and GLSL are extremely small and converting between them is, of course depending on the amount of code the shader has, a matter of a few minutes, or seconds when using one of those automatic converters around, because it is mostly just replacing some keywords.

Writing surface shaders in GLSL makes no sense, because surface shaders are only a small part of the final shader which unity will copy together for you. Okay, they could also support that process for GLSL, but the resulting shaders are very complex and anyway not suited for mobile devices, which is the online platform GLSL really makes sense for, as CG can be compiled just fine on mac, just not for OpenGL ES 2.0. I btw don´t like the concept of surface shaders, because they take a lot of control away from me.

I think you should all be avoiding GLSL for the following reasons:

  1. unity themselves mention it on their blog and pdf, that GLSL isn’t any faster than HLSL in most cases, but HLSL will work on anything.
  2. GLSL is poorly documented so your milage may vary.

It’s fine targetting GLSL if you never want to port to PC or any other platform, but this could potentially screw up webplayer as well for a lot of people. It’s pretty much only good for targetting mac or mobile.

Where HLSL is just as optimised but ported internally to the target platform. This is my understanding of it reading unity’s pdf.

That does not mean the GLSL shader will even run properly. I have several GLSL shaders which work fine on the mac but simply won’t ever work properly on the pc, even forcing unity into opengl doesn’t solve a damn thing. Yes the title bar of unity showed it was running under opengl.

So really, I can’t advocate GLSL as a platform for unity any longer going by what unity said.

But don’t forget to rename rows of matrices to columns and columns to rows. :slight_smile:

Unity compiles Cg to OpenGL ES 2.0. The difference between the GLSL code produced by Unity for OpenGL and the GLSL code for OpenGL ES 2.0 is probably not a big deal.

Could you elaborate that? Can’t you just add Cg code for the functions that you want to customize?

I’m very interested in those examples. Can you make them accessible please? (I only know of the opposite case where a GLSL shader runs fine with Unity on Windows but not on Mac.)

Going by what Unity says, you are absolutely correct. However, you should realize that Unity has absolutely no interest in programmers writing portable code: the more programmers depend on Unity, the more revenue will Unity earn. (The same argument goes for Microsoft and HLSL, C#, J#, J++, etc.)