209 lines
9.0 KiB
C#
209 lines
9.0 KiB
C#
using UnityEngine;
|
||
using UnityEngine.Experimental.Rendering;
|
||
using UnityEngine.Rendering;
|
||
|
||
|
||
namespace Lux_SRP_GrassDisplacement
|
||
{
|
||
public class GrassDisplacementRenderFeature : UnityEngine.Rendering.Universal.ScriptableRendererFeature
|
||
{
|
||
|
||
[System.Serializable]
|
||
public enum RTDisplacementSize {
|
||
_128 = 128,
|
||
_256 = 256,
|
||
_512 = 512,
|
||
_1024 = 1024
|
||
}
|
||
|
||
[System.Serializable]
|
||
public class GrassDisplacementSettings
|
||
{
|
||
public RTDisplacementSize Resolution = RTDisplacementSize._256;
|
||
public float Size = 20.0f;
|
||
public bool ShiftRenderTex = false;
|
||
//public bool SinglePassInstancing = false;
|
||
}
|
||
|
||
public GrassDisplacementSettings settings = new GrassDisplacementSettings();
|
||
GrassDisplacementPass m_GrassDisplacementPass;
|
||
|
||
public override void Create()
|
||
{
|
||
m_GrassDisplacementPass = new GrassDisplacementPass();
|
||
m_GrassDisplacementPass.renderPassEvent = UnityEngine.Rendering.Universal.RenderPassEvent.BeforeRenderingShadows;
|
||
|
||
// Apply settings
|
||
m_GrassDisplacementPass.m_Resolution = (int)settings.Resolution;
|
||
m_GrassDisplacementPass.m_Size = settings.Size;
|
||
m_GrassDisplacementPass.m_ShiftRenderTex = settings.ShiftRenderTex;
|
||
//m_GrassDisplacementPass.m_SinglePassInstancing = settings.SinglePassInstancing;
|
||
|
||
}
|
||
|
||
public override void AddRenderPasses(UnityEngine.Rendering.Universal.ScriptableRenderer renderer, ref UnityEngine.Rendering.Universal.RenderingData renderingData)
|
||
{
|
||
renderer.EnqueuePass(m_GrassDisplacementPass);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
// ---------------------------------------------------------
|
||
// The Pass
|
||
|
||
public class GrassDisplacementPass : UnityEngine.Rendering.Universal.ScriptableRenderPass
|
||
{
|
||
const string k_RenderGrassDisplacementFXTag = "Render Lux Grass Displacement FX";
|
||
ShaderTagId m_GrassDisplacementFXShaderTag = new ShaderTagId("LuxGrassDisplacementFX");
|
||
|
||
// There is no 0.5 in 8bit colors...
|
||
Color m_ClearColor = new Color(127.0f/255.0f, 127.0f/255.0f,1,1);
|
||
|
||
UnityEngine.Rendering.Universal.RenderTargetHandle m_GrassDisplacementFX = UnityEngine.Rendering.Universal.RenderTargetHandle.CameraTarget;
|
||
|
||
private Matrix4x4 projectionMatrix;
|
||
private Matrix4x4 worldToCameraMatrix;
|
||
|
||
public float m_Size = 20.0f;
|
||
public int m_Resolution = 256;
|
||
public bool m_ShiftRenderTex = false;
|
||
//public bool m_SinglePassInstancing = false;
|
||
|
||
private float stepSize;
|
||
private float oneOverStepSize;
|
||
|
||
private Vector4 posSize = Vector4.zero;
|
||
private static int DisplacementTexPosSizePID = Shader.PropertyToID("_Lux_DisplacementPosition");
|
||
|
||
private FilteringSettings transparentFilterSettings { get; set; }
|
||
|
||
//private ProfilingSampler psGrassDisplacement;
|
||
|
||
public GrassDisplacementPass()
|
||
{
|
||
m_GrassDisplacementFX.Init("_Lux_DisplacementRT");
|
||
transparentFilterSettings = new FilteringSettings(RenderQueueRange.transparent);
|
||
}
|
||
|
||
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
|
||
{
|
||
cameraTextureDescriptor.depthBufferBits = 0;
|
||
cameraTextureDescriptor.width = m_Resolution;
|
||
cameraTextureDescriptor.height = m_Resolution;
|
||
cameraTextureDescriptor.colorFormat = RenderTextureFormat.Default;
|
||
|
||
// Does not help for single pass instanced...
|
||
// cameraTextureDescriptor.vrUsage = VRTextureUsage.None;
|
||
// https://docs.unity3d.com/ScriptReference/Rendering.AttachmentDescriptor.ConfigureTarget.html
|
||
|
||
cmd.GetTemporaryRT(m_GrassDisplacementFX.id, cameraTextureDescriptor, FilterMode.Bilinear);
|
||
ConfigureTarget(m_GrassDisplacementFX.Identifier());
|
||
ConfigureClear(ClearFlag.Color, m_ClearColor);
|
||
|
||
// Set up all constants
|
||
stepSize = m_Size / (float)m_Resolution;
|
||
oneOverStepSize = 1.0f / stepSize;
|
||
var halfSize = m_Size * 0.5f;
|
||
projectionMatrix = Matrix4x4.Ortho(-halfSize, halfSize, -halfSize, halfSize, 0.1f, 80.0f);
|
||
projectionMatrix = GL.GetGPUProjectionMatrix(projectionMatrix, false);
|
||
worldToCameraMatrix.SetRow(0, new Vector4(1,0,0,0) ); //last is x pos
|
||
worldToCameraMatrix.SetRow(1, new Vector4(0,0,1,0) ); //last is z pos
|
||
worldToCameraMatrix.SetRow(2, new Vector4(0,1,0,0) ); //last is y pos
|
||
worldToCameraMatrix.SetRow(3, new Vector4(0,0,0,1) );
|
||
|
||
//psGrassDisplacement = new ProfilingSampler("k_RenderGrassDisplacementFXTag");
|
||
|
||
}
|
||
|
||
public override void Execute(ScriptableRenderContext context, ref UnityEngine.Rendering.Universal.RenderingData renderingData)
|
||
{
|
||
CommandBuffer cmd = CommandBufferPool.Get(k_RenderGrassDisplacementFXTag);
|
||
|
||
using (new ProfilingSample(cmd, k_RenderGrassDisplacementFXTag))
|
||
// This wil spam a lot of errors...
|
||
//using (new ProfilingScope(cmd, psGrassDisplacement))
|
||
{
|
||
context.ExecuteCommandBuffer(cmd);
|
||
cmd.Clear();
|
||
|
||
var drawSettings = CreateDrawingSettings(m_GrassDisplacementFXShaderTag, ref renderingData, SortingCriteria.CommonTransparent);
|
||
var filteringSettings = transparentFilterSettings;
|
||
|
||
var camera = renderingData.cameraData.camera;
|
||
var cameraTransform = camera.transform;
|
||
var cameraPos = cameraTransform.position;
|
||
|
||
var isStereoEnabled = renderingData.cameraData.isStereoEnabled;
|
||
if (isStereoEnabled) {
|
||
cmd.SetSinglePassStereo(SinglePassStereoMode.None);
|
||
}
|
||
|
||
// Push cameraPos forward – if enabled
|
||
var camForward = cameraTransform.forward;
|
||
// unstable
|
||
// cameraPos.x += camForward.x * m_Size * 0.5f;
|
||
// cameraPos.z += camForward.z * m_Size * 0.5f;
|
||
if (m_ShiftRenderTex) {
|
||
var t_camForward = new Vector2(camForward.x, camForward.z);
|
||
t_camForward.Normalize();
|
||
// still rather unstable...
|
||
cameraPos.x += t_camForward.x * m_Size * 0.33f;
|
||
cameraPos.z += t_camForward.y * m_Size * 0.33f;
|
||
}
|
||
|
||
// Store original Camera matrices
|
||
var worldToCameraMatrixOrig = camera.worldToCameraMatrix;
|
||
var projectionMatrixOrig = camera.projectionMatrix;
|
||
|
||
// Quantize movement to fit texel size of RT – this stabilzes the final visual result
|
||
Vector2 positionRT = Vector2.zero; // bad
|
||
positionRT.x = Mathf.Floor(cameraPos.x * oneOverStepSize) * stepSize;
|
||
positionRT.y = Mathf.Floor(cameraPos.z * oneOverStepSize) * stepSize;
|
||
|
||
// Update the custom worldToCameraMatrix – we only have to update the translation/position
|
||
worldToCameraMatrix.SetColumn(3, new Vector4(-positionRT.x, -positionRT.y, -cameraPos.y - 40.0f, 1) );
|
||
cmd.SetViewProjectionMatrices(worldToCameraMatrix, projectionMatrix);
|
||
|
||
// ---------------------------------------------------------
|
||
// Calc and set grass shader params
|
||
posSize.x = positionRT.x - m_Size * 0.5f;
|
||
posSize.y = positionRT.y - m_Size * 0.5f;
|
||
posSize.z = 1.0f / m_Size ;
|
||
cmd.SetGlobalVector(DisplacementTexPosSizePID, posSize );
|
||
|
||
// ---------------------------------------------------------
|
||
// Call execute
|
||
context.ExecuteCommandBuffer(cmd);
|
||
context.DrawRenderers(renderingData.cullResults, ref drawSettings, ref filteringSettings);
|
||
|
||
// ---------------------------------------------------------
|
||
// Restore Camera matrices
|
||
cmd.Clear();
|
||
cmd.SetViewProjectionMatrices(worldToCameraMatrixOrig, projectionMatrixOrig);
|
||
if (isStereoEnabled) {
|
||
//if (m_SinglePassInstancing) {
|
||
// cmd.SetSinglePassStereo(SinglePassStereoMode.Instancing);
|
||
//cmd.SetGlobalTexture("_Lux_DisplacementRT", m_GrassDisplacementFX.id);
|
||
//cmd.SetGlobalTexture("_Lux_DisplacementRT", m_GrassDisplacementFX.Identifier() );
|
||
//}
|
||
//else {
|
||
//cmd.SetSinglePassStereo(SinglePassStereoMode.SideBySide);
|
||
cmd.SetSinglePassStereo(SinglePassStereoMode.None);
|
||
//}
|
||
}
|
||
}
|
||
|
||
// ---------------------------------------------------------
|
||
// Call execute a 2nd time
|
||
context.ExecuteCommandBuffer(cmd);
|
||
CommandBufferPool.Release(cmd);
|
||
}
|
||
|
||
public override void FrameCleanup(CommandBuffer cmd)
|
||
{
|
||
cmd.ReleaseTemporaryRT(m_GrassDisplacementFX.id);
|
||
}
|
||
}
|
||
} |