Created
May 12, 2019 14:29
-
-
Save johans2/23060e5437488e3c8d520203f9af316b to your computer and use it in GitHub Desktop.
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
// Created by Johan Svensson. https://medium.com/dotcrossdot | |
// Slightly modified version of http://flafla2.github.io/2016/10/01/raymarching.html | |
// Most shader properties are moved to the material instead for better control. | |
using UnityEngine; | |
using System.Collections; | |
[ExecuteInEditMode] | |
[RequireComponent(typeof(Camera))] | |
[AddComponentMenu("Effects/Raymarch (Generic)")] | |
public class Raymarch : SceneViewFilter { | |
[SerializeField] | |
private Material blackHoleRayMarching; | |
public Camera CurrentCamera { | |
get { | |
if(!_CurrentCamera) | |
_CurrentCamera = GetComponent<Camera>(); | |
return _CurrentCamera; | |
} | |
} | |
private Camera _CurrentCamera; | |
[ImageEffectOpaque] | |
void OnRenderImage(RenderTexture source, RenderTexture destination) { | |
if(!blackHoleRayMarching) { | |
Graphics.Blit(source, destination); // do nothing | |
return; | |
} | |
// pass frustum rays to shader | |
blackHoleRayMarching.SetMatrix("_FrustumCornersES", GetFrustumCorners(CurrentCamera)); | |
blackHoleRayMarching.SetMatrix("_CameraInvViewMatrix", CurrentCamera.cameraToWorldMatrix); | |
blackHoleRayMarching.SetVector("_CameraWS", CurrentCamera.transform.position); | |
CustomGraphicsBlit(source, destination, blackHoleRayMarching, 0); // Replace Graphics.Blit with CustomGraphicsBlit | |
} | |
/// \brief Stores the normalized rays representing the camera frustum in a 4x4 matrix. Each row is a vector. | |
/// | |
/// The following rays are stored in each row (in eyespace, not worldspace): | |
/// Top Left corner: row=0 | |
/// Top Right corner: row=1 | |
/// Bottom Right corner: row=2 | |
/// Bottom Left corner: row=3 | |
private Matrix4x4 GetFrustumCorners(Camera cam) { | |
float camFov = cam.fieldOfView; | |
float camAspect = cam.aspect; | |
Matrix4x4 frustumCorners = Matrix4x4.identity; | |
float fovWHalf = camFov * 0.5f; | |
float tan_fov = Mathf.Tan(fovWHalf * Mathf.Deg2Rad); | |
Vector3 toRight = Vector3.right * tan_fov * camAspect; | |
Vector3 toTop = Vector3.up * tan_fov; | |
Vector3 topLeft = (-Vector3.forward - toRight + toTop); | |
Vector3 topRight = (-Vector3.forward + toRight + toTop); | |
Vector3 bottomRight = (-Vector3.forward + toRight - toTop); | |
Vector3 bottomLeft = (-Vector3.forward - toRight - toTop); | |
frustumCorners.SetRow(0, topLeft); | |
frustumCorners.SetRow(1, topRight); | |
frustumCorners.SetRow(2, bottomRight); | |
frustumCorners.SetRow(3, bottomLeft); | |
return frustumCorners; | |
} | |
/// \brief Custom version of Graphics.Blit that encodes frustum corner indices into the input vertices. | |
/// | |
/// In a shader you can expect the following frustum cornder index information to get passed to the z coordinate: | |
/// Top Left vertex: z=0, u=0, v=0 | |
/// Top Right vertex: z=1, u=1, v=0 | |
/// Bottom Right vertex: z=2, u=1, v=1 | |
/// Bottom Left vertex: z=3, u=1, v=0 | |
/// | |
/// \warning You may need to account for flipped UVs on DirectX machines due to differing UV semantics | |
/// between OpenGL and DirectX. Use the shader define UNITY_UV_STARTS_AT_TOP to account for this. | |
static void CustomGraphicsBlit(RenderTexture source, RenderTexture dest, Material fxMaterial, int passNr) { | |
RenderTexture.active = dest; | |
GL.PushMatrix(); | |
GL.LoadOrtho(); // Note: z value of vertices don't make a difference because we are using ortho projection | |
fxMaterial.SetPass(passNr); | |
GL.Begin(GL.QUADS); | |
// Here, GL.MultitexCoord2(0, x, y) assigns the value (x, y) to the TEXCOORD0 slot in the shader. | |
// GL.Vertex3(x,y,z) queues up a vertex at position (x, y, z) to be drawn. Note that we are storing | |
// our own custom frustum information in the z coordinate. | |
GL.MultiTexCoord2(0, 0.0f, 0.0f); | |
GL.Vertex3(0.0f, 0.0f, 3.0f); // BL | |
GL.MultiTexCoord2(0, 1.0f, 0.0f); | |
GL.Vertex3(1.0f, 0.0f, 2.0f); // BR | |
GL.MultiTexCoord2(0, 1.0f, 1.0f); | |
GL.Vertex3(1.0f, 1.0f, 1.0f); // TR | |
GL.MultiTexCoord2(0, 0.0f, 1.0f); | |
GL.Vertex3(0.0f, 1.0f, 0.0f); // TL | |
GL.End(); | |
GL.PopMatrix(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment