Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Importance Sampling Pipeline #84

Merged
merged 59 commits into from
Apr 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
dce1eab
Multiple Importance Sampling for HDRI Sky (Ray Generation)
skhiat Jan 20, 2020
041b98c
backup
skhiat Jan 21, 2020
4991934
Merge branch 'HDRP/staging' of https://github.com/Unity-Technologies/…
skhiat Jan 21, 2020
7dd03f6
Multiple helpers
skhiat Jan 22, 2020
86ef8fc
backup
skhiat Jan 24, 2020
7e90ad6
Merge branch 'HDRP/staging' of https://github.com/Unity-Technologies/…
skhiat Jan 24, 2020
e33d246
Add SampleCubemapProjectionNode (Project cubemap to Geometry)
skhiat Jan 28, 2020
a503a3b
delete useless files
skhiat Jan 28, 2020
fd735d7
Merge branch 'HDRP/staging' of https://github.com/Unity-Technologies/…
skhiat Jan 29, 2020
ef8942b
Merge branch 'HDRP/backplate_ao_fix' of https://github.com/Unity-Tech…
skhiat Jan 29, 2020
8ba607a
update
skhiat Jan 30, 2020
6424029
Cube To LatLong for CubeArray
skhiat Feb 5, 2020
cb03955
Merge branch 'HDRP/staging' of https://github.com/Unity-Technologies/…
skhiat Feb 5, 2020
a6fc066
Functional generation
skhiat Feb 5, 2020
8f1a57d
Integration on ray tracer step
skhiat Feb 5, 2020
2608bbb
Store HDRI Integral
skhiat Feb 6, 2020
64c4938
.
skhiat Feb 11, 2020
b344dad
Integrate HDRI Sky
skhiat Feb 18, 2020
f32a21d
Update Importance Sampling
skhiat Feb 20, 2020
e13acdf
Update Algorithm with Hemisphere Path
skhiat Feb 27, 2020
40db532
Backup
skhiat Feb 28, 2020
6a74733
Merge branch 'HDRP/staging' of https://github.com/Unity-Technologies/…
skhiat Feb 28, 2020
99ca181
Update merge
skhiat Feb 28, 2020
3c8372d
Update Merge 001
skhiat Feb 28, 2020
515efb1
Update Merge 002
skhiat Feb 28, 2020
61c45a0
Update Merge 003
skhiat Feb 28, 2020
c5cbee5
Update Merge 004
skhiat Feb 28, 2020
7ee966c
Update Merge 005
skhiat Feb 28, 2020
41652ea
Update Merge 006
skhiat Feb 28, 2020
d46c512
Update Merge 007
skhiat Feb 28, 2020
62e7145
Merge branch 'HDRP/staging' of https://github.com/Unity-Technologies/…
skhiat Feb 28, 2020
d471635
Cleanup
skhiat Feb 28, 2020
01cd199
Update Integration of HDRISky Upper Hemisphere
skhiat Feb 28, 2020
4dcb181
Remove useless dump images on disk
skhiat Feb 28, 2020
b34cb1d
Fix change log issue
skhiat Mar 1, 2020
948812f
Merge branch 'HDRP/staging' of https://github.com/Unity-Technologies/…
skhiat Mar 2, 2020
8f36170
Merge branch 'HDRP/staging' of https://github.com/Unity-Technologies/…
skhiat Mar 2, 2020
14aef23
backup
skhiat Mar 4, 2020
c664f39
Backup
skhiat Mar 4, 2020
142e571
Pre-Clean
skhiat Mar 5, 2020
5ca315a
Pre-Clean
skhiat Mar 5, 2020
702c965
Clean Up - remove file
skhiat Mar 5, 2020
fb257cb
Remove Debug Code
skhiat Mar 5, 2020
345abba
Merge branch 'HDRP/staging' of https://github.com/Unity-Technologies/…
skhiat Mar 5, 2020
15cb50c
Update
skhiat Mar 5, 2020
6198976
Update ChangeLog
skhiat Mar 5, 2020
980666a
Clean Up
skhiat Mar 5, 2020
e720700
update
skhiat Mar 5, 2020
83e0b16
Clean up
skhiat Mar 5, 2020
0a77e11
Remove useless texture
skhiat Mar 5, 2020
30e6541
Fix CGAlloc + Default Litetime of a RTHandle on the "RTHandleDeleter"
skhiat Mar 5, 2020
89eb94f
CleanUp
skhiat Mar 5, 2020
ae0ce0e
remove useless comment
skhiat Mar 5, 2020
031779c
Add variable (Atmospherical) + Rename/Comment
skhiat Mar 9, 2020
cee6e0c
Move parameter to CS, Clean & move to private RTHandleDeleter
skhiat Mar 19, 2020
d93c0fc
Merge branch 'HDRP/staging' into HDRP/multiple_importance_sampling_hd…
skhiat Mar 19, 2020
996bb5b
Merge branch 'HDRP/staging' into HDRP/multiple_importance_sampling_hd…
skhiat Apr 2, 2020
936f3ed
Merge branch 'HDRP/staging' of https://github.com/Unity-Technologies/…
skhiat Apr 9, 2020
cf1d17f
Merge branch 'HDRP/staging' into HDRP/multiple_importance_sampling_hd…
skhiat Apr 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions com.unity.render-pipelines.high-definition/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## [Unreleased]

### Added
- Added Pipeline for Importance Sampling (Marginals Generation)
- Enable by default Cookie for Light Baking
- Add warning if disabled and use Baking & Cookies
- Ray tracing support for VR single-pass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering.HighDefinition;

using System;
using System.Collections.Generic;

namespace UnityEditor.Rendering.HighDefinition
{
[CanEditMultipleObjects]
Expand All @@ -28,8 +31,9 @@ class HDRISkyEditor
SerializedDataParameter m_ShadowTint;

RTHandle m_IntensityTexture;
Material m_IntegrateHDRISkyMaterial; // Compute the HDRI sky intensity in lux for the skybox
Texture2D m_ReadBackTexture;
Material m_CubeToHemiLatLong;

public override bool hasAdvancedMode => true;

public override void OnEnable()
Expand Down Expand Up @@ -63,7 +67,9 @@ public override void OnEnable()
m_IntensityTexture = RTHandles.Alloc(1, 1, colorFormat: GraphicsFormat.R32G32B32A32_SFloat);
var hdrp = HDRenderPipeline.defaultAsset;
if (hdrp != null)
m_IntegrateHDRISkyMaterial = CoreUtils.CreateEngineMaterial(hdrp.renderPipelineResources.shaders.integrateHdriSkyPS);
{
m_CubeToHemiLatLong = CoreUtils.CreateEngineMaterial(hdrp.renderPipelineResources.shaders.cubeToHemiPanoPS);
}
m_ReadBackTexture = new Texture2D(1, 1, TextureFormat.RGBAFloat, false, false);
}

Expand All @@ -79,28 +85,50 @@ public override void OnDisable()
public void GetUpperHemisphereLuxValue()
{
Cubemap hdri = m_hdriSky.value.objectReferenceValue as Cubemap;

// null material can happen when no HDRP asset is present.
if (hdri == null || m_IntegrateHDRISkyMaterial == null)
if (hdri == null || m_CubeToHemiLatLong == null)
return;

m_IntegrateHDRISkyMaterial.SetTexture(HDShaderIDs._Cubemap, hdri);

Graphics.Blit(Texture2D.whiteTexture, m_IntensityTexture.rt, m_IntegrateHDRISkyMaterial);

// Copy the rendertexture containing the lux value inside a Texture2D
RenderTexture.active = m_IntensityTexture.rt;
m_ReadBackTexture.ReadPixels(new Rect(0.0f, 0.0f, 1, 1), 0, 0);
RTHandle latLongMap = RTHandles.Alloc( 4*hdri.width, hdri.width,
colorFormat: GraphicsFormat.R32G32B32A32_SFloat,
enableRandomWrite: true);
m_CubeToHemiLatLong.SetTexture (HDShaderIDs._SrcCubeTexture, hdri);
m_CubeToHemiLatLong.SetInt (HDShaderIDs._CubeMipLvl, 0);
m_CubeToHemiLatLong.SetInt (HDShaderIDs._CubeArrayIndex, 0);
m_CubeToHemiLatLong.SetInt (HDShaderIDs._BuildPDF, 0);
m_CubeToHemiLatLong.SetInt (HDShaderIDs._PreMultiplyByJacobian, 1);
m_CubeToHemiLatLong.SetInt (HDShaderIDs._PreMultiplyByCosTheta, 1);
m_CubeToHemiLatLong.SetInt (HDShaderIDs._PreMultiplyBySolidAngle, 0);
m_CubeToHemiLatLong.SetVector (HDShaderIDs._Sizes, new Vector4( (float)latLongMap.rt.width, (float)latLongMap.rt.height,
1.0f/((float)latLongMap.rt.width), 1.0f/((float)latLongMap.rt.height)));
Graphics.Blit(Texture2D.whiteTexture, latLongMap.rt, m_CubeToHemiLatLong, 0);

RTHandle totalRows = GPUScan.ComputeOperation(latLongMap, null, GPUScan.Operation.Total, GPUScan.Direction.Horizontal, latLongMap.rt.graphicsFormat);
RTHandle totalCols = GPUScan.ComputeOperation(totalRows, null, GPUScan.Operation.Total, GPUScan.Direction.Vertical, latLongMap.rt.graphicsFormat);

RenderTexture.active = totalCols.rt;
m_ReadBackTexture.ReadPixels(new Rect(0.0f, 0.0f, 1.0f, 1.0f), 0, 0);
RenderTexture.active = null;

// And then the value inside this texture
Color hdriIntensity = m_ReadBackTexture.GetPixel(0, 0);
m_UpperHemisphereLuxValue.value.floatValue = hdriIntensity.a;
float max = Mathf.Max(hdriIntensity.r, hdriIntensity.g, hdriIntensity.b);
if (max == 0.0f)
max = 1.0f;
m_UpperHemisphereLuxColor.value.vector3Value = new Vector3(hdriIntensity.r/max, hdriIntensity.g/max, hdriIntensity.b/max);
m_UpperHemisphereLuxColor.value.vector3Value *= 0.5f; // Arbitrary 25% to not have too dark or too bright shadow

// (2.0f*PI)*(0.5f*PI) == (PI^2)
float coef = (Mathf.PI*Mathf.PI)
/ // --------------------------------------------------------
((float)(latLongMap.rt.width*latLongMap.rt.height));
float ref3 = (hdriIntensity.r + hdriIntensity.g + hdriIntensity.b)/3.0f;
float maxRef = Mathf.Max(hdriIntensity.r, hdriIntensity.g, hdriIntensity.b);

m_UpperHemisphereLuxValue.value.floatValue = coef*ref3;

totalCols.Release();
totalRows.Release();
latLongMap.Release();

if (maxRef == 0.0f)
maxRef = 1.0f;

m_UpperHemisphereLuxColor.value.vector3Value = new Vector3(hdriIntensity.r/maxRef, hdriIntensity.g/maxRef, hdriIntensity.b/maxRef);
m_UpperHemisphereLuxColor.value.vector3Value *= 0.5f; // Arbitrary 50% to not have too dark or too bright shadow
}

public override void OnInspectorGUI()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#pragma only_renderers d3d11 ps4 xboxone vulkan metal switch

#pragma kernel CSMainAdd Add KerName=CSMainAdd
#pragma kernel CSMainSub Sub KerName=CSMainSub
#pragma kernel CSMainMult Mult KerName=CSMainMult
#pragma kernel CSMainDiv Div KerName=CSMainDiv
#pragma kernel CSMainMAD MAD KerName=CSMainMAD
#pragma kernel CSMainMAD_RG MAD_RG KerName=CSMainMAD_RG
#pragma kernel CSMainMean Mean KerName=CSMainMean
#pragma kernel CSMainSelfAdd READ_WRITE Add KerName=CSMainSelfAdd
#pragma kernel CSMainSelfSub READ_WRITE Sub KerName=CSMainSelfSub
#pragma kernel CSMainSelfMult READ_WRITE Mult KerName=CSMainSelfMult
#pragma kernel CSMainSelfDiv READ_WRITE Div KerName=CSMainSelfDiv
#pragma kernel CSMainSelfMAD READ_WRITE MAD KerName=CSMainSelfMAD
#pragma kernel CSMainSelfMAD_RG READ_WRITE MAD_RG KerName=CSMainSelfMAD_RG
#pragma kernel CSMainSelfMean READ_WRITE Mean KerName=CSMainSelfMean

#pragma kernel CSMainAddVal Val Add KerName=CSMainAddVal
#pragma kernel CSMainSubVal Val Sub KerName=CSMainSubVal
#pragma kernel CSMainMultVal Val Mult KerName=CSMainMultVal
#pragma kernel CSMainDivVal Val Div KerName=CSMainDivVal
#pragma kernel CSMainMADVal Val MAD KerName=CSMainMADVal
#pragma kernel CSMainMAD_RGVal Val MAD_RG KerName=CSMainMAD_RGVal
#pragma kernel CSMainMeanVal Val Mean KerName=CSMainMeanVal
#pragma kernel CSMainSelfAddVal Val READ_WRITE Add KerName=CSMainSelfAddVal
#pragma kernel CSMainSelfSubVal Val READ_WRITE Sub KerName=CSMainSelfSubVal
#pragma kernel CSMainSelfMultVal Val READ_WRITE Mult KerName=CSMainSelfMultVal
#pragma kernel CSMainSelfDivVal Val READ_WRITE Div KerName=CSMainSelfDivVal
#pragma kernel CSMainSelfMADVal Val READ_WRITE MAD KerName=CSMainSelfMADVal
#pragma kernel CSMainSelfMAD_RGVal Val READ_WRITE MAD_RG KerName=CSMainSelfMAD_RGVal
#pragma kernel CSMainSelfMeanVal Val READ_WRITE Mean KerName=CSMainSelfMeanVal

#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Macros.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariablesFunctions.hlsl"

#ifdef Val
float4 _InputVal;
#else
Texture2D<float4> _InputVal;
#endif

#ifdef READ_WRITE
RWTexture2D<float4> _Output;
#define _Input _Output
#else
Texture2D<float4> _Input;
RWTexture2D<float4> _Output;
#endif

uint4 _Sizes; // xy: InputSize; zw: OutputSize

[numthreads(8, 8, 1)]
void KerName(uint3 id : SV_DispatchThreadID)
{
if (all(id.xy < _Sizes.xy))
{
float4 v = _Input[id.xy];

#ifdef Val
#if defined(MAD)
float4 param0 = _InputVal.r;
float4 param1 = _InputVal.g;
#elif defined(MAD_RG)
float4 param = float4(_InputVal.r, _InputVal.g, 0.0f, 0.0f);
#else
float4 param = _InputVal;
#endif
#else
#if defined(MAD)
float4 param0 = _InputVal[uint2(0, 0)];
float4 param1 = _InputVal[uint2(1, 0)];
#elif defined(MAD_RG)
float4 param = float4(_InputVal[uint2(0, 0)].r, _InputVal[uint2(0, 0)].g, 0.0f, 0.0f);
#else
float4 param = _InputVal[uint2(0, 0)];
#endif
#endif

#ifdef Add
_Output[id.xy] = v + param;
#elif defined(Sub)
_Output[id.xy] = v - param;
#elif defined(Mult)
_Output[id.xy] = v*param;
#elif defined(Div)
float4 a = param;
_Output[id.xy] = sign(a)*v/max(abs(a), 1e-4f);
#elif defined(MAD)
_Output[id.xy] = v*param0 + param1;
#elif defined(MAD_RG)
_Output[id.xy] = v*param.r + param.g;
#elif defined(Mean)
float mean = dot(v.xyz, float3((1.0f/3.0f).xxx));
_Output[id.xy] = mean.xxxx;
#endif
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
Shader "Hidden/CubeToHemiPano" {
Properties {
_SrcBlend ("", Float) = 1
_DstBlend ("", Float) = 1
}

HLSLINCLUDE
#pragma editor_sync_compilation
#pragma target 4.5
#pragma only_renderers d3d11 ps4 xboxone vulkan metal switch

#include "UnityCG.cginc"

UNITY_DECLARE_TEXCUBE(_SrcCubeTexture);
UNITY_DECLARE_TEXCUBEARRAY(_SrcCubeTextureArray);

uniform int _CubeMipLvl;
uniform int _CubeArrayIndex;
uniform int _BuildPDF;
uniform int _PreMultiplyByCosTheta;
uniform int _PreMultiplyBySolidAngle;
uniform int _PreMultiplyByJacobian; // Premultiply by the Det of Jacobian, to be "Integration Ready"
float4 _Sizes; // float4( outSize.xy, 1/outSize.xy )

struct v2f
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};

v2f vert(float4 vertex : POSITION, float2 texcoord : TEXCOORD0)
{
v2f o;
o.vertex = UnityObjectToClipPos(vertex);
o.texcoord = texcoord.xy;
return o;
}

float2 DirectionToSphericalTexCoordinate(float3 dir_in) // use this for the lookup
{
float3 dir = normalize(dir_in);
// coordinate frame is (-Z,X) meaning negative Z is primary axis and X is secondary axis.
float recipPi = 1.0f/3.1415926535897932384626433832795f;
return float2( 1.0 - 0.5*recipPi*atan2( dir.x, -dir.z ), asin( dir.y )*recipPi + 0.5 );
}

float Rescale01(float x, float xmin, float xmax)
{
return (x - xmin)/(xmax - xmin);
}

float RescaleNormalized(float x, float newMin, float newMax)
{
return x*(newMax - newMin) + newMin;
}

float Rescale(float x, float xmin, float xmax, float newMin, float newMax)
{
return RescaleNormalized(Rescale01(x, xmin, xmax), newMin, newMax);
}

float3 SphericalTexCoordinateToDirection(float2 sphTexCoord)
{
float pi = 3.1415926535897932384626433832795;
float theta = (1.0f - sphTexCoord.x)*(pi*2.0f);
float phi = RescaleNormalized(sphTexCoord.y, 0.0f, pi*0.5f);

float csTh, siTh, csPh, siPh;
sincos(theta, siTh, csTh);
sincos(phi, siPh, csPh);

// theta is 0 at negative Z (backwards). Coordinate frame is (-Z,X) meaning negative Z is primary axis and X is secondary axis.
return float3(siTh*csPh, siPh, -csTh*csPh);
}

float3 GetDir(float2 texCoord)
{
return SphericalTexCoordinateToDirection(texCoord.xy);
}

float SampleToPDFMeasure(float3 value)
{
return (value.r + value.g + value.b)*(1.0f/3.0f);
}

float SampleToPDFMeasure(float4 value)
{
return SampleToPDFMeasure(value.rgb);
}

float GetScale(float angle)
{
float scale = 1.0f;
float pi = 3.1415926535897932384626433832795f;

if (_PreMultiplyByJacobian == 1)
{
scale *= sin(angle); // Spherical Jacobian
}
if (_PreMultiplyByCosTheta == 1)
{
scale *= cos(angle);
}
if (_PreMultiplyBySolidAngle == 1)
{
scale *= _Sizes.z*_Sizes.w;
scale *= pi*pi*0.25f;
}

return scale;
}

float4 frag(v2f i) : SV_Target
{
float3 dir = GetDir(i.texcoord.xy);

float3 output;
if (_BuildPDF == 1)
output = (float3)SampleToPDFMeasure(UNITY_SAMPLE_TEXCUBE_LOD(_SrcCubeTexture, dir, (float)_CubeMipLvl).rgb).xxx;
else
output = (float3)UNITY_SAMPLE_TEXCUBE_LOD(_SrcCubeTexture, dir, (float) _CubeMipLvl).rgb;

float pi = 3.1415926535897932384626433832795f;
float angle = i.texcoord.y*pi*0.5f;

output *= GetScale(angle);

return float4(output.rgb, max(output.r, max(output.g, output.b)));
}

float4 fragArray(v2f i) : SV_Target
{
float3 dir = GetDir(i.texcoord.xy);

float3 output;
if (_BuildPDF == 1)
output = SampleToPDFMeasure(UNITY_SAMPLE_TEXCUBEARRAY_LOD(_SrcCubeTextureArray, float4(dir, _CubeArrayIndex), (float)_CubeMipLvl).rgb).xxx;
else
output = UNITY_SAMPLE_TEXCUBEARRAY_LOD(_SrcCubeTextureArray, float4(dir, _CubeArrayIndex), (float)_CubeMipLvl).rgb;

float pi = 3.1415926535897932384626433832795f;
float angle = i.texcoord.y*pi*0.5f;

output *= GetScale(angle);

return float4(output.rgb, max(output.r, max(output.g, output.b)));
}

ENDHLSL

SubShader {
Pass
{
ZWrite Off
ZTest Always
Cull Off
Blend Off

HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
ENDHLSL
}

Pass
{
ZWrite Off
ZTest Always
Cull Off
Blend Off

HLSLPROGRAM
#pragma vertex vert
#pragma fragment fragArray
ENDHLSL
}
}
Fallback Off
}