浏览代码

Improve fog parametrization (+optimize)

Mean free path is now achromatic. All 4 scalar parameters can now be packed into a [0, 1] sRGB texture.
"Asymmetry" has been renamed to "anisotropy" in the UI (which is a more familiar term for artists).
/sample_game
Evgenii Golubev 7 年前
当前提交
7c8fbd71
共有 7 个文件被更改,包括 72 次插入57 次删除
  1. 10
      Assets/ScriptableRenderPipeline/Core/ShaderLibrary/VolumeRendering.hlsl
  2. 8
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  3. 58
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/HomogeneousFog.cs
  4. 26
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/HomogeneousFog.cs.hlsl
  5. 11
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/Resources/VolumetricLighting.compute
  6. 8
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  7. 8
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderVariables.hlsl

10
Assets/ScriptableRenderPipeline/Core/ShaderLibrary/VolumeRendering.hlsl


#ifndef UNITY_VOLUME_RENDERING_INCLUDED
#define UNITY_VOLUME_RENDERING_INCLUDED
float OpticalDepthHomogeneous(float extinction, float intervalLength)
{
return extinction * intervalLength;
}
float Transmittance(float opticalDepth)
{
return exp(-opticalDepth);
}
float3 OpticalDepthHomogeneous(float3 extinction, float intervalLength)
{
return extinction * intervalLength;

8
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


: VolumeProperties.GetNeutralVolumeProperties();
if (cs)
{
cmd.SetComputeVectorParam(cs, HDShaderIDs._GlobalFog_Extinction, globalFogProperties.extinction);
cmd.SetComputeFloatParam( cs, HDShaderIDs._GlobalFog_Asymmetry, globalFogProperties.asymmetry);
cmd.SetComputeFloatParam( cs, HDShaderIDs._GlobalFog_Extinction, globalFogProperties.extinction);
cmd.SetComputeFloatParam( cs, HDShaderIDs._GlobalFog_Asymmetry, globalFogProperties.asymmetry);
cmd.SetGlobalVector(HDShaderIDs._GlobalFog_Extinction, globalFogProperties.extinction);
cmd.SetGlobalFloat( HDShaderIDs._GlobalFog_Asymmetry, globalFogProperties.asymmetry);
cmd.SetGlobalFloat( HDShaderIDs._GlobalFog_Extinction, globalFogProperties.extinction);
cmd.SetGlobalFloat( HDShaderIDs._GlobalFog_Asymmetry, globalFogProperties.asymmetry);
}
return (globalFogComponent != null);

58
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/HomogeneousFog.cs


[GenerateHLSL]
public struct VolumeProperties
{
public Vector3 extinction;
public float asymmetry;
public Vector3 scattering;
public float align16;
public Vector3 scattering; // [0, 1], prefer sRGB
public float extinction; // [0, 1], prefer sRGB
public float asymmetry; // Global (scene) property
public float align16_0;
public float align16_1;
public float align16_2;
properties.extinction = Vector3.zero;
properties.scattering = Vector3.zero;
properties.extinction = 0;
properties.scattering = Vector3.zero;
return properties;
}

public class VolumeParameters
{
public Bounds bounds; // Position and dimensions in meters
public Color albedo; // Single scattering albedo [0, 1]
public Vector3 meanFreePath; // In meters [0.01, inf]
public float asymmetry; // [-1, 1]; 0 = isotropic
public Bounds bounds; // Position and dimensions in meters
public Color albedo; // Single scattering albedo [0, 1]
public float meanFreePath; // In meters [1, inf]. Should be chromatic - this is an optimization!
public float anisotropy; // [-1, 1]; 0 = isotropic
meanFreePath = new Vector3(100.0f, 100.0f, 100.0f);
asymmetry = 0.0f;
meanFreePath = 10.0f;
anisotropy = 0.0f;
}
public bool IsVolumeUnbounded()

public Vector3 GetAbsorptionCoefficient()
{
return Vector3.Max(GetExtinctionCoefficient() - GetScatteringCoefficient(), Vector3.zero);
float extinction = GetExtinctionCoefficient();
Vector3 scattering = GetScatteringCoefficient();
return Vector3.Max(new Vector3(extinction, extinction, extinction) - scattering, Vector3.zero);
return new Vector3(albedo.r / meanFreePath.x, albedo.g / meanFreePath.y, albedo.b / meanFreePath.z);
}
float extinction = GetExtinctionCoefficient();
public Vector3 GetExtinctionCoefficient()
{
return new Vector3(1.0f / meanFreePath.x, 1.0f / meanFreePath.y, 1.0f / meanFreePath.z);
return new Vector3(albedo.r * extinction, albedo.g * extinction, albedo.b * extinction);
public void SetAbsorptionAndScatteringCoefficients(Vector3 absorption, Vector3 scattering)
public float GetExtinctionCoefficient()
Debug.Assert(Mathf.Min(absorption.x, absorption.y, absorption.z) >= 0, "The absorption coefficient must be non-negative.");
Debug.Assert(Mathf.Min(scattering.x, scattering.y, scattering.z) >= 0, "The scattering coefficient must be non-negative.");
Vector3 extinction = absorption + scattering;
meanFreePath = new Vector3(1.0f / extinction.x, 1.0f / extinction.y, 1.0f / extinction.z);
albedo = new Color(scattering.x * meanFreePath.x, scattering.y * meanFreePath.y, scattering.z * meanFreePath.z);
Constrain();
return 1.0f / meanFreePath;
}
public void Constrain()

albedo.g = Mathf.Clamp01(albedo.g);
albedo.b = Mathf.Clamp01(albedo.b);
meanFreePath.x = Mathf.Max(meanFreePath.x, 0.01f);
meanFreePath.y = Mathf.Max(meanFreePath.y, 0.01f);
meanFreePath.z = Mathf.Max(meanFreePath.z, 0.01f);
meanFreePath = Mathf.Max(meanFreePath, 1.0f);
asymmetry = Mathf.Clamp(asymmetry, -1.0f, 1.0f);
anisotropy = Mathf.Clamp(anisotropy, -1.0f, 1.0f);
}
public VolumeProperties GetProperties()

properties.scattering = GetScatteringCoefficient();
properties.asymmetry = asymmetry;
properties.asymmetry = anisotropy;
return properties;
}

26
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/HomogeneousFog.cs.hlsl


// PackingRules = Exact
struct VolumeProperties
{
float3 extinction;
float3 scattering;
float extinction;
float3 scattering;
float align16;
float align16_0;
float align16_1;
float align16_2;
float3 GetExtinction(VolumeProperties value)
float3 GetScattering(VolumeProperties value)
{
return value.scattering;
}
float GetExtinction(VolumeProperties value)
{
return value.extinction;
}

}
float3 GetScattering(VolumeProperties value)
float GetAlign16_0(VolumeProperties value)
{
return value.align16_0;
}
float GetAlign16_1(VolumeProperties value)
return value.scattering;
return value.align16_1;
float GetAlign16(VolumeProperties value)
float GetAlign16_2(VolumeProperties value)
return value.align16;
return value.align16_2;
}

11
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/Volumetrics/Resources/VolumetricLighting.compute


// Computes the in-scattered radiance along the ray.
float3 PerformIntegration(PositionInputs posInput, Ray ray, uint numSteps)
{
float3 extinction = _GlobalFog_Extinction;
float asymmetry = _GlobalFog_Asymmetry;
float extinction = _GlobalFog_Extinction;
float asymmetry = _GlobalFog_Asymmetry;
LightLoopContext context;
// ZERO_INITIALIZE(LightLoopContext, context);

// Note: we apply the scattering coefficient and the constant part of the phase function later.
intensity *= HenyeyGreensteinPhasePartVarying(asymmetry, dot(L, ray.directionWS));
color *= Transmittance(OpticalDepthHomogeneous(extinction, dist));
intensity *= Transmittance(OpticalDepthHomogeneous(extinction, dist));
[branch] if (lightData.shadowIndex >= 0)
{

}
}
radiance += sampleRadiance * Transmittance(OpticalDepthHomogeneous(extinction, t)) * dt;
radiance += sampleRadiance * (Transmittance(OpticalDepthHomogeneous(extinction, t)) * dt);
}
float3 phaseConstant = scattering * HenyeyGreensteinPhasePartConstant(asymmetry);

cameraRay.maxLength = sqrt(dot(cameraRay.directionWS, cameraRay.directionWS));
cameraRay.directionWS *= rsqrt(dot(cameraRay.directionWS, cameraRay.directionWS)); // Normalize
float3 rayT = Transmittance(OpticalDepthHomogeneous(_GlobalFog_Extinction, cameraRay.maxLength));
float rayT = Transmittance(OpticalDepthHomogeneous(_GlobalFog_Extinction, cameraRay.maxLength));
const int numSamples = 64;
float3 inL = PerformIntegration(posInput, cameraRay, numSamples);

8
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


float3x3 ltcCoatT;
#ifdef VOLUMETRIC_SHADOWING_ENABLED
float3 globalFogExtinction;
float globalFogExtinction;
#endif
};

}
#ifdef VOLUMETRIC_SHADOWING_ENABLED
float3 volumetricShadow = Transmittance(OpticalDepthHomogeneous(preLightData.globalFogExtinction, dist));
float volumetricShadow = Transmittance(OpticalDepthHomogeneous(preLightData.globalFogExtinction, dist));
lightData.color *= volumetricShadow;
lightData.diffuseScale *= volumetricShadow;
lightData.specularScale *= volumetricShadow;
#endif
// Projector lights always have a cookies, so we can perform clipping inside the if().

8
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderVariables.hlsl


// Volumetric lighting. Should be a struct in 'UnityPerFrame'.
// Unfortunately, we cannot modify the layout of 'UnityPerFrame',
// and structures inside constant buffers are not supported by Unity.
float3 _GlobalFog_Extinction;
float _GlobalFog_Asymmetry;
float _GlobalFog_Align16;
float _GlobalFog_Extinction;
float _GlobalFog_Asymmetry;
float _GlobalFog_Align16_0;
float _GlobalFog_Align16_1;
float _GlobalFog_Align16_2;
CBUFFER_END
#ifdef USE_LEGACY_UNITY_MATRIX_VARIABLES

正在加载...
取消
保存