Created
January 28, 2020 23:14
-
-
Save josemorval/d3cf418fc9512d32c3d23e8806da6bf5 to your computer and use it in GitHub Desktop.
Revisions
-
josemorval created this gist
Jan 28, 2020 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,339 @@ // Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld' Shader "Unlit/VolumeMarching" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Transparent" "Queue"="Transparent"} LOD 100 Pass { Blend SrcAlpha OneMinusSrcAlpha CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float4 posWorld : TEXCOORD0; float4 vertex : SV_POSITION; }; // // Noise Shader Library for Unity - https://github.com/keijiro/NoiseShader // // Original work (webgl-noise) Copyright (C) 2011 Stefan Gustavson // Translation and modification was made by Keijiro Takahashi. // // This shader is based on the webgl-noise GLSL shader. For further details // of the original shader, please see the following description from the // original source code. // // // GLSL textureless classic 3D noise "cnoise", // with an RSL-style periodic variant "pnoise". // Author: Stefan Gustavson ([email protected]) // Version: 2011-10-11 // // Many thanks to Ian McEwan of Ashima Arts for the // ideas for permutation and gradient selection. // // Copyright (c) 2011 Stefan Gustavson. All rights reserved. // Distributed under the MIT license. See LICENSE file. // https://github.com/ashima/webgl-noise // float3 mod(float3 x, float3 y) { return x - y * floor(x / y); } float3 mod289(float3 x) { return x - floor(x / 289.0) * 289.0; } float4 mod289(float4 x) { return x - floor(x / 289.0) * 289.0; } float4 permute(float4 x) { return mod289(((x*34.0)+1.0)*x); } float4 taylorInvSqrt(float4 r) { return (float4)1.79284291400159 - r * 0.85373472095314; } float3 fade(float3 t) { return t*t*t*(t*(t*6.0-15.0)+10.0); } // Classic Perlin noise float cnoise(float3 P) { float3 Pi0 = floor(P); // Integer part for indexing float3 Pi1 = Pi0 + (float3)1.0; // Integer part + 1 Pi0 = mod289(Pi0); Pi1 = mod289(Pi1); float3 Pf0 = frac(P); // Fractional part for interpolation float3 Pf1 = Pf0 - (float3)1.0; // Fractional part - 1.0 float4 ix = float4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); float4 iy = float4(Pi0.y, Pi0.y, Pi1.y, Pi1.y); float4 iz0 = (float4)Pi0.z; float4 iz1 = (float4)Pi1.z; float4 ixy = permute(permute(ix) + iy); float4 ixy0 = permute(ixy + iz0); float4 ixy1 = permute(ixy + iz1); float4 gx0 = ixy0 / 7.0; float4 gy0 = frac(floor(gx0) / 7.0) - 0.5; gx0 = frac(gx0); float4 gz0 = (float4)0.5 - abs(gx0) - abs(gy0); float4 sz0 = step(gz0, (float4)0.0); gx0 -= sz0 * (step((float4)0.0, gx0) - 0.5); gy0 -= sz0 * (step((float4)0.0, gy0) - 0.5); float4 gx1 = ixy1 / 7.0; float4 gy1 = frac(floor(gx1) / 7.0) - 0.5; gx1 = frac(gx1); float4 gz1 = (float4)0.5 - abs(gx1) - abs(gy1); float4 sz1 = step(gz1, (float4)0.0); gx1 -= sz1 * (step((float4)0.0, gx1) - 0.5); gy1 -= sz1 * (step((float4)0.0, gy1) - 0.5); float3 g000 = float3(gx0.x,gy0.x,gz0.x); float3 g100 = float3(gx0.y,gy0.y,gz0.y); float3 g010 = float3(gx0.z,gy0.z,gz0.z); float3 g110 = float3(gx0.w,gy0.w,gz0.w); float3 g001 = float3(gx1.x,gy1.x,gz1.x); float3 g101 = float3(gx1.y,gy1.y,gz1.y); float3 g011 = float3(gx1.z,gy1.z,gz1.z); float3 g111 = float3(gx1.w,gy1.w,gz1.w); float4 norm0 = taylorInvSqrt(float4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); g000 *= norm0.x; g010 *= norm0.y; g100 *= norm0.z; g110 *= norm0.w; float4 norm1 = taylorInvSqrt(float4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); g001 *= norm1.x; g011 *= norm1.y; g101 *= norm1.z; g111 *= norm1.w; float n000 = dot(g000, Pf0); float n100 = dot(g100, float3(Pf1.x, Pf0.y, Pf0.z)); float n010 = dot(g010, float3(Pf0.x, Pf1.y, Pf0.z)); float n110 = dot(g110, float3(Pf1.x, Pf1.y, Pf0.z)); float n001 = dot(g001, float3(Pf0.x, Pf0.y, Pf1.z)); float n101 = dot(g101, float3(Pf1.x, Pf0.y, Pf1.z)); float n011 = dot(g011, float3(Pf0.x, Pf1.y, Pf1.z)); float n111 = dot(g111, Pf1); float3 fade_xyz = fade(Pf0); float4 n_z = lerp(float4(n000, n100, n010, n110), float4(n001, n101, n011, n111), fade_xyz.z); float2 n_yz = lerp(n_z.xy, n_z.zw, fade_xyz.y); float n_xyz = lerp(n_yz.x, n_yz.y, fade_xyz.x); return 2.2 * n_xyz; } // Classic Perlin noise, periodic variant float pnoise(float3 P, float3 rep) { float3 Pi0 = mod(floor(P), rep); // Integer part, modulo period float3 Pi1 = mod(Pi0 + (float3)1.0, rep); // Integer part + 1, mod period Pi0 = mod289(Pi0); Pi1 = mod289(Pi1); float3 Pf0 = frac(P); // Fractional part for interpolation float3 Pf1 = Pf0 - (float3)1.0; // Fractional part - 1.0 float4 ix = float4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); float4 iy = float4(Pi0.y, Pi0.y, Pi1.y, Pi1.y); float4 iz0 = (float4)Pi0.z; float4 iz1 = (float4)Pi1.z; float4 ixy = permute(permute(ix) + iy); float4 ixy0 = permute(ixy + iz0); float4 ixy1 = permute(ixy + iz1); float4 gx0 = ixy0 / 7.0; float4 gy0 = frac(floor(gx0) / 7.0) - 0.5; gx0 = frac(gx0); float4 gz0 = (float4)0.5 - abs(gx0) - abs(gy0); float4 sz0 = step(gz0, (float4)0.0); gx0 -= sz0 * (step((float4)0.0, gx0) - 0.5); gy0 -= sz0 * (step((float4)0.0, gy0) - 0.5); float4 gx1 = ixy1 / 7.0; float4 gy1 = frac(floor(gx1) / 7.0) - 0.5; gx1 = frac(gx1); float4 gz1 = (float4)0.5 - abs(gx1) - abs(gy1); float4 sz1 = step(gz1, (float4)0.0); gx1 -= sz1 * (step((float4)0.0, gx1) - 0.5); gy1 -= sz1 * (step((float4)0.0, gy1) - 0.5); float3 g000 = float3(gx0.x,gy0.x,gz0.x); float3 g100 = float3(gx0.y,gy0.y,gz0.y); float3 g010 = float3(gx0.z,gy0.z,gz0.z); float3 g110 = float3(gx0.w,gy0.w,gz0.w); float3 g001 = float3(gx1.x,gy1.x,gz1.x); float3 g101 = float3(gx1.y,gy1.y,gz1.y); float3 g011 = float3(gx1.z,gy1.z,gz1.z); float3 g111 = float3(gx1.w,gy1.w,gz1.w); float4 norm0 = taylorInvSqrt(float4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); g000 *= norm0.x; g010 *= norm0.y; g100 *= norm0.z; g110 *= norm0.w; float4 norm1 = taylorInvSqrt(float4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); g001 *= norm1.x; g011 *= norm1.y; g101 *= norm1.z; g111 *= norm1.w; float n000 = dot(g000, Pf0); float n100 = dot(g100, float3(Pf1.x, Pf0.y, Pf0.z)); float n010 = dot(g010, float3(Pf0.x, Pf1.y, Pf0.z)); float n110 = dot(g110, float3(Pf1.x, Pf1.y, Pf0.z)); float n001 = dot(g001, float3(Pf0.x, Pf0.y, Pf1.z)); float n101 = dot(g101, float3(Pf1.x, Pf0.y, Pf1.z)); float n011 = dot(g011, float3(Pf0.x, Pf1.y, Pf1.z)); float n111 = dot(g111, Pf1); float3 fade_xyz = fade(Pf0); float4 n_z = lerp(float4(n000, n100, n010, n110), float4(n001, n101, n011, n111), fade_xyz.z); float2 n_yz = lerp(n_z.xy, n_z.zw, fade_xyz.y); float n_xyz = lerp(n_yz.x, n_yz.y, fade_xyz.x); return 2.2 * n_xyz; } v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.posWorld = mul(unity_ObjectToWorld,v.vertex); return o; } float map(float3 p){ float t = 1.2*_Time.y; float v = 0.5*cnoise(2.1*p+t*float3(0.1,-1.,0.1)).x; v+=0.3*cnoise(4.13*p+t*float3(0.2,-1.,0.1)).x; v+=0.15*cnoise(8.23*p+t*float3(0.1,-1.,0.2)).x; v+=0.05*cnoise(16.23*p+t*float3(0.1,-1.,0.1)).x; v = saturate(v+0.05); v*=smoothstep(0.7,0.4+0.1*v,length(p)); return v; } float4 frag (v2f i) : SV_Target { //Ryan Brucks based https://shaderbits.com/blog/creating-volumetric-ray-marcher float3 cameraPos = _WorldSpaceCameraPos; float3 CurPos = i.posWorld.xyz; float3 dir = normalize(CurPos-cameraPos); int MaxSteps = 32; int ShadowSteps = 16; float dt = 0.5/float(MaxSteps); float ds = 0.5/float(ShadowSteps); float3 LightVector = normalize(float3(cos(0.5*_Time.y),1.,sin(0.5*_Time.y))); float shadowthresh = 0.01; float3 lightenergy = float3(0.,0.,0.); float curdensity = 0.; float transmittance = 1.; for (int i = 0; i < MaxSteps; i++) { float cursample = map(CurPos); //Sample Light Absorption and Scattering if( cursample > 0.01) { float3 lpos = CurPos; float shadowdist = 0; for (int s = 0; s < ShadowSteps; s++) { lpos += ds*LightVector; float lsample = saturate(map(lpos)); float3 shadowboxtest = floor( 0.5 + ( abs( 0.5 - lpos ) ) ); float exitshadowbox = shadowboxtest .x + shadowboxtest .y + shadowboxtest .z; shadowdist += lsample; if(shadowdist > shadowthresh || exitshadowbox >= 1 || abs(lpos.x)>0.5 || abs(lpos.y)>0.5 || abs(lpos.z)>0.5) break; } curdensity = saturate(cursample)*2.; float3 shadowterm = exp(-shadowdist*float3(8.,16.,32.)); float3 absorbedlight = shadowterm * curdensity; lightenergy += absorbedlight * transmittance; transmittance *= 1-curdensity; //Sky Lighting shadowdist = 0; lpos = CurPos + float3(0,0,0.05); float lsample = map(lpos); shadowdist += lsample; lpos = CurPos + float3(0,0,0.1); lsample = map(lpos); shadowdist += lsample; lpos = CurPos + float3(0,0,0.2); lsample = map(lpos); shadowdist += lsample; //shadowterm = exp(-shadowdist * AmbientDensity); //absorbedlight = exp(-shadowdist * AmbientDensity) * curdensity; lightenergy += exp(-shadowdist * 0.2) * curdensity * float3(0.5,0.5,0.8)*0.75 * transmittance; } CurPos += dt*dir; if(abs(CurPos.x)>0.5 || abs(CurPos.y)>0.5 || abs(CurPos.z)>0.5){ break; } } float4 col = float4(lightenergy,1.-transmittance); return col; } ENDCG } } }