Shader "Hidden/DebugVolumeRendering" { Properties { _Color ("Color", Color) = (1, 1, 1, 1) _Volume ("Volume", 3D) = "" {} _Intensity ("Intensity", Range(1.0, 5.0)) = 1.2 _Threshold ("Threshold", Range(0.0, 1.0)) = 0.95 _SliceMin ("Slice min", Vector) = (0.0, 0.0, 0.0, -1.0) _SliceMax ("Slice max", Vector) = (1.0, 1.0, 1.0, -1.0) } SubShader { Blend One One ZTest Always Tags {"RenderPipeline" = "UniversalPipeline" "RenderType" = "Transparent" "Queue" = "Transparent" } Cull front HLSLINCLUDE #pragma target 3.0 #pragma exclude_renderers vulkan ENDHLSL Pass { HLSLPROGRAM #define REQUIRE_DEPTH_TEXTURE 1 #define ITERATIONS 100 #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl" #ifndef ITERATIONS #define ITERATIONS 100 #endif half4 _Color; sampler3D _Volume; half _Intensity, _Threshold; half3 _SliceMin, _SliceMax; float4x4 _AxisRotationMatrix; uniform float4 _CameraDepthTexture_TexelSize; float _VolExposure; struct Ray { float3 origin; float3 dir; }; struct AABB { float3 min; float3 max; }; bool intersect(Ray r, AABB aabb, out float t0, out float t1) { float3 invR = 1.0 / r.dir; float3 tbot = invR * (aabb.min - r.origin); float3 ttop = invR * (aabb.max - r.origin); float3 tmin = min(ttop, tbot); float3 tmax = max(ttop, tbot); float2 t = max(tmin.xx, tmin.yz); t0 = max(t.x, t.y); t = min(tmax.xx, tmax.yz); t1 = min(t.x, t.y); return t0 <= t1; } float3 localize(float3 p) { return mul(unity_WorldToObject, float4(p, 1)).xyz; } float3 get_uv(float3 p) { // float3 local = localize(p); return (p + 0.5); } float4 sample_volume(float3 uv, float3 p) { float4 v = tex3D(_Volume, uv) * _Intensity; float3 axis = mul(_AxisRotationMatrix, float4(p, 0)).xyz; axis = get_uv(axis); float min = step(_SliceMin.x, axis.x) * step(_SliceMin.y, axis.y) * step(_SliceMin.z, axis.z); float max = step(axis.x, _SliceMax.x) * step(axis.y, _SliceMax.y) * step(axis.z, _SliceMax.z); return min * max * v; } bool outside(float3 uv) { const float EPSILON = 0.01; float lower = -EPSILON; float upper = 1 + EPSILON; return ( uv.x < lower || uv.y < lower || uv.z < lower || uv.x > upper || uv.y > upper || uv.z > upper ); } struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float4 vertex : SV_POSITION; float2 uv : TEXCOORD0; float3 world : TEXCOORD1; float3 local : TEXCOORD2; float4 ase_texcoord1 : TEXCOORD3; }; v2f vert(appdata v) { v2f o; //o.vertex = UnityObjectToClipPos(v.vertex); o.vertex = TransformObjectToHClip(v.vertex); o.uv = v.uv; o.world = mul(unity_ObjectToWorld, v.vertex).xyz; o.local = v.vertex.xyz; //Get screen pos For depth float4 ase_clipPos = TransformObjectToHClip((v.vertex).xyz); float4 screenPos = ComputeScreenPos(ase_clipPos); o.ase_texcoord1 = screenPos; return o; } float4 frag(v2f i) : SV_Target { //For depth float4 screenPos = i.ase_texcoord1; float4 ase_screenPosNorm = screenPos / screenPos.w; float clampDepth22 = Linear01Depth(SHADERGRAPH_SAMPLE_SCENE_DEPTH(ase_screenPosNorm.xy),_ZBufferParams); Ray ray; // ray.origin = localize(i.world); ray.origin = i.local; // world space direction to object space float3 dir = -(i.world - _WorldSpaceCameraPos); ray.dir = normalize(mul(unity_WorldToObject, dir)); AABB aabb; aabb.min = float3(-0.5, -0.5, -0.5); aabb.max = float3(0.5, 0.5, 0.5); float tnear; float tfar; intersect(ray, aabb, tnear, tfar); tnear = max(0.0, tnear); // float3 start = ray.origin + ray.dir * tnear; float3 start = ray.origin; float3 end = ray.origin + ray.dir * tfar; float dist = abs(tfar - tnear); // float dist = distance(start, end); float step_size = dist / float(ITERATIONS); float3 ds = normalize(end - start) * step_size; float4 dst = float4(0, 0, 0, 0); float3 p = start; [unroll] for (int iter = 0; iter < ITERATIONS; iter++) { float3 uv = get_uv(p); float4 v = sample_volume(uv, p); float4 src = v; src.a *= 0.5; src.rgb *= src.a; // blend dst = _VolExposure * src + dst; p += ds; //if (dst.a > _Threshold) break; } return saturate(dst) * _Color; } #pragma vertex vert #pragma fragment frag ENDHLSL } } }