You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
242 lines
9.7 KiB
242 lines
9.7 KiB
using Unity.Collections;
|
|
using UnityEngine.Experimental.Rendering;
|
|
|
|
namespace UnityEngine.Rendering.HighDefinition
|
|
{
|
|
internal class EyeCausticLUT
|
|
{
|
|
static class Uniforms
|
|
{
|
|
internal static int _OutputWidth = Shader.PropertyToID("_OutputWidth");
|
|
internal static int _OutputHeight = Shader.PropertyToID("_OutputHeight");
|
|
internal static int _OutputDepth = Shader.PropertyToID("_OutputDepth");
|
|
internal static int _OutputSlice = Shader.PropertyToID("_OutputSlice");
|
|
internal static int _UseCorneaSymmetryMirroring = Shader.PropertyToID("_UseCorneaSymmetryMirroring");
|
|
internal static int _ExtraScleraMargin = Shader.PropertyToID("_ExtraScleraMargin");
|
|
|
|
internal static int _LightWidth = Shader.PropertyToID("_LightWidth");
|
|
internal static int _LightHeight = Shader.PropertyToID("_LightHeight");
|
|
internal static int _LightDistance = Shader.PropertyToID("_LightDistance");
|
|
|
|
internal static int _LightLuminousFlux = Shader.PropertyToID("_LightLuminousFlux");
|
|
internal static int _LightGrazingAngleCos = Shader.PropertyToID("_LightGrazingAngleCos");
|
|
|
|
internal static int _CorneaFlatteningFactor = Shader.PropertyToID("_CorneaFlatteningFactor");
|
|
internal static int _CorneaApproxPrimitive = Shader.PropertyToID("_CorneaApproxPrimitive");
|
|
internal static int _CorneaPowerFactor = Shader.PropertyToID("_CorneaPowerFactor");
|
|
|
|
internal static int _RandomNumbers = Shader.PropertyToID("_RandomNumbers");
|
|
|
|
internal static int _NumberOfSamplesAccumulated = Shader.PropertyToID("_NumberOfSamplesAccumulated");
|
|
|
|
internal static int _GeneratedSamplesBuffer = Shader.PropertyToID("_GeneratedSamplesBuffer");
|
|
|
|
internal static int _OutputLutTex = Shader.PropertyToID("_OutputLutTex");
|
|
|
|
public static readonly int _PreIntegratedEyeCaustic = Shader.PropertyToID("_PreIntegratedEyeCaustic");
|
|
}
|
|
|
|
enum CorneaApproximationPrimitive
|
|
{
|
|
Sine = 0,
|
|
Sphere = 1
|
|
}
|
|
|
|
private float lightSize = 10.0f;
|
|
private float lightLuminousFlux = 12000;
|
|
private float lightDipBelowHorizonDegrees = 30.0f;
|
|
private float lightDistance = 10.0f;
|
|
private float corneaFlatteningFactor = 0.7f;
|
|
private float corneaPowerFactor = 1.5f;
|
|
private CorneaApproximationPrimitive selectedCorneaApproxPrim = CorneaApproximationPrimitive.Sphere;
|
|
|
|
private int lutWidth = 128;
|
|
private int lutHeight = 32;
|
|
private int lutDepth = 16;
|
|
private bool useCorneaSymmetryMirroring = true;
|
|
private float lutExtraScleraMargin = 0.15f;
|
|
|
|
private RenderTexture generatedLUT;
|
|
|
|
private ComputeBuffer generatedLutStagingBuffer;
|
|
private ComputeBuffer randomSamplesBuffer;
|
|
|
|
private const int LUT_GEN_KERNEL_SIZE = 64;
|
|
private const int LUT_GEN_NUMBER_OF_DISPATCHES = 512 * 32;
|
|
private const int LUT_GEN_SAMPLES_PER_SLICE = LUT_GEN_NUMBER_OF_DISPATCHES * LUT_GEN_KERNEL_SIZE;
|
|
|
|
private static ComputeShader s_Shader;
|
|
private static int[] s_Kernels = new int[3];
|
|
|
|
private void CreateLUTGenResources()
|
|
{
|
|
if (s_Shader == null)
|
|
{
|
|
s_Shader = GraphicsSettings.GetRenderPipelineSettings<HDRenderPipelineRuntimeShaders>().eyeMaterialCS;
|
|
s_Kernels[0] = s_Shader.FindKernel("SampleCaustic");
|
|
s_Kernels[1] = s_Shader.FindKernel("CopyToLUT");
|
|
s_Kernels[2] = s_Shader.FindKernel("ClearBuffer");
|
|
}
|
|
|
|
|
|
RenderTextureDescriptor volumeDesc = new RenderTextureDescriptor()
|
|
{
|
|
dimension = TextureDimension.Tex3D,
|
|
width = lutWidth,
|
|
height = lutHeight,
|
|
volumeDepth = lutDepth,
|
|
graphicsFormat = GraphicsFormat.R16_SFloat,
|
|
enableRandomWrite = true,
|
|
msaaSamples = 1,
|
|
};
|
|
|
|
if (generatedLUT != null)
|
|
{
|
|
generatedLUT.Release();
|
|
}
|
|
|
|
generatedLUT = new RenderTexture(volumeDesc)
|
|
{
|
|
wrapMode = TextureWrapMode.Clamp, hideFlags = HideFlags.HideAndDontSave, name = "Caustic LUT"
|
|
};
|
|
generatedLUT.Create();
|
|
|
|
generatedLutStagingBuffer = new ComputeBuffer(lutWidth * lutHeight, 4, ComputeBufferType.Raw);
|
|
generatedLutStagingBuffer.name = "Caustic LUT Staging";
|
|
randomSamplesBuffer = new ComputeBuffer(LUT_GEN_SAMPLES_PER_SLICE, sizeof(float) * 4, ComputeBufferType.Default);
|
|
}
|
|
|
|
private void FreeLUTGenResources()
|
|
{
|
|
randomSamplesBuffer.Release();
|
|
generatedLutStagingBuffer.Release();
|
|
}
|
|
|
|
private void GenerateLUT()
|
|
{
|
|
for (int i = 0; i != lutDepth; ++i)
|
|
{
|
|
ClearStaging();
|
|
GenerateLUTForSlice(i);
|
|
CopyFromStagingToLUT(lutDepth - i - 1);
|
|
}
|
|
}
|
|
|
|
private void GenerateLUTForSlice(int currentDepthSlice)
|
|
{
|
|
int sampleCount = LUT_GEN_SAMPLES_PER_SLICE;
|
|
|
|
NativeArray<Vector4> samples = new NativeArray<Vector4>(sampleCount, Allocator.Temp,
|
|
NativeArrayOptions.UninitializedMemory);
|
|
|
|
|
|
for (int i = 0; i < sampleCount; ++i)
|
|
{
|
|
float a = HaltonSequence.Get(i, 2);
|
|
float b = HaltonSequence.Get(i, 3);
|
|
float c = HaltonSequence.Get(i, 5);
|
|
float d = HaltonSequence.Get(i, 7);
|
|
|
|
Vector4 s = new Vector4(a, b, c, d);
|
|
samples[i] = s;
|
|
}
|
|
|
|
randomSamplesBuffer.SetData(samples);
|
|
samples.Dispose();
|
|
|
|
CommandBuffer cmd = CommandBufferPool.Get();
|
|
int kernel = s_Kernels[0];
|
|
|
|
cmd.SetComputeIntParam(s_Shader, Uniforms._OutputWidth, lutWidth);
|
|
cmd.SetComputeIntParam(s_Shader, Uniforms._OutputHeight, lutHeight);
|
|
cmd.SetComputeIntParam(s_Shader, Uniforms._OutputSlice, currentDepthSlice);
|
|
cmd.SetComputeFloatParam(s_Shader, Uniforms._ExtraScleraMargin, lutExtraScleraMargin);
|
|
cmd.SetComputeFloatParam(s_Shader, Uniforms._UseCorneaSymmetryMirroring, useCorneaSymmetryMirroring ? 1 : 0);
|
|
|
|
cmd.SetComputeFloatParam(s_Shader, Uniforms._LightWidth, lightSize);
|
|
cmd.SetComputeFloatParam(s_Shader, Uniforms._LightHeight, lightSize);
|
|
cmd.SetComputeFloatParam(s_Shader, Uniforms._LightDistance, lightDistance);
|
|
float cosGrazingAngle = Mathf.Cos(Mathf.PI * 0.5f + Mathf.Deg2Rad * lightDipBelowHorizonDegrees);
|
|
cmd.SetComputeFloatParam(s_Shader, Uniforms._LightGrazingAngleCos, cosGrazingAngle );
|
|
cmd.SetComputeFloatParam(s_Shader, Uniforms._LightLuminousFlux, lightLuminousFlux );
|
|
|
|
cmd.SetComputeIntParam(s_Shader, Uniforms._CorneaApproxPrimitive, (int)selectedCorneaApproxPrim);
|
|
cmd.SetComputeFloatParam(s_Shader, Uniforms._CorneaFlatteningFactor, corneaFlatteningFactor);
|
|
cmd.SetComputeFloatParam(s_Shader, Uniforms._CorneaPowerFactor, corneaPowerFactor);
|
|
|
|
cmd.SetComputeBufferParam(s_Shader, kernel, Uniforms._RandomNumbers, randomSamplesBuffer);
|
|
|
|
cmd.SetComputeBufferParam(s_Shader, kernel, Uniforms._GeneratedSamplesBuffer, generatedLutStagingBuffer);
|
|
|
|
cmd.DispatchCompute(s_Shader, kernel, LUT_GEN_NUMBER_OF_DISPATCHES, 1, 1);
|
|
Graphics.ExecuteCommandBuffer(cmd);
|
|
|
|
CommandBufferPool.Release(cmd);
|
|
}
|
|
|
|
void CopyFromStagingToLUT(int currentDepthSlice)
|
|
{
|
|
|
|
int sampleCount = LUT_GEN_SAMPLES_PER_SLICE;
|
|
CommandBuffer cmd = CommandBufferPool.Get();
|
|
int kernel = s_Kernels[1];
|
|
|
|
cmd.SetComputeIntParam(s_Shader, Uniforms._OutputWidth, lutWidth);
|
|
cmd.SetComputeIntParam(s_Shader, Uniforms._OutputHeight, lutHeight);
|
|
cmd.SetComputeIntParam(s_Shader, Uniforms._OutputDepth, lutDepth);
|
|
cmd.SetComputeIntParam(s_Shader, Uniforms._OutputSlice, currentDepthSlice);
|
|
cmd.SetComputeIntParam(s_Shader, Uniforms._NumberOfSamplesAccumulated, sampleCount);
|
|
|
|
|
|
cmd.SetComputeBufferParam(s_Shader, kernel, Uniforms._GeneratedSamplesBuffer, generatedLutStagingBuffer);
|
|
cmd.SetComputeTextureParam(s_Shader, kernel, Uniforms._OutputLutTex, generatedLUT);
|
|
|
|
cmd.DispatchCompute(s_Shader, kernel, (lutWidth + 7) / 8,
|
|
(lutHeight + 7) / 8, 1);
|
|
|
|
Graphics.ExecuteCommandBuffer(cmd);
|
|
|
|
CommandBufferPool.Release(cmd);
|
|
}
|
|
|
|
void ClearStaging()
|
|
{
|
|
CommandBuffer cmd = CommandBufferPool.Get();
|
|
int kernel = s_Kernels[2];
|
|
|
|
int entries = lutWidth * lutHeight;
|
|
|
|
cmd.SetComputeIntParam(s_Shader, Uniforms._OutputWidth, lutWidth);
|
|
cmd.SetComputeIntParam(s_Shader, Uniforms._OutputHeight, lutHeight);
|
|
|
|
cmd.SetComputeBufferParam(s_Shader, kernel, Uniforms._GeneratedSamplesBuffer, generatedLutStagingBuffer);
|
|
|
|
cmd.DispatchCompute(s_Shader, kernel, (entries + 63) / 64, 1, 1);
|
|
|
|
Graphics.ExecuteCommandBuffer(cmd);
|
|
|
|
CommandBufferPool.Release(cmd);
|
|
}
|
|
|
|
internal void Create()
|
|
{
|
|
CreateLUTGenResources();
|
|
GenerateLUT();
|
|
FreeLUTGenResources();
|
|
}
|
|
|
|
internal void Cleanup()
|
|
{
|
|
if (generatedLUT != null)
|
|
{
|
|
generatedLUT.Release();
|
|
generatedLUT = null;
|
|
}
|
|
}
|
|
|
|
internal void Bind(CommandBuffer cmd)
|
|
{
|
|
cmd.SetGlobalTexture(Uniforms._PreIntegratedEyeCaustic, generatedLUT);
|
|
}
|
|
}
|
|
}
|