Raymarching Cleanup

Removed redundant code from raymarching implementation
Moved last remaining raymarching variable (Extinction) to environment settings
This commit is contained in:
Reinier Vens 2022-07-13 04:15:20 +01:00
commit d61d2f19ed
150 changed files with 187 additions and 8921 deletions

View file

@ -27,6 +27,7 @@ public class NebulaSettings
[JsonProperty("fogBlend"), Key(5)] public float FloorBlend;
[JsonProperty("cloudBlend"), Key(6)] public float PatchBlend;
[JsonProperty("luminance"), Key(7)] public float Luminance;
[JsonProperty("extinction"), Key(13)] public float Extinction;
[JsonProperty("tintExponent"), Key(8)] public float TintExponent;
[JsonProperty("tintLodExponent"), Key(9)] public float TintLodExponent;
[JsonProperty("safetyDistance"), Key(10)] public float SafetyDistance;

View file

@ -0,0 +1,159 @@
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
/// <summary>
/// Based on github.com/yangrc1234/VolumeCloud
/// Generate halton sequence.
/// code from unity post-processing stack.
/// </summary>
public class HaltonSequence {
public int radix = 3;
private int storedIndex = 0;
public float Get() {
float result = 0f;
float fraction = 1f / (float)radix;
int index = storedIndex;
while (index > 0) {
result += (float)(index % radix) * fraction;
index /= radix;
fraction /= (float)radix;
}
storedIndex++;
return result;
}
}
public enum Quality {
Low,
Normal, //Low sample count
High, //High sample count and high shadow sample count.
Ultra
}
/// <summary>
/// Cloud renderer post processing.
/// </summary>
[ImageEffectAllowedInSceneView]
[ExecuteInEditMode,RequireComponent(typeof(Camera))]
[ImageEffectOpaque]
public class VolumeCloudRenderer : EffectBase {
[Header("Render Settings")]
[Range(0, 2)]
public int downSample = 1;
public Quality quality;
private Material mat;
private RenderTexture[] fullBuffer;
private int fullBufferIndex;
private RenderTexture undersampleBuffer;
private Matrix4x4 prevV;
private Camera mcam;
private HaltonSequence sequence = new HaltonSequence() { radix = 3 };
// The index of 4x4 pixels.
private int frameIndex = 0;
private float bayerOffsetIndex = 0;
private bool firstFrame = true;
[SerializeField]
private Shader cloudShader;
void EnsureMaterial(bool force = false) {
if (mat == null || force) {
mat = new Material(cloudShader);
}
}
private void OnDestroy() {
if (this.fullBuffer != null) {
for (int i = 0; i < fullBuffer.Length; i++) {
fullBuffer[i].Release();
fullBuffer[i] = null;
}
}
if (this.undersampleBuffer != null) {
this.undersampleBuffer.Release();
this.undersampleBuffer = null;
}
}
private void Start() {
this.EnsureMaterial(true);
}
[ImageEffectOpaque]
private void OnRenderImage(RenderTexture source, RenderTexture destination) {
if (cloudShader == null) {
Graphics.Blit(source, destination);
return;
}
mcam = GetComponent<Camera>();
var width = mcam.pixelWidth >> downSample;
var height = mcam.pixelHeight >> downSample;
this.EnsureMaterial();
EnsureArray(ref fullBuffer, 2);
firstFrame |= EnsureRenderTarget(ref fullBuffer[0], width, height, RenderTextureFormat.ARGBFloat, FilterMode.Bilinear);
firstFrame |= EnsureRenderTarget(ref fullBuffer[1], width, height, RenderTextureFormat.ARGBFloat, FilterMode.Bilinear);
firstFrame |= EnsureRenderTarget(ref undersampleBuffer, width , height, RenderTextureFormat.ARGBFloat, FilterMode.Bilinear);
frameIndex = (frameIndex + 1)% 16;
fullBufferIndex = (fullBufferIndex + 1) % 2;
/* Some code is from playdead TAA. */
//1. Pass1, Render a undersampled buffer. The buffer is dithered using bayer matrix(every 3x3 pixel) and halton sequence.
//If it's first frame, force a high quality sample to make the initial history buffer good enough.
if (firstFrame || quality == Quality.Ultra) {
mat.EnableKeyword("ULTRA_QUALITY");
mat.DisableKeyword("HIGH_QUALITY");
mat.DisableKeyword("MEDIUM_QUALITY");
mat.DisableKeyword("LOW_QUALITY");
} else if (quality == Quality.High) {
mat.DisableKeyword("ULTRA_QUALITY");
mat.EnableKeyword("HIGH_QUALITY");
mat.DisableKeyword("MEDIUM_QUALITY");
mat.DisableKeyword("LOW_QUALITY");
} else if (quality == Quality.Normal) {
mat.DisableKeyword("ULTRA_QUALITY");
mat.DisableKeyword("HIGH_QUALITY");
mat.EnableKeyword("MEDIUM_QUALITY");
mat.DisableKeyword("LOW_QUALITY");
} else if (quality == Quality.Low) {
mat.DisableKeyword("ULTRA_QUALITY");
mat.DisableKeyword("HIGH_QUALITY");
mat.DisableKeyword("MEDIUM_QUALITY");
mat.EnableKeyword("LOW_QUALITY");
}
mat.SetVector("_ProjectionExtents", mcam.GetProjectionExtents());
mat.SetFloat("_RaymarchOffset", sequence.Get());
mat.SetVector("_TexelSize", undersampleBuffer.texelSize);
Graphics.Blit(null, undersampleBuffer, mat, 0);
//2. Pass 2, blend undersampled image with history buffer to new buffer.
mat.SetTexture("_UndersampleCloudTex", undersampleBuffer);
mat.SetMatrix("_PrevVP", GL.GetGPUProjectionMatrix(mcam.projectionMatrix,false) * prevV);
mat.SetVector("_ProjectionExtents", mcam.GetProjectionExtents());
if (firstFrame) { //Wait, is this the first frame? If it is, the history buffer is empty yet. It will cause glitch if we use it directly. Fill it using the undersample buffer.
Graphics.Blit(undersampleBuffer, fullBuffer[fullBufferIndex]);
}
Graphics.Blit(fullBuffer[fullBufferIndex], fullBuffer[fullBufferIndex ^ 1], mat, 1);
//3. Pass3, Calculate lighting, blend final cloud image with final image.
mat.SetTexture("_CloudTex", fullBuffer[fullBufferIndex ^ 1]);
Graphics.Blit(source, destination, mat, 2);
//4. Cleanup
prevV = mcam.worldToCameraMatrix;
firstFrame = false;
}
}

