iphone gem shader spheremap problem

So I’m testing out the iphone gem shader here: http://www.unifycommunity.com/wiki/index.php?title=IPhoneGems

But I’m getting drastically different results in the editor and on an iphone 4. Whereas the gem surface shows an area of texture in the editor, it only shows one solid colour on the phone:

Scaling the amount of tiling from 1-500 didn’t seem to make any difference (except for a few moments when the very tiled version seemed to appear for a frame) , along with playing around with mip-map and anisotropy settings.

Heres the shader I’m using with all the non iOS stuff removed:

Shader "FX/Diamond"
{
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _Fog("Fog", Color) = (0,0,0,0)

        _RefractTexlow ("Refraction LowGPU", 2D) = "dummy.jpg" {
            TexGen SphereMap
        }
        _ReflectTexlow ("Reflect LowGPU", 2D) = "dummy.jpg" {
            TexGen SphereMap
        }

        _Shininess ("Shininess", Range (0.01, 1)) = 0.7
        _SpecColor ("Specular", Color) = (1,1,1,1)
        _Emission ("Emissive", Color) = (1,1,1,1)
    }   



/////////// Start iphone code////////////////
//This will cause a nice gem texture to be rendered using the low-GPU textures defined in the inspector//
//This section of the code is provided by BURNING THUMB SOFTWARE, 2010//

    SubShader {
                Pass {
                    
        Lighting On
            SeparateSpecular On
                    
            Color (0,0,0,0)
        //  Offset  -1, -1
            Cull Front
            //Blend OneMinusSrcAlpha One
            SetTexture [_ReflectTexlow] {
                constantColor [_Color]
                combine texture * constant, primary
            }
        }

        // Second pass - here we render the front faces of the diamonds.
        Pass {
        

            Fog { Color [_Fog]}
            ZWrite on
            Blend One One
            SetTexture [_RefractTexlow] {
                constantColor [_Emission]
                combine texture * constant
            }
        }
               
    }
}

I discovered this some years ago; I actually don’t know how it happens, because I didn’t think it was possible to look up texture data in the vertex shader, and that’s my guess at how it works, but I think the only solution is to use a Cg/GLSL shader.

So its more of an editor simulation bug than a shader bug (as in, it shouldnt be working in the editor which is giving me the false impression)?

I found someone with the same issue here: http://forum.unity3d.com/threads/101585-Problem-with-TexGen-Shaderlab?highlight=Texgen+Spheremap It sounds like the shader on the wiki used to work fine, but Unity has changed its functionality at some point. The below modification apparently works but makes the device require GLES 2.0. I thought you couldnt use cube maps on iOS, but I’ll check it later and edit this post:

// _Reflect ("Reflection", 2D) = "black" { TexGen SphereMap }

       _Reflect ("Environment Reflection", cube) = "white" {

            Cube

            texgen CubeReflect

        }

There are lots of things the Editor doesn’t emulate; emulation isn’t really too useful. I’d say that in general, it does a good job telling you if a shader won’t run at all, by turning them material magenta and providing Console feedback, but that’s about the extent of it.

Three years ago, you would have been right.

So Ive returned to this, and modified the original shader. This is still the first shader Ive worked with so its a learning experience. I now have a weird situation where the shader compiles and displays fine in the editor, but has a GLSL compilation error in Xcode when running.

The shader is below:

Shader "FX/DiamondOrig"
{
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
        _RefractTexlow ("Refract", cube) = "white" {
             Cube
            texgen CubeReflect
        }
        _ReflectTexlow ("Reflect", cube) = "white" {
             Cube
            texgen CubeReflect
        }
    }   

    SubShader {
                Pass {                    
           Lighting On          
            Color (0,0,0,0)
            Cull Front
            ZWrite Off
            SetTexture [_RefractTexlow] {
                constantColor [_Color]
                combine texture * constant, Primary
            }
            
          SetTexture [_ReflectTexlow] {
				combine previous, previous +- texture
			}
        }

        // Second pass - here we render the front faces of the diamonds.
        Pass {
            Fog {Color (0,0,0,0)}
            ZWrite on
            Blend One One
            SetTexture [_RefractTexlow] {
                constantColor [_Color]
                combine texture * constant
            }
            SetTexture [_ReflectTexlow] {
				combine previous + texture, previous +- texture
			}
        }            
    }
}

