Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Shader "Custom/RaycastSphere"
- {
- Properties
- {
- _Radius ("Radius", float) = 0.3
- _Centre ("Centre", vector) = (1,1,1) // See distanceEstimate()
- _Steps ("Steps", int) = 64 // higher values cause some ugly noise. Not sure how to fix that.
- }
- SubShader
- {
- Tags { "Queue"="Transparent" "RenderType"="Transparent"}
- LOD 100
- ZWrite Off
- ZTest Always
- Cull Off
- Blend SrcAlpha OneMinusSrcAlpha
- Pass
- {
- CGPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- #include "UnityCG.cginc"
- float3 _Centre;
- float _Radius;
- int _Steps;
- struct appdata
- {
- float4 vertex : POSITION;
- };
- struct v2f
- {
- float4 vertex : SV_POSITION;
- float3 wPos : TEXCOORD1;
- };
- //Called for each vertex on the surface of the object
- //Normally this is where you'd get the UV's and apply textures, but we don't care about that
- v2f vert (appdata v)
- {
- v2f o;
- o.vertex = UnityObjectToClipPos(v.vertex);
- o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;
- // ^ The location of the point in world coordinates
- return o;
- }
- bool sphereHit (float3 position) // Returns whether or not a ray has entered the geometry
- {
- return distance(fmod(abs(position), 2), _Centre) < (_Radius+0.000001);
- // Extra 0.00...1 is to avoid floating point errors. You get some interesting effects if you take it out
- }
- float distanceEstimate(float3 position) // Calculates the distance to the geometry given a point in space
- {
- return distance(fmod(abs(position), 2), _Centre) - _Radius;
- // Notice the mod 2 here. Effectively the world space is confined to the range 0-2. If you go past 2, you
- // wind up back at 0. You'll want to keep the center of the sphere between 0-2 as a result.
- }
- // march our ray forward until it hits something, or we pass _Steps
- int raycastHit (float3 position, float3 direction)
- {
- for (int i = 0; i < _Steps; i++)
- {
- if ( sphereHit(position) )
- {
- return i;
- }
- position += direction * distanceEstimate(position);
- }
- return -1; // no collision
- }
- //Fragments are visible bits of surface
- //Each one of these is tested in parallel for contact with our interior geometry
- fixed4 frag (v2f i) : SV_Target
- {
- float3 viewDirection = normalize(i.wPos - _WorldSpaceCameraPos);
- // ^ the unit vector connecting our camera to the point our ray intersects the surface of our object
- int steps_taken = raycastHit(_WorldSpaceCameraPos, viewDirection);
- // ^ how many steps it takes to reach our geometry. -1 If no collision
- if (steps_taken > 0)
- {
- return fixed4(1-(0.02*steps_taken),0,0,1); // More steps -> darker shade of red
- // a better solution would be a proper brightness transform using matricies
- }
- else
- {
- return fixed4(0,0,0,0); //Transparent if no collision
- }
- }
- ENDCG
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement