[GLSL] Fragment shader version 130 and varying variables

We created our own material definition, vertex shader and fragment shader based upon the Lighting material definition and shaders.

We had to increase the GLSL version for fragment shader for the default technique to 130 (OpenGL 3.0) because we use features from the version, such as the function textureSize().

Here’s the default technique :

Technique {

    LightMode MultiPass

    VertexShader GLSL100:   shader/vertex/world_colors/atlas_palette_vertex_shader.vert
    FragmentShader GLSL130: shader/fragment/world_colors/atlas_palette_fragment_shader.frag

    WorldParameters {
        WorldViewProjectionMatrix
        NormalMatrix
        WorldViewMatrix
        ViewMatrix
        CameraPosition
        WorldMatrix
        ViewProjectionMatrix
    }

    Defines {
        VERTEX_COLOR : UseVertexColor
        VERTEX_LIGHTING : VertexLighting            
        MATERIAL_COLORS : UseMaterialColors
        DIFFUSEMAP : DiffuseMap
        NORMALMAP : NormalMap
        SPECULARMAP : SpecularMap
        PARALLAXMAP : ParallaxMap
        NORMALMAP_PARALLAX : PackedNormalParallax
        STEEP_PARALLAX : SteepParallax
        ALPHAMAP : AlphaMap
        COLORRAMP : ColorRamp
        LIGHTMAP : LightMap
        SEPARATE_TEXCOORD : SeparateTexCoord
        DISCARD_ALPHA : AlphaDiscardThreshold
        USE_REFLECTION : EnvMap
        SPHERE_MAP : EnvMapAsSphereMap  
        NUM_BONES : NumberOfBones                        
        INSTANCING : UseInstancing
        PALETTE_WORLD_INDEX : UseAtlasPalette
        FRESNEL_OUTLINE : UseFresnelOutline
    }
}

My question is : considering that the type qualifiers attribute and varying are deprecated, why do we not get errors? I find it really weird.

Here’s the atlas_palette_vertex_shader.vert shader :

#import "Common/ShaderLib/Instancing.glsllib"
#import "Common/ShaderLib/Skinning.glsllib"
#import "Common/ShaderLib/Lighting.glsllib"
#ifdef VERTEX_LIGHTING
    #import "Common/ShaderLib/BlinnPhongLighting.glsllib"    
#endif


uniform vec4 m_Ambient;
uniform vec4 m_Diffuse;
uniform vec4 m_Specular;
uniform float m_Shininess;

uniform vec4 g_LightColor;
uniform vec4 g_LightPosition;
uniform vec4 g_AmbientLightColor;

varying vec2 texCoord;
#ifdef SEPARATE_TEXCOORD
  varying vec2 texCoord2;
  attribute vec2 inTexCoord2;
#endif

varying vec3 AmbientSum;
varying vec4 DiffuseSum;
varying vec3 SpecularSum;

attribute vec3 inPosition;
attribute vec2 inTexCoord;
attribute vec3 inNormal;

varying vec3 lightVec;

#ifdef VERTEX_COLOR
  attribute vec4 inColor;
#endif

#ifndef VERTEX_LIGHTING
  attribute vec4 inTangent;

  #ifndef NORMALMAP
    varying vec3 vNormal;
  #endif  
  varying vec3 vViewDir;
  varying vec4 vLightDir;
#else
  varying vec2 vertexLightValues;
  uniform vec4 g_LightDirection;
#endif

#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING) 
    varying vec3 vViewDirPrlx;
#endif

#if defined(USE_REFLECTION) || defined(FRESNEL_OUTLINE)
    uniform vec3 g_CameraPosition;
#endif

#ifdef USE_REFLECTION
    uniform vec3 m_FresnelParams;
    varying vec4 refVec;

    /**
     * Input:
     * attribute inPosition
     * attribute inNormal
     * uniform g_WorldMatrix
     * uniform g_CameraPosition
     *
     * Output:
     * varying refVec
     */
    void computeRef(in vec4 modelSpacePos){
        // vec3 worldPos = (g_WorldMatrix * modelSpacePos).xyz;
        vec3 worldPos = TransformWorld(modelSpacePos).xyz;

        vec3 I = normalize( g_CameraPosition - worldPos  ).xyz;
        // vec3 N = normalize( (g_WorldMatrix * vec4(inNormal, 0.0)).xyz );
        vec3 N = normalize( TransformWorld(vec4(inNormal, 0.0)).xyz );

        refVec.xyz = reflect(I, N);
        refVec.w   = m_FresnelParams.x + m_FresnelParams.y * pow(1.0 + dot(I, N), m_FresnelParams.z);
    }
