You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

182 lines
6.6 KiB
C#

// Copyright (c) <2015> <Playdead>
// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE.TXT)
// AUTHOR: Lasse Jon Fuglsang Pedersen <lasse@playdead.com>
#if UNITY_5_5_OR_NEWER
#define SUPPORT_STEREO
#endif
using UnityEngine;
namespace FogVolumePlaydeadTAA
{
public static class Vector2Extension
{
// positive if v2 is on the left side of v1
public static float SignedAngle(this Vector2 v1, Vector2 v2)
{
Vector2 n1 = v1.normalized;
Vector2 n2 = v2.normalized;
float dot = Vector2.Dot(n1, n2);
if (dot > 1.0f)
dot = 1.0f;
if (dot < -1.0f)
dot = -1.0f;
float theta = Mathf.Acos(dot);
float sgn = Vector2.Dot(new Vector2(-n1.y, n1.x), n2);
if (sgn >= 0.0f)
return theta;
else
return -theta;
}
public static Vector2 Rotate(this Vector2 v, float theta)
{
float cs = Mathf.Cos(theta);
float sn = Mathf.Sin(theta);
float x1 = v.x * cs - v.y * sn;
float y1 = v.x * sn + v.y * cs;
return new Vector2(x1, y1);
}
}
}
namespace FogVolumePlaydeadTAA
{
public static class Vector3Extension
{
public static Vector3 WithX(this Vector3 v, float x)
{
return new Vector3(x, v.y, v.z);
}
public static Vector3 WithY(this Vector3 v, float y)
{
return new Vector3(v.x, y, v.z);
}
public static Vector3 WithZ(this Vector3 v, float z)
{
return new Vector3(v.x, v.y, z);
}
}
}
namespace FogVolumePlaydeadTAA
{
public static class Matrix4x4Extension
{
public static Matrix4x4 GetPerspectiveProjection(float left, float right, float bottom, float top, float near, float far)
{
float x = (2.0f * near) / (right - left);
float y = (2.0f * near) / (top - bottom);
float a = (right + left) / (right - left);
float b = (top + bottom) / (top - bottom);
float c = -(far + near) / (far - near);
float d = -(2.0f * far * near) / (far - near);
float e = -1.0f;
Matrix4x4 m = new Matrix4x4();
m[0, 0] = x; m[0, 1] = 0; m[0, 2] = a; m[0, 3] = 0;
m[1, 0] = 0; m[1, 1] = y; m[1, 2] = b; m[1, 3] = 0;
m[2, 0] = 0; m[2, 1] = 0; m[2, 2] = c; m[2, 3] = d;
m[3, 0] = 0; m[3, 1] = 0; m[3, 2] = e; m[3, 3] = 0;
return m;
}
public static Matrix4x4 GetOrthographicProjection(float left, float right, float bottom, float top, float near, float far)
{
float x = 2.0f / (right - left);
float y = 2.0f / (top - bottom);
float z = -2.0f / (far - near);
float a = -(right + left) / (right - left);
float b = -(top + bottom) / (top - bottom);
float c = -(far + near) / (far - near);
float d = 1.0f;
Matrix4x4 m = new Matrix4x4();
m[0, 0] = x; m[0, 1] = 0; m[0, 2] = 0; m[0, 3] = a;
m[1, 0] = 0; m[1, 1] = y; m[1, 2] = 0; m[1, 3] = b;
m[2, 0] = 0; m[2, 1] = 0; m[2, 2] = z; m[2, 3] = c;
m[3, 0] = 0; m[3, 1] = 0; m[3, 2] = 0; m[3, 3] = d;
return m;
}
}
}
namespace FogVolumePlaydeadTAA
{
public static class CameraExtension
{
public static Vector4 GetProjectionExtents(this Camera camera)
{
return GetProjectionExtents(camera, 0.0f, 0.0f);
}
public static Vector4 GetProjectionExtents(this Camera camera, float texelOffsetX, float texelOffsetY)
{
if (camera == null)
return Vector4.zero;
float oneExtentY = camera.orthographic ? camera.orthographicSize : Mathf.Tan(0.5f * Mathf.Deg2Rad * camera.fieldOfView);
float oneExtentX = oneExtentY * camera.aspect;
float texelSizeX = oneExtentX / (0.5f * camera.pixelWidth);
float texelSizeY = oneExtentY / (0.5f * camera.pixelHeight);
float oneJitterX = texelSizeX * texelOffsetX;
float oneJitterY = texelSizeY * texelOffsetY;
return new Vector4(oneExtentX, oneExtentY, oneJitterX, oneJitterY);// xy = frustum extents at distance 1, zw = jitter at distance 1
}
#if SUPPORT_STEREO
public static Vector4 GetProjectionExtents(this Camera camera, Camera.StereoscopicEye eye)
{
return GetProjectionExtents(camera, eye, 0.0f, 0.0f);
}
public static Vector4 GetProjectionExtents(this Camera camera, Camera.StereoscopicEye eye, float texelOffsetX, float texelOffsetY)
{
Matrix4x4 inv = Matrix4x4.Inverse(camera.GetStereoProjectionMatrix(eye));
Vector3 ray00 = inv.MultiplyPoint3x4(new Vector3(-1.0f, -1.0f, 0.95f));
Vector3 ray11 = inv.MultiplyPoint3x4(new Vector3(1.0f, 1.0f, 0.95f));
ray00 /= -ray00.z;
ray11 /= -ray11.z;
float oneExtentX = 0.5f * (ray11.x - ray00.x);
float oneExtentY = 0.5f * (ray11.y - ray00.y);
float texelSizeX = oneExtentX / (0.5f * camera.pixelWidth);
float texelSizeY = oneExtentY / (0.5f * camera.pixelHeight);
float oneJitterX = 0.5f * (ray11.x + ray00.x) + texelSizeX * texelOffsetX;
float oneJitterY = 0.5f * (ray11.y + ray00.y) + texelSizeY * texelOffsetY;
return new Vector4(oneExtentX, oneExtentY, oneJitterX, oneJitterY);// xy = frustum extents at distance 1, zw = jitter at distance 1
}
#endif
public static Matrix4x4 GetProjectionMatrix(this Camera camera)
{
return GetProjectionMatrix(camera, 0.0f, 0.0f);
}
public static Matrix4x4 GetProjectionMatrix(this Camera camera, float texelOffsetX, float texelOffsetY)
{
if (camera == null)
return Matrix4x4.identity;
Vector4 extents = GetProjectionExtents(camera, texelOffsetX, texelOffsetY);
float cf = camera.farClipPlane;
float cn = camera.nearClipPlane;
float xm = extents.z - extents.x;
float xp = extents.z + extents.x;
float ym = extents.w - extents.y;
float yp = extents.w + extents.y;
if (camera.orthographic)
return Matrix4x4Extension.GetOrthographicProjection(xm, xp, ym, yp, cn, cf);
else
return Matrix4x4Extension.GetPerspectiveProjection(xm * cn, xp * cn, ym * cn, yp * cn, cn, cf);
}
}
}