296 lines
9.0 KiB
C#
296 lines
9.0 KiB
C#
using System;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace Artngame.SKYMASTER.PlanetCreator.Atmosphere
|
|
{
|
|
[RequireComponent(typeof(Camera))]
|
|
[ExecuteInEditMode]
|
|
public class AtmosphericScatter : MonoBehaviour
|
|
{
|
|
public bool enableVR;
|
|
|
|
[Range(0f, 1f)]
|
|
public float imageFXBlend = 1f;
|
|
|
|
public int downscale;
|
|
|
|
public float SCALE = 1000f;
|
|
|
|
private const int TRANSMITTANCE_WIDTH = 256;
|
|
|
|
private const int TRANSMITTANCE_HEIGHT = 64;
|
|
|
|
private const int TRANSMITTANCE_CHANNELS = 3;
|
|
|
|
private const int IRRADIANCE_WIDTH = 64;
|
|
|
|
private const int IRRADIANCE_HEIGHT = 16;
|
|
|
|
private const int IRRADIANCE_CHANNELS = 3;
|
|
|
|
private const int INSCATTER_WIDTH = 256;
|
|
|
|
private const int INSCATTER_HEIGHT = 128;
|
|
|
|
private const int INSCATTER_DEPTH = 32;
|
|
|
|
private const int INSCATTER_CHANNELS = 4;
|
|
|
|
public GameObject m_sun;
|
|
|
|
public Vector3 m_betaR = new Vector3(0.0058f, 0.0135f, 0.0331f);
|
|
|
|
public float m_mieG = 0.75f;
|
|
|
|
public float m_sunIntensity = 100f;
|
|
|
|
public ComputeShader m_writeData;
|
|
|
|
public Vector3 EarthPosition;
|
|
|
|
public float RG = 6360f;
|
|
|
|
public float RT = 6420f;
|
|
|
|
public float RL = 6421f;
|
|
|
|
public float HR = 8f;
|
|
|
|
public float HM = 1.2f;
|
|
|
|
private CommandBuffer lightingBuffer;
|
|
|
|
private Camera camera;
|
|
|
|
public float MinViewDistance = 3000f;
|
|
|
|
public RenderTexture m_transmittance;
|
|
|
|
public RenderTexture m_inscatter;
|
|
|
|
public RenderTexture m_irradiance;
|
|
|
|
public Material m_atmosphereImageEffect;
|
|
|
|
private Matrix4x4 left_world_from_view;
|
|
|
|
private Matrix4x4 right_world_from_view;
|
|
|
|
private Matrix4x4 left_screen_from_view;
|
|
|
|
private Matrix4x4 right_screen_from_view;
|
|
|
|
private Matrix4x4 left_view_from_screen;
|
|
|
|
private Matrix4x4 right_view_from_screen;
|
|
|
|
private void Start()
|
|
{
|
|
Application.runInBackground = false;
|
|
lightingBuffer = new CommandBuffer();
|
|
camera = GetComponent<Camera>();
|
|
if (imageFXBlend < 1f)
|
|
{
|
|
camera.AddCommandBuffer(CameraEvent.AfterImageEffects, lightingBuffer);
|
|
}
|
|
else
|
|
{
|
|
camera.AddCommandBuffer(CameraEvent.BeforeLighting, lightingBuffer);
|
|
}
|
|
camera.depthTextureMode = DepthTextureMode.DepthNormals;
|
|
CreateTextures();
|
|
CopyDataToTextures();
|
|
InitMaterial(m_atmosphereImageEffect);
|
|
UpdateMaterialTextures(m_atmosphereImageEffect);
|
|
}
|
|
|
|
private void CreateTextures()
|
|
{
|
|
m_transmittance = new RenderTexture(256, 64, 0, RenderTextureFormat.ARGBHalf)
|
|
{
|
|
wrapMode = TextureWrapMode.Clamp,
|
|
filterMode = FilterMode.Bilinear,
|
|
enableRandomWrite = true
|
|
};
|
|
m_transmittance.Create();
|
|
m_inscatter = new RenderTexture(256, 128, 0, RenderTextureFormat.ARGBHalf)
|
|
{
|
|
volumeDepth = 32,
|
|
wrapMode = TextureWrapMode.Clamp,
|
|
filterMode = FilterMode.Bilinear,
|
|
dimension = TextureDimension.Tex3D,
|
|
enableRandomWrite = true
|
|
};
|
|
m_inscatter.Create();
|
|
m_irradiance = new RenderTexture(64, 16, 0, RenderTextureFormat.ARGBHalf)
|
|
{
|
|
wrapMode = TextureWrapMode.Clamp,
|
|
filterMode = FilterMode.Bilinear,
|
|
enableRandomWrite = true
|
|
};
|
|
m_irradiance.Create();
|
|
}
|
|
|
|
private void CopyDataToTextures()
|
|
{
|
|
string path = Application.streamingAssetsPath + "/Textures/transmittance.raw";
|
|
ComputeBuffer computeBuffer = new ComputeBuffer(16384, 12);
|
|
CBUtility.WriteIntoRenderTexture(m_transmittance, 3, path, computeBuffer, m_writeData);
|
|
computeBuffer.Release();
|
|
path = Application.streamingAssetsPath + "/Textures/inscatter.raw";
|
|
computeBuffer = new ComputeBuffer(1048576, 16);
|
|
CBUtility.WriteIntoRenderTexture(m_inscatter, 4, path, computeBuffer, m_writeData);
|
|
computeBuffer.Release();
|
|
path = Application.streamingAssetsPath + "/Textures/irradiance.raw";
|
|
computeBuffer = new ComputeBuffer(1024, 12);
|
|
CBUtility.WriteIntoRenderTexture(m_irradiance, 3, path, computeBuffer, m_writeData);
|
|
computeBuffer.Release();
|
|
}
|
|
|
|
private void LateUpdate()
|
|
{
|
|
UpdateMat(m_atmosphereImageEffect);
|
|
camera.farClipPlane = Mathf.Max(MinViewDistance, (base.transform.position - base.transform.position.normalized * (RG * SCALE / 3f)).magnitude);
|
|
UpdateRenderBuffer();
|
|
}
|
|
|
|
private void UpdateRenderBuffer()
|
|
{
|
|
lightingBuffer.Clear();
|
|
lightingBuffer.SetGlobalFloat("imageFXBlend", imageFXBlend);
|
|
Matrix4x4 projectionMatrix = camera.projectionMatrix;
|
|
Vector4 value = new Vector4(1f / projectionMatrix[0], 1f / projectionMatrix[5], 1f, 1f);
|
|
lightingBuffer.SetGlobalVector("_CamScreenDir", value);
|
|
Matrix4x4 inverse = (camera.projectionMatrix * camera.worldToCameraMatrix).inverse;
|
|
lightingBuffer.SetGlobalMatrix("_ViewProjectInverse", inverse);
|
|
Matrix4x4 inverse2 = camera.cameraToWorldMatrix.inverse;
|
|
lightingBuffer.SetGlobalMatrix("_CameraInv", inverse2);
|
|
lightingBuffer.SetGlobalMatrix("_ViewMatrix", camera.worldToCameraMatrix);
|
|
lightingBuffer.SetGlobalFloat("_FarPlane", camera.farClipPlane);
|
|
lightingBuffer.SetGlobalTexture("_CameraDepthNormalsTexture", BuiltinRenderTextureType.GBuffer2);
|
|
if (camera.stereoEnabled)
|
|
{
|
|
left_world_from_view = camera.GetStereoViewMatrix(Camera.StereoscopicEye.Left).inverse;
|
|
right_world_from_view = camera.GetStereoViewMatrix(Camera.StereoscopicEye.Right).inverse;
|
|
left_screen_from_view = camera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Left);
|
|
right_screen_from_view = camera.GetStereoProjectionMatrix(Camera.StereoscopicEye.Right);
|
|
left_view_from_screen = GL.GetGPUProjectionMatrix(left_screen_from_view, renderIntoTexture: true).inverse;
|
|
right_view_from_screen = GL.GetGPUProjectionMatrix(right_screen_from_view, renderIntoTexture: true).inverse;
|
|
left_view_from_screen[1, 1] *= -1f;
|
|
right_view_from_screen[1, 1] *= -1f;
|
|
lightingBuffer.SetGlobalMatrix("_LeftWorldFromView", left_world_from_view);
|
|
lightingBuffer.SetGlobalMatrix("_RightWorldFromView", right_world_from_view);
|
|
lightingBuffer.SetGlobalMatrix("_LeftViewFromScreen", left_view_from_screen);
|
|
lightingBuffer.SetGlobalMatrix("_RightViewFromScreen", right_view_from_screen);
|
|
}
|
|
else
|
|
{
|
|
left_world_from_view = camera.cameraToWorldMatrix;
|
|
left_screen_from_view = camera.projectionMatrix;
|
|
left_view_from_screen = GL.GetGPUProjectionMatrix(left_screen_from_view, renderIntoTexture: true).inverse;
|
|
left_view_from_screen[1, 1] *= -1f;
|
|
lightingBuffer.SetGlobalMatrix("_LeftWorldFromView", left_world_from_view);
|
|
lightingBuffer.SetGlobalMatrix("_LeftViewFromScreen", left_view_from_screen);
|
|
}
|
|
RenderTargetIdentifier source = new RenderTargetIdentifier(BuiltinRenderTextureType.GBuffer0);
|
|
if (imageFXBlend < 1f)
|
|
{
|
|
source = new RenderTargetIdentifier(BuiltinRenderTextureType.CameraTarget);
|
|
}
|
|
RenderTargetIdentifier dest = new RenderTargetIdentifier(BuiltinRenderTextureType.CameraTarget);
|
|
int num = Shader.PropertyToID("_DownsampledTarget");
|
|
lightingBuffer.GetTemporaryRT(num, camera.pixelWidth / Mathf.Max(1, downscale), camera.pixelHeight / Mathf.Max(1, downscale), 0, FilterMode.Bilinear, RenderTextureFormat.ARGBFloat);
|
|
if (imageFXBlend < 1f)
|
|
{
|
|
lightingBuffer.SetGlobalFloat("invertY", 1f);
|
|
if (enableVR)
|
|
{
|
|
lightingBuffer.Blit(source, num);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lightingBuffer.SetGlobalFloat("invertY", 0f);
|
|
if (enableVR)
|
|
{
|
|
lightingBuffer.Blit(source, num, m_atmosphereImageEffect);
|
|
}
|
|
}
|
|
if (!enableVR)
|
|
{
|
|
lightingBuffer.Blit(source, num, m_atmosphereImageEffect);
|
|
}
|
|
if (imageFXBlend < 1f)
|
|
{
|
|
if (!enableVR)
|
|
{
|
|
lightingBuffer.SetGlobalFloat("invertY", 0f);
|
|
}
|
|
lightingBuffer.Blit(num, dest, m_atmosphereImageEffect);
|
|
}
|
|
else
|
|
{
|
|
lightingBuffer.Blit(num, dest);
|
|
}
|
|
lightingBuffer.ReleaseTemporaryRT(num);
|
|
}
|
|
|
|
private void UpdateMat(Material mat)
|
|
{
|
|
mat.SetVector("betaR", m_betaR / SCALE);
|
|
mat.SetFloat("mieG", m_mieG);
|
|
mat.SetVector("SUN_DIR", m_sun.transform.forward * -1f);
|
|
mat.SetFloat("SUN_INTENSITY", m_sunIntensity);
|
|
mat.SetVector("EARTH_POS", EarthPosition);
|
|
mat.SetVector("CAMERA_POS", base.transform.position);
|
|
mat.SetVector("betaMSca", Vector4.one * 0.004f / SCALE);
|
|
mat.SetVector("betaMEx", Vector4.one * 0.004f * 0.9f / SCALE);
|
|
mat.SetFloat("SCALE", SCALE);
|
|
mat.SetFloat("Rg", RG * SCALE);
|
|
mat.SetFloat("Rt", RT * SCALE);
|
|
mat.SetFloat("Rl", RL * SCALE);
|
|
mat.SetFloat("HR", HR * SCALE);
|
|
mat.SetFloat("HM", HM * SCALE);
|
|
}
|
|
|
|
private void UpdateMaterialTextures(Material mat)
|
|
{
|
|
mat.SetTexture("_Transmittance", m_transmittance);
|
|
mat.SetTexture("_Inscatter", m_inscatter);
|
|
mat.SetTexture("_Irradiance", m_irradiance);
|
|
}
|
|
|
|
private void InitMaterial(Material mat)
|
|
{
|
|
mat.SetFloat("M_PI", MathF.PI);
|
|
mat.SetFloat("SCALE", SCALE);
|
|
mat.SetFloat("Rg", 6360f * SCALE);
|
|
mat.SetFloat("Rt", 6420f * SCALE);
|
|
mat.SetFloat("Rl", 6421f * SCALE);
|
|
mat.SetFloat("RES_R", 32f);
|
|
mat.SetFloat("RES_MU", 128f);
|
|
mat.SetFloat("RES_MU_S", 32f);
|
|
mat.SetFloat("RES_NU", 8f);
|
|
mat.SetFloat("SUN_INTENSITY", m_sunIntensity);
|
|
mat.SetVector("SUN_DIR", m_sun.transform.forward * -1f);
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if ((bool)m_transmittance)
|
|
{
|
|
m_irradiance.Release();
|
|
}
|
|
if ((bool)m_transmittance)
|
|
{
|
|
m_transmittance.Release();
|
|
}
|
|
if ((bool)m_inscatter)
|
|
{
|
|
m_inscatter.Release();
|
|
}
|
|
}
|
|
}
|
|
}
|