
This tutorial introducesdisplacement maps as an example of an application of texture lookups in vertex shaders.
This tutorial requires some knowledge about texture mapping as described inSection “Textured Spheres”.
Most tutorials in this wikibook use texture lookups only in fragment shaders because texture lookups in vertex shaders are a Shader Model 3.0 feature, i.e., it is not supported by all GPUs (seeUnity's description of platform-specific rendering differences).
However,displacement mapping requires a lookup of a texture value for each vertex, which is used to displace, i.e., move, each vertex to a new position. For technical reasons, we cannot use the standardtex2d command. Instead we have to use the commandtex2dlod with a four-dimensional vector specifying the texture coordinates where the 4th component is 0. (This makes sure that we always read the value from the finestmipmap level and we don't request an automatic computation of the mipmap level, which is impossible in a vertex shader.) The command could look like this:
float4dispTexColor=tex2Dlod(_DisplacementTex,float4(i.texcoord.xy,0.0,0.0));
wherei.texcoord.xy are the two texture coordinates.
The example below converts the resulting colordispTexColor to a gray value and scales it with a user-specified uniform_MaxDisplacement:
floatdisplacement=dot(float3(0.21,0.72,0.07),dispTexColor.rgb)*_MaxDisplacement;
This displacement value is then used to move each vertex along its surface normal vector, i.e., we add the vertex position in object coordinates (i.vertex in the example) to the surface normal vector (i.normal) multiplied with the displacement value.
float4newVertexPos=i.vertex+float4(i.normal*displacement,0.0);
Note thati.normal is a three-dimensional vector; thus, we have to append a 0.0 coordinate to form a four-dimensional vector before we can add it to the vertex position.
The rest of the code applies the standard vertex transformations and colors the surface with a unlit texture map. Make sure to use it on meshes with relatively many vertices - otherwise the displaced surface will appear quite "blocky."
Shader"Vertex Displacement"{Properties{_MainTex("Main Texture",2D)="white"{}_DisplacementTex("Displacement Texture",2D)="white"{}_MaxDisplacement("Max Displacement",Float)=1.0}SubShader{Pass{CGPROGRAM#pragma vertex vert#pragma fragment fraguniformsampler2D_MainTex;uniformsampler2D_DisplacementTex;uniformfloat_MaxDisplacement;structvertexInput{float4vertex:POSITION;float3normal:NORMAL;float4texcoord:TEXCOORD0;};structvertexOutput{float4position:SV_POSITION;float4texcoord:TEXCOORD0;};vertexOutputvert(vertexInputi){vertexOutputo;// get color from displacement map, and convert to float from 0 to _MaxDisplacementfloat4dispTexColor=tex2Dlod(_DisplacementTex,float4(i.texcoord.xy,0.0,0.0));floatdisplacement=dot(float3(0.21,0.72,0.07),dispTexColor.rgb)*_MaxDisplacement;// displace vertices along surface normal vectorfloat4newVertexPos=i.vertex+float4(i.normal*displacement,0.0);// output datao.position=UnityObjectToClipPos(newVertexPos);o.texcoord=i.texcoord;returno;}float4frag(vertexOutputi):COLOR{returntex2D(_MainTex,i.texcoord.xy);}ENDCG}}}
Note that edges of the surface mesh might not match up if the colors at the edges of the texture image do not match or if the surface normal vectors of corresponding vertices do not match.
Congratulations, you have reached the end of this tutorial. You saw:
If you still want to learn more
tex2dlod, you could readUnity's description of platform-specific rendering differences andMicrosoft's description of tex2dlod.