Jan
28
2014

Ray-traced Fake Soft Shadows (Shader)

raytrace_pointlight_shadows_unity_indie_1

Mooore fake shadows testing! (based on direct3D shaders)

Info:
– Works with unity indie/free!
– Just a shader with sphere intersect function (so it basically only works with spheres..)
– Point light & sphere positions are sent to the shader
– Each sphere requires invidual shadow collector flat plane (they are combined with blend modes)
– Options for: Soft shadows, Hard Shadows, Tinted shadows
– 1 or more spotlight positions

Maybe small bug, sphere radius should be half in shader, seems that the shadows is too big..

Webplayer:
http://unitycoder.com/upload/demos/RaytracedShadowShader/ (1 spotlight, 3 shader variations )
http://unitycoder.com/upload/demos/RaytracedShadowShader2/ (2 spotlights)

Shader source:


// original source: http://content.gpwiki.org/D3DBook:Ray-traced_Shadows

Shader "Custom/RaytraceMultiShadowsHard" {

    Properties 
    {
        _Color ("Main Color", Color) = (0,1,0,1)
        _BallPos("BallPos", Vector) = (0, 0, 0, 0)
        _LightPos("lightPos", Vector) = (1, 10, 0, 0)
        _LightPos2("lightPos2", Vector) = (1, 10, 0, 0)
        _BallRadius("ballRadius", Float) = 1.0
    }

    SubShader {
    Tags {"Queue"="Transparent" "RenderType"="Transparent"} //Change this
        Pass {
        
//Blend DstColor SrcColor 
//Blend SrcAlpha OneMinusSrcAlpha    
        Blend SrcAlpha OneMinusSrcAlpha //Add This
        
            CGPROGRAM
// Upgrade NOTE: excluded shader from DX11 and Xbox360; has structs without semantics (struct v2f members wpos)
            #pragma exclude_renderers d3d11 xbox360
            #pragma vertex vert
            #pragma fragment frag alpha
            #pragma fragmentoption ARB_precision_hint_fastest
            //#pragma target 3.0

            #include "UnityCG.cginc"

    
        float4 _Color;
        float4 _BallPos;
        float4 _LightPos;
        float4 _LightPos2;
        float _BallRadius;
        


        //this function returns the distance of a point to a line:
        float dist_p2l(float3 pnt, float3 l0, float3 l1)
        {
            float3 v = l1 - l0;
            float3 w = pnt - l0;
         
            //determine the relations of the dot products of a triangle
            //formed by the vectors
            float c1 = dot(w,v);
            float c2 = dot(v,v);
            float b = c1/c2;
         
            //and use them to calculate the distance.
            float3 pb = l0 + b * v;
            return distance (pnt, pb);
        }
         
        float getSphereIntersect(float3 lightPos, float3 pixelPos, float3 ballPos, float ballRadius, out bool hit)
        {
            hit = true;
            float dist = dist_p2l(ballPos, pixelPos, lightPos);
            if (dist > ballRadius) 
            {
                hit=false; return 0;
            }else
            {
                //prepare the shadow intensity here.
//                return 1-cos(1.0-(dist/ballRadius));
                return dist/ballRadius;
            }
        }
        
        struct a2v {
            float4 vertex : POSITION;
            //float4 texcoord : TEXCOORD0;
        };

        struct v2f {
            float4 pos : SV_POSITION;
            // Shader warning in 'Custom/RaytraceShadows': Program 'vert', 'vert': function return value missing semantics (compiling for d3d11_9x) at line 22
            // Shader warning in 'Custom/RaytraceShadows': Program 'vert', 'getSphereIntersect': implicit truncation of vector type (compiling for d3d11_9x) at line 87
            //float4 wpos;
            float3 wpos;
            //float2 uv : TEXCOORD0;
        };
        
        v2f vert(a2v v) {
            v2f o;
            o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
            o.wpos = mul(_Object2World, v.vertex);
               //o.uv = v.texcoord.xy;
            return o;
        }

        float4 frag(v2f i) : COLOR 
        {
        
            bool hit;
            float shadowIntensity=10;
         
            shadowIntensity = getSphereIntersect(_LightPos,i.wpos, _BallPos, _BallRadius, hit);
         
//            float4 ret = _Color;
            float4 ret = float4(0,0,0,0);
            
            float a=0;
            
            if (hit)
            {
//                ret.rgb *= shadowIntensity;
//                ret.a = 1-shadowIntensity;
                a = 0.5f;
            }

            shadowIntensity = getSphereIntersect(_LightPos2,i.wpos, _BallPos, _BallRadius, hit);
            if (hit)
            {
//                ret.rgb *= shadowIntensity;
//                ret.a = 1-shadowIntensity;
                a += 0.25f;
            }
         
             ret.a = a;
                           
            return ret;
            
        //    fixed4 c = fixed4(1,0,0,1);
        //    return c;
        }
            
            
            
            
            
            ENDCG
        }
    }
}

 

 


4 Comments + Add Comment

Leave a comment

Connect

Twitter View LinkedIn profile Youtube Github Join Discord Twitch Instagram BlueSky

UnityLauncherPro

Get UnityLauncherPRO and work faster with Unity Projects!
*free unity hub alternative

@unitycoder_com

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.