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.
598 lines
16 KiB
C#
598 lines
16 KiB
C#
using UnityEngine;
|
|
using System.Collections;
|
|
|
|
#if UNITY_5_4_OR_NEWER
|
|
using UnityEngine.Rendering;
|
|
#endif
|
|
|
|
|
|
|
|
public enum suiCamToolType{
|
|
transparent,transparentCaustic,wakeEffects,normals,depthMask,localReflection,
|
|
underwaterMask,underwater,shorelineObject,shorelineCapture
|
|
};
|
|
|
|
|
|
public enum suiCamToolRender{
|
|
automatic,deferredShading,deferredLighting,forward
|
|
};
|
|
|
|
public enum suiCamHdrMode{
|
|
off,on,automatic
|
|
};
|
|
|
|
public enum suiCamClearFlags{
|
|
automatic, skybox, color
|
|
};
|
|
|
|
|
|
|
|
namespace Suimono.Core
|
|
{
|
|
|
|
|
|
[ExecuteInEditMode]
|
|
public class cameraTools : MonoBehaviour {
|
|
|
|
//Public Variables
|
|
public suiCamToolType cameraType;
|
|
public suiCamToolRender renderType = suiCamToolRender.automatic;
|
|
public suiCamHdrMode hdrMode = suiCamHdrMode.off;
|
|
public suiCamClearFlags clearMode = suiCamClearFlags.automatic;
|
|
public Color clearFlagColor = Color.black;
|
|
|
|
public int resolution = 256;
|
|
public float cameraOffset = 0f;
|
|
public float reflectionOffset = 0f;
|
|
public RenderTexture renderTexDiff;
|
|
public Shader renderShader;
|
|
public bool executeInEditMode = false;
|
|
public bool isUnderwater = false;
|
|
|
|
//public Camera useCamera;
|
|
|
|
[HideInInspector] public Renderer surfaceRenderer;
|
|
[HideInInspector] public Renderer scaleRenderer;
|
|
[HideInInspector] public float reflectionDistance = 200.0f;
|
|
[HideInInspector] public int setLayers;
|
|
|
|
|
|
//Private Variables
|
|
private RenderingPath usePath;
|
|
private Suimono.Core.SuimonoModule suimonoModuleObject;
|
|
private Camera cam;
|
|
private Camera copyCam;
|
|
private int currResolution = 256;
|
|
|
|
//Collect variables for reflection
|
|
private float clipPlaneOffset = 0.07f;
|
|
|
|
//Collect variables for GC
|
|
private Vector3 pos;
|
|
private Vector3 normal;
|
|
private float d;
|
|
private Vector4 reflectionPlane;
|
|
private Matrix4x4 reflection;
|
|
private Vector3 oldpos;
|
|
private Vector3 newpos;
|
|
private Vector4 clipPlane;
|
|
private Matrix4x4 projection;
|
|
private Vector3 euler;
|
|
private Matrix4x4 scaleOffset;
|
|
private Vector3 scale;
|
|
private Matrix4x4 mtx;
|
|
private Vector3 offsetPos;
|
|
private Matrix4x4 m;
|
|
private Vector3 cpos;
|
|
private Vector3 cnormal;
|
|
private Matrix4x4 proj;
|
|
private Vector4 q;
|
|
private Vector4 c;
|
|
private float hasStarted = 0f;
|
|
private Vector3 cameraPos = Vector3.zero;
|
|
private Suimono.Core.Suimono_ShorelineObject shoreObject;
|
|
|
|
|
|
|
|
|
|
|
|
void Start () {
|
|
|
|
//Get object references
|
|
suimonoModuleObject = (Suimono.Core.SuimonoModule) FindObjectOfType(typeof(Suimono.Core.SuimonoModule));
|
|
|
|
|
|
if (cameraType != suiCamToolType.localReflection){
|
|
if (transform.parent != null) surfaceRenderer = transform.parent.gameObject.GetComponent<Renderer>();
|
|
} else {
|
|
if (transform.parent != null){
|
|
surfaceRenderer = transform.parent.Find("Suimono_Object").gameObject.GetComponent<Renderer>();
|
|
scaleRenderer = transform.parent.Find("Suimono_ObjectScale").gameObject.GetComponent<Renderer>();
|
|
}
|
|
}
|
|
|
|
cam = gameObject.GetComponent<Camera>() as Camera;
|
|
SetCopyCamera();
|
|
//if (suimonoModuleObject != null && suimonoModuleObject.setCamera != null){
|
|
// copyCam = suimonoModuleObject.setCamera.GetComponent<Camera>();
|
|
//}
|
|
|
|
UpdateRenderTex();
|
|
CameraUpdate();
|
|
}
|
|
|
|
|
|
|
|
|
|
void OnPreRender(){
|
|
if (Application.isPlaying && cameraType == suiCamToolType.localReflection){
|
|
GL.invertCulling = true;
|
|
}
|
|
}
|
|
|
|
void OnPostRender(){
|
|
if (Application.isPlaying){
|
|
GL.invertCulling = false;
|
|
}
|
|
}
|
|
|
|
void Update(){
|
|
|
|
//update shoreline camera during edit mode
|
|
if (!Application.isPlaying && executeInEditMode){
|
|
CameraUpdate();
|
|
}
|
|
|
|
//set layermasks
|
|
if (cam != null){
|
|
if (cameraType == suiCamToolType.shorelineCapture){
|
|
cam.cullingMask = 1 << suimonoModuleObject.layerDepthNum;
|
|
}
|
|
}
|
|
|
|
|
|
//avoid frustum error
|
|
bool frustumError = false;
|
|
int zeroVectors = 0;
|
|
|
|
if (cameraType != suiCamToolType.shorelineObject){
|
|
if (cam.transform.rotation.x == 0) zeroVectors++;
|
|
if (cam.transform.rotation.y == 0) zeroVectors++;
|
|
if (cam.transform.rotation.z == 0) zeroVectors++;
|
|
|
|
if (zeroVectors > 1) frustumError = true;
|
|
|
|
if (frustumError){
|
|
Quaternion tRot = cam.transform.rotation;
|
|
if (cam.transform.rotation.x == 0) tRot.x = 0.001f;
|
|
if (cam.transform.rotation.y == 0) tRot.y = 0.001f;
|
|
if (cam.transform.rotation.z == 0) tRot.z = 0.001f;
|
|
cam.transform.rotation = tRot;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void LateUpdate(){
|
|
if (Application.isPlaying){
|
|
if (cameraType == suiCamToolType.shorelineObject){
|
|
if (hasStarted == 0f && Time.time > 0.2f){
|
|
CameraUpdate();
|
|
hasStarted = 1f;
|
|
}
|
|
} else {
|
|
CameraUpdate();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SetCopyCamera(){
|
|
|
|
//if (useCamera != null){
|
|
// copyCam = useCamera;
|
|
if (suimonoModuleObject != null){
|
|
if (suimonoModuleObject.setCamera != null){
|
|
if (suimonoModuleObject.setCameraComponent != null){
|
|
copyCam = suimonoModuleObject.setCameraComponent;
|
|
}
|
|
else {
|
|
copyCam = suimonoModuleObject.setCamera.GetComponent<Camera>();
|
|
}
|
|
}}
|
|
|
|
//}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CameraRender(){
|
|
|
|
//Setup Camera Matrices
|
|
if (cameraType == suiCamToolType.localReflection){
|
|
ReflectionPreRender();
|
|
}
|
|
|
|
//RENDER CAMERA
|
|
cam.targetTexture = renderTexDiff;
|
|
if (Application.isPlaying && cameraType == suiCamToolType.shorelineObject){
|
|
cam.enabled = false;
|
|
|
|
cameraPos.y = 3.0f;
|
|
cam.transform.localPosition = cameraPos;
|
|
|
|
cam.nearClipPlane = 0.01f;
|
|
cam.farClipPlane = 50f;
|
|
|
|
//if (cam.rect.x != 0f && cam.rect.y != 0f){
|
|
cam.Render();
|
|
//}
|
|
|
|
|
|
} else {
|
|
cam.enabled = true;
|
|
}
|
|
|
|
|
|
//Reset Camera Properties
|
|
if (cameraType == suiCamToolType.localReflection) ReflectionPostRender();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void CameraUpdate() {
|
|
|
|
SetCopyCamera();
|
|
|
|
//if (suimonoModuleObject != null){
|
|
// if (suimonoModuleObject.setCameraComponent != null){
|
|
// copyCam = suimonoModuleObject.setCameraComponent;
|
|
// }
|
|
//}
|
|
|
|
|
|
if (copyCam != null && cam != null){
|
|
|
|
//set camera settings
|
|
if (cameraType != suiCamToolType.shorelineObject){
|
|
cam.transform.position = copyCam.transform.position;
|
|
cam.transform.rotation = copyCam.transform.rotation;
|
|
cam.projectionMatrix = copyCam.projectionMatrix;
|
|
cam.fieldOfView = copyCam.fieldOfView;
|
|
}
|
|
|
|
//re-project camera for screen-space effects
|
|
if (cameraOffset != 0.0f){
|
|
cam.transform.Translate(Vector3.forward * cameraOffset);
|
|
}
|
|
|
|
//select rendering path
|
|
if (renderType == suiCamToolRender.automatic){
|
|
usePath = copyCam.actualRenderingPath;
|
|
|
|
//specific settings for transparent camera
|
|
if (cameraType == suiCamToolType.transparent){
|
|
if (copyCam.renderingPath == RenderingPath.Forward){
|
|
usePath = RenderingPath.DeferredLighting;
|
|
} else {
|
|
usePath = copyCam.renderingPath;
|
|
}
|
|
}
|
|
|
|
} else if (renderType == suiCamToolRender.deferredShading){
|
|
usePath = RenderingPath.DeferredShading;
|
|
|
|
} else if (renderType == suiCamToolRender.deferredLighting){
|
|
usePath = RenderingPath.DeferredLighting;
|
|
|
|
} else if (renderType == suiCamToolRender.forward){
|
|
usePath = RenderingPath.Forward;
|
|
}
|
|
|
|
//set effect rendering path
|
|
cam.renderingPath = usePath;
|
|
|
|
|
|
if (renderTexDiff != null){
|
|
|
|
//update texture resolution
|
|
if (resolution != currResolution){
|
|
|
|
if (cameraType == suiCamToolType.shorelineObject){
|
|
shoreObject = transform.parent.gameObject.GetComponent<Suimono.Core.Suimono_ShorelineObject>();
|
|
if (shoreObject != null){
|
|
resolution = shoreObject.useResolution;
|
|
}
|
|
}
|
|
|
|
currResolution = resolution;
|
|
UpdateRenderTex();
|
|
}
|
|
|
|
//render custom normal effects shader
|
|
if (cameraType == suiCamToolType.normals){
|
|
if (suimonoModuleObject.enableAdvancedDistort){
|
|
#if UNITY_5_6_OR_NEWER
|
|
cam.allowHDR = false;
|
|
#else
|
|
cam.hdr = false;
|
|
#endif
|
|
|
|
cam.SetReplacementShader(renderShader,"RenderType");
|
|
CameraRender();
|
|
} else {
|
|
renderTexDiff = null;
|
|
}
|
|
|
|
//render customwake effects shader
|
|
} else if (cameraType == suiCamToolType.wakeEffects){
|
|
if (suimonoModuleObject.enableAdvancedDistort){
|
|
cam.SetReplacementShader(renderShader,"RenderType");
|
|
CameraRender();
|
|
} else {
|
|
renderTexDiff = null;
|
|
}
|
|
|
|
//render transparency effects
|
|
} else if (cameraType == suiCamToolType.transparent){
|
|
if (suimonoModuleObject.enableTransparency){
|
|
CameraRender();
|
|
} else {
|
|
renderTexDiff = null;
|
|
}
|
|
|
|
//render caustics effects
|
|
} else if (cameraType == suiCamToolType.transparentCaustic){
|
|
if (suimonoModuleObject.enableCaustics){
|
|
CameraRender();
|
|
} else {
|
|
renderTexDiff = null;
|
|
}
|
|
|
|
} else {
|
|
CameraRender();
|
|
}
|
|
|
|
|
|
|
|
//pass texture to shader
|
|
if (cameraType == suiCamToolType.transparent){
|
|
Shader.SetGlobalTexture("_suimono_TransTex",renderTexDiff);
|
|
if (!suimonoModuleObject.enableCausticsBlending){
|
|
Shader.SetGlobalTexture("_suimono_CausticTex",renderTexDiff);
|
|
}
|
|
}
|
|
if (cameraType == suiCamToolType.transparentCaustic){
|
|
if (suimonoModuleObject.enableCausticsBlending &&
|
|
suimonoModuleObject.enableCaustics){
|
|
Shader.SetGlobalTexture("_suimono_CausticTex",renderTexDiff);
|
|
}
|
|
|
|
|
|
}
|
|
if (cameraType == suiCamToolType.wakeEffects){
|
|
Shader.SetGlobalTexture("_suimono_WakeTex",renderTexDiff);
|
|
}
|
|
if (cameraType == suiCamToolType.normals){
|
|
Shader.SetGlobalTexture("_suimono_NormalsTex",renderTexDiff);
|
|
}
|
|
if (cameraType == suiCamToolType.depthMask){
|
|
Shader.SetGlobalTexture("_suimono_depthMaskTex",renderTexDiff);
|
|
}
|
|
if (cameraType == suiCamToolType.underwaterMask){
|
|
Shader.SetGlobalTexture("_suimono_underwaterMaskTex",renderTexDiff);
|
|
}
|
|
if (cameraType == suiCamToolType.underwater){
|
|
Shader.SetGlobalTexture("_suimono_underwaterTex",renderTexDiff);
|
|
}
|
|
if (cameraType == suiCamToolType.localReflection){
|
|
if (surfaceRenderer != null) surfaceRenderer.sharedMaterial.SetTexture("_ReflectionTex",renderTexDiff);
|
|
}
|
|
if (cameraType == suiCamToolType.shorelineObject){
|
|
if (surfaceRenderer != null) surfaceRenderer.sharedMaterial.SetTexture("_MainTex",renderTexDiff);
|
|
}
|
|
if (cameraType == suiCamToolType.shorelineCapture){
|
|
Shader.SetGlobalTexture("_suimono_shorelineTex",renderTexDiff);
|
|
}
|
|
|
|
} else {
|
|
UpdateRenderTex();
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UpdateRenderTex(){
|
|
|
|
if (resolution < 4) resolution = 4;
|
|
|
|
if (renderTexDiff != null){
|
|
if (cam != null) cam.targetTexture = null;
|
|
DestroyImmediate(renderTexDiff);
|
|
}
|
|
//renderTexDiff = new RenderTexture(resolution,resolution,24,RenderTextureFormat.ARGBHalf,RenderTextureReadWrite.Linear);
|
|
//renderTexDiff = new RenderTexture(resolution,resolution,24,RenderTextureFormat.DefaultHDR,RenderTextureReadWrite.Linear);
|
|
//renderTexDiff = new RenderTexture(resolution,resolution,24,RenderTextureFormat.ARGBFloat,RenderTextureReadWrite.Linear);
|
|
renderTexDiff = new RenderTexture(resolution,resolution,24,RenderTextureFormat.ARGBFloat,RenderTextureReadWrite.Linear);
|
|
//renderTexDiff = new RenderTexture(resolution,resolution,24,RenderTextureFormat.ARGB4444,RenderTextureReadWrite.sRGB);
|
|
|
|
#if UNITY_5_4_OR_NEWER
|
|
renderTexDiff.dimension = TextureDimension.Tex2D;
|
|
#else
|
|
renderTexDiff.isCubemap = false;
|
|
#endif
|
|
|
|
#if UNITY_2017_1_OR_NEWER
|
|
renderTexDiff.autoGenerateMips = false;
|
|
#else
|
|
renderTexDiff.generateMips = false;
|
|
#endif
|
|
renderTexDiff.anisoLevel = 1;
|
|
renderTexDiff.filterMode = FilterMode.Trilinear;
|
|
renderTexDiff.wrapMode = TextureWrapMode.Clamp;
|
|
}
|
|
|
|
|
|
|
|
void ReflectionPreRender(){
|
|
|
|
// find out the reflection plane: position and normal in world space
|
|
pos = transform.parent.position;
|
|
|
|
if (isUnderwater){
|
|
normal = -transform.parent.transform.up; //underwater
|
|
} else {
|
|
normal = transform.parent.transform.up; //above water
|
|
}
|
|
|
|
//set camera properties
|
|
cam.CopyFrom(copyCam);
|
|
cam.backgroundColor = clearFlagColor;
|
|
|
|
//turn hdr off
|
|
if (hdrMode == suiCamHdrMode.off){
|
|
#if UNITY_5_6_OR_NEWER
|
|
cam.allowHDR = false;
|
|
#else
|
|
cam.hdr = false;
|
|
#endif
|
|
|
|
} else if (hdrMode == suiCamHdrMode.on){
|
|
#if UNITY_5_6_OR_NEWER
|
|
cam.allowHDR = true;
|
|
#else
|
|
cam.hdr = true;
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
if (isUnderwater){
|
|
cam.farClipPlane = 3;
|
|
cam.clearFlags = CameraClearFlags.Color;
|
|
cam.depthTextureMode = DepthTextureMode.Depth;
|
|
} else {
|
|
//cam.farClipPlane = reflectionDistance;
|
|
if (clearMode != suiCamClearFlags.automatic){
|
|
if (clearMode == suiCamClearFlags.skybox) cam.clearFlags = CameraClearFlags.Skybox;
|
|
if (clearMode == suiCamClearFlags.color){
|
|
cam.clearFlags = CameraClearFlags.Color;
|
|
cam.backgroundColor = clearFlagColor;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//render transparency effects
|
|
if (cameraType == suiCamToolType.localReflection){
|
|
if (renderShader != null){
|
|
cam.SetReplacementShader(renderShader,null);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
cam.cullingMask = setLayers;
|
|
|
|
// Render reflection
|
|
// Reflect camera around reflection plane
|
|
d = -Vector3.Dot (normal, pos) - clipPlaneOffset;
|
|
reflectionPlane = new Vector4(normal.x, normal.y-reflectionOffset, normal.z, d);
|
|
|
|
reflection = Matrix4x4.zero;
|
|
reflection = Set_CalculateReflectionMatrix (reflectionPlane);
|
|
|
|
oldpos = copyCam.transform.position;
|
|
newpos = reflection.MultiplyPoint( oldpos );
|
|
cam.worldToCameraMatrix = copyCam.worldToCameraMatrix * reflection;
|
|
|
|
// Setup oblique projection matrix so that near plane is our reflection
|
|
// plane. This way we clip everything below/above it for free.
|
|
clipPlane = Set_CameraSpacePlane(cam, pos, normal, 1f);
|
|
projection = copyCam.projectionMatrix;
|
|
projection = Set_CalculateObliqueMatrix (clipPlane);
|
|
cam.projectionMatrix = projection;
|
|
|
|
GL.invertCulling = true;
|
|
|
|
cam.transform.position = newpos;
|
|
euler = copyCam.transform.eulerAngles;
|
|
cam.transform.eulerAngles = new Vector3(0f, euler.y, euler.z);
|
|
}
|
|
|
|
|
|
void ReflectionPostRender(){
|
|
cam.transform.position = oldpos;
|
|
GL.invertCulling = false;
|
|
scaleOffset = Matrix4x4.TRS(new Vector3(0.5f,0.5f,0.5f), Quaternion.identity, new Vector3(0.5f,0.5f,0.5f) );
|
|
scale = transform.lossyScale;
|
|
mtx = transform.localToWorldMatrix * Matrix4x4.Scale(new Vector3(1.0f/scale.x, -1.0f/scale.y, 1.0f/scale.z) );
|
|
mtx = scaleOffset * copyCam.projectionMatrix * copyCam.worldToCameraMatrix * mtx;
|
|
}
|
|
|
|
|
|
public float Set_sgn(float a){
|
|
if (a > 0.0f) return 1.0f;
|
|
if (a < 0.0f) return -1.0f;
|
|
return 0.0f;
|
|
}
|
|
|
|
|
|
public Vector4 Set_CameraSpacePlane (Camera cm, Vector3 pos, Vector3 normal, float sideSign) {
|
|
offsetPos = pos + normal * (clipPlaneOffset);
|
|
m = cm.worldToCameraMatrix;
|
|
cpos = m.MultiplyPoint( offsetPos );
|
|
cnormal = m.MultiplyVector( normal ).normalized * sideSign;
|
|
return new Vector4( cnormal.x, cnormal.y, cnormal.z, -Vector3.Dot(cpos,cnormal) );
|
|
}
|
|
|
|
|
|
public Matrix4x4 Set_CalculateObliqueMatrix (Vector4 clipPlane) {
|
|
proj = copyCam.projectionMatrix;
|
|
q = proj.inverse * new Vector4(Set_sgn(clipPlane.x),Set_sgn(clipPlane.y),1f,1f);
|
|
c = clipPlane * (2f / (Vector4.Dot (clipPlane, q)));
|
|
proj[2] = c.x - proj[3];
|
|
proj[6] = c.y - proj[7];
|
|
proj[10] = c.z - proj[11];
|
|
proj[14] = c.w - proj[15];
|
|
return proj;
|
|
}
|
|
|
|
|
|
public Matrix4x4 Set_CalculateReflectionMatrix (Vector4 plane) {
|
|
|
|
var reflectionMat = Matrix4x4.zero;
|
|
|
|
reflectionMat.m00 = (1F - 2F*plane[0]*plane[0]);
|
|
reflectionMat.m01 = ( - 2F*plane[0]*plane[1]);
|
|
reflectionMat.m02 = ( - 2F*plane[0]*plane[2]);
|
|
reflectionMat.m03 = ( - 2F*plane[3]*plane[0]);
|
|
|
|
reflectionMat.m10 = ( - 2F*plane[1]*plane[0]);
|
|
reflectionMat.m11 = (1F - 2F*plane[1]*plane[1]);
|
|
reflectionMat.m12 = ( - 2F*plane[1]*plane[2]);
|
|
reflectionMat.m13 = ( - 2F*plane[3]*plane[1]);
|
|
|
|
reflectionMat.m20 = ( - 2F*plane[2]*plane[0]);
|
|
reflectionMat.m21 = ( - 2F*plane[2]*plane[1]);
|
|
reflectionMat.m22 = (1F - 2F*plane[2]*plane[2]);
|
|
reflectionMat.m23 = ( - 2F*plane[3]*plane[2]);
|
|
|
|
reflectionMat.m30 = 0F;
|
|
reflectionMat.m31 = 0F;
|
|
reflectionMat.m32 = 0F;
|
|
reflectionMat.m33 = 1F;
|
|
|
|
return reflectionMat;
|
|
}
|
|
|
|
|
|
|
|
}
|
|
} |