Accessing vertices in vert() before they are changed?

Hi, I haven’t been able to find an answer to this question.

I’m new with shaders and I’ve obtained 2 shaders that does the following:

The first shader takes the vertices height on the Y axis, and colors them depending on the height.

The second shader, warps the object to appear round.

The goal is to combine these, but make then work sequentially so the vertex color painting shader starts, and then the geometry(vertex position) modifying shader works afterwards.

In other words, what I need is the vertices’ to be colored based on the y-axis height BEFORE the warp.

My problem is that when i try to combine these shaders, I get the color AFTER the warp.

I will post the two shaders, and my attempt at combining them. I think the error is somewhere in the vert() function, but I honestly don’t know. I assume that I have to access the vertices, get their height and transfer the color BEFORE i start moving them around based on the warping code.

Any suggestions are greatly appreciated :slight_smile:

Here is the vertex painting shader:

Shader "Global-Mapper" {
Properties {
    _PeakColor ("PeakColor", Color) = (0.8,0.9,0.9,1)   
    _PeakLevel ("PeakLevel", Float) = 2
    _Level3Color ("Level3Color", Color) = (0.75,0.53,0,1)
    _Level3 ("Level3", Float) = 1.5
    _Level2Color ("Level2Color", Color) = (0.69,0.63,0.31,1)
    _Level2 ("Level2", Float) = 1
    _Level1Color ("Level1Color", Color) = (0.65,0.86,0.63,1)
    _WaterLevel ("WaterLevel", Float) = 0.5
    _WaterColor ("WaterColor", Color) = (0.37,0.78,0.92,1)
    _Slope ("Slope Fader", Range (0,1)) = 0
}
SubShader {
    Tags { "RenderType" = "Opaque" }
    Fog { Mode Off }
    Tags { "LightMode" = "Always" }
    CGPROGRAM
    #pragma surface surf Lambert vertex:vert
    struct Input {
        float3 customColor;
        float3 worldPos;
    };
    void vert (inout appdata_full v, out Input o) {
        o.customColor = abs(v.normal.y);
    }
    float _PeakLevel;
    float4 _PeakColor;
    float _Level3;
    float4 _Level3Color;
    float _Level2;
    float4 _Level2Color;
    float _Level1;
    float4 _Level1Color;
    float _Slope;
    float _WaterLevel;
    float4 _WaterColor;
    void surf (Input IN, inout SurfaceOutput o) {
        if (IN.worldPos.y >= _PeakLevel)
            o.Albedo = _PeakColor;
        if (IN.worldPos.y <= _PeakLevel)
            o.Albedo = lerp(_Level3Color, _PeakColor, (IN.worldPos.y - _Level3)/(_PeakLevel - _Level3));
        if (IN.worldPos.y <= _Level3)
            o.Albedo = lerp(_Level2Color, _Level3Color, (IN.worldPos.y - _Level2)/(_Level3 - _Level2));
        if (IN.worldPos.y <= _Level2)
            o.Albedo = lerp(_Level1Color, _Level2Color, (IN.worldPos.y - _WaterLevel)/(_Level2 - _WaterLevel));
        if (IN.worldPos.y <= _WaterLevel)
            o.Albedo = _WaterColor;
        o.Albedo *= saturate(IN.customColor + _Slope);          
    }
    ENDCG
}
Fallback "Diffuse"
}

And the geometry warping shader

Shader "Example/Normal Extrusion" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _Amount ("Extrusion Amount", Range(-1000.0,-1.0)) = -50.0
    }
    SubShader {
      Tags { "RenderType" = "Opaque" }
      CGPROGRAM
      #pragma surface surf Lambert vertex:vert
      struct Input {
          float2 uv_MainTex;
      };
      float _Amount;
   
		void vert (inout appdata_full v)
		{
			v.vertex = mul(_Object2World, v.vertex);
	  		
	  		float4 n = float4(v.normal.xyz ,1.0);
	  		n = mul(_Object2World, n);
	  		
	  		//define curve origin
	  		float3 origin = _WorldSpaceCameraPos.xyz;
	  		origin.y = -100.0;
	  
	  		//Find origin to vertex vector
	  		float3 diff = v.vertex.xyz - origin;
	  		
	  		
	  		//Compute dist in horizontal plane
	  		float dist = length(diff.xz);
	  		float3 up = float3(0.0,1.0,0.0); 
	  		float3 dir = normalize(float3(diff.x,0,diff.z));
	  		float r = diff.y;
	  		float Pi = acos(-1.0);
	  		float limit = Pi*r/2.0;
	  		if(dist <= limit)
	  		{
	  			float ang = dist/r;
	  			v.vertex.xyz = origin + dir*r*sin(ang) + up*r*cos(ang);
	  		}
	  		else
	  		{
	  			v.vertex.xyz = origin  + dir*r - up*(dist-limit);
	  		}
	  		
	  		v.vertex =  mul(_World2Object, v.vertex); 
	  		v.normal = mul(_World2Object, n).xyz;
	  }
	   
      sampler2D _MainTex;
      void surf (Input IN, inout SurfaceOutput o) {
          o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
      }
      ENDCG
    } 
    Fallback "Diffuse"
  }

And finally my combined (yet failing) attempt:

Shader "Global-Round-Mapper" {
    Properties {
      _MainTex ("Texture", 2D) = "white" {}
      _Amount ("Extrusion Amount", Range(-1000.0,-1.0)) = -50.0
      _PeakColor ("PeakColor", Color) = (0.8,0.9,0.9,1)   
    _PeakLevel ("PeakLevel", Float) = 2
    _Level3Color ("Level3Color", Color) = (0.75,0.53,0,1)
    _Level3 ("Level3", Float) = 1.5
    _Level2Color ("Level2Color", Color) = (0.69,0.63,0.31,1)
    _Level2 ("Level2", Float) = 1
    _Level1Color ("Level1Color", Color) = (0.65,0.86,0.63,1)
    _WaterLevel ("WaterLevel", Float) = 0.5
    _WaterColor ("WaterColor", Color) = (0.37,0.78,0.92,1)
    _Slope ("Slope Fader", Range (0,1)) = 0
    }
    
    
    SubShader {
	    	Tags { "RenderType" = "Opaque" }
		    Fog { Mode Off }
		    Tags { "LightMode" = "Always" }
		    CGPROGRAM
		    #pragma surface surf Lambert vertex:vert
		    
		    float _Amount;
		    
		    struct Input {
		        float3 customColor;
		        float3 worldPos;
		        float2 uv_MainTex;
		    };
		    
		    void vert (inout appdata_full v, out Input o) {
		        // these 2 lines sets the height color.
		        float3 vCopyNormal = v.normal;
		        o.customColor = abs(vCopyNormal.y);
		        o.customColor = float3(0.0,0.0,1.0);
		        
		        v.vertex = mul(_Object2World, v.vertex);
		  		float4 n = float4(v.normal.xyz ,1.0);
		  		n = mul(_Object2World, n);
		  		
		  		//define curve origin
		  		float3 origin = _WorldSpaceCameraPos.xyz;
		  		origin.y = -100.0;
		  
		  		//Find origin to vertex vector
		  		float3 diff = v.vertex.xyz - origin;
		  		
		  		//Compute dist in horizontal plane
		  		float dist = length(diff.xz);
		  		float3 up = float3(0.0,1.0,0.0); 
		  		float3 dir = normalize(float3(diff.x,0,diff.z));
		  		float r = diff.y;
		  		float Pi = acos(-1.0);
		  		float limit = Pi*r/2.0;
		  		if(dist <= limit)
		  		{
		  			float ang = dist/r;
		  			v.vertex.xyz = origin + dir*r*sin(ang) + up*r*cos(ang);
		  		}
		  		else
		  		{
		  			v.vertex.xyz = origin  + dir*r - up*(dist-limit);
		  		}
		  		v.vertex =  mul(_World2Object, v.vertex);
		  		v.normal = mul(_World2Object, n).xyz;
		    }
		    float _PeakLevel;
		    float4 _PeakColor;
		    float _Level3;
		    float4 _Level3Color;
		    float _Level2;
		    float4 _Level2Color;
		    float _Level1;
		    float4 _Level1Color;
		    float _Slope;
		    float _WaterLevel;
		    float4 _WaterColor;
		    
		    sampler2D _MainTex;
		    void surf (Input IN, inout SurfaceOutput o) {
		        if (IN.worldPos.y >= _PeakLevel)
		            o.Albedo = _PeakColor;
		        if (IN.worldPos.y <= _PeakLevel)
		            o.Albedo = lerp(_Level3Color, _PeakColor, (IN.worldPos.y - _Level3)/(_PeakLevel - _Level3));
		        if (IN.worldPos.y <= _Level3)
		            o.Albedo = lerp(_Level2Color, _Level3Color, (IN.worldPos.y - _Level2)/(_Level3 - _Level2));
		        if (IN.worldPos.y <= _Level2)
		            o.Albedo = lerp(_Level1Color, _Level2Color, (IN.worldPos.y - _WaterLevel)/(_Level2 - _WaterLevel));
		        if (IN.worldPos.y <= _WaterLevel)
		            o.Albedo = _WaterColor;
		            
		        //o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
		        o.Albedo *= saturate(IN.customColor + _Slope);          
		    }
		    ENDCG
	  }
      
     
    Fallback "Diffuse"
  }

It looks like the vert is adjusting the vertices, then worldSpace is calculated after that distortion, and passed through to the surface. You’ll want to have a “pure” version of the vert to refer to.

Add your own copy of the vertex->worldSpace and treat it like a normal vert, without distortion.

i.e.

  struct Input {
                 float3 customColor;
                 float3 worldPos;
                 **float4 boringWorldPos;**
                 float2 uv_MainTex;
             };

then in the vert program:

o.boringWorldPos = mul(_Object2World, v.vertex);//this is how you'd normally convert a vertex from model space to screen space

And finally, in your surf function, refer to "IN.boringWorldPos " instead of “IN.worldPos”