#endif

#ifdef FRESNEL_OUTLINE
    uniform float m_FresnelOutlineBias;
    uniform float m_FresnelOutlineScale;
    uniform float m_FresnelOutlinePower;

    varying float fresnelOutlineR;

    /*
     * Input :
     * attribute inPosition
     * attribute inNormal
     * uniform g_WorldMatrix
     * uniform g_CameraPosition
     *
     * Output :
     * varying fresnelOutlineR
     */
    void computeFresnelOutline(in vec4 modelSpacePos){
        vec3 worldPosition = (g_WorldMatrix * modelSpacePos).xyz;
        vec4 worldNormal = normalize(g_WorldMatrix * vec4(inNormal, 0.0));

        vec3 fresnelI = normalize(worldPosition - g_CameraPosition);

        fresnelOutlineR = m_FresnelOutlineBias + m_FresnelOutlineScale * pow(1.0 + dot(fresnelI, worldNormal.xyz), m_FresnelOutlinePower);
    }
#endif

void main(){
   vec4 modelSpacePos = vec4(inPosition, 1.0);
   vec3 modelSpaceNorm = inNormal;
   
   #ifndef VERTEX_LIGHTING
        vec3 modelSpaceTan  = inTangent.xyz;
   #endif

   #ifdef NUM_BONES
        #ifndef VERTEX_LIGHTING
        Skinning_Compute(modelSpacePos, modelSpaceNorm, modelSpaceTan);
        #else
        Skinning_Compute(modelSpacePos, modelSpaceNorm);
        #endif
   #endif

   gl_Position = TransformWorldViewProjection(modelSpacePos);// g_WorldViewProjectionMatrix * modelSpacePos;
   texCoord = inTexCoord;
   #ifdef SEPARATE_TEXCOORD
      texCoord2 = inTexCoord2;
   #endif

   vec3 wvPosition = TransformWorldView(modelSpacePos).xyz;// (g_WorldViewMatrix * modelSpacePos).xyz;
   vec3 wvNormal  = normalize(TransformNormal(modelSpaceNorm));//normalize(g_NormalMatrix * modelSpaceNorm);
   vec3 viewDir = normalize(-wvPosition);
  
   vec4 wvLightPos = (g_ViewMatrix * vec4(g_LightPosition.xyz,clamp(g_LightColor.w,0.0,1.0)));
   wvLightPos.w = g_LightPosition.w;
   vec4 lightColor = g_LightColor;

   #if (defined(NORMALMAP) || defined(PARALLAXMAP)) && !defined(VERTEX_LIGHTING)
     vec3 wvTangent = normalize(TransformNormal(modelSpaceTan));
     vec3 wvBinormal = cross(wvNormal, wvTangent);
     mat3 tbnMat = mat3(wvTangent, wvBinormal * inTangent.w,wvNormal);
   #endif
 
   #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
     vViewDir  = -wvPosition * tbnMat;    
     #if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) 
         vViewDirPrlx = vViewDir;
     #endif
     lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
     vLightDir.xyz = (vLightDir.xyz * tbnMat).xyz;
   #elif !defined(VERTEX_LIGHTING)
     vNormal = wvNormal;
     vViewDir = viewDir;
     #if defined(PARALLAXMAP)
        vViewDirPrlx  =  -wvPosition * tbnMat;
     #endif
     lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
   #endif

   #ifdef MATERIAL_COLORS
      AmbientSum  = (m_Ambient  * g_AmbientLightColor).rgb;
      DiffuseSum  =  m_Diffuse  * vec4(lightColor.rgb, 1.0);
      SpecularSum = (m_Specular * lightColor).rgb;
    #else
      // Defaults: Ambient and diffuse are white, specular is black.
      AmbientSum  = g_AmbientLightColor.rgb;
      DiffuseSum  =  vec4(lightColor.rgb, 1.0);
      SpecularSum = vec3(0.0);
    #endif

    #ifdef VERTEX_COLOR
      AmbientSum *= inColor.rgb;
      DiffuseSum *= inColor;
    #endif

    #ifdef VERTEX_LIGHTING
        float spotFallOff = 1.0;
        vec4 vLightDir;
        lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
        #if __VERSION__ >= 110
            // allow use of control flow
        if(lightColor.w > 1.0){
        #endif           
           spotFallOff = computeSpotFalloff(g_LightDirection, lightVec);
        #if __VERSION__ >= 110           
        }
        #endif
        
        vertexLightValues = computeLighting(wvNormal, viewDir, vLightDir.xyz, vLightDir.w * spotFallOff, m_Shininess);
    #endif

    #ifdef USE_REFLECTION 
        computeRef(modelSpacePos);
    #endif

    #ifdef FRESNEL_OUTLINE
        computeFresnelOutline(modelSpacePos);
    #endif
}