View file

@ -0,0 +1,19 @@
fileFormatVersion: 2
guid: 9f1db61281524fb40bc9a1f6acce6baf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- cloudShader: {fileID: 4800000, guid: 84e97169589c5e94e8521fe4deb2e3f8, type: 3}
- configuration: {fileID: 11400000, guid: a15886e93ac3e7847861da392782f13d, type: 2}
- heightPreprocessShader: {fileID: 7200000, guid: 40276bd53f35a694e8d4e025ca310775,
type: 3}
- cloudHeightProcessShader: {fileID: 4800000, guid: b80bf04ca56d3d642a6b925cff3f5ddf,
type: 3}
- heightLutTexture: {instanceID: 0}
- hiHeightTexture: {instanceID: 0}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -17,12 +17,12 @@ using static Unity.Mathematics.noise;
[RequireComponent( typeof( Camera ) )]
public class VolumeSampling : MonoBehaviour
{
public Material VolMaterial;
//public Material VolMaterial;
public Transform GridTransform;
public GameSettings Settings;
//public int DownsampleBlurMask = 2;
private Camera _camera;
private RenderBuffer[] _mrt;
// private Camera _camera;
// private RenderBuffer[] _mrt;
private Texture2D _blurMask;
private Texture2D _disabledBlurMask;
private float _flowScroll;
@ -38,17 +38,13 @@ public class VolumeSampling : MonoBehaviour
private void Start()
{
//Debug.Log($"Supported MRT count: {SystemInfo.supportedRenderTargetCount}");
_camera = GetComponent<Camera>();
_mrt = new RenderBuffer[2];
// _camera = GetComponent<Camera>();
// _mrt = new RenderBuffer[2];
//_blurMask = new RenderTexture(Screen.width, Screen.height, 0, GraphicsFormat.R8_UNorm);
_blurMask = Color.white.ToTexture();
_disabledBlurMask = Color.black.ToTexture();
}
private void OnPreRender()
{
}
//[ImageEffectOpaque]
void Update()
{
@ -97,6 +93,7 @@ public class VolumeSampling : MonoBehaviour
Shader.SetGlobalFloat("_NebulaFloorBlend", Settings.DefaultEnvironment.Nebula.FloorBlend);
Shader.SetGlobalFloat("_NebulaPatchBlend", Settings.DefaultEnvironment.Nebula.PatchBlend);
Shader.SetGlobalFloat("_NebulaLuminance", Settings.DefaultEnvironment.Nebula.Luminance);
Shader.SetGlobalFloat("_ExtinctionCoefficient", Settings.DefaultEnvironment.Nebula.Extinction);
Shader.SetGlobalFloat("_TintExponent", Settings.DefaultEnvironment.Nebula.TintExponent);
Shader.SetGlobalFloat("_TintLodExponent", Settings.DefaultEnvironment.Nebula.TintLodExponent);
Shader.SetGlobalFloat("_SafetyDistance", Settings.DefaultEnvironment.Nebula.SafetyDistance);