- Home /
Unity 5 tesselation problem
I have the following terrain shader I wrote, where I am trying to experiment with DX11 tesselation using portions of the examples http://docs.unity3d.com/Manual/SL-SurfaceShaderTessellation.html
Shader "Custom/Terrain" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_Phong ("Phong Strengh", Range(0,1)) = 0.5
// Should we keep _MainTex?
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
_HeightMap ("Height Map", 2D) = "white" {}
_TexSnow ("Snow Texture", 2D) = "white" {}
_TexMountainPeaks ("Mountain Peaks Texture", 2D) = "red" {}
_TexMountains ("Mountain Texture", 2D) = "red" {}
_TexHighlands ("Highlands Texture", 2D) = "red" {}
_TexPlains ("Plains Texture", 2D) = "green" {}
_TexPlainsBlendA ("Plains Texture Blend A", 2D) = "green" {}
_TexPlainsBlendB ("Plains Texture Blend B", 2D) = "green" {}
_TexBeaches ("Beach Texture", 2D) = "white" {}
_TexOceanFloor ("Ocean Floor Texture", 2D) = "blue" {}
_Radius ("Terrain Radius", Float) = 5000
_MinHeight ("Terrain Minimum Height", Float) = 5000
_MaxHeight ("Terrain Maximum Height", Float) = 5000
_HeightMountainPeaks ("Mountain Peaks Start Height", Range(0,1)) = 0.9
_HeightMountains ("Mountain Start Height", Range(0,1)) = 0.8
_HeightHighlands ("HighLands Start Height", Range(0,1)) = 0.7
_HeightPlains ("Plains Start Height", Range(0,1)) = 0.5
_HeightBeaches ("Beach Start Height", Range(0,1)) = 0.45
_BlendTolerance ("Blend Tolerance", Range(0.0, 0.5)) = 0.1
_SlopeTolerance ("Slope Tolerance", Range(0.001, 1)) = 0.5
_IceCapStrength ("Ice Cap Strength", Range(0, 1)) = 0
}
SubShader {
Tags {
"RenderType"="Opaque"
"Queue"="Geometry"
}
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows tessellate:tess tessphong:_Phong
//#include "Tessellation.cginc"
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
// noise functions TODO: add to a sperate library and include
#ifndef __noise_hlsl_
#define __noise_hlsl_
// hash based 3d value noise
// function taken from [url]https://www.shadertoy.com/view/XslGRr[/url]
// Created by inigo quilez - iq/2013
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
// ported from GLSL to HLSL
float hash( float n )
{
return frac(sin(n)*43758.5453);
}
float pnoise( float3 x )
{
// The noise function returns a value in the range -1.0f -> 1.0f
float3 p = floor(x);
float3 f = frac(x);
f = f*f*(3.0-2.0*f);
float n = p.x + p.y*57.0 + 113.0*p.z;
return lerp(lerp(lerp( hash(n+0.0), hash(n+1.0),f.x),
lerp( hash(n+57.0), hash(n+58.0),f.x),f.y),
lerp(lerp( hash(n+113.0), hash(n+114.0),f.x),
lerp( hash(n+170.0), hash(n+171.0),f.x),f.y),f.z);
}
float pnoiseNormalized(float3 x) {
return smoothstep(0, 1, pnoise(x));
}
#endif
float _Phong;
sampler2D _MainTex;
sampler2D _HeightMap;
sampler2D _TexSnow;
sampler2D _TexMountainPeaks;
sampler2D _TexMountains;
sampler2D _TexHighlands;
sampler2D _TexPlains;
sampler2D _TexPlainsBlendA;
sampler2D _TexPlainsBlendB;
sampler2D _TexBeaches;
sampler2D _TexOceanFloor;
float _Radius;
float _MinHeight;
float _MaxHeight;
float _HeightMountainPeaks;
float _HeightMountains;
float _HeightHighlands;
float _HeightPlains;
float _HeightBeaches;
float _BlendTolerance;
float _SlopeTolerance;
float _IceCapStrength;
struct Input {
float2 uv_MainTex;
float2 uv_HeightMap;
float2 uv_TexMountainPeaks;
float2 uv_TexMountains;
float2 uv_TexPlains;
float2 uv_TexBeaches;
float2 uv_TexOceanFloor;
float3 worldPos;
float3 cameraPos;
float3 worldNormal;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
// blends two colors together based on height and blend tolerance
fixed4 BlendByHeight(float startHeight, float height, fixed4 colorLow, fixed4 colorHigh, float noise) {
float bt = _BlendTolerance;
if(height >= startHeight - bt) {
return lerp(colorLow,
colorHigh,
smoothstep(startHeight - bt, startHeight, height));
} else {
return colorLow;
}
}
// returns a color that is blended with larger samples of itself. used to
// reduce the appearance of tiling
fixed4 tex2DTiled(sampler2D tex, float2 uv) {
return tex2D(tex, uv) * tex2D(tex, uv * -0.1) * tex2D(tex, uv * -0.01) * 4;
}
fixed4 tex2DTriPlanar(sampler2D tex, float3 coords, float3 norm) {
float3 blending = abs(norm);
blending = normalize(max(blending, 0.00001));
float b = (blending.x + blending.y + blending.z);
blending /= float3(b, b, b);
fixed4 xaxis = tex2DTiled(tex, coords.yz);
fixed4 yaxis = tex2DTiled(tex, coords.xz);
fixed4 zaxis = tex2DTiled(tex, coords.xy);
// blend the results of the 3 planar projections.
fixed4 retVal = xaxis * blending.x + yaxis * blending.y + zaxis * blending.z;
return retVal;
}
// returns color value based on 3 textures, and perlin noise
fixed4 tex2DBlend(sampler2D tA, sampler2D tB, sampler2D tC, float2 uv, float noise) {
fixed4 cA = tex2DTiled(tA, uv);
fixed4 cB = tex2DTiled(tB, uv);
fixed4 cC = tex2DTiled(tC, uv);
fixed4 c = lerp(cA, cB, noise);
fixed4 c2 = lerp(cA, cC, 1 - noise);
return lerp(c, c2, 0.5);
}
fixed4 tex2DBlendTriPlanar(sampler2D tA, sampler2D tB, sampler2D tC, float3 coords, float3 norm, float noise) {
fixed4 cA = tex2DTriPlanar(tA, coords, norm);
fixed4 cB = tex2DTriPlanar(tB, coords, norm);
fixed4 cC = tex2DTriPlanar(tC, coords, norm);
fixed4 c = lerp(cA, cB, noise);
fixed4 c2 = lerp(cA, cC, 1 - noise);
return lerp(c, c2, 0.5);
}
float4 tess() {
///float minDist = 10.0;
// maxDist = 25.0;
//return UnityDistanceBasedTess(v0.vertex, v1.vertex, v2.vertex, minDist, maxDist, 4);
return 4;
}
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 c = _Color;
// distance from the camera to the world origin
float dist = distance(_WorldSpaceCameraPos, float3(0,0,0)) - _Radius;
// get the height based on the radius of the world, strength, and normilize
float height = smoothstep(_MinHeight, _MaxHeight, length(IN.worldPos));
// generate some noise
float noise = pnoiseNormalized(IN.worldPos);
// sample correct texture based on height
if(height >= _HeightMountainPeaks) {
c = tex2DTriPlanar(_TexMountainPeaks, IN.worldPos, IN.worldNormal);
} else if(height >= _HeightMountains) {
c = BlendByHeight(_HeightMountainPeaks,
height,
tex2DTriPlanar(_TexMountains, IN.worldPos, IN.worldNormal),
tex2DTriPlanar(_TexMountainPeaks, IN.worldPos, IN.worldNormal),
noise);
} else if(height >= _HeightHighlands) {
c = BlendByHeight(_HeightMountains,
height,
tex2DBlendTriPlanar(_TexHighlands, _TexPlainsBlendA, _TexMountains, IN.worldPos, IN.worldNormal, noise),
tex2DTriPlanar(_TexMountains, IN.worldPos, IN.worldNormal),
noise);
} else if(height >= _HeightPlains) {
c = BlendByHeight(_HeightHighlands,
height,
tex2DBlend(_TexPlains, _TexPlainsBlendA, _TexPlainsBlendB, IN.uv_TexPlains, noise),
tex2DBlendTriPlanar(_TexHighlands, _TexPlainsBlendA, _TexMountains, IN.worldPos, IN.worldNormal, noise),
noise);
} else if(height >= _HeightBeaches) {
c = BlendByHeight(_HeightPlains,
height,
tex2D (_TexBeaches, IN.uv_TexBeaches),
tex2DBlend(_TexPlains, _TexPlainsBlendA, _TexPlainsBlendB, IN.uv_TexPlains, noise),
noise);
} else {
c = BlendByHeight(_HeightBeaches,
height,
tex2D (_TexOceanFloor, IN.uv_TexOceanFloor),
tex2D (_TexBeaches, IN.uv_TexBeaches),
noise);
}
// now find out if we should lerp in some snow texture for ice caps
float poleDistance = smoothstep(0, _Radius, abs(IN.worldPos.y));
if(poleDistance >= _IceCapStrength) {
c = lerp(c, tex2DTriPlanar(_TexSnow, IN.worldPos, IN.worldNormal), smoothstep(_IceCapStrength, 1, poleDistance));
}
// TEST
//if(abs(dot(IN.worldNormal, normalize(IN.worldPos))) <= _SlopeTolerance) {
//c = fixed4(1.0, 0, 0, 1);
// c = lerp(tex2DTriPlanar(_TexMountains, IN.worldPos, IN.worldNormal), c, abs(dot(IN.worldNormal, normalize(IN.worldPos))));
//}
// c = fixed4(abs(dot(IN.worldNormal, normalize(IN.worldPos))),
// dot(IN.worldNormal, normalize(IN.worldPos)),
// 0, 1);
// c.b = IN.worldNormal;
//c = lerp(c, tex2DTiled(_TexMountains, IN.uv_TexMountains), abs(dot(IN.worldNormal, normalize(IN.worldPos))));
// END TEST
o.Albedo = c.rgb;
//o.Albedo = fixed4(height, 0, 0, 1);
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
After adding the tesselation options though, it no longer comiples, and I get this error:
"Shader error in 'Custom/Terrain': invalid subscript 'texcoord4' at line 320 (on d3d11)"
I am confused, because I do not access a texcoord4, and there is no line 320 in my shader! Any ideas why I am getting this error?
Answer by rageingnonsense · Mar 20, 2015 at 07:18 PM
I figured it out. Turns out the vertex function is required for this to work! I neglected to add it from the last example in the link I provided. Tessellation does not make a noticeable improvement in my terrain, but it is nice to know how to do it.
I had a similar issue. I did have a vertex function but still it wasn't working.
The issue was the fact I was appdata_full
. As far as I can tell it only works with appdata
. This is easy enough to fix, you just have to declare your own appdata
struct. I changed my tessellation and vertex function to use this and voila - it worked.
Here's the one I used, change to suit your needs.
struct appdata {
float4 vertex : POSITION;
float4 tangent : TANGENT;
float3 normal : NOR$$anonymous$$AL;
float2 texcoord : TEXCOORD0;
};
Your answer
Follow this Question
Related Questions
Shader:DX11 get texture dimensions inside a shader 1 Answer
DX11 shader model 5 unavailable 0 Answers
Please suggest Car Paint shaders compatible with Unity 1 Answer
Marmoset + Unity 4 vs Unity 5 Lighting 0 Answers
Rim Shader Errors 0 Answers