runes
7 年前
当前提交
da8acc5e
共有 90 个文件被更改,包括 2687 次插入 和 440 次删除
-
88ScriptableRenderPipeline/Core/Editor/CoreEditorUtils.cs
-
69ScriptableRenderPipeline/Core/ShaderLibrary/BSDF.hlsl
-
7ScriptableRenderPipeline/Core/ShaderLibrary/CommonLighting.hlsl
-
39ScriptableRenderPipeline/Core/ShaderLibrary/CommonMaterial.hlsl
-
2ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl
-
3ScriptableRenderPipeline/Core/ShaderLibrary/Macros.hlsl
-
50ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.cs.hlsl
-
2ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.hlsl
-
8ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineMenuItems.cs
-
3ScriptableRenderPipeline/HDRenderPipeline/HDCustomSamplerId.cs
-
6ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
-
2ScriptableRenderPipeline/HDRenderPipeline/Lighting/Deferred.shader
-
1ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightLoop/Deferred.compute
-
1ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs
-
41ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs.hlsl
-
188ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
-
2ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitReference.hlsl
-
17ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/FragInputs.hlsl
-
5ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassDepthOnly.hlsl
-
5ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassDistortion.hlsl
-
5ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForward.hlsl
-
5ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForwardUnlit.hlsl
-
5ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassGBuffer.hlsl
-
8ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassLightTransport.hlsl
-
5ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassVelocity.hlsl
-
8ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/VaryingMesh.hlsl
-
7ScriptableRenderPipeline/HDRenderPipeline/Sky/SkyManager.cs
-
4ScriptableRenderPipeline/HDRenderPipeline/Lighting/DeferredDirectionalShadow.compute
-
2ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/BuildProbabilityTables.compute
-
2ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolve.shader
-
42ScriptableRenderPipeline/Core/Editor/CoreEditorStyles.cs
-
11ScriptableRenderPipeline/Core/Editor/CoreEditorStyles.cs.meta
-
8ScriptableRenderPipeline/Core/Volume.meta
-
20ScriptableRenderPipeline/HDRenderPipeline/Debug/LightingDebug.cs.hlsl
-
9ScriptableRenderPipeline/HDRenderPipeline/Debug/LightingDebug.cs.hlsl.meta
-
46ScriptableRenderPipeline/HDRenderPipeline/Debug/MaterialDebug.cs.hlsl
-
9ScriptableRenderPipeline/HDRenderPipeline/Debug/MaterialDebug.cs.hlsl.meta
-
8ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution.meta
-
8ScriptableRenderPipeline/Core/Volume/Editor.meta
-
8ScriptableRenderPipeline/Core/Volume/Editor/Drawers.meta
-
77ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ClampedFloatParameterDrawer.cs
-
11ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ClampedFloatParameterDrawer.cs.meta
-
77ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ClampedIntParameterDrawer.cs
-
11ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ClampedIntParameterDrawer.cs.meta
-
21ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ColorParameterDrawer.cs
-
11ScriptableRenderPipeline/Core/Volume/Editor/Drawers/ColorParameterDrawer.cs.meta
-
42ScriptableRenderPipeline/Core/Volume/Editor/Drawers/RangeParameterDrawer.cs
-
11ScriptableRenderPipeline/Core/Volume/Editor/Drawers/RangeParameterDrawer.cs.meta
-
20ScriptableRenderPipeline/Core/Volume/Editor/Drawers/Vector4ParameterDrawer.cs
-
11ScriptableRenderPipeline/Core/Volume/Editor/Drawers/Vector4ParameterDrawer.cs.meta
-
57ScriptableRenderPipeline/Core/Volume/Editor/SerializedDataParameter.cs
-
11ScriptableRenderPipeline/Core/Volume/Editor/SerializedDataParameter.cs.meta
-
266ScriptableRenderPipeline/Core/Volume/Editor/VolumeComponentEditor.cs
-
11ScriptableRenderPipeline/Core/Volume/Editor/VolumeComponentEditor.cs.meta
-
388ScriptableRenderPipeline/Core/Volume/Editor/VolumeEditor.cs
-
11ScriptableRenderPipeline/Core/Volume/Editor/VolumeEditor.cs.meta
-
31ScriptableRenderPipeline/Core/Volume/Editor/VolumeParameterDrawer.cs
-
11ScriptableRenderPipeline/Core/Volume/Editor/VolumeParameterDrawer.cs.meta
-
11ScriptableRenderPipeline/Core/Volume/Volume.cs.meta
-
73ScriptableRenderPipeline/Core/Volume/VolumeComponent.cs
-
11ScriptableRenderPipeline/Core/Volume/VolumeComponent.cs.meta
-
336ScriptableRenderPipeline/Core/Volume/VolumeManager.cs
-
11ScriptableRenderPipeline/Core/Volume/VolumeManager.cs.meta
-
424ScriptableRenderPipeline/Core/Volume/VolumeParameter.cs
-
11ScriptableRenderPipeline/Core/Volume/VolumeParameter.cs.meta
-
212ScriptableRenderPipeline/Core/Volume/Volume.cs
-
14ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolution.cs
-
14ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolution.cs.hlsl
-
9ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolution.cs.hlsl.meta
-
11ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolution.cs.meta
-
113ScriptableRenderPipeline/HDRenderPipeline/Sky/README.txt
-
8ScriptableRenderPipeline/HDRenderPipeline/Sky/README.txt.meta
-
9ScriptableRenderPipeline/HDRenderPipeline/Sky/SkyManager.cs.hlsl.meta
-
14ScriptableRenderPipeline/HDRenderPipeline/Sky/SkyManager.cs.hlsl
-
9ScriptableRenderPipeline/HDRenderPipeline/Sky/BlacksmithlSky.meta
-
0/ScriptableRenderPipeline/HDRenderPipeline/Lighting/DeferredDirectionalShadow.compute
-
0/ScriptableRenderPipeline/HDRenderPipeline/Lighting/DeferredDirectionalShadow.compute.meta
-
0/ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/RuntimeFilterIBL.cs.meta
-
0/ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolve.shader.meta
-
0/ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/ComputeGgxIblSampleData.compute.meta
-
0/ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/BuildProbabilityTables.compute.meta
-
0/ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/BuildProbabilityTables.compute
-
0/ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/RuntimeFilterIBL.cs
-
0/ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/GGXConvolve.shader
-
0/ScriptableRenderPipeline/HDRenderPipeline/Material/GGXConvolution/ComputeGgxIblSampleData.compute
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
public static class CoreEditorStyles |
|||
{ |
|||
public static readonly GUIStyle smallTickbox; |
|||
public static readonly GUIStyle miniLabelButton; |
|||
|
|||
public static readonly Texture2D paneOptionsIconDark; |
|||
public static readonly Texture2D paneOptionsIconLight; |
|||
|
|||
static CoreEditorStyles() |
|||
{ |
|||
smallTickbox = new GUIStyle("ShurikenCheckMark"); |
|||
|
|||
var transparentTexture = new Texture2D(1, 1, TextureFormat.ARGB32, false); |
|||
transparentTexture.SetPixel(0, 0, Color.clear); |
|||
transparentTexture.Apply(); |
|||
|
|||
miniLabelButton = new GUIStyle(EditorStyles.miniLabel); |
|||
miniLabelButton.normal = new GUIStyleState |
|||
{ |
|||
background = transparentTexture, |
|||
scaledBackgrounds = null, |
|||
textColor = Color.grey |
|||
}; |
|||
var activeState = new GUIStyleState |
|||
{ |
|||
background = transparentTexture, |
|||
scaledBackgrounds = null, |
|||
textColor = Color.white |
|||
}; |
|||
miniLabelButton.active = activeState; |
|||
miniLabelButton.onNormal = activeState; |
|||
miniLabelButton.onActive = activeState; |
|||
|
|||
paneOptionsIconDark = (Texture2D)EditorGUIUtility.Load("Builtin Skins/DarkSkin/Images/pane options.png"); |
|||
paneOptionsIconLight = (Texture2D)EditorGUIUtility.Load("Builtin Skins/LightSkin/Images/pane options.png"); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 106fd77ef6b30234597e56c849578bad |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 1189cbf559a12c64e92584c52d17a4a0 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
// |
|||
// This file was automatically generated. Please don't edit by hand. |
|||
// |
|||
|
|||
#ifndef LIGHTINGDEBUG_CS_HLSL |
|||
#define LIGHTINGDEBUG_CS_HLSL |
|||
// |
|||
// UnityEngine.Experimental.Rendering.HDPipeline.DebugLightingMode: static fields |
|||
// |
|||
#define DEBUGLIGHTINGMODE_NONE (0) |
|||
#define DEBUGLIGHTINGMODE_DIFFUSE_LIGHTING (1) |
|||
#define DEBUGLIGHTINGMODE_SPECULAR_LIGHTING (2) |
|||
#define DEBUGLIGHTINGMODE_VISUALIZE_CASCADE (3) |
|||
#define DEBUGLIGHTINGMODE_INDIRECT_DIFFUSE_OCCLUSION_FROM_SSAO (4) |
|||
#define DEBUGLIGHTINGMODE_INDIRECT_DIFFUSE_GTAO_FROM_SSAO (5) |
|||
#define DEBUGLIGHTINGMODE_INDIRECT_SPECULAR_OCCLUSION_FROM_SSAO (6) |
|||
#define DEBUGLIGHTINGMODE_INDIRECT_SPECULAR_GTAO_FROM_SSAO (7) |
|||
|
|||
|
|||
#endif |
|
|||
fileFormatVersion: 2 |
|||
guid: ac1ebeb5a5a2fed418218ce6b347e221 |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
// |
|||
// This file was automatically generated. Please don't edit by hand. |
|||
// |
|||
|
|||
#ifndef MATERIALDEBUG_CS_HLSL |
|||
#define MATERIALDEBUG_CS_HLSL |
|||
// |
|||
// UnityEngine.Experimental.Rendering.HDPipeline.Attributes.DebugViewVarying: static fields |
|||
// |
|||
#define DEBUGVIEWVARYING_NONE (0) |
|||
#define DEBUGVIEWVARYING_TEXCOORD0 (1) |
|||
#define DEBUGVIEWVARYING_TEXCOORD1 (2) |
|||
#define DEBUGVIEWVARYING_TEXCOORD2 (3) |
|||
#define DEBUGVIEWVARYING_TEXCOORD3 (4) |
|||
#define DEBUGVIEWVARYING_VERTEX_TANGENT_WS (5) |
|||
#define DEBUGVIEWVARYING_VERTEX_BITANGENT_WS (6) |
|||
#define DEBUGVIEWVARYING_VERTEX_NORMAL_WS (7) |
|||
#define DEBUGVIEWVARYING_VERTEX_COLOR (8) |
|||
#define DEBUGVIEWVARYING_VERTEX_COLOR_ALPHA (9) |
|||
#define DEBUGVIEWVARYING_LAST (10) |
|||
|
|||
// |
|||
// UnityEngine.Experimental.Rendering.HDPipeline.Attributes.DebugViewGbuffer: static fields |
|||
// |
|||
#define DEBUGVIEWGBUFFER_NONE (0) |
|||
#define DEBUGVIEWGBUFFER_DEPTH (10) |
|||
#define DEBUGVIEWGBUFFER_BAKE_DIFFUSE_LIGHTING_WITH_ALBEDO_PLUS_EMISSIVE (11) |
|||
#define DEBUGVIEWGBUFFER_BAKE_SHADOW_MASK0 (12) |
|||
#define DEBUGVIEWGBUFFER_BAKE_SHADOW_MASK1 (13) |
|||
#define DEBUGVIEWGBUFFER_BAKE_SHADOW_MASK2 (14) |
|||
#define DEBUGVIEWGBUFFER_BAKE_SHADOW_MASK3 (15) |
|||
#define DEBUGVIEWGBUFFER_LAST (16) |
|||
|
|||
// |
|||
// UnityEngine.Experimental.Rendering.HDPipeline.Attributes.DebugViewProperties: static fields |
|||
// |
|||
#define DEBUGVIEWPROPERTIES_NONE (0) |
|||
#define DEBUGVIEWPROPERTIES_TESSELLATION (16) |
|||
#define DEBUGVIEWPROPERTIES_PIXEL_DISPLACEMENT (17) |
|||
#define DEBUGVIEWPROPERTIES_VERTEX_DISPLACEMENT (18) |
|||
#define DEBUGVIEWPROPERTIES_TESSELLATION_DISPLACEMENT (19) |
|||
#define DEBUGVIEWPROPERTIES_DEPTH_OFFSET (20) |
|||
#define DEBUGVIEWPROPERTIES_LIGHTMAP (21) |
|||
|
|||
|
|||
#endif |
|
|||
fileFormatVersion: 2 |
|||
guid: cce0374c3f91d32489d7ce55fcbf8d2e |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 58f7be3dd9cacc14ab4933c864014bae |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 138c0b127ef07fd428612196694d782f |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 8c667ca46d23aa3468b6c4243b135b0d |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
using UnityEngine.Experimental.Rendering; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
[VolumeParameterDrawer(typeof(ClampedFloatParameter))] |
|||
sealed class ClampedFloatParameterDrawer : VolumeParameterDrawer |
|||
{ |
|||
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title) |
|||
{ |
|||
var value = parameter.value; |
|||
|
|||
if (value.propertyType != SerializedPropertyType.Float) |
|||
return false; |
|||
|
|||
var o = parameter.GetObjectRef<ClampedFloatParameter>(); |
|||
|
|||
if (o.clampMode == ParameterClampMode.MinMax) |
|||
{ |
|||
EditorGUILayout.Slider(value, o.min, o.max, title); |
|||
value.floatValue = Mathf.Clamp(value.floatValue, o.min, o.max); |
|||
} |
|||
else if (o.clampMode == ParameterClampMode.Min) |
|||
{ |
|||
float v = EditorGUILayout.FloatField(title, value.floatValue); |
|||
value.floatValue = Mathf.Max(v, o.min); |
|||
} |
|||
else if (o.clampMode == ParameterClampMode.Max) |
|||
{ |
|||
float v = EditorGUILayout.FloatField(title, value.floatValue); |
|||
value.floatValue = Mathf.Min(v, o.max); |
|||
} |
|||
else |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
[VolumeParameterDrawer(typeof(InstantClampedFloatParameter))] |
|||
sealed class InstantClampedFloatParameterDrawer : VolumeParameterDrawer |
|||
{ |
|||
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title) |
|||
{ |
|||
var value = parameter.value; |
|||
|
|||
if (value.propertyType != SerializedPropertyType.Float) |
|||
return false; |
|||
|
|||
var o = parameter.GetObjectRef<InstantClampedFloatParameter>(); |
|||
|
|||
if (o.clampMode == ParameterClampMode.MinMax) |
|||
{ |
|||
EditorGUILayout.Slider(value, o.min, o.max, title); |
|||
value.floatValue = Mathf.Clamp(value.floatValue, o.min, o.max); |
|||
} |
|||
else if (o.clampMode == ParameterClampMode.Min) |
|||
{ |
|||
float v = EditorGUILayout.FloatField(title, value.floatValue); |
|||
value.floatValue = Mathf.Max(v, o.min); |
|||
} |
|||
else if (o.clampMode == ParameterClampMode.Max) |
|||
{ |
|||
float v = EditorGUILayout.FloatField(title, value.floatValue); |
|||
value.floatValue = Mathf.Min(v, o.max); |
|||
} |
|||
else |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f9816364c4bdf314db38db52fc67a3f2 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
using UnityEngine.Experimental.Rendering; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
[VolumeParameterDrawer(typeof(ClampedIntParameter))] |
|||
sealed class ClampedIntParameterDrawer : VolumeParameterDrawer |
|||
{ |
|||
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title) |
|||
{ |
|||
var value = parameter.value; |
|||
|
|||
if (value.propertyType != SerializedPropertyType.Integer) |
|||
return false; |
|||
|
|||
var o = parameter.GetObjectRef<ClampedIntParameter>(); |
|||
|
|||
if (o.clampMode == ParameterClampMode.MinMax) |
|||
{ |
|||
EditorGUILayout.IntSlider(value, o.min, o.max, title); |
|||
value.intValue = Mathf.Clamp(value.intValue, o.min, o.max); |
|||
} |
|||
else if (o.clampMode == ParameterClampMode.Min) |
|||
{ |
|||
int v = EditorGUILayout.IntField(title, value.intValue); |
|||
value.intValue = Mathf.Max(v, o.min); |
|||
} |
|||
else if (o.clampMode == ParameterClampMode.Max) |
|||
{ |
|||
int v = EditorGUILayout.IntField(title, value.intValue); |
|||
value.intValue = Mathf.Min(v, o.max); |
|||
} |
|||
else |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
|
|||
[VolumeParameterDrawer(typeof(InstantClampedIntParameter))] |
|||
sealed class InstantClampedIntParameterDrawer : VolumeParameterDrawer |
|||
{ |
|||
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title) |
|||
{ |
|||
var value = parameter.value; |
|||
|
|||
if (value.propertyType != SerializedPropertyType.Integer) |
|||
return false; |
|||
|
|||
var o = parameter.GetObjectRef<InstantClampedIntParameter>(); |
|||
|
|||
if (o.clampMode == ParameterClampMode.MinMax) |
|||
{ |
|||
EditorGUILayout.IntSlider(value, o.min, o.max, title); |
|||
value.intValue = Mathf.Clamp(value.intValue, o.min, o.max); |
|||
} |
|||
else if (o.clampMode == ParameterClampMode.Min) |
|||
{ |
|||
int v = EditorGUILayout.IntField(title, value.intValue); |
|||
value.intValue = Mathf.Max(v, o.min); |
|||
} |
|||
else if (o.clampMode == ParameterClampMode.Max) |
|||
{ |
|||
int v = EditorGUILayout.IntField(title, value.intValue); |
|||
value.intValue = Mathf.Min(v, o.max); |
|||
} |
|||
else |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 6d2f589334fbc8444b30925a405106d8 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
using UnityEngine.Experimental.Rendering; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
[VolumeParameterDrawer(typeof(ColorParameter))] |
|||
sealed class ColorParameterDrawer : VolumeParameterDrawer |
|||
{ |
|||
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title) |
|||
{ |
|||
var value = parameter.value; |
|||
|
|||
if (value.propertyType != SerializedPropertyType.Color) |
|||
return false; |
|||
|
|||
var o = parameter.GetObjectRef<ColorParameter>(); |
|||
value.colorValue = EditorGUILayout.ColorField(title, value.colorValue, o.showEyeDropper, o.showAlpha, o.showAlpha); |
|||
return true; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 34ad702e46732ff438113b62a10ae80e |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
using UnityEngine.Experimental.Rendering; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
[VolumeParameterDrawer(typeof(RangeParameter))] |
|||
sealed class RangeParameterDrawer : VolumeParameterDrawer |
|||
{ |
|||
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title) |
|||
{ |
|||
var value = parameter.value; |
|||
|
|||
if (value.propertyType != SerializedPropertyType.Vector2) |
|||
return false; |
|||
|
|||
var o = parameter.GetObjectRef<RangeParameter>(); |
|||
var v = value.vector2Value; |
|||
|
|||
// The layout system breaks alignement when mixing inspector fields with custom layouted
|
|||
// fields as soon as a scrollbar is needed in the inspector, so we'll do the layout
|
|||
// manually instead
|
|||
const int kFloatFieldWidth = 50; |
|||
const int kSeparatorWidth = 5; |
|||
float indentOffset = EditorGUI.indentLevel * 15f; |
|||
var lineRect = GUILayoutUtility.GetRect(1, EditorGUIUtility.singleLineHeight); |
|||
lineRect.xMin += 4f; |
|||
lineRect.y += 2f; |
|||
var labelRect = new Rect(lineRect.x, lineRect.y, EditorGUIUtility.labelWidth - indentOffset, lineRect.height); |
|||
var floatFieldLeft = new Rect(labelRect.xMax, lineRect.y, kFloatFieldWidth + indentOffset, lineRect.height); |
|||
var sliderRect = new Rect(floatFieldLeft.xMax + kSeparatorWidth - indentOffset, lineRect.y, lineRect.width - labelRect.width - kFloatFieldWidth * 2 - kSeparatorWidth * 2, lineRect.height); |
|||
var floatFieldRight = new Rect(sliderRect.xMax + kSeparatorWidth - indentOffset, lineRect.y, kFloatFieldWidth + indentOffset, lineRect.height); |
|||
|
|||
EditorGUI.PrefixLabel(labelRect, title); |
|||
v.x = EditorGUI.FloatField(floatFieldLeft, v.x); |
|||
EditorGUI.MinMaxSlider(sliderRect, ref v.x, ref v.y, o.min, o.max); |
|||
v.y = EditorGUI.FloatField(floatFieldRight, v.y); |
|||
|
|||
value.vector2Value = v; |
|||
return true; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 54ad01bd6d555e0438e364d8b0f17e06 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using UnityEngine; |
|||
using UnityEngine.Experimental.Rendering; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
[VolumeParameterDrawer(typeof(Vector4Parameter))] |
|||
sealed class Vector4ParametrDrawer : VolumeParameterDrawer |
|||
{ |
|||
public override bool OnGUI(SerializedDataParameter parameter, GUIContent title) |
|||
{ |
|||
var value = parameter.value; |
|||
|
|||
if (value.propertyType != SerializedPropertyType.Vector4) |
|||
return false; |
|||
|
|||
value.vector4Value = EditorGUILayout.Vector4Field(title, value.vector4Value); |
|||
return true; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 9c51e2ea627a393478d0b5c2a086136d |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using UnityEngine.Assertions; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
public sealed class SerializedDataParameter |
|||
{ |
|||
public SerializedProperty overrideState { get; private set; } |
|||
public SerializedProperty value { get; private set; } |
|||
public Attribute[] attributes { get; private set; } |
|||
public Type referenceType { get; private set; } |
|||
|
|||
SerializedProperty m_BaseProperty; |
|||
object m_ReferenceValue; |
|||
|
|||
public string displayName |
|||
{ |
|||
get { return m_BaseProperty.displayName; } |
|||
} |
|||
|
|||
internal SerializedDataParameter(SerializedProperty property) |
|||
{ |
|||
// Find the actual property type, optional attributes & reference
|
|||
var path = property.propertyPath.Split('.'); |
|||
object obj = property.serializedObject.targetObject; |
|||
FieldInfo field = null; |
|||
|
|||
foreach (var p in path) |
|||
{ |
|||
field = obj.GetType().GetField(p, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); |
|||
obj = field.GetValue(obj); |
|||
} |
|||
|
|||
Assert.IsNotNull(field); |
|||
|
|||
m_BaseProperty = property.Copy(); |
|||
overrideState = m_BaseProperty.FindPropertyRelative("m_OverrideState"); |
|||
value = m_BaseProperty.FindPropertyRelative("m_Value"); |
|||
attributes = field.GetCustomAttributes(false).Cast<Attribute>().ToArray(); |
|||
referenceType = obj.GetType(); |
|||
m_ReferenceValue = obj; |
|||
} |
|||
|
|||
public T GetAttribute<T>() |
|||
where T : Attribute |
|||
{ |
|||
return (T)attributes.FirstOrDefault(x => x is T); |
|||
} |
|||
|
|||
public T GetObjectRef<T>() |
|||
{ |
|||
return (T)m_ReferenceValue; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: abf61146103c4444290de1048016607b |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using UnityEngine; |
|||
using UnityEngine.Assertions; |
|||
using UnityEngine.Experimental.Rendering; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] |
|||
public sealed class VolumeComponentEditorAttribute : Attribute |
|||
{ |
|||
public readonly Type componentType; |
|||
|
|||
public VolumeComponentEditorAttribute(Type componentType) |
|||
{ |
|||
this.componentType = componentType; |
|||
} |
|||
} |
|||
|
|||
public class VolumeComponentEditor |
|||
{ |
|||
internal VolumeComponent target { get; private set; } |
|||
internal SerializedObject serializedObject { get; private set; } |
|||
|
|||
internal SerializedProperty baseProperty; |
|||
internal SerializedProperty activeProperty; |
|||
|
|||
Editor m_Inspector; |
|||
List<SerializedDataParameter> m_Parameters; |
|||
|
|||
static Dictionary<Type, VolumeParameterDrawer> s_ParameterDrawers; |
|||
|
|||
static VolumeComponentEditor() |
|||
{ |
|||
s_ParameterDrawers = new Dictionary<Type, VolumeParameterDrawer>(); |
|||
ReloadDecoratorTypes(); |
|||
} |
|||
|
|||
[Callbacks.DidReloadScripts] |
|||
static void OnEditorReload() |
|||
{ |
|||
ReloadDecoratorTypes(); |
|||
} |
|||
|
|||
static void ReloadDecoratorTypes() |
|||
{ |
|||
s_ParameterDrawers.Clear(); |
|||
|
|||
// Look for all the valid parameter drawers
|
|||
var types = AppDomain.CurrentDomain.GetAssemblies() |
|||
.SelectMany( |
|||
a => a.GetTypes() |
|||
.Where( |
|||
t => t.IsSubclassOf(typeof(VolumeParameterDrawer)) |
|||
&& t.IsDefined(typeof(VolumeParameterDrawerAttribute), false) |
|||
) |
|||
); |
|||
|
|||
// Store them
|
|||
foreach (var type in types) |
|||
{ |
|||
var attr = (VolumeParameterDrawerAttribute)type.GetCustomAttributes(typeof(VolumeParameterDrawerAttribute), false)[0]; |
|||
var decorator = (VolumeParameterDrawer)Activator.CreateInstance(type); |
|||
s_ParameterDrawers.Add(attr.parameterType, decorator); |
|||
} |
|||
} |
|||
|
|||
public void Repaint() |
|||
{ |
|||
m_Inspector.Repaint(); |
|||
} |
|||
|
|||
internal void Init(VolumeComponent target, Editor inspector) |
|||
{ |
|||
this.target = target; |
|||
m_Inspector = inspector; |
|||
serializedObject = new SerializedObject(target); |
|||
activeProperty = serializedObject.FindProperty("active"); |
|||
OnEnable(); |
|||
} |
|||
|
|||
public virtual void OnEnable() |
|||
{ |
|||
m_Parameters = new List<SerializedDataParameter>(); |
|||
|
|||
// Grab all valid serializable field on the VolumeComponent
|
|||
var fields = target.GetType() |
|||
.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) |
|||
.Where(t => t.FieldType.IsSubclassOf(typeof(VolumeParameter))) |
|||
.Where(t => |
|||
(t.IsPublic && t.GetCustomAttributes(typeof(NonSerializedAttribute), false).Length == 0) || |
|||
(t.GetCustomAttributes(typeof(SerializeField), false).Length > 0) |
|||
) |
|||
.Where(t => t.GetCustomAttributes(typeof(HideInInspector), false).Length == 0) |
|||
.ToList(); |
|||
|
|||
// Prepare all serialized objects for this editor
|
|||
foreach (var field in fields) |
|||
{ |
|||
var property = serializedObject.FindProperty(field.Name); |
|||
var parameter = new SerializedDataParameter(property); |
|||
m_Parameters.Add(parameter); |
|||
} |
|||
} |
|||
|
|||
public virtual void OnDisable() |
|||
{ |
|||
} |
|||
|
|||
internal void OnInternalInspectorGUI() |
|||
{ |
|||
serializedObject.Update(); |
|||
TopRowFields(); |
|||
OnInspectorGUI(); |
|||
EditorGUILayout.Space(); |
|||
serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
|
|||
public virtual void OnInspectorGUI() |
|||
{ |
|||
// Display every field as-is
|
|||
foreach (var parameter in m_Parameters) |
|||
PropertyField(parameter); |
|||
} |
|||
|
|||
public virtual string GetDisplayTitle() |
|||
{ |
|||
return ObjectNames.NicifyVariableName(target.GetType().Name); |
|||
} |
|||
|
|||
void TopRowFields() |
|||
{ |
|||
using (new EditorGUILayout.HorizontalScope()) |
|||
{ |
|||
if (GUILayout.Button(CoreEditorUtils.GetContent("All|Toggle all overrides on. To maximize performances you should only toggle overrides that you actually need."), CoreEditorStyles.miniLabelButton, GUILayout.Width(17f), GUILayout.ExpandWidth(false))) |
|||
SetAllOverridesTo(true); |
|||
|
|||
if (GUILayout.Button(CoreEditorUtils.GetContent("None|Toggle all overrides off."), CoreEditorStyles.miniLabelButton, GUILayout.Width(32f), GUILayout.ExpandWidth(false))) |
|||
SetAllOverridesTo(false); |
|||
|
|||
GUILayout.FlexibleSpace(); |
|||
} |
|||
} |
|||
|
|||
internal void SetAllOverridesTo(bool state) |
|||
{ |
|||
Undo.RecordObject(target, "Toggle All"); |
|||
target.SetAllOverridesTo(state); |
|||
serializedObject.Update(); |
|||
} |
|||
|
|||
// Takes a serialized VolumeParameter<T> as input
|
|||
protected SerializedDataParameter Unpack(SerializedProperty property) |
|||
{ |
|||
Assert.IsNotNull(property); |
|||
return new SerializedDataParameter(property); |
|||
} |
|||
|
|||
protected void PropertyField(SerializedDataParameter property) |
|||
{ |
|||
var title = CoreEditorUtils.GetContent(property.displayName); |
|||
PropertyField(property, title); |
|||
} |
|||
|
|||
protected void PropertyField(SerializedDataParameter property, GUIContent title) |
|||
{ |
|||
// Handle unity built-in decorators (Space, Header, Tooltip etc)
|
|||
foreach (var attr in property.attributes) |
|||
{ |
|||
if (attr is PropertyAttribute) |
|||
{ |
|||
if (attr is SpaceAttribute) |
|||
{ |
|||
EditorGUILayout.GetControlRect(false, (attr as SpaceAttribute).height); |
|||
} |
|||
else if (attr is HeaderAttribute) |
|||
{ |
|||
var rect = EditorGUILayout.GetControlRect(false, EditorGUIUtility.singleLineHeight); |
|||
rect.y += 0f; |
|||
rect = EditorGUI.IndentedRect(rect); |
|||
EditorGUI.LabelField(rect, (attr as HeaderAttribute).header, EditorStyles.miniLabel); |
|||
} |
|||
else if (attr is TooltipAttribute) |
|||
{ |
|||
if (string.IsNullOrEmpty(title.tooltip)) |
|||
title.tooltip = (attr as TooltipAttribute).tooltip; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Custom parameter drawer
|
|||
VolumeParameterDrawer drawer; |
|||
s_ParameterDrawers.TryGetValue(property.referenceType, out drawer); |
|||
|
|||
bool invalidProp = false; |
|||
|
|||
if (drawer != null && !drawer.IsAutoProperty()) |
|||
{ |
|||
if (drawer.OnGUI(property, title)) |
|||
return; |
|||
|
|||
invalidProp = true; |
|||
} |
|||
|
|||
// ObjectParameter<T> is a special case
|
|||
if (VolumeParameter.IsObjectParameter(property.referenceType)) |
|||
{ |
|||
bool expanded = property.value.isExpanded; |
|||
expanded = EditorGUILayout.Foldout(expanded, title, true); |
|||
|
|||
if (expanded) |
|||
{ |
|||
EditorGUI.indentLevel++; |
|||
|
|||
// Not the fastest way to do it but that'll do just fine for now
|
|||
var it = property.value.Copy(); |
|||
var end = it.GetEndProperty(); |
|||
bool first = true; |
|||
|
|||
while (it.Next(first) && !SerializedProperty.EqualContents(it, end)) |
|||
{ |
|||
PropertyField(Unpack(it)); |
|||
first = false; |
|||
} |
|||
|
|||
EditorGUI.indentLevel--; |
|||
} |
|||
|
|||
property.value.isExpanded = expanded; |
|||
return; |
|||
} |
|||
|
|||
using (new EditorGUILayout.HorizontalScope()) |
|||
{ |
|||
// Override checkbox
|
|||
var overrideRect = GUILayoutUtility.GetRect(17f, 17f, GUILayout.ExpandWidth(false)); |
|||
overrideRect.yMin += 4f; |
|||
overrideRect.xMin += EditorGUI.indentLevel * 15f; |
|||
DrawOverrideCheckbox(overrideRect, property.overrideState); |
|||
|
|||
// Property
|
|||
using (new EditorGUI.DisabledScope(!property.overrideState.boolValue)) |
|||
{ |
|||
if (drawer != null && !invalidProp) |
|||
{ |
|||
if (drawer.OnGUI(property, title)) |
|||
return; |
|||
} |
|||
|
|||
// Default unity field
|
|||
EditorGUILayout.PropertyField(property.value, title); |
|||
} |
|||
} |
|||
} |
|||
|
|||
void DrawOverrideCheckbox(Rect rect, SerializedProperty property) |
|||
{ |
|||
var oldColor = GUI.color; |
|||
GUI.color = new Color(0.6f, 0.6f, 0.6f, 0.75f); |
|||
property.boolValue = GUI.Toggle(rect, property.boolValue, CoreEditorUtils.GetContent("|Override this setting for this volume."), CoreEditorStyles.smallTickbox); |
|||
GUI.color = oldColor; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: d6bb22372ebe2bc42a227c8f8c1795ac |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEngine; |
|||
using UnityEngine.Assertions; |
|||
using UnityEngine.Experimental.Rendering; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
[CustomEditor(typeof(Volume))] |
|||
public sealed class VolumeEditor : Editor |
|||
{ |
|||
SerializedProperty m_IsGlobal; |
|||
SerializedProperty m_BlendRadius; |
|||
SerializedProperty m_Weight; |
|||
SerializedProperty m_Priority; |
|||
SerializedProperty m_Components; |
|||
|
|||
Dictionary<Type, Type> m_EditorTypes; // Component type => Editor type
|
|||
List<VolumeComponentEditor> m_Editors; |
|||
|
|||
static VolumeComponent s_ClipboardContent; |
|||
|
|||
Volume actualTarget |
|||
{ |
|||
get { return target as Volume; } |
|||
} |
|||
|
|||
void OnEnable() |
|||
{ |
|||
var o = new PropertyFetcher<Volume>(serializedObject); |
|||
m_IsGlobal = o.Find(x => x.isGlobal); |
|||
m_BlendRadius = o.Find(x => x.blendDistance); |
|||
m_Weight = o.Find(x => x.weight); |
|||
m_Priority = o.Find(x => x.priority); |
|||
m_Components = o.Find(x => x.components); |
|||
|
|||
m_EditorTypes = new Dictionary<Type, Type>(); |
|||
m_Editors = new List<VolumeComponentEditor>(); |
|||
|
|||
// Gets the list of all available component editors
|
|||
var editorTypes = AppDomain.CurrentDomain.GetAssemblies() |
|||
.SelectMany( |
|||
a => a.GetTypes() |
|||
.Where( |
|||
t => t.IsSubclassOf(typeof(VolumeComponentEditor)) |
|||
&& t.IsDefined(typeof(VolumeComponentEditorAttribute), false) |
|||
) |
|||
).ToList(); |
|||
|
|||
// Map them to their corresponding component type
|
|||
foreach (var editorType in editorTypes) |
|||
{ |
|||
var attribute = (VolumeComponentEditorAttribute)editorType.GetCustomAttributes(typeof(VolumeComponentEditorAttribute), false)[0]; |
|||
m_EditorTypes.Add(attribute.componentType, editorType); |
|||
} |
|||
|
|||
// Create editors for existing components
|
|||
var components = actualTarget.components; |
|||
for (int i = 0; i < components.Count; i++) |
|||
CreateEditor(components[i], m_Components.GetArrayElementAtIndex(i)); |
|||
|
|||
// Keep track of undo/redo to redraw the inspector when that happens
|
|||
Undo.undoRedoPerformed += OnUndoRedoPerformed; |
|||
} |
|||
|
|||
void OnDisable() |
|||
{ |
|||
Undo.undoRedoPerformed -= OnUndoRedoPerformed; |
|||
|
|||
if (m_Editors == null) |
|||
return; // Hasn't been inited yet
|
|||
|
|||
foreach (var editor in m_Editors) |
|||
editor.OnDisable(); |
|||
|
|||
m_Editors.Clear(); |
|||
m_EditorTypes.Clear(); |
|||
} |
|||
|
|||
public override void OnInspectorGUI() |
|||
{ |
|||
serializedObject.Update(); |
|||
|
|||
if (actualTarget.isDirty) |
|||
{ |
|||
RefreshEditors(); |
|||
actualTarget.isDirty = false; |
|||
} |
|||
|
|||
using (var scope = new EditorGUILayout.VerticalScope()) |
|||
{ |
|||
EditorGUILayout.PropertyField(m_IsGlobal); |
|||
|
|||
if (!m_IsGlobal.boolValue) // Blend radius is not needed for global volumes
|
|||
{ |
|||
EditorGUILayout.PropertyField(m_BlendRadius); |
|||
m_BlendRadius.floatValue = Mathf.Max(m_BlendRadius.floatValue, 0f); |
|||
} |
|||
|
|||
EditorGUILayout.PropertyField(m_Weight); |
|||
EditorGUILayout.PropertyField(m_Priority); |
|||
|
|||
EditorGUILayout.Space(); |
|||
|
|||
// Component list
|
|||
for (int i = 0; i < m_Editors.Count; i++) |
|||
{ |
|||
var editor = m_Editors[i]; |
|||
string title = editor.GetDisplayTitle(); |
|||
int id = i; // Needed for closure capture below
|
|||
|
|||
CoreEditorUtils.DrawSplitter(); |
|||
bool displayContent = CoreEditorUtils.DrawHeaderToggle( |
|||
title, |
|||
editor.baseProperty, |
|||
editor.activeProperty, |
|||
pos => OnContextClick(pos, editor.target, id) |
|||
); |
|||
|
|||
if (displayContent) |
|||
{ |
|||
using (new EditorGUI.DisabledScope(!editor.activeProperty.boolValue)) |
|||
editor.OnInternalInspectorGUI(); |
|||
} |
|||
} |
|||
|
|||
if (m_Editors.Count > 0) |
|||
CoreEditorUtils.DrawSplitter(); |
|||
else |
|||
EditorGUILayout.HelpBox("No override set on this volume.", MessageType.Info); |
|||
|
|||
using (new EditorGUILayout.HorizontalScope()) |
|||
{ |
|||
GUILayout.FlexibleSpace(); |
|||
|
|||
//if (GUILayout.Button(CoreEditorUtils.GetContent("Add Component"), GUILayout.Width(230f), GUILayout.Height(24f)))
|
|||
//{
|
|||
|
|||
//}
|
|||
|
|||
GUILayout.FlexibleSpace(); |
|||
} |
|||
|
|||
// Handle components drag'n'drop
|
|||
var e = Event.current; |
|||
if (e.type == EventType.DragUpdated) |
|||
{ |
|||
if (IsDragValid(scope.rect, e.mousePosition)) |
|||
{ |
|||
DragAndDrop.visualMode = DragAndDropVisualMode.Link; |
|||
e.Use(); |
|||
} |
|||
else |
|||
{ |
|||
DragAndDrop.visualMode = DragAndDropVisualMode.Rejected; |
|||
} |
|||
} |
|||
else if (e.type == EventType.DragPerform) |
|||
{ |
|||
if (IsDragValid(scope.rect, e.mousePosition)) |
|||
{ |
|||
DragAndDrop.AcceptDrag(); |
|||
|
|||
var objs = DragAndDrop.objectReferences; |
|||
foreach (var o in objs) |
|||
{ |
|||
var compType = ((MonoScript)o).GetClass(); |
|||
AddComponent(compType); |
|||
} |
|||
|
|||
e.Use(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
|
|||
bool IsDragValid(Rect rect, Vector2 mousePos) |
|||
{ |
|||
if (!rect.Contains(mousePos)) |
|||
return false; |
|||
|
|||
var objs = DragAndDrop.objectReferences; |
|||
foreach (var o in objs) |
|||
{ |
|||
if (o.GetType() != typeof(MonoScript)) |
|||
return false; |
|||
|
|||
var script = (MonoScript)o; |
|||
var scriptType = script.GetClass(); |
|||
|
|||
if (!scriptType.IsSubclassOf(typeof(VolumeComponent))) |
|||
return false; |
|||
|
|||
if (actualTarget.components.Exists(t => t.GetType() == scriptType)) |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
void RefreshEditors() |
|||
{ |
|||
// Disable all editors first
|
|||
foreach (var editor in m_Editors) |
|||
editor.OnDisable(); |
|||
|
|||
// Remove them
|
|||
m_Editors.Clear(); |
|||
|
|||
// Recreate editors for existing settings, if any
|
|||
for (int i = 0; i < actualTarget.components.Count; i++) |
|||
CreateEditor(actualTarget.components[i], m_Components.GetArrayElementAtIndex(i)); |
|||
} |
|||
|
|||
// index is only used when we need to re-create a component in a specific spot (e.g. reset)
|
|||
void CreateEditor(VolumeComponent settings, SerializedProperty property, int index = -1) |
|||
{ |
|||
var settingsType = settings.GetType(); |
|||
Type editorType; |
|||
|
|||
if (!m_EditorTypes.TryGetValue(settingsType, out editorType)) |
|||
editorType = typeof(VolumeComponentEditor); |
|||
|
|||
var editor = (VolumeComponentEditor)Activator.CreateInstance(editorType); |
|||
editor.Init(settings, this); |
|||
editor.baseProperty = property.Copy(); |
|||
|
|||
if (index < 0) |
|||
m_Editors.Add(editor); |
|||
else |
|||
m_Editors[index] = editor; |
|||
} |
|||
|
|||
void AddComponent(Type type) |
|||
{ |
|||
serializedObject.Update(); |
|||
|
|||
var component = (VolumeComponent)CreateInstance(type); |
|||
Undo.RegisterCreatedObjectUndo(component, "Add Volume Component"); |
|||
|
|||
// Grow the list first, then add - that's how serialized lists work in Unity
|
|||
m_Components.arraySize++; |
|||
var effectProp = m_Components.GetArrayElementAtIndex(m_Components.arraySize - 1); |
|||
effectProp.objectReferenceValue = component; |
|||
|
|||
// Create & store the internal editor object for this effect
|
|||
CreateEditor(component, effectProp); |
|||
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
} |
|||
|
|||
void RemoveComponent(int id) |
|||
{ |
|||
// Huh. Hack to keep foldout state on the next element...
|
|||
bool nextFoldoutState = false; |
|||
if (id < m_Editors.Count - 1) |
|||
nextFoldoutState = m_Editors[id + 1].baseProperty.isExpanded; |
|||
|
|||
// Remove from the cached editors list
|
|||
m_Editors[id].OnDisable(); |
|||
m_Editors.RemoveAt(id); |
|||
|
|||
serializedObject.Update(); |
|||
|
|||
var property = m_Components.GetArrayElementAtIndex(id); |
|||
var effect = property.objectReferenceValue; |
|||
|
|||
// Unassign it (should be null already but serialization does funky things
|
|||
property.objectReferenceValue = null; |
|||
|
|||
// ...and remove the array index itself from the list
|
|||
m_Components.DeleteArrayElementAtIndex(id); |
|||
|
|||
// Finally refresh editor reference to the serialized settings list
|
|||
for (int i = 0; i < m_Editors.Count; i++) |
|||
m_Editors[i].baseProperty = m_Components.GetArrayElementAtIndex(i).Copy(); |
|||
|
|||
// Set the proper foldout state if needed
|
|||
if (id < m_Editors.Count) |
|||
m_Editors[id].baseProperty.isExpanded = nextFoldoutState; |
|||
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
|
|||
// Destroy the setting object after ApplyModifiedProperties(). If we do it before, redo
|
|||
// actions will be in the wrong order and the reference to the setting object in the
|
|||
// list will be lost.
|
|||
Undo.DestroyObjectImmediate(effect); |
|||
} |
|||
|
|||
// Reset is done by deleting and removing the object from the list and adding a new one in
|
|||
// the same spot as it was before
|
|||
void ResetComponent(Type type, int id) |
|||
{ |
|||
// Remove from the cached editors list
|
|||
m_Editors[id].OnDisable(); |
|||
m_Editors[id] = null; |
|||
|
|||
serializedObject.Update(); |
|||
|
|||
var property = m_Components.GetArrayElementAtIndex(id); |
|||
var prevSettings = property.objectReferenceValue; |
|||
|
|||
// Unassign it but down remove it from the array to keep the index available
|
|||
property.objectReferenceValue = null; |
|||
|
|||
// Create a new object
|
|||
var newEffect = (VolumeComponent)CreateInstance(type); |
|||
Undo.RegisterCreatedObjectUndo(newEffect, "Reset Volume Component"); |
|||
|
|||
// Put it in the reserved space
|
|||
property.objectReferenceValue = newEffect; |
|||
|
|||
// Create & store the internal editor object for this effect
|
|||
CreateEditor(newEffect, property, id); |
|||
|
|||
serializedObject.ApplyModifiedProperties(); |
|||
|
|||
// Same as RemoveComponent, destroy at the end so it's recreated first on Undo to make
|
|||
// sure the GUID exists before undoing the list state
|
|||
Undo.DestroyObjectImmediate(prevSettings); |
|||
} |
|||
|
|||
void OnContextClick(Vector2 position, VolumeComponent targetComponent, int id) |
|||
{ |
|||
var menu = new GenericMenu(); |
|||
menu.AddItem(CoreEditorUtils.GetContent("Reset"), false, () => ResetComponent(targetComponent.GetType(), id)); |
|||
menu.AddItem(CoreEditorUtils.GetContent("Remove"), false, () => RemoveComponent(id)); |
|||
menu.AddSeparator(string.Empty); |
|||
menu.AddItem(CoreEditorUtils.GetContent("Copy Settings"), false, () => CopySettings(targetComponent)); |
|||
|
|||
if (CanPaste(targetComponent)) |
|||
menu.AddItem(CoreEditorUtils.GetContent("Paste Settings"), false, () => PasteSettings(targetComponent)); |
|||
else |
|||
menu.AddDisabledItem(CoreEditorUtils.GetContent("Paste Settings")); |
|||
|
|||
menu.AddSeparator(string.Empty); |
|||
menu.AddItem(CoreEditorUtils.GetContent("Toggle All"), false, () => m_Editors[id].SetAllOverridesTo(true)); |
|||
menu.AddItem(CoreEditorUtils.GetContent("Toggle None"), false, () => m_Editors[id].SetAllOverridesTo(false)); |
|||
|
|||
menu.DropDown(new Rect(position, Vector2.zero)); |
|||
} |
|||
|
|||
// Copy/pasting is simply done by creating an in memory copy of the selected component and
|
|||
// copying over the serialized data to another; it doesn't use nor affect the OS clipboard
|
|||
bool CanPaste(VolumeComponent targetComponent) |
|||
{ |
|||
return s_ClipboardContent != null |
|||
&& s_ClipboardContent.GetType() == targetComponent.GetType(); |
|||
} |
|||
|
|||
void CopySettings(VolumeComponent targetComponent) |
|||
{ |
|||
if (s_ClipboardContent != null) |
|||
{ |
|||
CoreUtils.Destroy(s_ClipboardContent); |
|||
s_ClipboardContent = null; |
|||
} |
|||
|
|||
s_ClipboardContent = (VolumeComponent)CreateInstance(targetComponent.GetType()); |
|||
EditorUtility.CopySerializedIfDifferent(targetComponent, s_ClipboardContent); |
|||
} |
|||
|
|||
void PasteSettings(VolumeComponent targetComponent) |
|||
{ |
|||
Assert.IsNotNull(s_ClipboardContent); |
|||
Assert.AreEqual(s_ClipboardContent.GetType(), targetComponent.GetType()); |
|||
|
|||
Undo.RecordObject(targetComponent, "Paste Settings"); |
|||
EditorUtility.CopySerializedIfDifferent(s_ClipboardContent, targetComponent); |
|||
} |
|||
|
|||
void OnUndoRedoPerformed() |
|||
{ |
|||
actualTarget.isDirty = true; |
|||
|
|||
// Dumb hack to make sure the serialized object is up to date on undo
|
|||
serializedObject.Update(); |
|||
serializedObject.ApplyModifiedProperties(); |
|||
|
|||
// Seems like there's an issue with the inspector not repainting after some undo events
|
|||
// This will take care of that
|
|||
Repaint(); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 9a033a261241d6e48af8ca011ab7c5c1 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] |
|||
public sealed class VolumeParameterDrawerAttribute : Attribute |
|||
{ |
|||
public readonly Type parameterType; |
|||
|
|||
public VolumeParameterDrawerAttribute(Type parameterType) |
|||
{ |
|||
this.parameterType = parameterType; |
|||
} |
|||
} |
|||
|
|||
// Default parameter drawer - simply displays the serialized property as Unity would
|
|||
public abstract class VolumeParameterDrawer |
|||
{ |
|||
// Override this and return false if you want to customize the override checkbox position,
|
|||
// else it'll automatically draw it and put the property content in a horizontal scope.
|
|||
public virtual bool IsAutoProperty() |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
// Return false is the input parameter is invalid - unity will display the default editor
|
|||
// for this control then
|
|||
public abstract bool OnGUI(SerializedDataParameter parameter, GUIContent title); |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: d8ce10b4215bd81438b65f7e23ac0946 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 172515602e62fb746b5d573b38a5fe58 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.ObjectModel; |
|||
using System.Reflection; |
|||
using System.Linq; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
[Serializable] |
|||
public class VolumeComponent : ScriptableObject |
|||
{ |
|||
// Used to control the state of this override - handy to quickly turn a volume override
|
|||
// on & off in the editor
|
|||
public bool active = true; |
|||
|
|||
internal ReadOnlyCollection<VolumeParameter> parameters { get; private set; } |
|||
|
|||
void OnEnable() |
|||
{ |
|||
// Automatically grab all fields of type VolumeParameter for this instance
|
|||
parameters = this.GetType() |
|||
.GetFields(BindingFlags.Public | BindingFlags.Instance) |
|||
.Where(t => t.FieldType.IsSubclassOf(typeof(VolumeParameter))) |
|||
.OrderBy(t => t.MetadataToken) // Guaranteed order
|
|||
.Select(t => (VolumeParameter)t.GetValue(this)) |
|||
.ToList() |
|||
.AsReadOnly(); |
|||
} |
|||
|
|||
public void SetAllOverridesTo(bool state) |
|||
{ |
|||
SetAllOverridesTo(parameters, state); |
|||
} |
|||
|
|||
void SetAllOverridesTo(IEnumerable<VolumeParameter> enumerable, bool state) |
|||
{ |
|||
foreach (var prop in enumerable) |
|||
{ |
|||
prop.overrideState = state; |
|||
var t = prop.GetType(); |
|||
|
|||
if (VolumeParameter.IsObjectParameter(t)) |
|||
{ |
|||
// This method won't be called a lot but this is sub-optimal, fix me
|
|||
var innerParams = (ReadOnlyCollection<VolumeParameter>) |
|||
t.GetProperty("parameters", BindingFlags.NonPublic | BindingFlags.Instance) |
|||
.GetValue(prop, null); |
|||
|
|||
if (innerParams != null) |
|||
SetAllOverridesTo(innerParams, state); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Custom hashing function used to compare the state of settings (it's not meant to be
|
|||
// unique but to be a quick way to check if two setting sets have the same state or not).
|
|||
// Hash collision rate should be pretty low.
|
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
//return parameters.Aggregate(17, (i, p) => i * 23 + p.GetHash());
|
|||
|
|||
int hash = 17; |
|||
|
|||
foreach (var p in parameters) |
|||
hash = hash * 23 + p.GetHashCode(); |
|||
|
|||
return hash; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 556096baecf4aeb4e9f0d3efce77e08f |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using UnityEngine.Assertions; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
public sealed class VolumeManager |
|||
{ |
|||
//>>> System.Lazy<T> is broken in Unity (legacy runtime) so we'll have to do it ourselves :|
|
|||
static volatile VolumeManager s_Instance; |
|||
static object s_LockObj = new Object(); |
|||
|
|||
public static VolumeManager instance |
|||
{ |
|||
get |
|||
{ |
|||
// Double-lock checking
|
|||
if (s_Instance == null) |
|||
{ |
|||
lock (s_LockObj) // Lock on a separate object to avoid deadlocks
|
|||
{ |
|||
if (s_Instance == null) |
|||
s_Instance = new VolumeManager(); |
|||
} |
|||
} |
|||
|
|||
return s_Instance; |
|||
} |
|||
} |
|||
//<<<
|
|||
|
|||
// Max amount of layers available in Unity
|
|||
const int k_MaxLayerCount = 32; |
|||
|
|||
// List of all volumes (sorted by priority) per layer
|
|||
readonly List<Volume>[] m_Volumes; |
|||
|
|||
// Keep track of sorting states for all layers
|
|||
readonly bool[] m_SortNeeded; |
|||
|
|||
// Internal state of all component types
|
|||
readonly Dictionary<Type, VolumeComponent> m_Components; |
|||
|
|||
// Internal list of default state for each component type - this is used to reset component
|
|||
// states on update instead of having to implement a Reset method on all components (which
|
|||
// would be error-prone)
|
|||
readonly List<VolumeComponent> m_ComponentsDefaultState; |
|||
|
|||
// Recycled list used for volume traversal
|
|||
readonly List<Collider> m_TempColliders; |
|||
|
|||
// In the editor, when entering play-mode, it will call the constructor and OnEditorReload()
|
|||
// which in turn will call ReloadBaseTypes() twice, so we need to keep track of the reloads
|
|||
// to avoid wasting any more CPU than required
|
|||
static bool s_StopReloads = false; |
|||
|
|||
VolumeManager() |
|||
{ |
|||
m_Volumes = new List<Volume>[k_MaxLayerCount]; |
|||
m_SortNeeded = new bool[k_MaxLayerCount]; |
|||
m_TempColliders = new List<Collider>(8); |
|||
m_Components = new Dictionary<Type, VolumeComponent>(); |
|||
m_ComponentsDefaultState = new List<VolumeComponent>(); |
|||
|
|||
ReloadBaseTypes(); |
|||
} |
|||
|
|||
#if UNITY_EDITOR
|
|||
// Called every time Unity recompiles scripts in the editor. We need this to keep track of
|
|||
// any new custom component the user might add to the project.
|
|||
[UnityEditor.Callbacks.DidReloadScripts] |
|||
static void OnEditorReload() |
|||
{ |
|||
if (!s_StopReloads) |
|||
instance.ReloadBaseTypes(); |
|||
|
|||
s_StopReloads = false; |
|||
} |
|||
#endif
|
|||
|
|||
// This will be called only once at runtime and everytime script reload kicks-in in the
|
|||
// editor as we need to keep track of any compatible component in the project
|
|||
void ReloadBaseTypes() |
|||
{ |
|||
// Clean component map & default states
|
|||
foreach (var component in m_Components) |
|||
CoreUtils.Destroy(component.Value); |
|||
|
|||
foreach (var component in m_ComponentsDefaultState) |
|||
CoreUtils.Destroy(component); |
|||
|
|||
m_Components.Clear(); |
|||
m_ComponentsDefaultState.Clear(); |
|||
|
|||
// Rebuild it from scratch
|
|||
var types = AppDomain.CurrentDomain.GetAssemblies() |
|||
.SelectMany( |
|||
a => a.GetTypes() |
|||
.Where( |
|||
t => t.IsSubclassOf(typeof(VolumeComponent)) |
|||
) |
|||
); |
|||
|
|||
foreach (var type in types) |
|||
{ |
|||
// We need two instances, one for global state tracking and another one to keep a
|
|||
// default state that will act as the lowest priority global volume (so that we have
|
|||
// a state to fallback to when exiting volumes)
|
|||
var inst = (VolumeComponent)ScriptableObject.CreateInstance(type); |
|||
m_Components.Add(type, inst); |
|||
|
|||
inst = (VolumeComponent)ScriptableObject.CreateInstance(type); |
|||
inst.SetAllOverridesTo(true); |
|||
m_ComponentsDefaultState.Add(inst); |
|||
} |
|||
|
|||
s_StopReloads = true; |
|||
} |
|||
|
|||
public T GetComponent<T>() |
|||
where T : VolumeComponent |
|||
{ |
|||
var comp = GetComponent(typeof(T)); |
|||
return (T)comp; |
|||
} |
|||
|
|||
public VolumeComponent GetComponent(Type type) |
|||
{ |
|||
VolumeComponent comp; |
|||
m_Components.TryGetValue(type, out comp); |
|||
Assert.IsNotNull(comp, "Component map is corrupted, \"" + type + "\" not found"); |
|||
return comp; |
|||
} |
|||
|
|||
public void Register(Volume volume, int layer) |
|||
{ |
|||
var volumes = m_Volumes[layer]; |
|||
|
|||
if (volumes == null) |
|||
{ |
|||
volumes = new List<Volume>(); |
|||
m_Volumes[layer] = volumes; |
|||
} |
|||
|
|||
Assert.IsFalse(volumes.Contains(volume), "Volume has already been registered"); |
|||
volumes.Add(volume); |
|||
SetLayerDirty(layer); |
|||
} |
|||
|
|||
public void Unregister(Volume volume, int layer) |
|||
{ |
|||
var volumes = m_Volumes[layer]; |
|||
|
|||
if (volumes == null) |
|||
return; |
|||
|
|||
volumes.Remove(volume); |
|||
} |
|||
|
|||
internal void SetLayerDirty(int layer) |
|||
{ |
|||
Assert.IsTrue(layer >= 0 && layer <= k_MaxLayerCount, "Invalid layer bit"); |
|||
m_SortNeeded[layer] = true; |
|||
} |
|||
|
|||
internal void UpdateVolumeLayer(Volume volume, int prevLayer, int newLayer) |
|||
{ |
|||
Assert.IsTrue(prevLayer >= 0 && prevLayer <= k_MaxLayerCount, "Invalid layer bit"); |
|||
Unregister(volume, prevLayer); |
|||
Register(volume, newLayer); |
|||
} |
|||
|
|||
// Go through all listed components and lerp overriden values in the global state
|
|||
void OverrideData(List<VolumeComponent> components, float interpFactor) |
|||
{ |
|||
foreach (var component in components) |
|||
{ |
|||
if (!component.active) |
|||
continue; |
|||
|
|||
var target = GetComponent(component.GetType()); |
|||
int count = component.parameters.Count; |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
var toParam = component.parameters[i]; |
|||
if (toParam.overrideState) |
|||
{ |
|||
var fromParam = target.parameters[i]; |
|||
fromParam.Interp(fromParam, toParam, interpFactor); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Faster version of OverrideData to force replace values in the global state
|
|||
void ReplaceData(List<VolumeComponent> components) |
|||
{ |
|||
foreach (var component in components) |
|||
{ |
|||
var target = GetComponent(component.GetType()); |
|||
int count = component.parameters.Count; |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
target.parameters[i].SetValue(component.parameters[i]); |
|||
} |
|||
} |
|||
|
|||
// Update the global state - should be called once per frame in the update loop before
|
|||
// anything else
|
|||
public void Update(Transform trigger, LayerMask layerMask) |
|||
{ |
|||
#if UNITY_EDITOR
|
|||
// Editor specific hack to work around serialization doing funky things when exiting
|
|||
// play mode -> re-create the world when bad things happen
|
|||
if (m_ComponentsDefaultState == null |
|||
|| (m_ComponentsDefaultState.Count > 0 && m_ComponentsDefaultState[0] == null)) |
|||
{ |
|||
ReloadBaseTypes(); |
|||
} |
|||
else |
|||
#endif
|
|||
{ |
|||
// Start by resetting the global state to default values
|
|||
ReplaceData(m_ComponentsDefaultState); |
|||
} |
|||
|
|||
// Do magic
|
|||
bool onlyGlobal = trigger == null; |
|||
int mask = layerMask.value; |
|||
var triggerPos = onlyGlobal ? Vector3.zero : trigger.position; |
|||
|
|||
for (int i = 0; i < k_MaxLayerCount; i++) |
|||
{ |
|||
// Skip layers not in the mask
|
|||
if ((mask & (1 << i)) == 0) |
|||
continue; |
|||
|
|||
// Skip empty layers
|
|||
var volumes = m_Volumes[i]; |
|||
|
|||
if (volumes == null) |
|||
continue; |
|||
|
|||
// Sort the volume list if needed
|
|||
if (m_SortNeeded[i]) |
|||
{ |
|||
SortByPriority(volumes); |
|||
m_SortNeeded[i] = false; |
|||
} |
|||
|
|||
// Traverse all volumes
|
|||
foreach (var volume in volumes) |
|||
{ |
|||
// Skip disabled volumes and volumes without any data or weight
|
|||
if (!volume.enabled || volume.weight <= 0f) |
|||
continue; |
|||
|
|||
var components = volume.components; |
|||
|
|||
// Global volumes always have influence
|
|||
if (volume.isGlobal) |
|||
{ |
|||
OverrideData(components, Mathf.Clamp01(volume.weight)); |
|||
continue; |
|||
} |
|||
|
|||
if (onlyGlobal) |
|||
continue; |
|||
|
|||
// If volume isn't global and has no collider, skip it as it's useless
|
|||
var colliders = m_TempColliders; |
|||
volume.GetComponents(colliders); |
|||
if (colliders.Count == 0) |
|||
continue; |
|||
|
|||
// Find closest distance to volume, 0 means it's inside it
|
|||
float closestDistanceSqr = float.PositiveInfinity; |
|||
|
|||
foreach (var collider in colliders) |
|||
{ |
|||
if (!collider.enabled) |
|||
continue; |
|||
|
|||
var closestPoint = collider.ClosestPoint(triggerPos); |
|||
var d = (closestPoint - triggerPos).sqrMagnitude; |
|||
|
|||
if (d < closestDistanceSqr) |
|||
closestDistanceSqr = d; |
|||
} |
|||
|
|||
colliders.Clear(); |
|||
float blendDistSqr = volume.blendDistance * volume.blendDistance; |
|||
|
|||
// Volume has no influence, ignore it
|
|||
// Note: Volume doesn't do anything when `closestDistanceSqr = blendDistSqr` but
|
|||
// we can't use a >= comparison as blendDistSqr could be set to 0 in which
|
|||
// case volume would have total influence
|
|||
if (closestDistanceSqr > blendDistSqr) |
|||
continue; |
|||
|
|||
// Volume has influence
|
|||
float interpFactor = 1f; |
|||
|
|||
if (blendDistSqr > 0f) |
|||
interpFactor = 1f - (closestDistanceSqr / blendDistSqr); |
|||
|
|||
// No need to clamp01 the interpolation factor as it'll always be in [0;1[ range
|
|||
OverrideData(components, interpFactor * Mathf.Clamp01(volume.weight)); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Stable insertion sort. Faster than List<T>.Sort() for our needs.
|
|||
static void SortByPriority(List<Volume> volumes) |
|||
{ |
|||
Assert.IsNotNull(volumes, "Trying to sort volumes of non-initialized layer"); |
|||
|
|||
for (int i = 1; i < volumes.Count; i++) |
|||
{ |
|||
var temp = volumes[i]; |
|||
int j = i - 1; |
|||
|
|||
// Sort order is ascending
|
|||
while (j >= 0 && volumes[j].priority > temp.priority) |
|||
{ |
|||
volumes[j + 1] = volumes[j]; |
|||
j--; |
|||
} |
|||
|
|||
volumes[j + 1] = temp; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: f709aacbf8d0b0048889f52315d67d58 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.ObjectModel; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
// We need this base class to be able to store a list of VolumeParameter in collections as we
|
|||
// can't store VolumeParameter<T> with variable T types in the same collection. As a result some
|
|||
// of the following is a bit hacky...
|
|||
public abstract class VolumeParameter |
|||
{ |
|||
[SerializeField] |
|||
protected bool m_OverrideState; |
|||
|
|||
public virtual bool overrideState |
|||
{ |
|||
get { return m_OverrideState; } |
|||
set { m_OverrideState = value; } |
|||
} |
|||
|
|||
internal abstract void Interp(VolumeParameter from, VolumeParameter to, float t); |
|||
|
|||
public T GetValue<T>() |
|||
{ |
|||
return ((VolumeParameter<T>)this).value; |
|||
} |
|||
|
|||
internal abstract void SetValue(VolumeParameter parameter); |
|||
|
|||
public static bool IsObjectParameter(Type type) |
|||
{ |
|||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ObjectParameter<>)) |
|||
return true; |
|||
|
|||
return type.BaseType != null |
|||
&& IsObjectParameter(type.BaseType); |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public class VolumeParameter<T> : VolumeParameter |
|||
{ |
|||
[SerializeField] |
|||
protected T m_Value; |
|||
|
|||
public virtual T value |
|||
{ |
|||
get { return m_Value; } |
|||
set { m_Value = value; } |
|||
} |
|||
|
|||
public VolumeParameter() |
|||
: this(default(T), false) |
|||
{ |
|||
} |
|||
|
|||
protected VolumeParameter(T value, bool overrideState) |
|||
{ |
|||
m_Value = value; |
|||
this.overrideState = overrideState; |
|||
} |
|||
|
|||
internal override void Interp(VolumeParameter from, VolumeParameter to, float t) |
|||
{ |
|||
// Note: this is relatively unsafe (assumes that from and to are both holding type T)
|
|||
Interp(from.GetValue<T>(), to.GetValue<T>(), t); |
|||
} |
|||
|
|||
public virtual void Interp(T from, T to, float t) |
|||
{ |
|||
// Returns `b` if `dt > 0` by default so we don't have to write overrides for bools and
|
|||
// enumerations.
|
|||
m_Value = t > 0f ? to : from; |
|||
} |
|||
|
|||
public void Override(T x) |
|||
{ |
|||
overrideState = true; |
|||
m_Value = x; |
|||
} |
|||
|
|||
internal override void SetValue(VolumeParameter parameter) |
|||
{ |
|||
m_Value = parameter.GetValue<T>(); |
|||
} |
|||
|
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hash = 17; |
|||
hash = hash * 23 + overrideState.GetHashCode(); |
|||
hash = hash * 23 + value.GetHashCode(); |
|||
return hash; |
|||
} |
|||
} |
|||
|
|||
//
|
|||
// Implicit conversion; assuming the following:
|
|||
//
|
|||
// var myFloatProperty = new ParameterOverride<float> { value = 42f; };
|
|||
//
|
|||
// It allows for implicit casts:
|
|||
//
|
|||
// float myFloat = myFloatProperty.value; // No implicit cast
|
|||
// float myFloat = myFloatProperty; // Implicit cast
|
|||
//
|
|||
// For safety reason this is one-way only.
|
|||
//
|
|||
public static implicit operator T(VolumeParameter<T> prop) |
|||
{ |
|||
return prop.m_Value; |
|||
} |
|||
} |
|||
|
|||
public enum ParameterClampMode |
|||
{ |
|||
Min, |
|||
Max, |
|||
MinMax |
|||
} |
|||
|
|||
//
|
|||
// The serialization system in Unity can't serialize generic types, the workaround is to extend
|
|||
// and flatten pre-defined generic types.
|
|||
// For enums it's recommended to make your own types on the spot, like so:
|
|||
//
|
|||
// [Serializable]
|
|||
// public sealed class MyEnumParameter : VolumeParameter<MyEnum> { }
|
|||
// public enum MyEnum { One, Two }
|
|||
//
|
|||
|
|||
[Serializable] |
|||
public sealed class BoolParameter : VolumeParameter<bool> { } |
|||
|
|||
[Serializable] |
|||
public sealed class IntParameter : VolumeParameter<int> |
|||
{ |
|||
public override void Interp(int from, int to, float t) |
|||
{ |
|||
// Int snapping interpolation. Don't use this for enums as they don't necessarily have
|
|||
// contiguous values. Use the default interpolator instead (same as bool).
|
|||
m_Value = (int)(from + (to - from) * t); |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public sealed class InstantIntParameter : VolumeParameter<int> { } |
|||
|
|||
[Serializable] |
|||
public sealed class ClampedIntParameter : VolumeParameter<int> |
|||
{ |
|||
public ParameterClampMode clampMode = ParameterClampMode.MinMax; |
|||
public int min = 0; |
|||
public int max = 10; |
|||
|
|||
public override int value |
|||
{ |
|||
get { return m_Value; } |
|||
set |
|||
{ |
|||
switch (clampMode) |
|||
{ |
|||
case ParameterClampMode.Min: m_Value = Mathf.Max(min, value); break; |
|||
case ParameterClampMode.Max: m_Value = Mathf.Min(max, value); break; |
|||
case ParameterClampMode.MinMax: m_Value = Mathf.Clamp(value, min, max); break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public override void Interp(int from, int to, float t) |
|||
{ |
|||
m_Value = (int)(from + (to - from) * t); |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public sealed class InstantClampedIntParameter : VolumeParameter<int> |
|||
{ |
|||
public ParameterClampMode clampMode = ParameterClampMode.MinMax; |
|||
public int min = 0; |
|||
public int max = 10; |
|||
|
|||
public override int value |
|||
{ |
|||
get { return m_Value; } |
|||
set |
|||
{ |
|||
switch (clampMode) |
|||
{ |
|||
case ParameterClampMode.Min: m_Value = Mathf.Max(min, value); break; |
|||
case ParameterClampMode.Max: m_Value = Mathf.Min(max, value); break; |
|||
case ParameterClampMode.MinMax: m_Value = Mathf.Clamp(value, min, max); break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public sealed class FloatParameter : VolumeParameter<float> |
|||
{ |
|||
public override void Interp(float from, float to, float t) |
|||
{ |
|||
m_Value = from + (to - from) * t; |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public sealed class InstantFloatParameter : VolumeParameter<float> { } |
|||
|
|||
[Serializable] |
|||
public sealed class ClampedFloatParameter : VolumeParameter<float> |
|||
{ |
|||
public ParameterClampMode clampMode = ParameterClampMode.MinMax; |
|||
public float min = 0f; |
|||
public float max = 1f; |
|||
|
|||
public override float value |
|||
{ |
|||
get { return m_Value; } |
|||
set |
|||
{ |
|||
switch (clampMode) |
|||
{ |
|||
case ParameterClampMode.Min: m_Value = Mathf.Max(min, value); break; |
|||
case ParameterClampMode.Max: m_Value = Mathf.Min(max, value); break; |
|||
case ParameterClampMode.MinMax: m_Value = Mathf.Clamp(value, min, max); break; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// We could override FloatParameter here but that would require making it not-sealed which
|
|||
// will stop the compiler from doing specific optimizations on virtual methods - considering
|
|||
// how often float is used, duplicating the code in this case is a definite win
|
|||
public override void Interp(float from, float to, float t) |
|||
{ |
|||
m_Value = from + (to - from) * t; |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public sealed class InstantClampedFloatParameter : VolumeParameter<float> |
|||
{ |
|||
public ParameterClampMode clampMode = ParameterClampMode.MinMax; |
|||
public float min = 0f; |
|||
public float max = 1f; |
|||
|
|||
public override float value |
|||
{ |
|||
get { return m_Value; } |
|||
set |
|||
{ |
|||
switch (clampMode) |
|||
{ |
|||
case ParameterClampMode.Min: m_Value = Mathf.Max(min, value); break; |
|||
case ParameterClampMode.Max: m_Value = Mathf.Min(max, value); break; |
|||
case ParameterClampMode.MinMax: m_Value = Mathf.Clamp(value, min, max); break; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Holds a min & a max values clamped in a range (MinMaxSlider in the editor)
|
|||
[Serializable] |
|||
public sealed class RangeParameter : VolumeParameter<Vector2> |
|||
{ |
|||
public float min = 0; |
|||
public float max = 1; |
|||
|
|||
public override Vector2 value |
|||
{ |
|||
get { return m_Value; } |
|||
set |
|||
{ |
|||
m_Value.x = Mathf.Max(value.x, min); |
|||
m_Value.y = Mathf.Min(value.y, max); |
|||
} |
|||
} |
|||
|
|||
public override void Interp(Vector2 from, Vector2 to, float t) |
|||
{ |
|||
m_Value.x = from.x + (to.x - from.x) * t; |
|||
m_Value.y = from.y + (to.y - from.y) * t; |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public sealed class InstantRangeParameter : VolumeParameter<Vector2> |
|||
{ |
|||
public float min = 0; |
|||
public float max = 1; |
|||
|
|||
public override Vector2 value |
|||
{ |
|||
get { return m_Value; } |
|||
set |
|||
{ |
|||
m_Value.x = Mathf.Max(value.x, min); |
|||
m_Value.y = Mathf.Min(value.y, max); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 32-bit RGBA
|
|||
[Serializable] |
|||
public sealed class ColorParameter : VolumeParameter<Color> |
|||
{ |
|||
public bool hdr = false; |
|||
public bool showAlpha = true; |
|||
public bool showEyeDropper = true; |
|||
|
|||
public override void Interp(Color from, Color to, float t) |
|||
{ |
|||
// Lerping color values is a sensitive subject... We looked into lerping colors using
|
|||
// HSV and LCH but they have some downsides that make them not work correctly in all
|
|||
// situations, so we stick with RGB lerping for now, at least its behavior is
|
|||
// predictable despite looking desaturated when `t ~= 0.5` and it's faster anyway.
|
|||
m_Value.r = from.r + (to.r - from.r) * t; |
|||
m_Value.g = from.g + (to.g - from.g) * t; |
|||
m_Value.b = from.b + (to.b - from.b) * t; |
|||
m_Value.a = from.a + (to.a - from.a) * t; |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public sealed class InstantColorParameter : VolumeParameter<Color> { } |
|||
|
|||
[Serializable] |
|||
public sealed class Vector2Parameter : VolumeParameter<Vector2> |
|||
{ |
|||
public override void Interp(Vector2 from, Vector2 to, float t) |
|||
{ |
|||
m_Value.x = from.x + (to.x - from.x) * t; |
|||
m_Value.y = from.y + (to.y - from.y) * t; |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public sealed class InstantVector2Parameter : VolumeParameter<Vector2> { } |
|||
|
|||
[Serializable] |
|||
public sealed class Vector3Parameter : VolumeParameter<Vector3> |
|||
{ |
|||
public override void Interp(Vector3 from, Vector3 to, float t) |
|||
{ |
|||
m_Value.x = from.x + (to.x - from.x) * t; |
|||
m_Value.y = from.y + (to.y - from.y) * t; |
|||
m_Value.z = from.z + (to.z - from.z) * t; |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public sealed class InstantVector3Parameter : VolumeParameter<Vector3> { } |
|||
|
|||
[Serializable] |
|||
public sealed class Vector4Parameter : VolumeParameter<Vector4> |
|||
{ |
|||
public override void Interp(Vector4 from, Vector4 to, float t) |
|||
{ |
|||
m_Value.x = from.x + (to.x - from.x) * t; |
|||
m_Value.y = from.y + (to.y - from.y) * t; |
|||
m_Value.z = from.z + (to.z - from.z) * t; |
|||
m_Value.w = from.w + (to.w - from.w) * t; |
|||
} |
|||
} |
|||
|
|||
[Serializable] |
|||
public sealed class InstantVector4Parameter : VolumeParameter<Vector4> { } |
|||
|
|||
// Used as a container to store custom serialized classes/structs inside volume components
|
|||
[Serializable] |
|||
public class ObjectParameter<T> : VolumeParameter<T> |
|||
{ |
|||
internal ReadOnlyCollection<VolumeParameter> parameters { get; private set; } |
|||
|
|||
// Force override state to true for container objects
|
|||
public override bool overrideState |
|||
{ |
|||
get { return true; } |
|||
set { m_OverrideState = true; } |
|||
} |
|||
|
|||
public override T value |
|||
{ |
|||
get { return m_Value; } |
|||
set |
|||
{ |
|||
m_Value = value; |
|||
|
|||
if (m_Value == null) |
|||
{ |
|||
parameters = null; |
|||
return; |
|||
} |
|||
|
|||
// Automatically grab all fields of type VolumeParameter contained in this instance
|
|||
parameters = m_Value.GetType() |
|||
.GetFields(BindingFlags.Public | BindingFlags.Instance) |
|||
.Where(t => t.FieldType.IsSubclassOf(typeof(VolumeParameter))) |
|||
.OrderBy(t => t.MetadataToken) // Guaranteed order
|
|||
.Select(t => (VolumeParameter)t.GetValue(m_Value)) |
|||
.ToList() |
|||
.AsReadOnly(); |
|||
} |
|||
} |
|||
|
|||
internal override void Interp(VolumeParameter from, VolumeParameter to, float t) |
|||
{ |
|||
if (m_Value == null) |
|||
return; |
|||
|
|||
var paramOrigin = parameters; |
|||
var paramFrom = ((ObjectParameter<T>)from).parameters; |
|||
var paramTo = ((ObjectParameter<T>)to).parameters; |
|||
|
|||
for (int i = 0; i < paramFrom.Count; i++) |
|||
{ |
|||
if (paramOrigin[i].overrideState) |
|||
paramOrigin[i].Interp(paramFrom[i], paramTo[i], t); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: d53242bc2649d524aa42f2a84eb077b2 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
[ExecuteInEditMode] |
|||
public class Volume : MonoBehaviour |
|||
{ |
|||
[Tooltip("A global volume is applied to the whole scene.")] |
|||
public bool isGlobal = false; |
|||
|
|||
[Tooltip("Volume priority in the stack. Higher number means higher priority. Negative values are supported.")] |
|||
public float priority = 0f; |
|||
|
|||
[Tooltip("Outer distance to start blending from. A value of 0 means no blending and the volume overrides will be applied immediatly upon entry.")] |
|||
public float blendDistance = 0f; |
|||
|
|||
[Range(0f, 1f), Tooltip("Total weight of this volume in the scene. 0 means it won't do anything, 1 means full effect.")] |
|||
public float weight = 1f; |
|||
|
|||
public List<VolumeComponent> components = new List<VolumeComponent>(); |
|||
|
|||
// Editor-only
|
|||
[NonSerialized] |
|||
public bool isDirty; |
|||
|
|||
// Needed for state tracking (see the comments in Update)
|
|||
int m_PreviousLayer; |
|||
float m_PreviousPriority; |
|||
|
|||
void OnEnable() |
|||
{ |
|||
// Make sure every setting is valid. If a profile holds a script that doesn't exist
|
|||
// anymore, nuke it to keep the volume clean. Note that if you delete a script that is
|
|||
// currently in use in a volume you'll still get a one-time error in the console, it's
|
|||
// harmless and happens because Unity does a redraw of the editor (and thus the current
|
|||
// frame) before the recompilation step.
|
|||
components.RemoveAll(x => x == null); |
|||
|
|||
m_PreviousLayer = gameObject.layer; |
|||
VolumeManager.instance.Register(this, m_PreviousLayer); |
|||
} |
|||
|
|||
void OnDisable() |
|||
{ |
|||
VolumeManager.instance.Unregister(this, gameObject.layer); |
|||
} |
|||
|
|||
void Reset() |
|||
{ |
|||
isDirty = true; |
|||
} |
|||
|
|||
void Update() |
|||
{ |
|||
// Unfortunately we need to track the current layer to update the volume manager in
|
|||
// real-time as the user could change it at any time in the editor or at runtime.
|
|||
// Because no event is raised when the layer changes, we have to track it on every
|
|||
// frame :/
|
|||
int layer = gameObject.layer; |
|||
if (layer != m_PreviousLayer) |
|||
{ |
|||
VolumeManager.instance.UpdateVolumeLayer(this, m_PreviousLayer, layer); |
|||
m_PreviousLayer = layer; |
|||
} |
|||
|
|||
// Same for priority. We could use a property instead, but it doesn't play nice with the
|
|||
// serialization system. Using a custom Attribute/PropertyDrawer for a property is
|
|||
// possible but it doesn't work with Undo/Redo in the editor, which makes it useless for
|
|||
// our case.
|
|||
if (priority != m_PreviousPriority) |
|||
{ |
|||
VolumeManager.instance.SetLayerDirty(layer); |
|||
m_PreviousPriority = priority; |
|||
} |
|||
} |
|||
|
|||
public T Add<T>(bool overrides = false) |
|||
where T : VolumeComponent |
|||
{ |
|||
if (Has<T>()) |
|||
throw new InvalidOperationException("Component already exists in the volume"); |
|||
|
|||
var component = ScriptableObject.CreateInstance<T>(); |
|||
component.SetAllOverridesTo(overrides); |
|||
isDirty = true; |
|||
return component; |
|||
} |
|||
|
|||
public void Remove<T>() |
|||
where T : VolumeComponent |
|||
{ |
|||
int toRemove = -1; |
|||
var type = typeof(T); |
|||
|
|||
for (int i = 0; i < components.Count; i++) |
|||
{ |
|||
if (components[i].GetType() == type) |
|||
{ |
|||
toRemove = i; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (toRemove >= 0) |
|||
{ |
|||
components.RemoveAt(toRemove); |
|||
isDirty = true; |
|||
} |
|||
} |
|||
|
|||
public bool Has<T>() |
|||
where T : VolumeComponent |
|||
{ |
|||
var type = typeof(T); |
|||
|
|||
foreach (var component in components) |
|||
{ |
|||
if (component.GetType() == type) |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public bool TryGet<T>(out T component) |
|||
where T : VolumeComponent |
|||
{ |
|||
var type = typeof(T); |
|||
component = null; |
|||
|
|||
foreach (var comp in components) |
|||
{ |
|||
if (comp.GetType() == type) |
|||
{ |
|||
component = (T)comp; |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
#if UNITY_EDITOR
|
|||
// TODO: Look into a better volume previsualization system
|
|||
List<Collider> m_TempColliders; |
|||
|
|||
void OnDrawGizmos() |
|||
{ |
|||
if (m_TempColliders == null) |
|||
m_TempColliders = new List<Collider>(); |
|||
|
|||
var colliders = m_TempColliders; |
|||
GetComponents(colliders); |
|||
|
|||
if (isGlobal || colliders == null) |
|||
return; |
|||
|
|||
var scale = transform.localScale; |
|||
var invScale = new Vector3(1f / scale.x, 1f / scale.y, 1f / scale.z); |
|||
Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, scale); |
|||
Gizmos.color = new Color(0f, 1f, 0.1f, 0.6f); |
|||
|
|||
// Draw a separate gizmo for each collider
|
|||
foreach (var collider in colliders) |
|||
{ |
|||
if (!collider.enabled) |
|||
continue; |
|||
|
|||
// We'll just use scaling as an approximation for volume skin. It's far from being
|
|||
// correct (and is completely wrong in some cases). Ultimately we'd use a distance
|
|||
// field or at least a tesselate + push modifier on the collider's mesh to get a
|
|||
// better approximation, but the current Gizmo system is a bit limited and because
|
|||
// everything is dynamic in Unity and can be changed at anytime, it's hard to keep
|
|||
// track of changes in an elegant way (which we'd need to implement a nice cache
|
|||
// system for generated volume meshes).
|
|||
var type = collider.GetType(); |
|||
|
|||
if (type == typeof(BoxCollider)) |
|||
{ |
|||
var c = (BoxCollider)collider; |
|||
Gizmos.DrawCube(c.center, c.size); |
|||
Gizmos.DrawWireCube(c.center, c.size + invScale * blendDistance * 2f); |
|||
} |
|||
else if (type == typeof(SphereCollider)) |
|||
{ |
|||
var c = (SphereCollider)collider; |
|||
Gizmos.DrawSphere(c.center, c.radius); |
|||
Gizmos.DrawWireSphere(c.center, c.radius + invScale.x * blendDistance); |
|||
} |
|||
else if (type == typeof(MeshCollider)) |
|||
{ |
|||
var c = (MeshCollider)collider; |
|||
|
|||
// Only convex mesh colliders are allowed
|
|||
if (!c.convex) |
|||
c.convex = true; |
|||
|
|||
// Mesh pivot should be centered or this won't work
|
|||
Gizmos.DrawMesh(c.sharedMesh); |
|||
Gizmos.DrawWireMesh(c.sharedMesh, Vector3.zero, Quaternion.identity, Vector3.one + invScale * blendDistance * 2f); |
|||
} |
|||
|
|||
// Nothing for capsule (DrawCapsule isn't exposed in Gizmo), terrain, wheel and
|
|||
// other colliders...
|
|||
} |
|||
|
|||
colliders.Clear(); |
|||
} |
|||
#endif
|
|||
} |
|||
} |
|
|||
using UnityEngine.Rendering; |
|||
using System; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering.HDPipeline |
|||
{ |
|||
// For multiple importance sampling
|
|||
// TODO: not working currently, will be updated later
|
|||
[GenerateHLSL(PackingRules.Exact)] |
|||
public enum LightSamplingParameters |
|||
{ |
|||
TextureHeight = 256, |
|||
TextureWidth = 512 |
|||
} |
|||
} |
|
|||
// |
|||
// This file was automatically generated. Please don't edit by hand. |
|||
// |
|||
|
|||
#ifndef GGXCONVOLUTION_CS_HLSL |
|||
#define GGXCONVOLUTION_CS_HLSL |
|||
// |
|||
// UnityEngine.Experimental.Rendering.HDPipeline.LightSamplingParameters: static fields |
|||
// |
|||
#define LIGHTSAMPLINGPARAMETERS_TEXTURE_HEIGHT (256) |
|||
#define LIGHTSAMPLINGPARAMETERS_TEXTURE_WIDTH (512) |
|||
|
|||
|
|||
#endif |
|
|||
fileFormatVersion: 2 |
|||
guid: d2c1bda84c2c45f4782732c8e3f3ba1b |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
nonModifiableTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: f96a85514b0168541b31f8f052d55f1d |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
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. |
|
|||
fileFormatVersion: 2 |
|||
guid: 4eead1bf6efbd0a4e852367accddc070 |
|||
timeCreated: 1480334378 |
|||
licenseType: Pro |
|||
TextScriptImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: 839dd86bae5fa4d46bf4facd02608862 |
|||
timeCreated: 1483546512 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
// |
|||
// This file was automatically generated. Please don't edit by hand. |
|||
// |
|||
|
|||
#ifndef SKYMANAGER_CS_HLSL |
|||
#define SKYMANAGER_CS_HLSL |
|||
// |
|||
// UnityEngine.Experimental.Rendering.HDPipeline.LightSamplingParameters: static fields |
|||
// |
|||
#define LIGHTSAMPLINGPARAMETERS_TEXTURE_HEIGHT (256) |
|||
#define LIGHTSAMPLINGPARAMETERS_TEXTURE_WIDTH (512) |
|||
|
|||
|
|||
#endif |
|
|||
fileFormatVersion: 2 |
|||
guid: 65f9231eb40b6914eb24ea0b555778f0 |
|||
folderAsset: yes |
|||
timeCreated: 1481646017 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue