Incorporate spherical harmonics in VFX Graph
This commit is contained in:
@@ -129,7 +129,7 @@ PrefabInstance:
|
||||
m_Modifications:
|
||||
- target: {fileID: -973084862543737302, guid: 25c54d8c074f08447ab1c822a6a052fa, type: 3}
|
||||
propertyPath: m_PropertySheet.m_Uint.m_Array.Array.size
|
||||
value: 1
|
||||
value: 2
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -973084862543737302, guid: 25c54d8c074f08447ab1c822a6a052fa, type: 3}
|
||||
propertyPath: m_PropertySheet.m_Float.m_Array.Array.size
|
||||
@@ -139,6 +139,10 @@ PrefabInstance:
|
||||
propertyPath: m_PropertySheet.m_Uint.m_Array.Array.data[0].m_Name
|
||||
value: SplatCount
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -973084862543737302, guid: 25c54d8c074f08447ab1c822a6a052fa, type: 3}
|
||||
propertyPath: m_PropertySheet.m_Uint.m_Array.Array.data[1].m_Name
|
||||
value: SHDegrees
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -973084862543737302, guid: 25c54d8c074f08447ab1c822a6a052fa, type: 3}
|
||||
propertyPath: m_PropertySheet.m_Float.m_Array.Array.data[0].m_Name
|
||||
value: ScaleMultiplier
|
||||
@@ -147,6 +151,10 @@ PrefabInstance:
|
||||
propertyPath: m_PropertySheet.m_Uint.m_Array.Array.data[0].m_Value
|
||||
value: 200000
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -973084862543737302, guid: 25c54d8c074f08447ab1c822a6a052fa, type: 3}
|
||||
propertyPath: m_PropertySheet.m_Uint.m_Array.Array.data[1].m_Value
|
||||
value: 3
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -973084862543737302, guid: 25c54d8c074f08447ab1c822a6a052fa, type: 3}
|
||||
propertyPath: m_PropertySheet.m_Float.m_Array.Array.data[0].m_Value
|
||||
value: 64
|
||||
@@ -155,6 +163,10 @@ PrefabInstance:
|
||||
propertyPath: m_PropertySheet.m_Uint.m_Array.Array.data[0].m_Overridden
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -973084862543737302, guid: 25c54d8c074f08447ab1c822a6a052fa, type: 3}
|
||||
propertyPath: m_PropertySheet.m_Uint.m_Array.Array.data[1].m_Overridden
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: -973084862543737302, guid: 25c54d8c074f08447ab1c822a6a052fa, type: 3}
|
||||
propertyPath: m_PropertySheet.m_Float.m_Array.Array.data[0].m_Overridden
|
||||
value: 1
|
||||
@@ -211,6 +223,10 @@ PrefabInstance:
|
||||
propertyPath: m_Name
|
||||
value: splat_45000
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 8980549144392899874, guid: 25c54d8c074f08447ab1c822a6a052fa, type: 3}
|
||||
propertyPath: m_IsActive
|
||||
value: 1
|
||||
objectReference: {fileID: 0}
|
||||
m_RemovedComponents: []
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace SplatVfx
|
||||
[field: SerializeField] public Quaternion[] RotationArray { get; set; }
|
||||
[field: SerializeField] public Color[] ColorArray { get; set; }
|
||||
[field: SerializeField] public float[] OpacityArray { get; set; }
|
||||
[field: SerializeField] public float[,] SHArray { get; set; }
|
||||
[field: SerializeField] public float[] SHArray { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace SplatVfx
|
||||
_cachedBuffers.rotation.SetData(RotationArray);
|
||||
_cachedBuffers.color.SetData(ColorArray);
|
||||
_cachedBuffers.opacity.SetData(OpacityArray);
|
||||
// _cachedBuffers.sh.SetData(SHArray);
|
||||
_cachedBuffers.sh.SetData(SHArray);
|
||||
}
|
||||
return _cachedBuffers;
|
||||
}
|
||||
|
||||
@@ -40,11 +40,11 @@ namespace SplatVfx
|
||||
set => _opacityBufferProperty = value;
|
||||
}
|
||||
|
||||
// public string RotationBufferProperty
|
||||
// {
|
||||
// get => (string)_rotationBufferProperty;
|
||||
// set => _rotationBufferProperty = value;
|
||||
// }
|
||||
public string SHBufferProperty
|
||||
{
|
||||
get => (string)_shBufferProperty;
|
||||
set => _shBufferProperty = value;
|
||||
}
|
||||
|
||||
[VFXPropertyBinding("System.UInt32"), SerializeField]
|
||||
ExposedProperty _splatCountProperty = "SplatCount";
|
||||
@@ -64,6 +64,9 @@ namespace SplatVfx
|
||||
[VFXPropertyBinding("UnityEngine.GraphicsBuffer"), SerializeField]
|
||||
ExposedProperty _rotationBufferProperty = "RotationBuffer";
|
||||
|
||||
[VFXPropertyBinding("UnityEngine.GraphicsBuffer"), SerializeField]
|
||||
ExposedProperty _shBufferProperty = "SHBuffer";
|
||||
|
||||
public override bool IsValid(VisualEffect component)
|
||||
=> SplatData != null &&
|
||||
// component.HasUInt(_splatCountProperty) &&
|
||||
@@ -81,6 +84,7 @@ namespace SplatVfx
|
||||
component.SetGraphicsBuffer(_colorBufferProperty, SplatData.ColorBuffer);
|
||||
component.SetGraphicsBuffer(_opacityBufferProperty, SplatData.OpacityBuffer);
|
||||
component.SetGraphicsBuffer(_rotationBufferProperty, SplatData.RotationBuffer);
|
||||
component.SetGraphicsBuffer(_shBufferProperty, SplatData.SHBuffer);
|
||||
}
|
||||
|
||||
// public override string ToString()
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace SplatVfx.Editor
|
||||
splatData.RotationArray = new Quaternion[header_info.num_element];
|
||||
splatData.ColorArray = new Color[header_info.num_element];
|
||||
splatData.OpacityArray = new float[header_info.num_element];
|
||||
splatData.SHArray = new float[header_info.num_element, 45];
|
||||
splatData.SHArray = new float[header_info.num_element * 45];
|
||||
|
||||
for (int i = 0; i < header_info.num_element; i++)
|
||||
{
|
||||
|
||||
+3388
-44
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,112 @@
|
||||
#define sh(i) (float3)SHBuffer.Load3(Index * 45 + (i - 1) * 15)
|
||||
|
||||
const float SH_C0 = 0.28209479177387814f;
|
||||
const float SH_C1 = 0.4886025119029199f;
|
||||
const float SH_C2[] = {
|
||||
1.0925484305920792f,
|
||||
-1.0925484305920792f,
|
||||
0.31539156525252005f,
|
||||
-1.0925484305920792f,
|
||||
0.5462742152960396f
|
||||
};
|
||||
const float SH_C3[] = {
|
||||
-0.5900435899266435f,
|
||||
2.890611442640554f,
|
||||
-0.4570457994644658f,
|
||||
0.3731763325901154f,
|
||||
-0.4570457994644658f,
|
||||
1.445305721320277f,
|
||||
-0.5900435899266435f
|
||||
};
|
||||
|
||||
// float3 CalculateSHColor(uint Index, uint Degrees, float3 Direction, StructuredBuffer<float3> SHBuffer) {
|
||||
float3 CalculateSHColor(uint Index, uint Degrees, float4x4 DirClr, ByteAddressBuffer SHBuffer) {
|
||||
float3 dir = DirClr[0].xyz;
|
||||
float3 result = DirClr[1].xyz;
|
||||
|
||||
if (Degrees > 0)
|
||||
{
|
||||
float x = dir.x;
|
||||
float y = dir.y;
|
||||
float z = dir.z;
|
||||
result = result - SH_C1 * y * sh(1) + SH_C1 * z * sh(2) - SH_C1 * x * sh(3);
|
||||
|
||||
if (Degrees > 1)
|
||||
{
|
||||
float xx = x * x, yy = y * y, zz = z * z;
|
||||
float xy = x * y, yz = y * z, xz = x * z;
|
||||
result = result +
|
||||
SH_C2[0] * xy * sh(4) +
|
||||
SH_C2[1] * yz * sh(5) +
|
||||
SH_C2[2] * (2.0f * zz - xx - yy) * sh(6) +
|
||||
SH_C2[3] * xz * sh(7) +
|
||||
SH_C2[4] * (xx - yy) * sh(8);
|
||||
|
||||
if (Degrees > 2)
|
||||
{
|
||||
result = result +
|
||||
SH_C3[0] * y * (3.0f * xx - yy) * sh(9) +
|
||||
SH_C3[1] * xy * z * sh(10) +
|
||||
SH_C3[2] * y * (4.0f * zz - xx - yy) * sh(11) +
|
||||
SH_C3[3] * z * (2.0f * zz - 3.0f * xx - 3.0f * yy) * sh(12) +
|
||||
SH_C3[4] * x * (4.0f * zz - xx - yy) * sh(13) +
|
||||
SH_C3[5] * z * (xx - yy) * sh(14) +
|
||||
SH_C3[6] * x * (xx - 3.0f * yy) * sh(15);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return max(result, 0.0f);
|
||||
}
|
||||
|
||||
/*
|
||||
// The implementation is loosely based on code for
|
||||
// "Differentiable Point-Based Radiance Fields for
|
||||
// Efficient View Synthesis" by Zhang et al. (2022)
|
||||
glm::vec3 pos = means[idx];
|
||||
glm::vec3 dir = pos - campos;
|
||||
dir = dir / glm::length(dir);
|
||||
|
||||
glm::vec3* sh = ((glm::vec3*)shs) + idx * max_coeffs;
|
||||
glm::vec3 result = SH_C0 * sh[0];
|
||||
|
||||
if (deg > 0)
|
||||
{
|
||||
float x = dir.x;
|
||||
float y = dir.y;
|
||||
float z = dir.z;
|
||||
result = result - SH_C1 * y * sh[1] + SH_C1 * z * sh[2] - SH_C1 * x * sh[3];
|
||||
|
||||
if (deg > 1)
|
||||
{
|
||||
float xx = x * x, yy = y * y, zz = z * z;
|
||||
float xy = x * y, yz = y * z, xz = x * z;
|
||||
result = result +
|
||||
SH_C2[0] * xy * sh[4] +
|
||||
SH_C2[1] * yz * sh[5] +
|
||||
SH_C2[2] * (2.0f * zz - xx - yy) * sh[6] +
|
||||
SH_C2[3] * xz * sh[7] +
|
||||
SH_C2[4] * (xx - yy) * sh[8];
|
||||
|
||||
if (deg > 2)
|
||||
{
|
||||
result = result +
|
||||
SH_C3[0] * y * (3.0f * xx - yy) * sh[9] +
|
||||
SH_C3[1] * xy * z * sh[10] +
|
||||
SH_C3[2] * y * (4.0f * zz - xx - yy) * sh[11] +
|
||||
SH_C3[3] * z * (2.0f * zz - 3.0f * xx - 3.0f * yy) * sh[12] +
|
||||
SH_C3[4] * x * (4.0f * zz - xx - yy) * sh[13] +
|
||||
SH_C3[5] * z * (xx - yy) * sh[14] +
|
||||
SH_C3[6] * x * (xx - 3.0f * yy) * sh[15];
|
||||
}
|
||||
}
|
||||
}
|
||||
result += 0.5f;
|
||||
|
||||
// RGB colors are clamped to positive values. If values are
|
||||
// clamped, we need to keep track of this for the backward pass.
|
||||
clamped[3 * idx + 0] = (result.x < 0);
|
||||
clamped[3 * idx + 1] = (result.y < 0);
|
||||
clamped[3 * idx + 2] = (result.z < 0);
|
||||
return glm::max(result, 0.0f);
|
||||
*/
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c71f6c8aac32d6e489a61477b1469ca4
|
||||
guid: 6540886fa9a94b64f9d1cdf9197828e7
|
||||
ShaderIncludeImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
@@ -1,6 +0,0 @@
|
||||
// Multiply two 4x4 matrices
|
||||
// Returns C = A * B
|
||||
float4x4 MatrixMultiply(float4x4 A, float4x4 B) {
|
||||
// Matrix multiplication: C[i][j] = sum of A[i][k] * B[k][j]
|
||||
return mul(A, B);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
float cross2(float2 u, float2 v)
|
||||
{
|
||||
return u.x * v.y - u.y * v.x;
|
||||
}
|
||||
|
||||
float4x4 SelectGreaterAxes(
|
||||
float4x4 axes,
|
||||
float2 ss_x,
|
||||
float2 ss_y,
|
||||
float2 ss_z)
|
||||
{
|
||||
float3 axis_x = axes[0].xyz;
|
||||
float3 axis_y = axes[1].xyz;
|
||||
float3 axis_z = axes[2].xyz;
|
||||
|
||||
float4x4 result = (float4x4)0;
|
||||
|
||||
float area_xy = abs(cross2(ss_x, ss_y));
|
||||
float area_xz = abs(cross2(ss_x, ss_z));
|
||||
float area_yz = abs(cross2(ss_y, ss_z));
|
||||
|
||||
if (area_xy > area_xz && area_xy > area_yz)
|
||||
{
|
||||
result[0].xyz = axis_x;
|
||||
result[1].xyz = axis_y;
|
||||
}
|
||||
else if (area_xz > area_xy && area_xz > area_yz)
|
||||
{
|
||||
result[0].xyz = axis_x;
|
||||
result[1].xyz = axis_z;
|
||||
}
|
||||
else
|
||||
{
|
||||
result[0].xyz = axis_y;
|
||||
result[1].xyz = axis_z;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e07830e6ff48d44b80448b30e80f9ed
|
||||
ShaderIncludeImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user