Ive narrowed the error down to one line: "combine previous + texture, previous +- texture" in the 2nd pass. The error occurs even if I replace that line with the ReflectTexLow line from the first pass, so I guess its something to do with the flags Im setting for that pass rather than the pass itself.

Heres the error from xcode:

-------- GLSL source: 
uniform highp mat4 glstate_matrix_mvp;
uniform highp mat4 glstate_matrix_modelview0;
attribute highp vec4 _glesVertex;
attribute mediump vec3 _glesNormal;
uniform lowp vec4 _glesFFColor;
varying lowp vec4 v_color;
attribute highp vec4 _glesMultiTexCoord0;
varying highp vec3 v_texCoord0;
uniform highp mat4 glstate_matrix_texture0;
attribute highp vec4 _glesMultiTexCoord1;
varying highp vec3 v_texCoord1;
uniform highp mat4 glstate_matrix_texture1;
void main()
{
    gl_Position = glstate_matrix_mvp * _glesVertex;
    vec4 vertexColor = _glesFFColor;
    highp vec4 eyePosition  = glstate_matrix_modelview0 * _glesVertex;
    v_texCoord0 = vec3(glstate_matrix_texture0 * _glesMultiTexCoord0);
    vec3 n = v_texCoord0.xyz;
    v_texCoord0 = reflect(eyePosition.xyz * eyePosition.w, n);
    v_texCoord1 = vec3(glstate_matrix_texture1 * _glesMultiTexCoord1);
    vec3 n = v_texCoord1.xyz;
    v_texCoord1 = reflect(eyePosition.xyz * eyePosition.w, n);
    v_color = vertexColor;
}
-------- GLSL error: ERROR: 0:23: Regular non-array variable 'n' may not be redeclared

-------- GLSL error: ERROR: One or more attached shaders not successfully compiled

I guess you’ll have to write something other than a fixed function shader. I don’t think this is a bug Unity can fix, right?

Thanks for the help Jessy. I’ve ended up adding a specular pass to replace the reflection cubemap. Its not as nice and has some artefacts on certain surfaces, but given its that or nothing, I went with it.

Im not sure how it would affect performance on an iphone. I think it might be faster, even? It is a shame it requires a light in the scene though. I’m currently using a directional light at 1.5 intensity to emulate the look of the original shader (there doesnt seem to be a way to get the shininess value from the slider, but I have it set about 85% of the way to the end. Hopefully that will help anyone in a similar situation.

Shader "FX/DiamondOrig"
{
    Properties {
        _Color ("Color", Color) = (1,1,1,1)
       _SpecColor ("Specular Color", Color) = (1,1,1,1)
       _Shininess ("Specular Falloff", Range (0.01, 1)) = 0.85

        _RefractTexlow ("Refract", cube) = "white" {
             Cube
            texgen CubeReflect
        }

    }   


    SubShader {
                Pass {
                             
        Lighting Off
              
            Color (0,0,0,0)
            Cull Front
            ZWrite Off
            SetTexture [_RefractTexlow] {
                constantColor [_Color]
                combine texture * constant, Primary
            }

        }

        // Second pass - here we render the front faces of the diamonds.
        Pass {
         Material {
                Shininess [_Shininess]
                Specular [_SpecColor]
            }
        Tags { "LightMode" = "Vertex" }
        
       Lighting On
       SeparateSpecular On
       Fog { Color (0,0,0,0)}
       Color (0,0,0,0)
            ZWrite on
            Blend One One
                        
            SetTexture [_RefractTexlow] {
                constantColor [_Color]
                combine texture * constant
            }

        }
               
    }
}

By the way, for anyone about to use it - the separate specular pass in the above appears not to work on the iphone. Ive read a few forum posts saying separatespecular doesn`t work at all, but I also notice its used in some of the mobile shaders. The result is still functional, but a little lifeless compared to the original shader.

I logged relevant bugs years ago. I don’t think they’ll get fixed, but I’m fine with that. The “mobile” shaders obviously didn’t get the time devoted that they needed, but soon it won’t matter. Mobile devices will be as powerful as low-end PC targets; that improvement is where the money is these days so that’s the place to watch for rapid hardware advancement.