Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Terrain via raymarching
- // Use in Unity as Post Process shader
- Shader "rays/Terrain"
- {
- Properties
- {
- [HideInInspector]
- _MainTex ("Texture", 2D) = "white" {}
- [HideInInspector]
- camera("camera",Vector) = (0.0,0.0,0.0,0.0)
- }
- SubShader
- {
- Cull Off ZWrite Off ZTest Always
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- #include "UnityCG.cginc"
- #include "Lighting.cginc"
- // raymarching stuff
- #include "sdfUtilities.cginc"
- uniform sampler2D _CameraDepthTexture;
- uniform sampler2D _MainTex;
- uniform float4x4 _FrustumCornersES;
- uniform float4x4 _CameraInvViewMatrix;
- uniform float4 _MainTex_TexelSize;
- uniform float3 _LightDir;
- uniform float _DrawDistance;
- uniform float4 _Color;
- uniform float4 _FogColor;
- uniform float _Gloss;
- uniform float _SpecularPower;
- uniform float3 _Center;
- uniform float _Radius;
- struct appdata
- {
- float4 vertex : POSITION;
- float2 uv : TEXCOORD0;
- };
- struct v2f
- {
- float4 pos : SV_POSITION;
- float2 uv : TEXCOORD0;
- float4 wPos : TEXCOORD2;
- float3 ray : TEXCOORD1;
- };
- #define STEPS 1024
- #define MAX_DISTANCE 500
- #define MIN_DISTANCE 0.001
- #define PRECISION 0.001
- #define PI 3.14159265359
- #define PI2 6.2831
- #define FOG_EXTINCTION 0.2
- v2f vert (appdata v)
- {
- v2f output;
- half index = v.vertex.z;
- v.vertex.z = 0.1;
- output.wPos = mul(unity_ObjectToWorld, v.vertex);
- output.pos = UnityObjectToClipPos(v.vertex);
- output.uv = v.uv;
- #if UNITY_UV_STARTS_AT_TOP
- if (_MainTex_TexelSize.y < 0)
- output.uv.y = 1 - output.uv.y;
- #endif
- output.ray = _FrustumCornersES[(int)index].xyz;
- output.ray /= abs(output.ray.z);
- output.ray = mul(_CameraInvViewMatrix, output.ray);
- return output;
- }
- fixed4 lambert(fixed3 normal, fixed3 viewDirection)
- {
- fixed3 lightDir = _WorldSpaceLightPos0.xyz;
- fixed3 lightCol = _LightColor0.rgb;
- fixed3 halfDir = normalize(lightDir - viewDirection);
- fixed nDotL = saturate ( dot(normal, lightDir));
- fixed specular = pow( dot(normal,halfDir), _SpecularPower )*_Gloss;
- fixed4 finalLight;
- finalLight.rgb = _Color * lightCol * nDotL + specular;
- finalLight.a = 1;
- return finalLight;
- }
- float noise (float3 n)
- {
- return frac(sin(dot(n, float3(95.43583, 93.323197, 94.993431))) * 65536.32);
- }
- float perlin_a (float3 n)
- {
- float3 base = floor(n * 64.0) * 0.015625;
- float3 dd = float3(0.015625, 0.0, 0.0);
- float a = noise(base);
- float b = noise(base + dd.xyy);
- float c = noise(base + dd.yxy);
- float d = noise(base + dd.xxy);
- float3 p = (n - base) * 64.0;
- float t = lerp(a, b, p.x);
- float tt = lerp(c, d, p.x);
- return lerp(t, tt, p.y);
- }
- float perlin_b (float3 normal)
- {
- float3 base = float3(normal.x, normal.y, floor(normal.z * 64.0) * 0.015625);
- float3 dd = float3(0.015625, 0.0, 0.0);
- float3 p = (normal - base) * 64.0;
- float front = perlin_a(base + dd.yyy);
- float back = perlin_a(base + dd.yyx);
- return lerp(front, back, p.z);
- }
- float fbm(float3 normal)
- {
- float total = 0.0;
- float m1 = 1.0;
- float m2 = 0.1;
- for (int i = 0; i < 5; i++)
- {
- total += perlin_b(normal * m1) * m2;
- m2 *= 2.0;
- m1 *= 0.5;
- }
- return total;
- }
- float3 heightMap (float3 normal)
- {
- return float3(fbm((5.0 * normal) + fbm((5.0 * normal) * 3.0 - 1000.0) * 0.05),0,0);
- }
- float map(float3 position)
- {
- return position.y-32.0*float4(float3( (heightMap(float3(position.xz*0.005,1.0)*0.1)-1.0)),1.0).r;
- }
- float3 calculateNormals (float3 position)
- {
- const float eps = 0.01;
- return normalize (float3( map(position+ float3(eps, 0, 0) )
- - map(position- float3(eps, 0, 0) ),
- map(position+ float3(0, eps, 0) )
- - map (position- float3(0, eps, 0) ),
- map(position+ float3(0, 0, eps) )
- - map(position- float3(0, 0, eps) )
- )
- );
- }
- fixed4 renderSurface(float3 position, float3 viewDirection)
- {
- float3 n = calculateNormals(position);
- return lambert(n, viewDirection);
- }
- float SDFplane( float3 position, float4 normal)
- {
- normal = normalize(normal);
- return dot(position, normal.rgb) + normal.w;
- }
- float getHeight(float x, float z)
- {
- return sin(x)*sin(z);
- }
- bool castRay( float3 rayOrigin, float3 rayDirection, float resT)
- {
- float delt = MIN_DISTANCE;
- float minT = MAX_DISTANCE;
- float maxT = STEPS;
- for (float t = minT; t < maxT; t+=delt)
- {
- float3 position = rayOrigin + rayDirection *t;
- if ( position.y < getHeight(position.x, position.z) )
- {
- resT = t - 0.5f * delt;
- return true;
- }
- }
- return false;
- }
- float3 applyFog( float3 shading, float distance)
- {
- float fog = 1.0 - exp(distance * FOG_EXTINCTION);
- float4 fogColor = _FogColor;
- return lerp(shading, fogColor.rgb, fog);
- }
- float4 terrainColor(float3 rayOrigin, float3 rayDirection, float t)
- {
- float3 position = rayOrigin + rayDirection * t;
- float3 normals = calculateNormals(position);
- float3 shading = renderSurface(position, normals );
- return float4(applyFog(shading, t), 1);
- }
- float4 rayMarch (float3 rayOrigin, float3 rayDirection)
- {
- for (int i=0; i< STEPS; i++)
- {
- float t = map(rayOrigin);
- //for perf - break when max_distance is reached
- if (rayOrigin.x> MAX_DISTANCE || rayOrigin.x< -MAX_DISTANCE || rayOrigin.z> MAX_DISTANCE || rayOrigin.z< -MAX_DISTANCE) break; // size
- if ( t< PRECISION )
- return float4( applyFog ( float3( 5.0/rayOrigin.y,0.0,0.0 ), t) , 1);
- rayOrigin+=t*rayDirection;
- }
- return 0;
- }
- fixed4 frag (v2f input) : SV_Target
- {
- float3 rayDir = normalize(input.ray.rgb);
- float3 rayOrigin = _WorldSpaceCameraPos;
- float3 worldPos = input.wPos;
- float3 viewDirection = normalize(input.wPos - rayOrigin);
- //sample framebuffer
- fixed4 color = tex2D( _MainTex, input.uv);
- //get depth
- float zDepth = LinearEyeDepth( tex2D(_CameraDepthTexture, input.uv).r );
- zDepth *= length (input.ray.rgb);
- float4 rayCastTerrain = rayMarch(rayOrigin,rayDir);
- return lerp(color, rayCastTerrain , rayCastTerrain.a);
- }
- ENDCG
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement