Last active
November 11, 2019 21:41
-
-
Save michaelybecker/ff366a836b0407ef27d7daa554829687 to your computer and use it in GitHub Desktop.
Raymarched shadertoy clouds in Unity (SPI ready)
This file contains 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 characters
Shader "Custom/Raymarcher4" | |
{ | |
// based on MichaelPohoreski's no-noise texture variation of iq's brilliant https://www.shadertoy.com/view/XslGRr | |
// code is a mess. Reader beware. | |
// wanted to put it out there as a quick & dirty example of raymarching in Unity, since info is scarce. | |
// of particular note: SPI macros for instancing on stereoscopic devices, and the rewritten camera logic (no more rays-through-uvs, we're in "real" camera land now!) | |
// hope this is useful! | |
Properties | |
{ | |
} | |
SubShader | |
{ | |
Tags { "Queue" = "Transparent" } | |
Blend SrcAlpha OneMinusSrcAlpha | |
Pass | |
{ | |
CGPROGRAM | |
#pragma vertex vert | |
#pragma fragment frag | |
#pragma multi_compile_instancing | |
#include "UnityCG.cginc" | |
#include "UnityLightingCommon.cginc" | |
struct appdata | |
{ | |
float4 vertex : POSITION; | |
UNITY_VERTEX_INPUT_INSTANCE_ID | |
float2 uv : TEXCOORD0; | |
}; | |
struct v2f | |
{ | |
float3 wPos : float3; | |
float4 v: float4; | |
float4 pos : SV_POSITION; | |
UNITY_VERTEX_OUTPUT_STEREO | |
}; | |
UNITY_INSTANCING_BUFFER_START(Props) | |
UNITY_INSTANCING_BUFFER_END(Props) | |
v2f vert(appdata v) | |
{ | |
v2f o; | |
UNITY_SETUP_INSTANCE_ID(v); | |
UNITY_INITIALIZE_OUTPUT(v2f, o); | |
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); | |
o.pos = UnityObjectToClipPos(v.vertex); | |
o.v = v.vertex; | |
o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz; | |
return o; | |
} | |
float iqhash(float n) | |
{ | |
return frac(sin(n) * 43758.5453); | |
} | |
float noise(float3 x) | |
{ | |
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(iqhash(n + 0.0), iqhash(n + 1.0), f.x), | |
lerp(iqhash(n + 57.0), iqhash(n + 58.0), f.x), f.y), | |
lerp(lerp(iqhash(n + 113.0), iqhash(n + 114.0), f.x), | |
lerp(iqhash(n + 170.0), iqhash(n + 171.0), f.x), f.y), f.z); | |
} | |
//change: factor in headpose | |
float map5(in float3 p, in float3 ro) | |
{ | |
float3 q = p - float3(0.0, 0.1, 1.0) * _Time.y / 3; | |
float f; | |
f = 0.50000 * noise(q); q = q * 2.02; | |
f += 0.25000 * noise(q); q = q * 2.03; | |
f += 0.12500 * noise(q); q = q * 2.01; | |
f += 0.06250 * noise(q); q = q * 2.02; | |
f += 0.03125 * noise(q); | |
return saturate(1.5 - p.y - 2.0 + 1.75 * f + ro.y - .9); | |
} | |
float map4(in float3 p, in float3 ro) | |
{ | |
float3 q = p - float3(0.0, 0.1, 1.0) * _Time.y; | |
float f; | |
f = 0.50000 * noise(q); q = q * 2.02; | |
f += 0.25000 * noise(q); q = q * 2.03; | |
f += 0.12500 * noise(q); q = q * 2.01; | |
f += 0.06250 * noise(q); | |
return saturate(1.5 - p.y - 2.0 + 1.75 * f + ro.y - .7); | |
} | |
float map3(in float3 p, in float3 ro) | |
{ | |
float3 q = p - float3(0.0, 0.1, 1.0) * _Time.y; | |
float f; | |
f = 0.50000 * noise(q); q = q * 2.02; | |
f += 0.25000 * noise(q); q = q * 2.03; | |
f += 0.12500 * noise(q); | |
return saturate(1.5 - p.y - 2.0 + 1.75 * f + ro.y - .7); | |
} | |
float map2(in float3 p, in float3 ro) | |
{ | |
float3 q = p - float3(0.0, 0.1, 1.0) * _Time.y; | |
float f; | |
f = 0.50000 * noise(q); q = q * 2.02; | |
f += 0.25000 * noise(q); | |
return saturate(1.5 - p.y - 2.0 + 1.75 * f + ro.y - .7); | |
} | |
float4 integrate(in float4 sum, in float dif, in float den, in float3 bgcol, in float t) | |
{ | |
// lighting | |
float3 lin = float3(0.65, 0.7, 0.75) * 1.4 + float3(1.0, 0.6, 0.3) * dif; | |
float4 col = float4(lerp(float3(1.0, 0.95, 0.8), float3(0.25, 0.3, 0.35), den), den); | |
//col.xyz *= lin; | |
col.xyz *= lin; | |
col.xyz = lerp(col.xyz, bgcol, 1.0 - exp(-.0001 * t * t)); | |
// front to back blending | |
col.a *= 0.4; | |
col.rgb *= col.a; | |
return sum + col * (1.0 - sum.a); | |
} | |
#define MARCH(STEPS,MAPLOD, ro) for(int i=0; i<STEPS; i++) { float3 pos = ro + t*rd; if( sum.a > 0.99 ) break; float den = MAPLOD( pos, ro ); if( den>0.01 ) { float dif = saturate((den - MAPLOD(pos+0.3*_WorldSpaceLightPos0.xyz,ro))/0.6); sum = integrate( sum, dif, den, bgcol, t ); } t += max(4.05,0.02*t); } | |
float4 raymarch(in float3 ro, in float3 rd, in float3 bgcol) | |
{ | |
float4 sum = float4(0.0,0.0,0.0,0.0); | |
float t = 0.0;//0.05*texelFetch( iChannel0, px&255, 0 ).x; | |
MARCH(5, map5, ro); | |
//MARCH(30, map4, ro); | |
//MARCH(30, map3, ro); | |
//MARCH(30, map2, ro); | |
return saturate(sum); | |
} | |
float4 render(in float3 ro, in float3 rd) | |
{ | |
// background sky | |
float sun = saturate(dot(_WorldSpaceLightPos0.xyz, rd)); | |
//float3 col = float3(0.6, 0.71, 0.75) - rd.y * 0.2 * float3(1.0, 0.5, 1.0) + 0.15 * 0.5; | |
float3 col = float3(.0, .0, .0); | |
//col += 0.2 * float3(1.0, .6, 0.1) * pow(sun, 8.0); | |
// clouds | |
float4 res = raymarch(ro, rd, col); | |
col = col * (1.0 - res.w) + res.xyz; | |
// sun glare | |
col += 0.2 * float3(1.0, 0.4, 0.2) * pow(sun, 3.0); | |
if (col.x < .2) | |
{ | |
//discard; | |
} | |
else { | |
//col *= 2; | |
} | |
return float4(col, 1.0); | |
} | |
float opScale(float3 p, float s) | |
{ | |
//return MandelBulb(p / s, 17) * s; | |
} | |
fixed4 frag(v2f i) : SV_Target | |
{ | |
float4 objectOrigin = mul(unity_ObjectToWorld, float4(0.0,0.0,0.0,1.0)); | |
float3 viewDirection = normalize(i.wPos - _WorldSpaceCameraPos); | |
float3 worldPosition = i.wPos; | |
float3 ro = _WorldSpaceCameraPos; | |
float3 rd = viewDirection; | |
//float curDistance = 5. - distance(objectOrigin.xyz, i.v); | |
fixed4 r = render(ro, rd); | |
return fixed4(r.xyz,1.); | |
} | |
ENDCG | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment