TG9six 03a642d635 first push
first push
2025-09-06 17:17:39 +04:00

205 lines
6.8 KiB
C#

//------------------------------------------------------------------------------------------------------------------
// Volumetric Fog & Mist 2
// Created by Kronnect
//------------------------------------------------------------------------------------------------------------------
using UnityEngine;
using UnityEngine.Rendering.Universal;
namespace VolumetricFogAndMist2 {
public partial class VolumetricFog : MonoBehaviour {
const string SURFACE_CAM_NAME = "SurfaceCam";
public enum HeightmapCaptureResolution {
_64 = 64,
_128 = 128,
_256 = 256,
_512 = 512,
_1024 = 1024
}
RenderTexture rt;
Camera cam;
int camStartFrameCount;
Matrix4x4 camMatrix;
Vector3 lastCamPos;
void DisposeSurfaceCapture() {
DisableSurfaceCapture();
if (rt != null) {
rt.Release();
DestroyImmediate(rt);
}
}
void CheckSurfaceCapture() {
if (cam == null) {
Transform childCam = transform.Find(SURFACE_CAM_NAME);
if (childCam != null) {
cam = childCam.GetComponent<Camera>();
if (cam == null) {
DestroyImmediate(childCam.gameObject);
}
}
}
}
void DisableSurfaceCapture() {
if (cam != null) {
cam.enabled = false;
}
}
void SurfaceCaptureSupportCheck() {
Transform childCam = transform.Find(SURFACE_CAM_NAME);
if (childCam != null) {
cam = childCam.GetComponent<Camera>();
}
if (!activeProfile.terrainFit) {
DisposeSurfaceCapture();
return;
}
if (cam == null) {
if (childCam != null) {
DestroyImmediate(childCam.gameObject);
}
if (cam == null) {
GameObject camObj = new GameObject(SURFACE_CAM_NAME, typeof(Camera));
camObj.transform.SetParent(transform, false);
cam = camObj.GetComponent<Camera>();
cam.depthTextureMode = DepthTextureMode.None;
cam.clearFlags = CameraClearFlags.Depth;
cam.allowHDR = false;
cam.allowMSAA = false;
}
cam.stereoTargetEye = StereoTargetEyeMask.None;
}
UniversalAdditionalCameraData camData = cam.GetComponent<UniversalAdditionalCameraData>();
if (camData != null) {
camData.dithering = false;
camData.renderPostProcessing = false;
camData.renderShadows = false;
camData.requiresColorTexture = false;
camData.requiresDepthTexture = false;
camData.stopNaN = false;
}
cam.orthographic = true;
cam.nearClipPlane = 1f;
if (rt != null && rt.width != (int)activeProfile.terrainFitResolution) {
if (cam.targetTexture == rt) {
cam.targetTexture = null;
}
rt.Release();
DestroyImmediate(rt);
}
if (rt == null) {
rt = new RenderTexture((int)activeProfile.terrainFitResolution, (int)activeProfile.terrainFitResolution, 24, RenderTextureFormat.Depth);
rt.antiAliasing = 1;
}
int thisLayer = 1 << gameObject.layer;
if ((activeProfile.terrainLayerMask & thisLayer) != 0) {
activeProfile.terrainLayerMask &= ~thisLayer; // exclude fog layer
}
cam.cullingMask = activeProfile.terrainLayerMask;
cam.targetTexture = rt;
if (activeProfile.terrainFit) {
ScheduleShadowCapture();
} else {
cam.enabled = false;
}
}
/// <summary>
/// Updates shadows on this volumetric fog
/// </summary>
public void ScheduleShadowCapture() {
if (cam != null) {
cam.enabled = true;
camStartFrameCount = Time.frameCount;
if (!fogMat.IsKeywordEnabled(ShaderParams.SKW_SURFACE)) {
fogMat.EnableKeyword(ShaderParams.SKW_SURFACE);
}
}
}
void SetupCameraCaptureMatrix() {
Vector3 camPos = transform.position + new Vector3(0, transform.lossyScale.y * 0.51f, 0);
cam.farClipPlane = 10000;
cam.transform.position = camPos;
cam.transform.eulerAngles = new Vector3(90, 0, 0);
Vector3 size = transform.lossyScale;
cam.orthographicSize = Mathf.Max(size.x * 0.5f, size.z * 0.5f);
ComputeSufaceTransform(cam.projectionMatrix, cam.worldToCameraMatrix);
fogMat.SetMatrix(ShaderParams.SurfaceCaptureMatrix, camMatrix);
fogMat.SetTexture(ShaderParams.SurfaceDepthTexture, cam.targetTexture);
fogMat.SetVector(ShaderParams.SurfaceData, new Vector4(camPos.y, activeProfile.terrainFogHeight, activeProfile.terrainFogMinAltitude, activeProfile.terrainFogMaxAltitude));
}
void SurfaceCaptureUpdate() {
if (!activeProfile.terrainFit) return;
if (cam == null) return;
SetupCameraCaptureMatrix();
if (!cam.enabled && lastCamPos != cam.transform.position) {
lastCamPos = cam.transform.position;
ScheduleShadowCapture();
} else if (Time.frameCount > camStartFrameCount + 1 && Application.isPlaying) {
cam.enabled = false;
}
}
static Matrix4x4 identityMatrix = Matrix4x4.identity;
void ComputeSufaceTransform(Matrix4x4 proj, Matrix4x4 view) {
// Currently CullResults ComputeDirectionalShadowMatricesAndCullingPrimitives doesn't
// apply z reversal to projection matrix. We need to do it manually here.
if (SystemInfo.usesReversedZBuffer) {
proj.m20 = -proj.m20;
proj.m21 = -proj.m21;
proj.m22 = -proj.m22;
proj.m23 = -proj.m23;
}
Matrix4x4 worldToShadow = proj * view;
var textureScaleAndBias = identityMatrix;
textureScaleAndBias.m00 = 0.5f;
textureScaleAndBias.m11 = 0.5f;
textureScaleAndBias.m22 = 0.5f;
textureScaleAndBias.m03 = 0.5f;
textureScaleAndBias.m23 = 0.5f;
textureScaleAndBias.m13 = 0.5f;
// Apply texture scale and offset to save a MAD in shader.
camMatrix = textureScaleAndBias * worldToShadow;
}
}
}