Here’s the atlas_palette_fragment_shader.frag shader :

#import "Common/ShaderLib/Parallax.glsllib"
#import "Common/ShaderLib/Optics.glsllib"
#ifndef VERTEX_LIGHTING
    #import "Common/ShaderLib/BlinnPhongLighting.glsllib"
    #import "Common/ShaderLib/Lighting.glsllib"
#endif

varying vec2 texCoord;
#ifdef SEPARATE_TEXCOORD
  varying vec2 texCoord2;
#endif

varying vec3 AmbientSum;
varying vec4 DiffuseSum;
varying vec3 SpecularSum;

#ifndef VERTEX_LIGHTING
  uniform vec4 g_LightDirection;
  //varying vec3 vPosition;
  varying vec3 vViewDir;
  varying vec4 vLightDir;
  varying vec3 lightVec;
#else
  varying vec2 vertexLightValues;
#endif

#ifdef DIFFUSEMAP
  uniform sampler2D m_DiffuseMap;
#endif

#ifdef SPECULARMAP
  uniform sampler2D m_SpecularMap;
#endif

#ifdef PARALLAXMAP
  uniform sampler2D m_ParallaxMap;  
#endif
#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING) 
    uniform float m_ParallaxHeight;
    varying vec3 vViewDirPrlx;
#endif

#ifdef LIGHTMAP
  uniform sampler2D m_LightMap;
#endif
  
#ifdef NORMALMAP
  uniform sampler2D m_NormalMap;   
#else
  varying vec3 vNormal;
#endif

#ifdef ALPHAMAP
  uniform sampler2D m_AlphaMap;
#endif

#ifdef COLORRAMP
  uniform sampler2D m_ColorRamp;
#endif

uniform float m_AlphaDiscardThreshold;

#ifndef VERTEX_LIGHTING
    uniform float m_Shininess;
    #ifdef USE_REFLECTION 
        uniform float m_ReflectionPower;
        uniform float m_ReflectionIntensity;
        varying vec4 refVec;

        uniform ENVMAP m_EnvMap;
    #endif
#endif

#ifdef PALETTE_WORLD_INDEX
    const int m_PaletteWorldWidth = 8;
    const int m_PaletteWorldHeight = 5;
    uniform int m_PaletteWorldIndex;
#endif

#ifdef FRESNEL_OUTLINE
    uniform vec4 m_FresnelOutlineColor;
    varying float fresnelOutlineR;
#endif

