Evgenii Golubev
8 年前
当前提交
60fc261c
共有 8 个文件被更改,包括 1064 次插入 和 15 次删除
-
53Assets/ScriptableRenderLoop/HDRenderLoop/Sky/Resources/SkyHDRI.shader
-
1Assets/ScriptableRenderLoop/HDRenderLoop/Sky/SkyRenderer.cs
-
147Assets/TestScenes/HDTest/HDRenderLoopTest.unity
-
390Assets/ScriptableRenderLoop/HDRenderLoop/Sky/AtmosphericParameters.cs
-
12Assets/ScriptableRenderLoop/HDRenderLoop/Sky/AtmosphericParameters.cs.meta
-
113Assets/ScriptableRenderLoop/HDRenderLoop/Sky/README.txt
-
354Assets/ScriptableRenderLoop/HDRenderLoop/Sky/Resources/AtmosphericScattering.hlsl
-
9Assets/ScriptableRenderLoop/HDRenderLoop/Sky/Resources/AtmosphericScattering.hlsl.meta
|
|||
using UnityEngine; |
|||
|
|||
[ExecuteInEditMode] |
|||
public class AtmosphericParameters : MonoBehaviour |
|||
{ |
|||
public enum OcclusionDownscale { x1 = 1, x2 = 2, x4 = 4 } |
|||
public enum OcclusionSamples { x64 = 0, x164 = 1, x244 = 2 } |
|||
public enum DepthTexture { Enable, Disable/*, Ignore*/ } // 'Ignore' appears to be currently unused.
|
|||
public enum ScatterDebugMode { None, Scattering, Occlusion, OccludedScattering, Rayleigh, Mie, Height } |
|||
|
|||
[Header("Global Settings")] |
|||
public Gradient worldRayleighColorRamp = null; |
|||
public float worldRayleighColorIntensity = 1f; |
|||
public float worldRayleighDensity = 10f; |
|||
public float worldRayleighExtinctionFactor = 1.1f; |
|||
public float worldRayleighIndirectScatter = 0.33f; |
|||
public Gradient worldMieColorRamp = null; |
|||
public float worldMieColorIntensity = 1f; |
|||
public float worldMieDensity = 15f; |
|||
public float worldMieExtinctionFactor = 0f; |
|||
public float worldMiePhaseAnisotropy = 0.9f; |
|||
public float worldNearScatterPush = 0f; |
|||
public float worldNormalDistance = 1000f; |
|||
|
|||
[Header("Height Settings")] |
|||
public Color heightRayleighColor = Color.white; |
|||
public float heightRayleighIntensity = 1f; |
|||
public float heightRayleighDensity = 10f; |
|||
public float heightMieDensity = 0f; |
|||
public float heightExtinctionFactor = 1.1f; |
|||
public float heightSeaLevel = 0f; |
|||
public float heightDistance = 50f; |
|||
public Vector3 heightPlaneShift = Vector3.zero; |
|||
public float heightNearScatterPush = 0f; |
|||
public float heightNormalDistance = 1000f; |
|||
|
|||
[Header("Sky Dome")] |
|||
/*public*/ Vector3 skyDomeScale = new Vector3(1f, 1f, 1f); |
|||
/*public*/ Vector3 skyDomeRotation = Vector3.zero; |
|||
/*public*/ Transform skyDomeTrackedYawRotation = null; |
|||
/*public*/ bool skyDomeVerticalFlip = false; |
|||
/*public*/ Cubemap skyDomeCube = null; |
|||
/*public*/ float skyDomeExposure = 1f; |
|||
/*public*/ Color skyDomeTint = Color.white; |
|||
/*public*/ Vector3 skyDomeOffset = Vector3.zero; |
|||
|
|||
/* |
|||
[Header("Scatter Occlusion")] |
|||
public bool useOcclusion = false; |
|||
public float occlusionBias = 0f; |
|||
public float occlusionBiasIndirect = 0.6f; |
|||
public float occlusionBiasClouds = 0.3f; |
|||
public OcclusionDownscale occlusionDownscale = OcclusionDownscale.x2; |
|||
public OcclusionSamples occlusionSamples = OcclusionSamples.x64; |
|||
public bool occlusionDepthFixup = true; |
|||
public float occlusionDepthThreshold = 25f; |
|||
public bool occlusionFullSky = false; |
|||
public float occlusionBiasSkyRayleigh = 0.2f; |
|||
public float occlusionBiasSkyMie = 0.4f; |
|||
*/ |
|||
|
|||
[Header("Other")] |
|||
public Shader atmosphericShaderOverride = null; |
|||
// public Shader occlusionShaderOverride = null;
|
|||
public float worldScaleExponent = 1.0f; |
|||
// public bool forcePerPixel = true;
|
|||
// public bool forcePostEffect = true;
|
|||
[Tooltip("Soft clouds need depth values. Ignore means externally controlled.")] |
|||
public DepthTexture depthTexture = DepthTexture.Enable; |
|||
public ScatterDebugMode debugMode = ScatterDebugMode.None; |
|||
|
|||
// [HideInInspector] public Shader occlusionShaderOverride;
|
|||
|
|||
// Camera m_currentCamera;
|
|||
|
|||
// UnityEngine.Rendering.CommandBuffer m_occlusionCmdAfterShadows, m_occlusionCmdBeforeScreen;
|
|||
|
|||
Material m_atmosphericMaterial = null; |
|||
// Material m_occlusionMaterial = null;
|
|||
bool m_isAwake = false; |
|||
|
|||
public static AtmosphericParameters instance { get; private set; } |
|||
|
|||
void Awake() |
|||
{ |
|||
if (worldRayleighColorRamp == null) |
|||
{ |
|||
worldRayleighColorRamp = new Gradient(); |
|||
worldRayleighColorRamp.SetKeys( |
|||
new[] { new GradientColorKey(new Color(0.3f, 0.4f, 0.6f), 0f), |
|||
new GradientColorKey(new Color(0.5f, 0.6f, 0.8f), 1f) }, |
|||
new[] { new GradientAlphaKey(1f, 0f), |
|||
new GradientAlphaKey(1f, 1f) } |
|||
); |
|||
} |
|||
|
|||
if (worldMieColorRamp == null) |
|||
{ |
|||
worldMieColorRamp = new Gradient(); |
|||
worldMieColorRamp.SetKeys( |
|||
new[] { new GradientColorKey(new Color(0.95f, 0.75f, 0.5f), 0f), |
|||
new GradientColorKey(new Color(1f, 0.9f, 8.0f), 1f) }, |
|||
new[] { new GradientAlphaKey(1f, 0f), |
|||
new GradientAlphaKey(1f, 1f) } |
|||
); |
|||
} |
|||
|
|||
if (atmosphericShaderOverride != null) |
|||
{ |
|||
// Override the default shader.
|
|||
m_atmosphericMaterial = new Material(atmosphericShaderOverride); |
|||
m_atmosphericMaterial.hideFlags = HideFlags.HideAndDontSave; |
|||
} |
|||
|
|||
/* |
|||
if (occlusionShaderOverride != null) |
|||
{ |
|||
// Override the default shader.
|
|||
m_occlusionMaterial = new Material(occlusionShaderOverride); |
|||
m_occlusionMaterial.hideFlags = HideFlags.HideAndDontSave; |
|||
} |
|||
*/ |
|||
|
|||
m_isAwake = true; |
|||
} |
|||
|
|||
public void OnValidate() |
|||
{ |
|||
if (!m_isAwake) return; |
|||
|
|||
Light light = gameObject.GetComponentInParent<Light>(); |
|||
|
|||
if (light == null || light.type != LightType.Directional) |
|||
{ |
|||
Debug.LogErrorFormat("Unexpected: AtmosphericParameters is not attached to a directional light."); |
|||
return; |
|||
} |
|||
|
|||
worldScaleExponent = Mathf.Clamp(worldScaleExponent, 1f, 2f); |
|||
worldNormalDistance = Mathf.Clamp(worldNormalDistance, 1f, 10000f); |
|||
worldNearScatterPush = Mathf.Clamp(worldNearScatterPush, -200f, 300f); |
|||
worldRayleighDensity = Mathf.Clamp(worldRayleighDensity, 0, 1000f); |
|||
worldMieDensity = Mathf.Clamp(worldMieDensity, 0f, 1000f); |
|||
worldRayleighIndirectScatter = Mathf.Clamp(worldRayleighIndirectScatter, 0f, 1f); |
|||
worldMiePhaseAnisotropy = Mathf.Clamp01(worldMiePhaseAnisotropy); |
|||
|
|||
heightNormalDistance = Mathf.Clamp(heightNormalDistance, 1f, 10000f); |
|||
heightNearScatterPush = Mathf.Clamp(heightNearScatterPush, -200f, 300f); |
|||
heightRayleighDensity = Mathf.Clamp(heightRayleighDensity, 0, 1000f); |
|||
heightMieDensity = Mathf.Clamp(heightMieDensity, 0, 1000f); |
|||
|
|||
/* |
|||
occlusionBias = Mathf.Clamp01(occlusionBias); |
|||
occlusionBiasIndirect = Mathf.Clamp01(occlusionBiasIndirect); |
|||
occlusionBiasClouds = Mathf.Clamp01(occlusionBiasClouds); |
|||
occlusionBiasSkyRayleigh = Mathf.Clamp01(occlusionBiasSkyRayleigh); |
|||
occlusionBiasSkyMie = Mathf.Clamp01(occlusionBiasSkyMie); |
|||
*/ |
|||
|
|||
skyDomeExposure = Mathf.Clamp(skyDomeExposure, 0f, 8f); |
|||
|
|||
if (instance == this) |
|||
{ |
|||
// TODO: what's the point of doing this?
|
|||
OnDisable(); |
|||
OnEnable(); |
|||
} |
|||
|
|||
// TODO: why would I want to do that here?
|
|||
// #if UNITY_EDITOR
|
|||
// UnityEditor.SceneView.RepaintAll();
|
|||
// #endif
|
|||
} |
|||
|
|||
void OnEnable() |
|||
{ |
|||
if (!m_isAwake) return; |
|||
|
|||
// Define select preprocessor symbols.
|
|||
UpdateKeywords(true); |
|||
|
|||
if (depthTexture == DepthTexture.Disable) |
|||
{ |
|||
// Disable depth texture rendering.
|
|||
Camera.current.depthTextureMode = DepthTextureMode.None; |
|||
} |
|||
|
|||
// Set shader constants.
|
|||
UpdateStaticUniforms(); |
|||
UpdateDynamicUniforms(); |
|||
|
|||
if (instance && instance != this) |
|||
{ |
|||
Debug.LogErrorFormat("Unexpected: AtmosphericParameters.instance already set (to: {0}). Still overriding with: {1}.", instance.name, name); |
|||
} |
|||
|
|||
instance = this; |
|||
} |
|||
|
|||
void OnDisable() |
|||
{ |
|||
// Undefine all preprocessor symbols.
|
|||
UpdateKeywords(false); |
|||
|
|||
if (instance && instance != this) |
|||
{ |
|||
Debug.LogErrorFormat("Unexpected: AtmosphericParameters.instance set to: {0}, not to: {1}. Leaving alone.", instance.name, name); |
|||
} |
|||
else |
|||
{ |
|||
instance = null; |
|||
} |
|||
} |
|||
|
|||
void UpdateKeywords(bool enable) |
|||
{ |
|||
Shader.DisableKeyword("ATMOSPHERICS_OCCLUSION"); |
|||
Shader.DisableKeyword("ATMOSPHERICS_OCCLUSION_FULLSKY"); |
|||
Shader.DisableKeyword("ATMOSPHERICS_OCCLUSION_EDGE_FIXUP"); |
|||
Shader.DisableKeyword("ATMOSPHERICS_SUNRAYS"); |
|||
Shader.DisableKeyword("ATMOSPHERICS_DEBUG"); |
|||
|
|||
if (enable) |
|||
{ |
|||
/* |
|||
if (useOcclusion) |
|||
{ |
|||
Shader.EnableKeyword("ATMOSPHERICS_OCCLUSION"); |
|||
|
|||
if(occlusionDepthFixup && occlusionDownscale != OcclusionDownscale.x1) |
|||
Shader.EnableKeyword("ATMOSPHERICS_OCCLUSION_EDGE_FIXUP"); |
|||
|
|||
if(occlusionFullSky) |
|||
Shader.EnableKeyword("ATMOSPHERICS_OCCLUSION_FULLSKY"); |
|||
} |
|||
*/ |
|||
|
|||
if (debugMode != ScatterDebugMode.None) |
|||
{ |
|||
Shader.EnableKeyword("ATMOSPHERICS_DEBUG"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void UpdateStaticUniforms() |
|||
{ |
|||
Shader.SetGlobalVector("_SkyDomeOffset", skyDomeOffset); |
|||
Shader.SetGlobalVector("_SkyDomeScale", skyDomeScale); |
|||
Shader.SetGlobalTexture("_SkyDomeCube", skyDomeCube); |
|||
Shader.SetGlobalFloat("_SkyDomeExposure", skyDomeExposure); |
|||
Shader.SetGlobalColor("_SkyDomeTint", skyDomeTint); |
|||
|
|||
/* |
|||
Shader.SetGlobalFloat("_ShadowBias", useOcclusion ? occlusionBias : 1f); |
|||
Shader.SetGlobalFloat("_ShadowBiasIndirect", useOcclusion ? occlusionBiasIndirect : 1f); |
|||
Shader.SetGlobalFloat("_ShadowBiasClouds", useOcclusion ? occlusionBiasClouds : 1f); |
|||
Shader.SetGlobalVector("_ShadowBiasSkyRayleighMie", useOcclusion ? new Vector4(occlusionBiasSkyRayleigh, occlusionBiasSkyMie, 0f, 0f) : Vector4.zero); |
|||
Shader.SetGlobalFloat("_OcclusionDepthThreshold", occlusionDepthThreshold); |
|||
*/ |
|||
|
|||
Shader.SetGlobalFloat("_WorldScaleExponent", worldScaleExponent); |
|||
|
|||
Shader.SetGlobalFloat("_WorldNormalDistanceRcp", 1f/worldNormalDistance); |
|||
Shader.SetGlobalFloat("_WorldNearScatterPush", -Mathf.Pow(Mathf.Abs(worldNearScatterPush), worldScaleExponent) * Mathf.Sign(worldNearScatterPush)); |
|||
|
|||
Shader.SetGlobalFloat("_WorldRayleighDensity", -worldRayleighDensity / 100000f); |
|||
Shader.SetGlobalFloat("_MiePhaseAnisotropy", worldMiePhaseAnisotropy); |
|||
Shader.SetGlobalVector("_RayleighInScatterPct", new Vector4(1f - worldRayleighIndirectScatter, worldRayleighIndirectScatter, 0f, 0f)); |
|||
|
|||
Shader.SetGlobalFloat("_HeightNormalDistanceRcp", 1f/heightNormalDistance); |
|||
Shader.SetGlobalFloat("_HeightNearScatterPush", -Mathf.Pow(Mathf.Abs(heightNearScatterPush), worldScaleExponent) * Mathf.Sign(heightNearScatterPush)); |
|||
Shader.SetGlobalFloat("_HeightRayleighDensity", -heightRayleighDensity / 100000f); |
|||
|
|||
Shader.SetGlobalFloat("_HeightSeaLevel", heightSeaLevel); |
|||
Shader.SetGlobalFloat("_HeightDistanceRcp", 1f/heightDistance); |
|||
Shader.SetGlobalVector("_HeightPlaneShift", heightPlaneShift); |
|||
Shader.SetGlobalVector("_HeightRayleighColor", (Vector4)heightRayleighColor * heightRayleighIntensity); |
|||
Shader.SetGlobalFloat("_HeightExtinctionFactor", heightExtinctionFactor); |
|||
Shader.SetGlobalFloat("_RayleighExtinctionFactor", worldRayleighExtinctionFactor); |
|||
Shader.SetGlobalFloat("_MieExtinctionFactor", worldMieExtinctionFactor); |
|||
|
|||
var rayleighColorM20 = worldRayleighColorRamp.Evaluate(0.00f); |
|||
var rayleighColorM10 = worldRayleighColorRamp.Evaluate(0.25f); |
|||
var rayleighColorO00 = worldRayleighColorRamp.Evaluate(0.50f); |
|||
var rayleighColorP10 = worldRayleighColorRamp.Evaluate(0.75f); |
|||
var rayleighColorP20 = worldRayleighColorRamp.Evaluate(1.00f); |
|||
|
|||
var mieColorM20 = worldMieColorRamp.Evaluate(0.00f); |
|||
var mieColorO00 = worldMieColorRamp.Evaluate(0.50f); |
|||
var mieColorP20 = worldMieColorRamp.Evaluate(1.00f); |
|||
|
|||
Shader.SetGlobalVector("_RayleighColorM20", (Vector4)rayleighColorM20 * worldRayleighColorIntensity); |
|||
Shader.SetGlobalVector("_RayleighColorM10", (Vector4)rayleighColorM10 * worldRayleighColorIntensity); |
|||
Shader.SetGlobalVector("_RayleighColorO00", (Vector4)rayleighColorO00 * worldRayleighColorIntensity); |
|||
Shader.SetGlobalVector("_RayleighColorP10", (Vector4)rayleighColorP10 * worldRayleighColorIntensity); |
|||
Shader.SetGlobalVector("_RayleighColorP20", (Vector4)rayleighColorP20 * worldRayleighColorIntensity); |
|||
|
|||
Shader.SetGlobalVector("_MieColorM20", (Vector4)mieColorM20 * worldMieColorIntensity); |
|||
Shader.SetGlobalVector("_MieColorO00", (Vector4)mieColorO00 * worldMieColorIntensity); |
|||
Shader.SetGlobalVector("_MieColorP20", (Vector4)mieColorP20 * worldMieColorIntensity); |
|||
|
|||
Shader.SetGlobalInt("_AtmosphericsDebugMode", (int)debugMode); |
|||
} |
|||
|
|||
void OnWillRenderObject() |
|||
{ |
|||
/* |
|||
if (!m_isAwake) return; |
|||
|
|||
// For now, we only use the directional light we are attached to, and the current camera.
|
|||
|
|||
if (depthTexture == DepthTexture.Disable) |
|||
{ |
|||
// Disable depth texture rendering.
|
|||
Camera.current.depthTextureMode = DepthTextureMode.None; |
|||
} |
|||
|
|||
// Set shader constants.
|
|||
UpdateDynamicUniforms(); |
|||
|
|||
|
|||
if (useOcclusion) { |
|||
var camRgt = m_currentCamera.transform.right; |
|||
var camUp = m_currentCamera.transform.up; |
|||
var camFwd = m_currentCamera.transform.forward; |
|||
|
|||
var dy = Mathf.Tan(m_currentCamera.fieldOfView * 0.5f * Mathf.Deg2Rad); |
|||
var dx = dy * m_currentCamera.aspect; |
|||
|
|||
var vpCenter = camFwd * m_currentCamera.farClipPlane; |
|||
var vpRight = camRgt * dx * m_currentCamera.farClipPlane; |
|||
var vpUp = camUp * dy * m_currentCamera.farClipPlane; |
|||
|
|||
m_occlusionMaterial.SetVector("_CameraPosition", m_currentCamera.transform.position); |
|||
m_occlusionMaterial.SetVector("_ViewportCorner", vpCenter - vpRight - vpUp); |
|||
m_occlusionMaterial.SetVector("_ViewportRight", vpRight * 2f); |
|||
m_occlusionMaterial.SetVector("_ViewportUp", vpUp * 2f); |
|||
var farDist = m_currentCamera ? m_currentCamera.farClipPlane : 1000f; |
|||
var refDist = (Mathf.Min(farDist, QualitySettings.shadowDistance) - 1f) / farDist; |
|||
m_occlusionMaterial.SetFloat("_OcclusionSkyRefDistance", refDist); |
|||
|
|||
var srcRect = m_currentCamera.pixelRect; |
|||
var downscale = 1f / (float)(int)occlusionDownscale; |
|||
var occWidth = Mathf.RoundToInt(srcRect.width * downscale); |
|||
var occHeight = Mathf.RoundToInt(srcRect.height * downscale); |
|||
var occlusionId = Shader.PropertyToID("_OcclusionTexture"); |
|||
|
|||
m_occlusionCmdBeforeScreen.Clear(); |
|||
m_occlusionCmdBeforeScreen.GetTemporaryRT(occlusionId, occWidth, occHeight, 0, FilterMode.Bilinear, RenderTextureFormat.R8, RenderTextureReadWrite.sRGB); |
|||
m_occlusionCmdBeforeScreen.Blit( |
|||
null, |
|||
occlusionId, |
|||
m_occlusionMaterial, |
|||
(int)occlusionSamples |
|||
); |
|||
m_occlusionCmdBeforeScreen.SetGlobalTexture(occlusionId, occlusionId); |
|||
} |
|||
*/ |
|||
} |
|||
|
|||
void UpdateDynamicUniforms() |
|||
{ |
|||
/* For now, we only use the directional light we are attached to, and the current camera. */ |
|||
|
|||
var trackedYaw = skyDomeTrackedYawRotation ? skyDomeTrackedYawRotation.eulerAngles.y : 0f; |
|||
Shader.SetGlobalMatrix("_SkyDomeRotation", |
|||
Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(skyDomeRotation.x, 0f, 0f), Vector3.one) |
|||
* Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0f, skyDomeRotation.y - trackedYaw, 0f), Vector3.one) |
|||
* Matrix4x4.TRS(Vector3.zero, Quaternion.identity, new Vector3(1f, skyDomeVerticalFlip ? -1f : 1f, 1f)) |
|||
); |
|||
|
|||
Shader.SetGlobalVector("_SunDirection", -transform.forward); |
|||
Shader.SetGlobalFloat("_WorldMieDensity", -worldMieDensity / 100000f); |
|||
Shader.SetGlobalFloat("_HeightMieDensity", -heightMieDensity / 100000f); |
|||
|
|||
var pixelRect = Camera.current ? Camera.current.pixelRect |
|||
: new Rect(0f, 0f, Screen.width, Screen.height); |
|||
var scale = 1.0f; //(float)(int)occlusionDownscale;
|
|||
var depthTextureScaledTexelSize = new Vector4(scale / pixelRect.width, |
|||
scale / pixelRect.height, |
|||
-scale / pixelRect.width, |
|||
-scale / pixelRect.height); |
|||
Shader.SetGlobalVector("_DepthTextureScaledTexelSize", depthTextureScaledTexelSize); |
|||
} |
|||
|
|||
void OnRenderObject() |
|||
{ |
|||
/* This component is not rendered directly. */ |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 97f65a78ace4fbf4187144e9fe724009 |
|||
timeCreated: 1479992550 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
# Atmospheric Scattering |
|||
|
|||
Atmospheric scattering is a solution developed for nicer aerial perspective in The Blacksmith. It provides a model emulating atmospheric Rayleigh, Mie and height scattering (and also takes a lot of shortcuts in the name of performance and artistic control). Take a look at the blog post at this address http://blogs.unity3d.com/?p=27218 to get a high-level overview of the components making up the final composition. |
|||
|
|||
|
|||
### Options description |
|||
|
|||
This component comes with quite a lot of options - but you normally don't have to tweak more than a handful of them to get good results - start with the densities and colors and that will get you started nicely. |
|||
|
|||
|
|||
#### World Components |
|||
|
|||
**World Rayleigh Color Ramp**: The color or colors used for rayleigh scattering. It's a ramp instead of a single color because you can have different scattering colors depending on the angle to the unit being shaded. Values to the left in the ramp are mapped to angles below horizon, whereas values to the right are mapped to angles above the horizon. |
|||
|
|||
**World Rayleigh Color Intensity**: An HDR color scale for the rayleigh color ramp. |
|||
|
|||
**World Rayleigh Density**: The density of the rayleigh component. |
|||
|
|||
**World Rayleigh Extinction Factor**: How much light is out-scattered or absorbed on its way to the eye. Basically how much to darken the shaded pixel. |
|||
|
|||
**World Rayleigh Indirect Scatter**: Which percentage of the rayleigh scattering should be considered 'indirect' scattering. (relevant for occlusion only) |
|||
|
|||
**World Mie Color Ramp**: The color or colors used for mie scattering. It's a ramp instead of a single color because you can have different scattering colors depending on the angle to the unit being shaded. Values to the left in the ramp are mapped to angles below horizon, whereas values to the right are mapped to angles above the horizon. |
|||
|
|||
**World Mie Color Intensity**: An HDR color scale for the mie color ramp. |
|||
|
|||
**World Mie Density**: The density of the mie component. |
|||
|
|||
**World Mie Extinction Factor**: How much light is out-scattered or absorbed on its way to the eye. Basically how much to darken the shaded pixel. |
|||
|
|||
**World Mie Phase Anisotropy**: How focused the forward directionality of the mie scattering is. Values close to 1 produce a small, very sharp mie component, whereas values below 0.5 creates a very large and unfocused mie component. |
|||
|
|||
**World Near Scatter Push**: Allows the scattering to be pushed out to have no scattering directly in front of the camera, or pulled in to have more scattering close to the camera. |
|||
|
|||
**World Normal Distance**: A measure of the scale of the scene. Essentially this desaturates the scattering near the camera, and interpolates into full color ramp at the edge of the specified distance. |
|||
|
|||
|
|||
#### Height Components |
|||
|
|||
**Height Rayleigh Color**: The general global scattering color for height fog. |
|||
|
|||
**Height Rayleigh Intensity**: An HDR color scale for the height global fog color. |
|||
|
|||
**Height Rayleigh Density**: The density of the global height fog. |
|||
|
|||
**Height Mie Density**: The density of the mie scattering being added to the global height fog. |
|||
|
|||
**Height Extinction Factor**: How much light is out-scattered or absorbed on its way to the eye. Basically how much to darken the shaded pixel. |
|||
|
|||
**Height Sea Level**: Sea level height offset from origin. |
|||
|
|||
**Height Distance**: Falloff distance from sea level |
|||
|
|||
**Height Plane Shift**: An optional plane vector for a tilted sea level. |
|||
|
|||
**Height Near Scatter Push**: Allows the scattering to be pushed out to have no scattering directly in front of the camera, or pulled in to have more scattering close to the camera. |
|||
|
|||
**Height Normal Distance**: A measure of the scale of the scene. Essentially this desaturates the scattering near the camera, and interpolates into full color at the edge of the specified distance. |
|||
|
|||
|
|||
#### Sky Dome |
|||
|
|||
**Sky Dome Scale**: The scale of the skydome. We use this to virtually squash the sky sphere into behaving like a dome. The xz-dimensions affect how much scattering the horizon picks up, whereas the y-dimension dictates how far up on the sky the scattering is blended. |
|||
|
|||
**Sky Dome Rotation**: An optional rotation of the skydome. Usually, only Y-rotation makes sense. |
|||
|
|||
**Sky Dome Tracked Yaw Rotation**: Optionally have the skydome rotate to track a transform, typically a light source. Use in combination with rotation to perfectly align and track the sun to the skydome. |
|||
|
|||
**Sky Dome Vertical Flip**: We have the option of putting two skybox textures into the same cubemap. This flags flips the UV projection to show the bottom half instead of the top half. |
|||
|
|||
**Sky Dome Cube**: An HDR cubemap to use as sky dome. |
|||
|
|||
**Sky Dome Exposure**: The exposure of the sky cubemap. |
|||
|
|||
**Sky Dome Tint**: Tint color for the cubemap. |
|||
|
|||
|
|||
#### Scatter Occlusion |
|||
|
|||
**Use Occlusion**: This flag enables scatter occlusion. |
|||
|
|||
**Occlusion Bias**: Controls how strongly occlusion affects direct scattering. |
|||
|
|||
**Occlusion BiasIndirect**: Controls how strongly occlusion affects indirect scattering. |
|||
|
|||
**Occlusion BiasClouds**: Controls how strongly occlusion affects placed clouds. |
|||
|
|||
**Occlusion Downscale**: Controls the downscale factor for occlusion gathering. |
|||
|
|||
**Occlusion Samples**: The number of samples to use in gathering. |
|||
|
|||
**Occlusion DepthFixup**: Whether to attempt to fix upsampling across depth discontinuities (currently d3d11 only). |
|||
|
|||
**Occlusion DepthThreshold**: The threshold defining discontinuous depth. |
|||
|
|||
**Occlusion FullSky**: Whether to gather occlusion even for skydome pixels. |
|||
|
|||
**Occlusion BiasSkyRayleigh **: Controls how strongly occlusion affects rayleigh scattering on the skydome. |
|||
|
|||
**Occlusion BiasSkyMie **: Controls how strongly occlusion affects mie scattering on the skydome. |
|||
|
|||
|
|||
#### Other |
|||
|
|||
**World ScaleExponent**: An option to exponentially scale the world for scattering calculations (fake aerial perspective in small scenes). |
|||
|
|||
**Force Per Pixel**: Force all scatter calculations to run at per-pixel frequency. |
|||
|
|||
**Force Post Effect**: Force all scatter calculations to run in a post-process (requires the AtmosphericScatteringDeferred component on the camera, and doesn't apply to transparent object) |
|||
|
|||
**Depth Texture**: Whether to enable, disable or leave alone the camera depth texture settings. (required for depth fixup and soft cloud planes) |
|||
|
|||
**Debug Mode**: Various debug visualizations of the different rendering components. |
|
|||
#ifndef FILE_ATMOSPHERICSCATTERING |
|||
#define FILE_ATMOSPHERICSCATTERING |
|||
|
|||
#define ATMOSPHERICS_DBG_NONE 0 |
|||
#define ATMOSPHERICS_DBG_SCATTERING 1 |
|||
#define ATMOSPHERICS_DBG_OCCLUSION 2 |
|||
#define ATMOSPHERICS_DBG_OCCLUDEDSCATTERING 3 |
|||
#define ATMOSPHERICS_DBG_RAYLEIGH 4 |
|||
#define ATMOSPHERICS_DBG_MIE 5 |
|||
#define ATMOSPHERICS_DBG_HEIGHT 6 |
|||
|
|||
uniform int _AtmosphericsDebugMode; |
|||
|
|||
uniform float3 _SunDirection; |
|||
|
|||
uniform float _ShadowBias; |
|||
uniform float _ShadowBiasIndirect; |
|||
uniform float _ShadowBiasClouds; |
|||
uniform float _OcclusionDepthThreshold; |
|||
uniform float4 _OcclusionTexture_TexelSize; |
|||
|
|||
uniform float4 _DepthTextureScaledTexelSize; |
|||
|
|||
uniform float _WorldScaleExponent; |
|||
uniform float _WorldNormalDistanceRcp; |
|||
uniform float _WorldNearScatterPush; |
|||
uniform float _WorldRayleighDensity; |
|||
uniform float _WorldMieDensity; |
|||
|
|||
uniform float3 _RayleighColorM20; |
|||
uniform float3 _RayleighColorM10; |
|||
uniform float3 _RayleighColorO00; |
|||
uniform float3 _RayleighColorP10; |
|||
uniform float3 _RayleighColorP20; |
|||
uniform float3 _RayleighColorP45; |
|||
|
|||
uniform float3 _MieColorM20; |
|||
uniform float3 _MieColorO00; |
|||
uniform float3 _MieColorP20; |
|||
uniform float3 _MieColorP45; |
|||
|
|||
uniform float _HeightNormalDistanceRcp; |
|||
uniform float _HeightNearScatterPush; |
|||
uniform float _HeightRayleighDensity; |
|||
uniform float _HeightMieDensity; |
|||
uniform float _HeightSeaLevel; |
|||
uniform float3 _HeightPlaneShift; |
|||
uniform float _HeightDistanceRcp; |
|||
|
|||
uniform float _RayleighCoeffScale; |
|||
uniform float3 _RayleighSunTintIntensity; |
|||
uniform float2 _RayleighInScatterPct; |
|||
|
|||
uniform float _MieCoeffScale; |
|||
uniform float3 _MieSunTintIntensity; |
|||
uniform float _MiePhaseAnisotropy; |
|||
|
|||
uniform float _HeightExtinctionFactor; |
|||
uniform float _RayleighExtinctionFactor; |
|||
uniform float _MieExtinctionFactor; |
|||
|
|||
uniform float4 _HeightRayleighColor; |
|||
|
|||
SAMPLER2D(sampler_CameraDepthTexture) |
|||
#define SRL_BilinearSampler sampler_CameraDepthTexture // Used for all textures |
|||
|
|||
TEXTURE2D(_CameraDepthTexture); |
|||
TEXTURE2D(_OcclusionTexture); |
|||
|
|||
float HenyeyGreensteinPhase(float g, float cosTheta) { |
|||
float gSqr = g * g; |
|||
float a1 = (1.f - gSqr); |
|||
float a2 = (2.f + gSqr); |
|||
float b1 = 1.f + cosTheta * cosTheta; |
|||
float b2 = pow(abs(1.f + gSqr - 2.f * g * cosTheta), 1.5f); |
|||
return (a1 / a2) * (b1 / b2); |
|||
} |
|||
|
|||
float RayleighPhase(float cosTheta) { |
|||
const float f = 3.f / (16.f * PI); |
|||
return f + f * cosTheta * cosTheta; |
|||
} |
|||
|
|||
float MiePhase(float cosTheta, float anisotropy) { |
|||
const float f = 3.f / (8.f * PI); |
|||
return f * HenyeyGreensteinPhase(anisotropy, cosTheta); |
|||
} |
|||
|
|||
float HeightDensity(float h, float H) { |
|||
return exp(-h/H); |
|||
} |
|||
|
|||
float3 WorldScale(float3 p) { |
|||
p.xz = sign(p.xz) * pow(abs(p.xz), _WorldScaleExponent); |
|||
return p; |
|||
} |
|||
|
|||
void VolundTransferScatter(float3 worldPos, out float4 coords1, out float4 coords2, out float4 coords3) { |
|||
const float3 scaledWorldPos = WorldScale(worldPos); |
|||
const float3 worldCamPos = WorldScale(_WorldSpaceCameraPos.xyz); |
|||
|
|||
const float c_MieScaleHeight = 1200.f; |
|||
const float worldRayleighDensity = 1.f; |
|||
const float worldMieDensity = HeightDensity(scaledWorldPos.y, c_MieScaleHeight); |
|||
|
|||
const float3 worldVec = scaledWorldPos.xyz - worldCamPos.xyz; |
|||
const float worldVecLen = length(worldVec); |
|||
const float3 worldDir = worldVec / worldVecLen; |
|||
|
|||
const float3 worldDirUnscaled = normalize(worldPos - _WorldSpaceCameraPos.xyz); |
|||
|
|||
const float viewSunCos = dot(worldDirUnscaled, _SunDirection); |
|||
const float rayleighPh = min(1.f, RayleighPhase(viewSunCos) * 12.f); |
|||
const float miePh = MiePhase(viewSunCos, _MiePhaseAnisotropy); |
|||
|
|||
const float angle20 = 0.324f / 1.5f; |
|||
const float angle10 = 0.174f / 1.5f; |
|||
const float angleY = worldDir.y * saturate(worldVecLen / 250.0); |
|||
|
|||
float3 rayleighColor; |
|||
if(angleY >= angle10) rayleighColor = lerp(_RayleighColorP10, _RayleighColorP20, saturate((angleY - angle10) / (angle20 - angle10))); |
|||
else if(angleY >= 0.f) rayleighColor = lerp(_RayleighColorO00, _RayleighColorP10, angleY / angle10); |
|||
else if(angleY >= -angle10) rayleighColor = lerp(_RayleighColorM10, _RayleighColorO00, (angleY + angle10) / angle10); |
|||
else rayleighColor = lerp(_RayleighColorM20, _RayleighColorM10, saturate((angleY + angle20) / (angle20 - angle10))); |
|||
|
|||
float3 mieColor; |
|||
if(angleY >= 0.f) mieColor = lerp(_MieColorO00, _MieColorP20, saturate(angleY / angle20)); |
|||
else mieColor = lerp(_MieColorM20, _MieColorO00, saturate((angleY + angle20) / angle20)); |
|||
|
|||
const float pushedDistance = max(0.f, worldVecLen + _WorldNearScatterPush); |
|||
const float pushedDensity = /*HeightDensity **/ pushedDistance /** exp(-scaledWorldPos.y / 8000.f)*/; |
|||
const float rayleighScatter = (1.f - exp(_WorldRayleighDensity * pushedDensity)) * rayleighPh; |
|||
#ifdef IS_RENDERING_SKY |
|||
const float mieScatter = (1.f - exp(_WorldMieDensity * pushedDensity)); |
|||
#else |
|||
const float mieScatter = (1.f - exp(_WorldMieDensity * pushedDensity)) * miePh; |
|||
#endif |
|||
|
|||
const float heightShift = dot(worldVec, _HeightPlaneShift); |
|||
const float heightScaledOffset = (scaledWorldPos.y - heightShift - _HeightSeaLevel) * _HeightDistanceRcp; |
|||
const float HeightDensity = exp(-heightScaledOffset); |
|||
const float pushedHeightDistance = max(0.f, worldVecLen + _HeightNearScatterPush); |
|||
const float heightScatter = (1.f - exp(_HeightRayleighDensity * pushedHeightDistance)) * HeightDensity; |
|||
#ifdef IS_RENDERING_SKY |
|||
const float heightMieScatter = (1.f - exp(_HeightMieDensity * pushedHeightDistance)) * HeightDensity; |
|||
#else |
|||
const float heightMieScatter = (1.f - exp(_HeightMieDensity * pushedHeightDistance)) * HeightDensity * miePh; |
|||
#endif |
|||
|
|||
rayleighColor = lerp(Luminance(rayleighColor).rrr, rayleighColor, saturate(pushedDistance * _WorldNormalDistanceRcp)); |
|||
float3 heightRayleighColor = lerp(Luminance(_HeightRayleighColor.xyz).rrr, _HeightRayleighColor.xyz, saturate(pushedHeightDistance * _HeightNormalDistanceRcp)); |
|||
|
|||
coords1.rgb = rayleighScatter * rayleighColor; |
|||
coords1.a = rayleighScatter; |
|||
|
|||
coords3.rgb = saturate(heightScatter) * heightRayleighColor; |
|||
coords3.a = heightScatter; |
|||
|
|||
coords2.rgb = mieScatter * mieColor + saturate(heightMieScatter) * mieColor; |
|||
coords2.a = mieScatter; |
|||
} |
|||
|
|||
void VolundTransferScatter(float3 scaledWorldPos, out float4 coords1) { |
|||
float4 c1, c2, c3; |
|||
VolundTransferScatter(scaledWorldPos, c1, c2, c3); |
|||
|
|||
#ifdef IS_RENDERING_SKY |
|||
coords1.rgb = c3.rgb; |
|||
coords1.a = max(0.f, 1.f - c3.a * _HeightExtinctionFactor); |
|||
#else |
|||
coords1.rgb = c1.rgb; |
|||
coords1.rgb += c3.rgb; |
|||
coords1.a = max(0.f, 1.f - c1.a * _RayleighExtinctionFactor - c3.a * _HeightExtinctionFactor); |
|||
#endif |
|||
|
|||
coords1.rgb += c2.rgb; |
|||
coords1.a *= max(0.f, 1.f - c2.a * _MieExtinctionFactor); |
|||
|
|||
#ifdef ATMOSPHERICS_DEBUG |
|||
if(_AtmosphericsDebugMode == ATMOSPHERICS_DBG_RAYLEIGH) |
|||
coords1.rgb = c1.rgb; |
|||
else if(_AtmosphericsDebugMode == ATMOSPHERICS_DBG_MIE) |
|||
coords1.rgb = c2.rgb; |
|||
else if(_AtmosphericsDebugMode == ATMOSPHERICS_DBG_HEIGHT) |
|||
coords1.rgb = c3.rgb; |
|||
#endif |
|||
} |
|||
|
|||
float2 UVFromPos(float2 pos) { |
|||
return pos / _ScreenParams.xy; |
|||
} |
|||
|
|||
float3 VolundApplyScatter(float4 coords1, float2 pos, float3 color) { |
|||
#ifdef ATMOSPHERICS_DEBUG |
|||
if(_AtmosphericsDebugMode == ATMOSPHERICS_DBG_OCCLUSION) |
|||
return 1; |
|||
else if(_AtmosphericsDebugMode == ATMOSPHERICS_DBG_SCATTERING || _AtmosphericsDebugMode == ATMOSPHERICS_DBG_OCCLUDEDSCATTERING) |
|||
return coords1.rgb; |
|||
else if(_AtmosphericsDebugMode == ATMOSPHERICS_DBG_RAYLEIGH || _AtmosphericsDebugMode == ATMOSPHERICS_DBG_MIE || _AtmosphericsDebugMode == ATMOSPHERICS_DBG_HEIGHT) |
|||
return coords1.rgb; |
|||
#endif |
|||
|
|||
return color * coords1.a + coords1.rgb; |
|||
} |
|||
|
|||
float3 VolundApplyScatterAdd(float coords1, float3 color) { |
|||
return color * coords1; |
|||
} |
|||
|
|||
void VolundTransferScatterOcclusion(float3 scaledWorldPos, out float4 coords1, out float3 coords2) { |
|||
float4 c1, c2, c3; |
|||
VolundTransferScatter(scaledWorldPos, c1, c2, c3); |
|||
|
|||
coords1.rgb = c1.rgb * _RayleighInScatterPct.x; |
|||
coords1.a = max(0.f, 1.f - c1.a * _RayleighExtinctionFactor - c3.a * _HeightExtinctionFactor); |
|||
|
|||
coords1.rgb += c2.rgb; |
|||
coords1.a *= max(0.f, 1.f - c2.a * _MieExtinctionFactor); |
|||
|
|||
coords2.rgb = c3.rgb + c1.rgb * _RayleighInScatterPct.y; |
|||
|
|||
#ifdef ATMOSPHERICS_DEBUG |
|||
if(_AtmosphericsDebugMode == ATMOSPHERICS_DBG_RAYLEIGH) |
|||
coords1.rgb = c1.rgb; |
|||
else if(_AtmosphericsDebugMode == ATMOSPHERICS_DBG_MIE) |
|||
coords1.rgb = c2.rgb; |
|||
else if(_AtmosphericsDebugMode == ATMOSPHERICS_DBG_HEIGHT) |
|||
coords1.rgb = c3.rgb; |
|||
#endif |
|||
} |
|||
|
|||
float VolundSampleScatterOcclusion(float2 pos) { |
|||
#if defined(ATMOSPHERICS_OCCLUSION) |
|||
float2 uv = UVFromPos(pos); |
|||
#if defined(ATMOSPHERICS_OCCLUSION_EDGE_FIXUP) |
|||
float4 baseUV = float4(uv.x, uv.y, 0.f, 0.f); |
|||
|
|||
float cDepth = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV, 0.f).r; |
|||
cDepth = LinearEyeDepth(cDepth); |
|||
|
|||
float4 xDepth; |
|||
baseUV.xy = uv + _DepthTextureScaledTexelSize.zy; xDepth.x = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV); |
|||
baseUV.xy = uv + _DepthTextureScaledTexelSize.xy; xDepth.y = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV); |
|||
baseUV.xy = uv + _DepthTextureScaledTexelSize.xw; xDepth.z = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV); |
|||
baseUV.xy = uv + _DepthTextureScaledTexelSize.zw; xDepth.w = SAMPLE_TEXTURE2D_LOD(_CameraDepthTexture, SRL_BilinearSampler, baseUV); |
|||
|
|||
xDepth.x = LinearEyeDepth4(xDepth.x); |
|||
xDepth.y = LinearEyeDepth4(xDepth.y); |
|||
xDepth.z = LinearEyeDepth4(xDepth.z); |
|||
xDepth.w = LinearEyeDepth4(xDepth.w); |
|||
|
|||
float4 diffDepth = xDepth - cDepth.rrrr; |
|||
float4 maskDepth = abs(diffDepth) < _OcclusionDepthThreshold; |
|||
float maskWeight = dot(maskDepth, maskDepth); |
|||
|
|||
UNITY_BRANCH |
|||
if(maskWeight == 4.f || maskWeight == 0.f) { |
|||
return SAMPLE_TEXTURE2D_LOD(_OcclusionTexture, SRL_BilinearSampler, uv, 0.f).r; |
|||
} else { |
|||
float4 occ = GATHER_TEXTURE2D(_OcclusionTexture, SRL_BilinearSampler, uv); |
|||
|
|||
float4 fWeights; |
|||
fWeights.xy = frac(uv * _OcclusionTexture_TexelSize.zw - 0.5f); |
|||
fWeights.zw = float2(1.f, 1.f) - fWeights.xy; |
|||
|
|||
float4 mfWeights = float4(fWeights.z * fWeights.y, fWeights.x * fWeights.y, fWeights.x * fWeights.w, fWeights.z * fWeights.w); |
|||
return dot(occ, mfWeights * maskDepth) / dot(mfWeights, maskDepth); |
|||
} |
|||
#endif //defined(ATMOSPHERICS_OCCLUSION_EDGE_FIXUP) |
|||
#else //defined(ATMOSPHERICS_OCCLUSION) |
|||
return 1.f; |
|||
#endif //defined(ATMOSPHERICS_OCCLUSION) |
|||
} |
|||
|
|||
float3 VolundApplyScatterOcclusion(float4 coords1, float3 coords2, float2 pos, float3 color) { |
|||
float occlusion = VolundSampleScatterOcclusion(pos); |
|||
|
|||
#ifdef ATMOSPHERICS_DEBUG |
|||
if(_AtmosphericsDebugMode == ATMOSPHERICS_DBG_SCATTERING) |
|||
return coords1.rgb + coords2.rgb; |
|||
else if(_AtmosphericsDebugMode == ATMOSPHERICS_DBG_OCCLUSION) |
|||
return occlusion; |
|||
else if(_AtmosphericsDebugMode == ATMOSPHERICS_DBG_OCCLUDEDSCATTERING) |
|||
return coords1.rgb * min(1.f, occlusion + _ShadowBias) + coords2.rgb * min(1.f, occlusion + _ShadowBiasIndirect); |
|||
else if(_AtmosphericsDebugMode == ATMOSPHERICS_DBG_RAYLEIGH || _AtmosphericsDebugMode == ATMOSPHERICS_DBG_MIE || _AtmosphericsDebugMode == ATMOSPHERICS_DBG_HEIGHT) |
|||
return coords1.rgb; |
|||
#endif |
|||
|
|||
return |
|||
color * coords1.a |
|||
+ coords1.rgb * min(1.f, occlusion + _ShadowBias) + coords2.rgb * min(1.f, occlusion + _ShadowBiasIndirect); |
|||
; |
|||
} |
|||
|
|||
float VolundCloudOcclusion(float2 pos) { |
|||
#if defined(ATMOSPHERICS_OCCLUSION) |
|||
return min(1.f, VolundSampleScatterOcclusion(pos) + _ShadowBiasClouds); |
|||
#else |
|||
return 1.f; |
|||
#endif |
|||
} |
|||
|
|||
|
|||
float4 VolundApplyCloudScatter(float4 coords1, float4 color) { |
|||
#if defined(DBG_ATMOSPHERICS_SCATTERING) || defined(DBG_ATMOSPHERICS_OCCLUDEDSCATTERING) |
|||
return float4(coords1.rgb, color.a); |
|||
#elif defined(DBG_ATMOSPHERICS_OCCLUSION) |
|||
return 1; |
|||
#endif |
|||
|
|||
color.rgb = color.rgb * coords1.a + coords1.rgb; |
|||
return color; |
|||
} |
|||
|
|||
float4 VolundApplyCloudScatterOcclusion(float4 coords1, float3 coords2, float2 pos, float4 color) { |
|||
float occlusion = VolundSampleScatterOcclusion(pos); |
|||
#ifdef ATMOSPHERICS_OCCLUSION_DEBUG2 |
|||
color.rgb = coords1.rgb * min(1.f, occlusion + _ShadowBias) + coords2.rgb * min(1.f, occlusion + _ShadowBiasIndirect); |
|||
return color; |
|||
#endif |
|||
#ifdef ATMOSPHERICS_OCCLUSION_DEBUG |
|||
return occlusion; |
|||
#endif |
|||
|
|||
color.rgb = color.rgb * coords1.a + coords1.rgb * min(1.f, occlusion + _ShadowBias) + coords2.rgb * min(1.f, occlusion + _ShadowBiasIndirect); |
|||
|
|||
float cloudOcclusion = min(1.f, occlusion + _ShadowBiasClouds); |
|||
color.a *= cloudOcclusion; |
|||
|
|||
return color; |
|||
} |
|||
|
|||
// Original vert/frag macros |
|||
#if defined(ATMOSPHERICS_OCCLUSION) |
|||
#define VOLUND_SCATTER_COORDS(idx1, idx2) float4 scatterCoords1 : TEXCOORD##idx1; float3 scatterCoords2 : TEXCOORD##idx2; |
|||
#define VOLUND_TRANSFER_SCATTER(pos, o) o.scatterCoords1 = pos.xyzz; o.scatterCoords2 = pos.xyz; |
|||
#define VOLUND_APPLY_SCATTER(i, color) VolundTransferScatterOcclusion(i.scatterCoords1.xyz, i.scatterCoords1, i.scatterCoords2); color = VolundApplyScatterOcclusion(i.scatterCoords1, i.scatterCoords2, i.pos.xy, color) |
|||
#define VOLUND_CLOUD_SCATTER(i, color) VolundTransferScatterOcclusion(i.scatterCoords1.xyz, i.scatterCoords1, i.scatterCoords2); color = VolundApplyCloudScatterOcclusion(i.scatterCoords1, i.scatterCoords2, i.pos.xy, color) |
|||
#else |
|||
#define VOLUND_SCATTER_COORDS(idx1, idx2) float4 scatterCoords1 : TEXCOORD##idx1; |
|||
#define VOLUND_TRANSFER_SCATTER(pos, o) o.scatterCoords1 = pos.xyzz; |
|||
#define VOLUND_APPLY_SCATTER(i, color) VolundTransferScatter(i.scatterCoords1.xyz, i.scatterCoords1); color = VolundApplyScatter(i.scatterCoords1, i.pos.xy, color); |
|||
#define VOLUND_CLOUD_SCATTER(i, color) VolundTransferScatter(i.scatterCoords1.xyz, i.scatterCoords1); color = VolundApplyCloudScatter(i.scatterCoords1, color); |
|||
#endif |
|||
|
|||
#if !defined(SURFACE_SCATTER_COORDS) |
|||
/* surface shader analysis currently forces us to include stuff even when unused */ |
|||
/* we also have to convince the analyzer to not optimize out stuff we need */ |
|||
#define SURFACE_SCATTER_COORDS float3 scaledWorldPos; float4 scatterCoords1; float3 scatterCoords2; |
|||
#define SURFACE_SCATTER_TRANSFER(pos, o) o.scatterCoords1.r = o.scatterCoords2.r = pos.x; |
|||
#define SURFACE_SCATTER_APPLY(i, color) color += (i.scaledWorldPos + i.scatterCoords1.xyz + i.scatterCoords2.xyz) * 0.000001f |
|||
#endif |
|||
|
|||
#endif //FILE_ATMOSPHERICSCATTERING |
|
|||
fileFormatVersion: 2 |
|||
guid: b0be9dce952dbb9479a5eb30e49c07a3 |
|||
timeCreated: 1480068393 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue