├── .gitignore ├── Assets ├── DistanceFunc.cginc ├── DistanceFunc.cginc.meta ├── RaymarchGeneric.cs ├── RaymarchGeneric.cs.meta ├── RaymarchGeneric.shader ├── RaymarchGeneric.shader.meta ├── SceneViewFilter.cs ├── SceneViewFilter.cs.meta ├── color_ramp.png ├── color_ramp.png.meta ├── heat_ramp.png ├── heat_ramp.png.meta ├── testbed.unity └── testbed.unity.meta ├── LICENSE.txt ├── ProjectSettings ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── NetworkManager.asset ├── Physics2DSettings.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset ├── UnityAdsSettings.asset └── UnityConnectSettings.asset └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # =============== # 2 | # Unity generated # 3 | # =============== # 4 | [Tt]emp/ 5 | [Oo]bj/ 6 | [Bb]uild 7 | [Ll]ibrary/ 8 | sysinfo.txt 9 | *.stackdump 10 | 11 | # ===================================== # 12 | # Visual Studio / MonoDevelop generated # 13 | # ===================================== # 14 | [Ee]xported[Oo]bj/ 15 | .vs/ 16 | /*.userprefs 17 | /*.csproj 18 | /*.pidb 19 | /*.suo 20 | /*.sln* 21 | /*.user 22 | /*.unityproj 23 | /*.booproj 24 | 25 | # ============ # 26 | # OS generated # 27 | # ============ # 28 | .DS_Store* 29 | ._* 30 | .Spotlight-V100 31 | .Trashes 32 | Icon? 33 | ehthumbs.db 34 | [Tt]humbs.db 35 | -------------------------------------------------------------------------------- /Assets/DistanceFunc.cginc: -------------------------------------------------------------------------------- 1 | // Adapted from: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm 2 | 3 | // SIGNED DISTANCE FUNCTIONS // 4 | // These all return the minimum distance from point p to the desired shape's surface, given the other parameters. 5 | // The result is negative if you are inside the shape. All shapes are centered about the origin, so you may need to 6 | // transform your input point (p) to account for translation or rotation 7 | 8 | // Sphere 9 | // s: radius 10 | float sdSphere(float3 p, float s) 11 | { 12 | return length(p) - s; 13 | } 14 | 15 | // Box 16 | // b: size of box in x/y/z 17 | float sdBox(float3 p, float3 b) 18 | { 19 | float3 d = abs(p) - b; 20 | return min(max(d.x, max(d.y, d.z)), 0.0) + 21 | length(max(d, 0.0)); 22 | } 23 | 24 | // Torus 25 | // t.x: diameter 26 | // t.y: thickness 27 | float sdTorus(float3 p, float2 t) 28 | { 29 | float2 q = float2(length(p.xz) - t.x, p.y); 30 | return length(q) - t.y; 31 | } 32 | 33 | // Cylinder 34 | // h.x = diameter 35 | // h.y = height 36 | float sdCylinder(float3 p, float2 h) 37 | { 38 | float2 d = abs(float2(length(p.xz), p.y)) - h; 39 | return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)); 40 | } 41 | 42 | float sdCone(float3 p, float2 c) 43 | { 44 | // c must be normalized 45 | float q = length(p.xy); 46 | return dot(c, float2(q, p.z)); 47 | } 48 | 49 | // (Infinite) Plane 50 | // n.xyz: normal of the plane (normalized). 51 | // n.w: offset 52 | float sdPlane(float3 p, float4 n) 53 | { 54 | // n must be normalized 55 | return dot(p, n.xyz) + n.w; 56 | } 57 | 58 | float sdHexPrism(float3 p, float2 h) 59 | { 60 | float3 q = abs(p); 61 | return max(q.z - h.y, max((q.x*0.866025 + q.y*0.5), q.y) - h.x); 62 | } 63 | 64 | float sdTriPrism(float3 p, float2 h) 65 | { 66 | float3 q = abs(p); 67 | return max(q.z - h.y, max(q.x*0.866025 + p.y*0.5, -p.y) - h.x*0.5); 68 | } 69 | 70 | float sdCapsule(float3 p, float3 a, float3 b, float r) 71 | { 72 | float3 pa = p - a, ba = b - a; 73 | float h = clamp(dot(pa, ba) / dot(ba, ba), 0.0, 1.0); 74 | return length(pa - ba*h) - r; 75 | } 76 | 77 | float sdCappedCone(in float3 p, in float3 c) 78 | { 79 | float2 q = float2(length(p.xz), p.y); 80 | float2 v = float2(c.z*c.y / c.x, -c.z); 81 | float2 w = v - q; 82 | float2 vv = float2(dot(v, v), v.x*v.x); 83 | float2 qv = float2(dot(v, w), v.x*w.x); 84 | float2 d = max(qv, 0.0)*qv / vv; 85 | return sqrt(dot(w, w) - max(d.x, d.y))* sign(max(q.y*v.x - q.x*v.y, w.y)); 86 | } 87 | 88 | float sdEllipsoid(in float3 p, in float3 r) 89 | { 90 | return (length(p / r) - 1.0) * min(min(r.x, r.y), r.z); 91 | } 92 | 93 | // BOOLEAN OPERATIONS // 94 | // Apply these operations to multiple "primitive" distance functions to create complex shapes. 95 | 96 | // Union 97 | float opU(float d1, float d2) 98 | { 99 | return min(d1, d2); 100 | } 101 | 102 | // Union (with material data) 103 | float2 opU_mat( float2 d1, float2 d2 ) 104 | { 105 | return (d1.x d2.x) ? d1 : d2; 134 | } -------------------------------------------------------------------------------- /Assets/DistanceFunc.cginc.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 65c859c06887ee44599599c328ba420a 3 | timeCreated: 1455387414 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/RaymarchGeneric.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | [ExecuteInEditMode] 4 | [RequireComponent(typeof(Camera))] 5 | [AddComponentMenu("Effects/Raymarch (Generic Complete)")] 6 | public class RaymarchGeneric : SceneViewFilter 7 | { 8 | public Transform SunLight; 9 | 10 | [SerializeField] 11 | private Shader _EffectShader; 12 | [SerializeField] 13 | private Texture2D _MaterialColorRamp; 14 | [SerializeField] 15 | private Texture2D _PerfColorRamp; 16 | [SerializeField] 17 | private float _RaymarchDrawDistance = 40; 18 | [SerializeField] 19 | private bool _DebugPerformance = false; 20 | 21 | public Material EffectMaterial 22 | { 23 | get 24 | { 25 | if (!_EffectMaterial && _EffectShader) 26 | { 27 | _EffectMaterial = new Material(_EffectShader); 28 | _EffectMaterial.hideFlags = HideFlags.HideAndDontSave; 29 | } 30 | 31 | return _EffectMaterial; 32 | } 33 | } 34 | private Material _EffectMaterial; 35 | 36 | public Camera CurrentCamera 37 | { 38 | get 39 | { 40 | if (!_CurrentCamera) 41 | _CurrentCamera = GetComponent(); 42 | return _CurrentCamera; 43 | } 44 | } 45 | private Camera _CurrentCamera; 46 | 47 | void OnDrawGizmos() 48 | { 49 | Gizmos.color = Color.green; 50 | 51 | Matrix4x4 corners = GetFrustumCorners(CurrentCamera); 52 | Vector3 pos = CurrentCamera.transform.position; 53 | 54 | for (int x = 0; x < 4; x++) { 55 | corners.SetRow(x, CurrentCamera.cameraToWorldMatrix * corners.GetRow(x)); 56 | Gizmos.DrawLine(pos, pos + (Vector3)(corners.GetRow(x))); 57 | } 58 | 59 | /* 60 | // UNCOMMENT TO DEBUG RAY DIRECTIONS 61 | Gizmos.color = Color.red; 62 | int n = 10; // # of intervals 63 | for (int x = 1; x < n; x++) { 64 | float i_x = (float)x / (float)n; 65 | 66 | var w_top = Vector3.Lerp(corners.GetRow(0), corners.GetRow(1), i_x); 67 | var w_bot = Vector3.Lerp(corners.GetRow(3), corners.GetRow(2), i_x); 68 | for (int y = 1; y < n; y++) { 69 | float i_y = (float)y / (float)n; 70 | 71 | var w = Vector3.Lerp(w_top, w_bot, i_y).normalized; 72 | Gizmos.DrawLine(pos + (Vector3)w, pos + (Vector3)w * 1.2f); 73 | } 74 | } 75 | */ 76 | } 77 | 78 | [ImageEffectOpaque] 79 | void OnRenderImage(RenderTexture source, RenderTexture destination) 80 | { 81 | if (!EffectMaterial) 82 | { 83 | Graphics.Blit(source, destination); // do nothing 84 | return; 85 | } 86 | 87 | // Set any custom shader variables here. For example, you could do: 88 | // EffectMaterial.SetFloat("_MyVariable", 13.37f); 89 | // This would set the shader uniform _MyVariable to value 13.37 90 | 91 | EffectMaterial.SetVector("_LightDir", SunLight ? SunLight.forward : Vector3.down); 92 | 93 | // Construct a Model Matrix for the Torus 94 | Matrix4x4 MatTorus = Matrix4x4.TRS( 95 | Vector3.right * Mathf.Sin(Time.time) * 5, 96 | Quaternion.identity, 97 | Vector3.one); 98 | MatTorus *= Matrix4x4.TRS( 99 | Vector3.zero, 100 | Quaternion.Euler(new Vector3(0, 0, (Time.time * 200) % 360)), 101 | Vector3.one); 102 | // Send the torus matrix to our shader 103 | EffectMaterial.SetMatrix("_MatTorus_InvModel", MatTorus.inverse); 104 | 105 | EffectMaterial.SetTexture("_ColorRamp_Material", _MaterialColorRamp); 106 | EffectMaterial.SetTexture("_ColorRamp_PerfMap", _PerfColorRamp); 107 | 108 | EffectMaterial.SetFloat("_DrawDistance", _RaymarchDrawDistance); 109 | 110 | if(EffectMaterial.IsKeywordEnabled("DEBUG_PERFORMANCE") != _DebugPerformance) { 111 | if(_DebugPerformance) 112 | EffectMaterial.EnableKeyword("DEBUG_PERFORMANCE"); 113 | else 114 | EffectMaterial.DisableKeyword("DEBUG_PERFORMANCE"); 115 | } 116 | 117 | EffectMaterial.SetMatrix("_FrustumCornersES", GetFrustumCorners(CurrentCamera)); 118 | EffectMaterial.SetMatrix("_CameraInvViewMatrix", CurrentCamera.cameraToWorldMatrix); 119 | EffectMaterial.SetVector("_CameraWS", CurrentCamera.transform.position); 120 | 121 | CustomGraphicsBlit(source, destination, EffectMaterial, 0); 122 | } 123 | 124 | /// \brief Stores the normalized rays representing the camera frustum in a 4x4 matrix. Each row is a vector. 125 | /// 126 | /// The following rays are stored in each row (in eyespace, not worldspace): 127 | /// Top Left corner: row=0 128 | /// Top Right corner: row=1 129 | /// Bottom Right corner: row=2 130 | /// Bottom Left corner: row=3 131 | private Matrix4x4 GetFrustumCorners(Camera cam) 132 | { 133 | float camFov = cam.fieldOfView; 134 | float camAspect = cam.aspect; 135 | 136 | Matrix4x4 frustumCorners = Matrix4x4.identity; 137 | 138 | float fovWHalf = camFov * 0.5f; 139 | 140 | float tan_fov = Mathf.Tan(fovWHalf * Mathf.Deg2Rad); 141 | 142 | Vector3 toRight = Vector3.right * tan_fov * camAspect; 143 | Vector3 toTop = Vector3.up * tan_fov; 144 | 145 | Vector3 topLeft = (-Vector3.forward - toRight + toTop); 146 | Vector3 topRight = (-Vector3.forward + toRight + toTop); 147 | Vector3 bottomRight = (-Vector3.forward + toRight - toTop); 148 | Vector3 bottomLeft = (-Vector3.forward - toRight - toTop); 149 | 150 | frustumCorners.SetRow(0, topLeft); 151 | frustumCorners.SetRow(1, topRight); 152 | frustumCorners.SetRow(2, bottomRight); 153 | frustumCorners.SetRow(3, bottomLeft); 154 | 155 | return frustumCorners; 156 | } 157 | 158 | /// \brief Custom version of Graphics.Blit that encodes frustum corner indices into the input vertices. 159 | /// 160 | /// In a shader you can expect the following frustum cornder index information to get passed to the z coordinate: 161 | /// Top Left vertex: z=0, u=0, v=0 162 | /// Top Right vertex: z=1, u=1, v=0 163 | /// Bottom Right vertex: z=2, u=1, v=1 164 | /// Bottom Left vertex: z=3, u=1, v=0 165 | /// 166 | /// \warning You may need to account for flipped UVs on DirectX machines due to differing UV semantics 167 | /// between OpenGL and DirectX. Use the shader define UNITY_UV_STARTS_AT_TOP to account for this. 168 | static void CustomGraphicsBlit(RenderTexture source, RenderTexture dest, Material fxMaterial, int passNr) 169 | { 170 | RenderTexture.active = dest; 171 | 172 | fxMaterial.SetTexture("_MainTex", source); 173 | 174 | GL.PushMatrix(); 175 | GL.LoadOrtho(); // Note: z value of vertices don't make a difference because we are using ortho projection 176 | 177 | fxMaterial.SetPass(passNr); 178 | 179 | GL.Begin(GL.QUADS); 180 | 181 | // Here, GL.MultitexCoord2(0, x, y) assigns the value (x, y) to the TEXCOORD0 slot in the shader. 182 | // GL.Vertex3(x,y,z) queues up a vertex at position (x, y, z) to be drawn. Note that we are storing 183 | // our own custom frustum information in the z coordinate. 184 | GL.MultiTexCoord2(0, 0.0f, 0.0f); 185 | GL.Vertex3(0.0f, 0.0f, 3.0f); // BL 186 | 187 | GL.MultiTexCoord2(0, 1.0f, 0.0f); 188 | GL.Vertex3(1.0f, 0.0f, 2.0f); // BR 189 | 190 | GL.MultiTexCoord2(0, 1.0f, 1.0f); 191 | GL.Vertex3(1.0f, 1.0f, 1.0f); // TR 192 | 193 | GL.MultiTexCoord2(0, 0.0f, 1.0f); 194 | GL.Vertex3(0.0f, 1.0f, 0.0f); // TL 195 | 196 | GL.End(); 197 | GL.PopMatrix(); 198 | } 199 | 200 | } 201 | -------------------------------------------------------------------------------- /Assets/RaymarchGeneric.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 65eefbdf61ecef64aa5ed2d721cf15d3 3 | timeCreated: 1455335241 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/RaymarchGeneric.shader: -------------------------------------------------------------------------------- 1 | Shader "Hidden/RaymarchGeneric" 2 | { 3 | Properties 4 | { 5 | _MainTex ("Texture", 2D) = "white" {} 6 | } 7 | SubShader 8 | { 9 | // No culling or depth 10 | Cull Off ZWrite Off ZTest Always 11 | 12 | Pass 13 | { 14 | CGPROGRAM 15 | #pragma vertex vert 16 | #pragma fragment frag 17 | // Compile one version of the shader with performance debugging 18 | // This way we can simply set a shader keyword to test perf 19 | #pragma multi_compile __ DEBUG_PERFORMANCE 20 | // You may need to use an even later shader model target, depending on how many instructions you have 21 | // or if you need variable-length for loops. 22 | #pragma target 3.0 23 | 24 | #include "UnityCG.cginc" 25 | #include "DistanceFunc.cginc" 26 | 27 | uniform sampler2D _CameraDepthTexture; 28 | // These are are set by our script (see RaymarchGeneric.cs) 29 | uniform sampler2D _MainTex; 30 | uniform float4 _MainTex_TexelSize; 31 | 32 | uniform float4x4 _CameraInvViewMatrix; 33 | uniform float4x4 _FrustumCornersES; 34 | uniform float4 _CameraWS; 35 | 36 | uniform float3 _LightDir; 37 | uniform float4x4 _MatTorus_InvModel; 38 | uniform sampler2D _ColorRamp_Material; 39 | uniform sampler2D _ColorRamp_PerfMap; 40 | 41 | uniform float _DrawDistance; 42 | 43 | struct appdata 44 | { 45 | // Remember, the z value here contains the index of _FrustumCornersES to use 46 | float4 vertex : POSITION; 47 | float2 uv : TEXCOORD0; 48 | }; 49 | 50 | struct v2f 51 | { 52 | float4 pos : SV_POSITION; 53 | float2 uv : TEXCOORD0; 54 | float3 ray : TEXCOORD1; 55 | }; 56 | 57 | v2f vert (appdata v) 58 | { 59 | v2f o; 60 | 61 | // Index passed via custom blit function in RaymarchGeneric.cs 62 | half index = v.vertex.z; 63 | v.vertex.z = 0.1; 64 | 65 | o.pos = mul(UNITY_MATRIX_MVP, v.vertex); 66 | o.uv = v.uv.xy; 67 | 68 | #if UNITY_UV_STARTS_AT_TOP 69 | if (_MainTex_TexelSize.y < 0) 70 | o.uv.y = 1 - o.uv.y; 71 | #endif 72 | 73 | // Get the eyespace view ray (normalized) 74 | o.ray = _FrustumCornersES[(int)index].xyz; 75 | // Dividing by z "normalizes" it in the z axis 76 | // Therefore multiplying the ray by some number i gives the viewspace position 77 | // of the point on the ray with [viewspace z]=i 78 | o.ray /= abs(o.ray.z); 79 | 80 | // Transform the ray from eyespace to worldspace 81 | o.ray = mul(_CameraInvViewMatrix, o.ray); 82 | 83 | return o; 84 | } 85 | 86 | // This is the distance field function. The distance field represents the closest distance to the surface 87 | // of any object we put in the scene. If the given point (point p) is inside of an object, we return a 88 | // negative answer. 89 | // return.x: result of distance field 90 | // return.y: material data for closest object 91 | float2 map(float3 p) { 92 | // Apply inverse model matrix to point when sampling torus 93 | // This allows for more complex transformations/animation on the torus 94 | float3 torus_point = mul(_MatTorus_InvModel, float4(p,1)).xyz; 95 | float2 d_torus = float2(sdTorus(torus_point, float2(1, 0.2)), 0.5); 96 | 97 | float2 d_box = float2(sdBox(p - float3(-3,0,0), float3(0.75,0.5,0.5)), 0.25); 98 | float2 d_sphere = float2(sdSphere(p - float3(3,0,0), 1), 0.75); 99 | 100 | float2 ret = opU_mat(d_torus, d_box); 101 | ret = opU_mat(ret, d_sphere); 102 | 103 | return ret; 104 | } 105 | 106 | float3 calcNormal(in float3 pos) 107 | { 108 | const float2 eps = float2(0.001, 0.0); 109 | // The idea here is to find the "gradient" of the distance field at pos 110 | // Remember, the distance field is not boolean - even if you are inside an object 111 | // the number is negative, so this calculation still works. 112 | // Essentially you are approximating the derivative of the distance field at this point. 113 | float3 nor = float3( 114 | map(pos + eps.xyy).x - map(pos - eps.xyy).x, 115 | map(pos + eps.yxy).x - map(pos - eps.yxy).x, 116 | map(pos + eps.yyx).x - map(pos - eps.yyx).x); 117 | return normalize(nor); 118 | } 119 | 120 | // Raymarch along given ray 121 | // ro: ray origin 122 | // rd: ray direction 123 | // s: unity depth buffer 124 | fixed4 raymarch(float3 ro, float3 rd, float s) { 125 | fixed4 ret = fixed4(0,0,0,0); 126 | 127 | const int maxstep = 64; 128 | float t = 0; // current distance traveled along ray 129 | for (int i = 0; i < maxstep; ++i) { 130 | // If we run past the depth buffer, or if we exceed the max draw distance, 131 | // stop and return nothing (transparent pixel). 132 | // this way raymarched objects and traditional meshes can coexist. 133 | if (t >= s || t > _DrawDistance) { 134 | ret = fixed4(0, 0, 0, 0); 135 | break; 136 | } 137 | 138 | float3 p = ro + rd * t; // World space position of sample 139 | float2 d = map(p); // Sample of distance field (see map()) 140 | 141 | // If the sample <= 0, we have hit something (see map()). 142 | if (d.x < 0.001) { 143 | float3 n = calcNormal(p); 144 | float light = dot(-_LightDir.xyz, n); 145 | ret = fixed4(tex2D(_ColorRamp_Material, float2(d.y,0)).xyz * light, 1); 146 | break; 147 | } 148 | 149 | // If the sample > 0, we haven't hit anything yet so we should march forward 150 | // We step forward by distance d, because d is the minimum distance possible to intersect 151 | // an object (see map()). 152 | t += d; 153 | } 154 | 155 | return ret; 156 | } 157 | 158 | // Modified raymarch loop that displays a heatmap of ray sample counts 159 | // Useful for performance testing and analysis 160 | // ro: ray origin 161 | // rd: ray direction 162 | // s: unity depth buffer 163 | fixed4 raymarch_perftest(float3 ro, float3 rd, float s) { 164 | const int maxstep = 64; 165 | float t = 0; // current distance traveled along ray 166 | 167 | for (int i = 0; i < maxstep; ++i) { 168 | float3 p = ro + rd * t; // World space position of sample 169 | float2 d = map(p); // Sample of distance field (see map()) 170 | 171 | // If the sample <= 0, we have hit something (see map()). 172 | // If t > drawdist, we can safely bail because we have reached the max draw distance 173 | if (d.x < 0.001 || t > _DrawDistance) { 174 | // Simply return the number of steps taken, mapped to a color ramp. 175 | float perf = (float)i / maxstep; 176 | return fixed4(tex2D(_ColorRamp_PerfMap, float2(perf, 0)).xyz, 1); 177 | } 178 | 179 | t += d; 180 | } 181 | // By this point the loop guard (i < maxstep) is false. Therefore 182 | // we have reached maxstep steps. 183 | return fixed4(tex2D(_ColorRamp_PerfMap, float2(1, 0)).xyz, 1); 184 | } 185 | 186 | fixed4 frag (v2f i) : SV_Target 187 | { 188 | // ray direction 189 | float3 rd = normalize(i.ray.xyz); 190 | // ray origin (camera position) 191 | float3 ro = _CameraWS; 192 | 193 | float2 duv = i.uv; 194 | #if UNITY_UV_STARTS_AT_TOP 195 | if (_MainTex_TexelSize.y < 0) 196 | duv.y = 1 - duv.y; 197 | #endif 198 | 199 | // Convert from depth buffer (eye space) to true distance from camera 200 | // This is done by multiplying the eyespace depth by the length of the "z-normalized" 201 | // ray (see vert()). Think of similar triangles: the view-space z-distance between a point 202 | // and the camera is proportional to the absolute distance. 203 | float depth = LinearEyeDepth(tex2D(_CameraDepthTexture, duv).r); 204 | depth *= length(i.ray); 205 | 206 | fixed3 col = tex2D(_MainTex,i.uv); 207 | 208 | #if defined (DEBUG_PERFORMANCE) 209 | fixed4 add = raymarch_perftest(ro, rd, depth); 210 | #else 211 | fixed4 add = raymarch(ro, rd, depth); 212 | #endif 213 | 214 | // Returns final color using alpha blending 215 | return fixed4(col*(1.0 - add.w) + add.xyz * add.w,1.0); 216 | } 217 | ENDCG 218 | } 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /Assets/RaymarchGeneric.shader.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 09742a9e52e9516488b1cfc71d0e443b 3 | timeCreated: 1455337450 4 | licenseType: Free 5 | ShaderImporter: 6 | defaultTextures: [] 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/SceneViewFilter.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | #if UNITY_EDITOR 3 | using UnityEditor; 4 | #endif 5 | 6 | public class SceneViewFilter : MonoBehaviour 7 | { 8 | #if UNITY_EDITOR 9 | bool hasChanged = false; 10 | 11 | public virtual void OnValidate() 12 | { 13 | hasChanged = true; 14 | } 15 | 16 | static SceneViewFilter() 17 | { 18 | SceneView.onSceneGUIDelegate += CheckMe; 19 | } 20 | 21 | static void CheckMe(SceneView sv) 22 | { 23 | if (Event.current.type != EventType.Layout) 24 | return; 25 | if (!Camera.main) 26 | return; 27 | // Get a list of everything on the main camera that should be synced. 28 | SceneViewFilter[] cameraFilters = Camera.main.GetComponents(); 29 | SceneViewFilter[] sceneFilters = sv.camera.GetComponents(); 30 | 31 | // Let's see if the lists are different lengths or something like that. 32 | // If so, we simply destroy all scene filters and recreate from maincame 33 | if (cameraFilters.Length != sceneFilters.Length) 34 | { 35 | Recreate(sv); 36 | return; 37 | } 38 | for (int i = 0; i < cameraFilters.Length; i++) 39 | { 40 | if (cameraFilters[i].GetType() != sceneFilters[i].GetType()) 41 | { 42 | Recreate(sv); 43 | return; 44 | } 45 | } 46 | 47 | // Ok, WHICH filters, or their order hasn't changed. 48 | // Let's copy all settings for any filter that has changed. 49 | for (int i = 0; i < cameraFilters.Length; i++) 50 | if (cameraFilters[i].hasChanged || sceneFilters[i].enabled != cameraFilters[i].enabled) 51 | { 52 | EditorUtility.CopySerialized(cameraFilters[i], sceneFilters[i]); 53 | cameraFilters[i].hasChanged = false; 54 | } 55 | } 56 | 57 | static void Recreate(SceneView sv) 58 | { 59 | SceneViewFilter filter; 60 | while (filter = sv.camera.GetComponent()) 61 | DestroyImmediate(filter); 62 | 63 | foreach (SceneViewFilter f in Camera.main.GetComponents()) 64 | { 65 | SceneViewFilter newFilter = sv.camera.gameObject.AddComponent(f.GetType()) as SceneViewFilter; 66 | EditorUtility.CopySerialized(f, newFilter); 67 | } 68 | } 69 | #endif 70 | } -------------------------------------------------------------------------------- /Assets/SceneViewFilter.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b44ff8d63ffba6646a6b93f181c49e74 3 | timeCreated: 1464638310 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/color_ramp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/Assets/color_ramp.png -------------------------------------------------------------------------------- /Assets/color_ramp.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 26a0db22407d740e38807b456182332e 3 | timeCreated: 1475295189 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 2 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 0 11 | linearTexture: 0 12 | correctGamma: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 0 25 | cubemapConvolution: 0 26 | cubemapConvolutionSteps: 7 27 | cubemapConvolutionExponent: 1.5 28 | seamlessCubemap: 0 29 | textureFormat: -1 30 | maxTextureSize: 2048 31 | textureSettings: 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapMode: -1 36 | nPOTScale: 1 37 | lightmap: 0 38 | rGBM: 0 39 | compressionQuality: 50 40 | allowsAlphaSplitting: 0 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 47 | spritePixelsToUnits: 100 48 | alphaIsTransparency: 0 49 | spriteTessellationDetail: -1 50 | textureType: 5 51 | buildTargetSettings: [] 52 | spriteSheet: 53 | serializedVersion: 2 54 | sprites: [] 55 | outline: [] 56 | spritePackingTag: 57 | userData: 58 | assetBundleName: 59 | assetBundleVariant: 60 | -------------------------------------------------------------------------------- /Assets/heat_ramp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/Assets/heat_ramp.png -------------------------------------------------------------------------------- /Assets/heat_ramp.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f904b160f51724469ba27807b2c5887d 3 | timeCreated: 1475298432 4 | licenseType: Free 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 2 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 0 11 | linearTexture: 0 12 | correctGamma: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 0 25 | cubemapConvolution: 0 26 | cubemapConvolutionSteps: 7 27 | cubemapConvolutionExponent: 1.5 28 | seamlessCubemap: 0 29 | textureFormat: -1 30 | maxTextureSize: 2048 31 | textureSettings: 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapMode: 1 36 | nPOTScale: 1 37 | lightmap: 0 38 | rGBM: 0 39 | compressionQuality: 50 40 | allowsAlphaSplitting: 0 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 47 | spritePixelsToUnits: 100 48 | alphaIsTransparency: 0 49 | spriteTessellationDetail: -1 50 | textureType: 5 51 | buildTargetSettings: [] 52 | spriteSheet: 53 | serializedVersion: 2 54 | sprites: [] 55 | outline: [] 56 | spritePackingTag: 57 | userData: 58 | assetBundleName: 59 | assetBundleVariant: 60 | -------------------------------------------------------------------------------- /Assets/testbed.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/Assets/testbed.unity -------------------------------------------------------------------------------- /Assets/testbed.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ad5f0e33ea622bf4cb0fc3054b1f4230 3 | timeCreated: 1455397261 4 | licenseType: Free 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Adrian Biagioli 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/ClusterInputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/NavMeshAreas.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 5.4.1f1 2 | m_StandardAssetsVersion: 0 3 | -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /ProjectSettings/UnityAdsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/UnityAdsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flafla2/Generic-Raymarch-Unity/b66fa0885cfa9cb65ad3f55bf0f13e9d96e30ca4/ProjectSettings/UnityConnectSettings.asset -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Distance Field Raymarcher for Unity 2 | ----------------------------------- 3 | 4 | This is an implementation of Distance Field Raymarching in the Unity game engine. It was created to be used as a reference implementation in future projects. For a comprehensive technical writeup about how Distance Field Raymarching works, see [this article on my blog](http://flafla2.github.io/2016/10/01/raymarching.html). 5 | 6 | Below are a few of the major features of this implementation: 7 | 8 | 1. **Complete Implementation of Distance Field Raymarching**. This repository demonstrates how to construct a fully working implementation of Distance Field Raymarching. Using this repository as a base, you can focus on implementation details instead of the more technical aspects of raymarching. Additionally, I include a number of useful Distance Field primitives (sphere, box, torus, cylinder, etc) and Combine Operations (Union, Intersection, Subtraction) - see ``DistanceFunc.cginc`` for details. Below is a gif of the included demo scene: 9 | ![](https://thumbs.gfycat.com/VainFaintGermanspaniel-size_restricted.gif) 10 | 2. **Interaction with mesh-based Objects**. This implementation takes Unity's depth buffer into account, so your raymarched objects can intersect and interact with traditional mesh-based objects. 11 | ![](https://thumbs.gfycat.com/SimpleInfiniteBlackandtancoonhound-size_restricted.gif) 12 | 3. **Heatmap-based Performance Testing**. The system has support for heatmap-based performance testing using a color ramp. Below is an example of this output (red = many samples per pixel, blue = fewer samples): 13 | 14 | 4. **Open Source and License**. This implementation is released under the liberal MIT License, so it is easy use it in your projects. 15 | --------------------------------------------------------------------------------