void main(){
    vec2 newTexCoord;
     
    #if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING) 
     
       #ifdef STEEP_PARALLAX
           #ifdef NORMALMAP_PARALLAX
               //parallax map is stored in the alpha channel of the normal map         
               newTexCoord = steepParallaxOffset(m_NormalMap, vViewDirPrlx, texCoord, m_ParallaxHeight);
           #else
               //parallax map is a texture
               newTexCoord = steepParallaxOffset(m_ParallaxMap, vViewDirPrlx, texCoord, m_ParallaxHeight);         
           #endif
       #else
           #ifdef NORMALMAP_PARALLAX
               //parallax map is stored in the alpha channel of the normal map         
               newTexCoord = classicParallaxOffset(m_NormalMap, vViewDirPrlx, texCoord, m_ParallaxHeight);
           #else
               //parallax map is a texture
               newTexCoord = classicParallaxOffset(m_ParallaxMap, vViewDirPrlx, texCoord, m_ParallaxHeight);
           #endif
       #endif
    #else
       newTexCoord = texCoord;
    #endif

    #ifdef PALETTE_WORLD_INDEX
        ivec2 textureDimensions = textureSize(m_DiffuseMap, 0);
        newTexCoord.x += float(m_PaletteWorldWidth) * float(m_PaletteWorldIndex) / float(textureDimensions.x);
    #endif
    
    #ifdef DIFFUSEMAP
      vec4 diffuseColor = texture2D(m_DiffuseMap, newTexCoord);
    #else
      vec4 diffuseColor = vec4(1.0);
    #endif

    float alpha = DiffuseSum.a * diffuseColor.a;
    #ifdef ALPHAMAP
       alpha = alpha * texture2D(m_AlphaMap, newTexCoord).r;
    #endif
    #ifdef DISCARD_ALPHA
        if(alpha < m_AlphaDiscardThreshold){
            discard;
        }
    #endif


    // ***********************
    // Read from textures
    // ***********************
    #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
      vec4 normalHeight = texture2D(m_NormalMap, newTexCoord);
      //Note the -2.0 and -1.0. We invert the green channel of the normal map, 
      //as it's complient with normal maps generated with blender.
      //see http://hub.jmonkeyengine.org/forum/topic/parallax-mapping-fundamental-bug/#post-256898
      //for more explanation.
      vec3 normal = normalize((normalHeight.xyz * vec3(2.0,-2.0,2.0) - vec3(1.0,-1.0,1.0)));
      #ifdef LATC
        normal.z = sqrt(1.0 - (normal.x * normal.x) - (normal.y * normal.y));
      #endif      
    #elif !defined(VERTEX_LIGHTING)
      vec3 normal = vNormal;
      #if !defined(LOW_QUALITY) && !defined(V_TANGENT)
         normal = normalize(normal);
      #endif
    #endif

    #ifdef SPECULARMAP
      vec4 specularColor = texture2D(m_SpecularMap, newTexCoord);
    #else
      vec4 specularColor = vec4(1.0);
    #endif

    #ifdef LIGHTMAP
       vec3 lightMapColor;
       #ifdef SEPARATE_TEXCOORD
          lightMapColor = texture2D(m_LightMap, texCoord2).rgb;
       #else
          lightMapColor = texture2D(m_LightMap, texCoord).rgb;
       #endif
       specularColor.rgb *= lightMapColor;
       diffuseColor.rgb  *= lightMapColor;
    #endif

    #ifdef VERTEX_LIGHTING
       vec2 light = vertexLightValues.xy;
       #ifdef COLORRAMP
            diffuseColor.rgb  *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;
            specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;
            light.xy = vec2(1.0);
       #endif

       gl_FragColor.rgb =  AmbientSum     * diffuseColor.rgb + 
                           DiffuseSum.rgb * diffuseColor.rgb  * vec3(light.x) +
                           SpecularSum    * specularColor.rgb * vec3(light.y);
    #else
       vec4 lightDir = vLightDir;
       lightDir.xyz = normalize(lightDir.xyz);
       vec3 viewDir = normalize(vViewDir);
       float spotFallOff = 1.0;

       #if __VERSION__ >= 110
        // allow use of control flow
        if(g_LightDirection.w != 0.0){
       #endif
          spotFallOff =  computeSpotFalloff(g_LightDirection, lightVec);
       #if __VERSION__ >= 110
          if(spotFallOff <= 0.0){
              gl_FragColor.rgb = AmbientSum * diffuseColor.rgb;
              gl_FragColor.a   = alpha;
              return;
          }
         }        
       #endif

       vec2   light = computeLighting(normal, viewDir, lightDir.xyz, lightDir.w * spotFallOff, m_Shininess) ;
       #ifdef COLORRAMP
            diffuseColor.rgb  *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;
            specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;
            light.xy = vec2(1.0);
       #endif

       // Workaround, since it is not possible to modify varying variables
       vec4 SpecularSum2 = vec4(SpecularSum, 1.0);
       #ifdef USE_REFLECTION
            vec4 refColor = Optics_GetEnvColor(m_EnvMap, refVec.xyz);

            // Interpolate light specularity toward reflection color
            // Multiply result by specular map
            specularColor = mix(SpecularSum2 * light.y, refColor, refVec.w) * specularColor;

            SpecularSum2 = vec4(1.0);
            light.y = 1.0;
       #endif

       #ifdef FRESNEL_OUTLINE
            specularColor = mix(SpecularSum2 * light.y, m_FresnelOutlineColor, fresnelOutlineR) * specularColor;
            SpecularSum2 = vec4(1.0);
            light.y = 1.0;
       #endif

       gl_FragColor.rgb =  AmbientSum       * diffuseColor.rgb  +
                           DiffuseSum.rgb   * diffuseColor.rgb  * vec3(light.x) +
                           SpecularSum2.rgb * specularColor.rgb * vec3(light.y);
    #endif
    gl_FragColor.a = alpha;
}

We use the phong lighting, the UseAtlasPalette is set to true and sometimes the fresnel outline is set to true too.

It’s rather different between drivers how forgiving they are and how much backwards ‘compatibility’ they allow in compatibility mode.

1 Like

Oh damn, so it might not work on other machines.

Thank you very much for that information.

Well if you are worry and that your shader aims 1.3 or higher you can turn any “varrying” keywords in “in” or “out” accordingly.

Though if you don’t want to care put this line at the top of your shaders

This will “fix” the keywords depending on the version you use. So you can continue to use “varying” even with higher glsl versions.

5 Likes