- Home /
Making Parts of the Terrain invisible, depending on y coordinate f the vertex
I've been trying to do this for days, and I think I am close to a solution. This is the code for the advanced Terrain shader 2: / Code provided by Chris Morris of Six Times Nothing (http://www.sixtimesnothing.com) / / Free to use and modify /
Shader "Hidden/TerrainEngine/Splatmap/Lightmap-FirstPass" {
Properties {
_Control ("Control (RGBA)", 2D) = "red" {}
_Splat3 ("Layer 3 (A)", 2D) = "white" {}
_Splat2 ("Layer 2 (B)", 2D) = "white" {}
_Splat1 ("Layer 1 (G)", 2D) = "white" {}
_Splat0 ("Layer 0 (R)", 2D) = "white" {}
// used in fallback on old cards
_MainTex ("BaseMap (RGB)", 2D) = "white" {}
_Color ("Main Color", Color) = (1,1,1,1)
}
SubShader {
Tags {
"SplatCount" = "4"
"Queue" = "Geometry-100"
"RenderType" = "Opaque"
}
CGPROGRAM
#pragma surface surf BlinnPhong vertex:vert
#pragma target 3.0
#include "UnityCG.cginc"
struct Input {
float3 worldPos;
float2 uv_Control : TEXCOORD0;
float2 uv_Splat0 : TEXCOORD1;
float2 uv_Splat1 : TEXCOORD2;
float2 uv_Splat2 : TEXCOORD3;
float2 uv_Splat3 : TEXCOORD4;
fixed4 color : COLOR;
};
// Supply the shader with tangents for the terrain
void vert (inout appdata_full v) {
// A general tangent estimation
float3 T1 = float3(1, 0, 1);
float3 Bi = cross(T1, v.normal);
float3 newTangent = cross(v.normal, Bi);
normalize(newTangent);
v.tangent.xyz = newTangent.xyz;
if (dot(cross(v.normal,newTangent),Bi) < 0)
v.tangent.w = -1.0f;
else
v.tangent.w = 1.0f;
}
sampler2D _Control;
sampler2D _BumpMap0, _BumpMap1, _BumpMap2, _BumpMap3;
sampler2D _Splat0,_Splat1,_Splat2,_Splat3;
float _Tile0, _Tile1, _Tile2, _Tile3, _TerrainX, _TerrainZ;
float4 _v4CameraPos;
void surf (Input IN, inout SurfaceOutput o) {
half4 splat_control = tex2D (_Control, IN.uv_Control);
half3 col;
// first texture which is usually some kind of rock texture gets mixed with itself
// see: http://forum.unity3d.com/threads/116509-Improved-Terrain-Texture-Tiling
col = splat_control.r * tex2D (_Splat0, IN.uv_Splat0).rgb * tex2D (_Splat0, IN.uv_Splat0 * -0.125).rgb * 4;
o.Normal = splat_control.r * UnpackNormal(tex2D(_BumpMap0, float2(IN.uv_Control.x * (_TerrainX/_Tile0), IN.uv_Control.y * (_TerrainZ/_Tile0))));
col += splat_control.g * tex2D (_Splat1, IN.uv_Splat1).rgb;
o.Normal += splat_control.g * UnpackNormal(tex2D(_BumpMap1, float2(IN.uv_Control.x * (_TerrainX/_Tile1), IN.uv_Control.y * (_TerrainZ/_Tile1))));
col += splat_control.b * tex2D (_Splat2, IN.uv_Splat2).rgb;
o.Normal += splat_control.b * UnpackNormal(tex2D(_BumpMap2, float2(IN.uv_Control.x * (_TerrainX/_Tile2), IN.uv_Control.y * (_TerrainZ/_Tile2))));
col += splat_control.a * tex2D (_Splat3, IN.uv_Splat3).rgb;
o.Normal += splat_control.a * UnpackNormal(tex2D(_BumpMap3, float2(IN.uv_Control.x * (_TerrainX/_Tile3), IN.uv_Control.y * (_TerrainZ/_Tile3))));
o.Albedo = col;
o.Alpha = 0.0;
}
ENDCG
}
// Fallback to Diffuse
Fallback "Diffuse"
}
And I'd like the shader to discard Vertices that are too low (y, object space) . And then I found this on Wikibooks/proframming CG/Unikty:
Shader "Cg shader using discard" {
SubShader {
Pass {
Cull Off // turn off triangle culling, alternatives are:
// Cull Back (or nothing): cull only back faces
// Cull Front : cull only front faces
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct vertexInput {
float4 vertex : POSITION;
};
struct vertexOutput {
float4 pos : SV_POSITION;
float4 posInObjectCoords : TEXCOORD0;
};
vertexOutput vert(vertexInput input)
{
vertexOutput output;
output.pos = mul(UNITY_MATRIX_MVP, input.vertex);
output.posInObjectCoords = input.vertex;
return output;
}
float4 frag(vertexOutput input) : COLOR
{
if (input.posInObjectCoords.y > 0.0)
{
discard; // drop the fragment if y coordinate > 0
}
return float4(0.0, 1.0, 0.0, 1.0); // green
}
ENDCG
}
}
}
And I'd like to fuse them so that the Terrain shader works as usual, but it discards if the Y Coordinate of the Vertices are too low, and achieve a nonsquare Terrain. You'd help me A LOT if you could help me with this because as I said I tried doing it for days now... I tried it myself, but I am really new to shaders and got compiler Errors all the time. And it's critical for the Game as the Scene consists of floating islands and they don't look good when they are square.
I know you shouldn't ask people to write code for you, but I tried just about everything and it isn't too complicated....
I know almost nothing about shaders, but it looks to me like the bottom code snippet which you seem to be taking as ".y" in World Space is ins$$anonymous$$d addressing a color model.
Answer by Jessespike · Sep 28, 2015 at 09:10 PM
Merging the CG Shader with the Surface Shader, may seem confusing at first, but it's actually not too bad. In the surface shader (the splatmap):
Add a property to define where the cutoff point is (line 10):
_DiscardHeight("Discard Height", float) = 0
Declare a variable to access the property (line 63)
float _DiscardHeight;
Compare the heights and discard (inside surf()):
if (IN.worldPos.y < _DiscardHeight) {
discard;
}
I hope the OP responds with the results on this interesting question/answer; irregular terrain shapes sounds like something with replay value for many.
Thank you so much for your answers. I literally searched for days for an answer. I'll try it right now! :D
It worked! It's perfectly suited for my game, although I have to say for any other people trying to use this, that the edges are really low poly.
EDIT: The edges are actually very smooth, but because of LOD you shuoldn't use it if the Terrain object is too far away from the camera
Your answer
Follow this Question
Related Questions
Terrain custom shader not lit per pixel? 1 Answer
Blended texture Shader 1 Answer
How to force the compilation of a shader in Unity? 5 Answers
Unity Terrain - shader for custom post-splat? 0 Answers
CG diffuse shader 1 Answer