当前提交
85affe1f
共有 675 个文件被更改,包括 4619 次插入 和 1156 次删除
-
4MaterialGraphProject/Assets/SRP.meta
-
4MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline.meta
-
2MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Camera/CameraSwitcher.cs
-
82MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Camera/FreeCamera.cs
-
19MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/CommandBufferPool.cs
-
107MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugActionManager.cs
-
14MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugItemHandler.cs
-
6MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugItemUI.cs
-
3MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugMenuManager.cs
-
56MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugMenuState.cs
-
3MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugMenuUI.cs
-
4MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugMenuUpdater.cs
-
14MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugPanel.cs
-
39MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/DebugPanelUI.cs
-
1MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Debugging.cs
-
13MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Editor/DebugMenuEditor.cs
-
4MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateBool.cs
-
4MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateColor.cs
-
4MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateFloat.cs
-
4MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateInt.cs
-
4MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Debugging/Serialization/DebugItemStateUInt.cs
-
2MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderGenerator/Editor/CSharpToHLSL.cs
-
193MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/BSDF.hlsl
-
26MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Common.hlsl
-
46MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/CommonLighting.hlsl
-
29MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/CommonMaterial.hlsl
-
13MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/EntityLighting.hlsl
-
8MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Fibonacci.hlsl
-
174MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl
-
9MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/PerPixelDisplacement.hlsl
-
9MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/Shadow.hlsl
-
310MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl
-
46MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Shadow/ShadowSampling.hlsl
-
10MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/VolumeRendering.hlsl
-
32MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ShaderLibrary/Wind.hlsl
-
2MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Singleton.cs
-
90MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/TextureCache.cs
-
28MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/LegacyShadersToLightweightPipelineUpgrader.cs
-
46MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/LightweightAssetInspector.cs
-
72MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/LightweightPipelineUpgraders.cs
-
3MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/ShaderGUI/LightweightUnlitGUI.cs
-
8MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/StandardToLightweightMaterialUpgrader.cs
-
1MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/UpgradeCommon.cs
-
888MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/LightweightPipeline.cs
-
13MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineAsset.asset
-
98MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineAsset.cs
-
106MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/LightweightPipelineUtils.cs
-
4MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Materials/Lightweight-DefaultParticle.mat
-
2MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Materials/Lightweight-StandardShader.mat
-
4MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Materials/Lightweight-StandardSimpleLighting.mat
-
67MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightUnlit.shader
-
84MaterialGraphProject/Assets/UnityShaderEditor/Editor/Templates/lightweightSubshaderPBR.template
-
6MaterialGraphProject/Packages/manifest.json
-
8MaterialGraphProject/Assets/SRP/PostProcessing.meta
-
249MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/CoreUtils.cs
-
13MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/CoreUtils.cs.meta
-
121MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Editor/CoreEditorUtils.cs
-
13MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Editor/CoreEditorUtils.cs.meta
-
60MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Editor/PropertyFetcher.cs
-
13MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Editor/PropertyFetcher.cs.meta
-
10MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Inputs.meta
-
60MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ProfilingSample.cs
-
13MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/ProfilingSample.cs.meta
-
10MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Resources/Editor.meta
-
23MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Resources/GPUCopy.compute
-
10MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Resources/GPUCopy.compute.meta
-
33MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Resources/GPUCopy.cs
-
13MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Resources/GPUCopy.cs.meta
-
164MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Resources/GPUCopyAsset.cs
-
13MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Resources/GPUCopyAsset.cs.meta
-
17MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Resources/GPUCopyDefinition.asset
-
10MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Resources/GPUCopyDefinition.asset.meta
-
9MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/Core/Shadow.meta
-
437MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/ShaderGUI/LightweightStandardGUI.cs
-
253MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Editor/ShaderGUI/LightweightStandardSimpleLightingGUI.cs
-
24MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/LightweightConstantBuffer.cs
-
13MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/LightweightConstantBuffer.cs.meta
-
46MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightBlit.shader
-
10MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightBlit.shader.meta
-
46MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightCopyDepth.shader
-
10MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightCopyDepth.shader.meta
-
135MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightCore.cginc
-
380MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightLighting.cginc
-
226MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassLit.cginc
-
9MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassLit.cginc.meta
-
20MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassShadow.cginc
-
9MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightPassShadow.cginc.meta
-
93MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightShadows.cginc
-
142MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandard.shader
-
172MaterialGraphProject/Assets/SRP/ScriptableRenderPipeline/LightweightPipeline/Shaders/LightweightStandardSimpleLighting.shader
-
39MaterialGraphProject/Assets/SRP/PostProcessing/.gitignore
-
0MaterialGraphProject/Assets/SRP/PostProcessing/.npmignore
-
21MaterialGraphProject/Assets/SRP/PostProcessing/LICENSE
-
8MaterialGraphProject/Assets/SRP/PostProcessing/PostProcessing/Editor.meta
|
|||
fileFormatVersion: 2 |
|||
guid: fd470011795144262bf5aa4bf5f396a1 |
|||
guid: 22c204b70537f8d46a054fa00bf16298 |
|||
timeCreated: 1505274236 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|
|||
{ |
|||
"registry": "https://staging-packages.unity.com", |
|||
"dependencies": { |
|||
"com.unity.postprocessing": "0.1.0" |
|||
} |
|||
"dependencies": { |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 38d8e45b559f16145a6d92d0fff86c50 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEngine.Rendering; |
|||
using UnityEngine.Rendering.PostProcessing; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
using UnityObject = UnityEngine.Object; |
|||
|
|||
[Flags] |
|||
public enum ClearFlag |
|||
{ |
|||
None = 0, |
|||
Color = 1, |
|||
Depth = 2, |
|||
|
|||
All = Depth | Color |
|||
} |
|||
|
|||
public static class CoreUtils |
|||
{ |
|||
// Render Target Management.
|
|||
public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier buffer, ClearFlag clearFlag, Color clearColor, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown) |
|||
{ |
|||
cmd.SetRenderTarget(buffer, miplevel, cubemapFace); |
|||
|
|||
if (clearFlag != ClearFlag.None) |
|||
cmd.ClearRenderTarget((clearFlag & ClearFlag.Depth) != 0, (clearFlag & ClearFlag.Color) != 0, clearColor); |
|||
} |
|||
|
|||
public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier buffer, ClearFlag clearFlag = ClearFlag.None, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown) |
|||
{ |
|||
SetRenderTarget(cmd, buffer, clearFlag, Color.black, miplevel, cubemapFace); |
|||
} |
|||
|
|||
public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown) |
|||
{ |
|||
SetRenderTarget(cmd, colorBuffer, depthBuffer, ClearFlag.None, Color.black, miplevel, cubemapFace); |
|||
} |
|||
|
|||
public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown) |
|||
{ |
|||
SetRenderTarget(cmd, colorBuffer, depthBuffer, clearFlag, Color.black, miplevel, cubemapFace); |
|||
} |
|||
|
|||
public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag, Color clearColor, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown) |
|||
{ |
|||
cmd.SetRenderTarget(colorBuffer, depthBuffer, miplevel, cubemapFace); |
|||
|
|||
if (clearFlag != ClearFlag.None) |
|||
cmd.ClearRenderTarget((clearFlag & ClearFlag.Depth) != 0, (clearFlag & ClearFlag.Color) != 0, clearColor); |
|||
} |
|||
|
|||
public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthBuffer) |
|||
{ |
|||
SetRenderTarget(cmd, colorBuffers, depthBuffer, ClearFlag.None, Color.black); |
|||
} |
|||
|
|||
public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag = ClearFlag.None) |
|||
{ |
|||
SetRenderTarget(cmd, colorBuffers, depthBuffer, clearFlag, Color.black); |
|||
} |
|||
|
|||
public static void SetRenderTarget(CommandBuffer cmd, RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag, Color clearColor) |
|||
{ |
|||
cmd.SetRenderTarget(colorBuffers, depthBuffer); |
|||
|
|||
if (clearFlag != ClearFlag.None) |
|||
cmd.ClearRenderTarget((clearFlag & ClearFlag.Depth) != 0, (clearFlag & ClearFlag.Color) != 0, clearColor); |
|||
} |
|||
|
|||
public static void ClearCubemap(CommandBuffer cmd, RenderTargetIdentifier buffer, Color clearColor) |
|||
{ |
|||
for(int i = 0; i < 6; ++i) |
|||
SetRenderTarget(cmd, buffer, ClearFlag.Color, Color.black, 0, (CubemapFace)i); |
|||
} |
|||
|
|||
// Draws a full screen triangle as a faster alternative to drawing a full screen quad.
|
|||
public static void DrawFullScreen(CommandBuffer commandBuffer, Material material, |
|||
MaterialPropertyBlock properties = null, int shaderPassId = 0) |
|||
{ |
|||
commandBuffer.DrawProcedural(Matrix4x4.identity, material, shaderPassId, MeshTopology.Triangles, 3, 1, properties); |
|||
} |
|||
|
|||
public static void DrawFullScreen(CommandBuffer commandBuffer, Material material, |
|||
RenderTargetIdentifier colorBuffer, |
|||
MaterialPropertyBlock properties = null, int shaderPassId = 0) |
|||
{ |
|||
commandBuffer.SetRenderTarget(colorBuffer); |
|||
commandBuffer.DrawProcedural(Matrix4x4.identity, material, shaderPassId, MeshTopology.Triangles, 3, 1, properties); |
|||
} |
|||
|
|||
public static void DrawFullScreen(CommandBuffer commandBuffer, Material material, |
|||
RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthStencilBuffer, |
|||
MaterialPropertyBlock properties = null, int shaderPassId = 0) |
|||
{ |
|||
commandBuffer.SetRenderTarget(colorBuffer, depthStencilBuffer); |
|||
commandBuffer.DrawProcedural(Matrix4x4.identity, material, shaderPassId, MeshTopology.Triangles, 3, 1, properties); |
|||
} |
|||
|
|||
public static void DrawFullScreen(CommandBuffer commandBuffer, Material material, |
|||
RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthStencilBuffer, |
|||
MaterialPropertyBlock properties = null, int shaderPassId = 0) |
|||
{ |
|||
commandBuffer.SetRenderTarget(colorBuffers, depthStencilBuffer); |
|||
commandBuffer.DrawProcedural(Matrix4x4.identity, material, shaderPassId, MeshTopology.Triangles, 3, 1, properties); |
|||
} |
|||
|
|||
// Important: the first RenderTarget must be created with 0 depth bits!
|
|||
public static void DrawFullScreen(CommandBuffer commandBuffer, Material material, |
|||
RenderTargetIdentifier[] colorBuffers, |
|||
MaterialPropertyBlock properties = null, int shaderPassId = 0) |
|||
{ |
|||
// It is currently not possible to have MRT without also setting a depth target.
|
|||
// To work around this deficiency of the CommandBuffer.SetRenderTarget() API,
|
|||
// we pass the first color target as the depth target. If it has 0 depth bits,
|
|||
// no depth target ends up being bound.
|
|||
DrawFullScreen(commandBuffer, material, colorBuffers, colorBuffers[0], properties, shaderPassId); |
|||
} |
|||
|
|||
// Post-processing misc
|
|||
public static bool IsPostProcessingActive(PostProcessLayer layer) |
|||
{ |
|||
return layer != null |
|||
&& layer.enabled; |
|||
} |
|||
|
|||
public static bool IsTemporalAntialiasingActive(PostProcessLayer layer) |
|||
{ |
|||
return IsPostProcessingActive(layer) |
|||
&& layer.antialiasingMode == PostProcessLayer.Antialiasing.TemporalAntialiasing |
|||
&& layer.temporalAntialiasing.IsSupported(); |
|||
} |
|||
|
|||
// Unity specifics
|
|||
public static Material CreateEngineMaterial(string shaderPath) |
|||
{ |
|||
var mat = new Material(Shader.Find(shaderPath)) |
|||
{ |
|||
hideFlags = HideFlags.HideAndDontSave |
|||
}; |
|||
return mat; |
|||
} |
|||
|
|||
public static Material CreateEngineMaterial(Shader shader) |
|||
{ |
|||
var mat = new Material(shader) |
|||
{ |
|||
hideFlags = HideFlags.HideAndDontSave |
|||
}; |
|||
return mat; |
|||
} |
|||
|
|||
public static void SetKeyword(Material m, string keyword, bool state) |
|||
{ |
|||
if (state) |
|||
m.EnableKeyword(keyword); |
|||
else |
|||
m.DisableKeyword(keyword); |
|||
} |
|||
|
|||
public static void SelectKeyword(Material material, string keyword1, string keyword2, bool enableFirst) |
|||
{ |
|||
material.EnableKeyword(enableFirst ? keyword1 : keyword2); |
|||
material.DisableKeyword(enableFirst ? keyword2 : keyword1); |
|||
} |
|||
|
|||
public static void SelectKeyword(Material material, string[] keywords, int enabledKeywordIndex) |
|||
{ |
|||
material.EnableKeyword(keywords[enabledKeywordIndex]); |
|||
|
|||
for (int i = 0; i < keywords.Length; i++) |
|||
{ |
|||
if (i != enabledKeywordIndex) |
|||
material.DisableKeyword(keywords[i]); |
|||
} |
|||
} |
|||
|
|||
public static void Destroy(UnityObject obj) |
|||
{ |
|||
if (obj != null) |
|||
{ |
|||
#if UNITY_EDITOR
|
|||
if (Application.isPlaying) |
|||
UnityObject.Destroy(obj); |
|||
else |
|||
UnityObject.DestroyImmediate(obj); |
|||
#else
|
|||
UnityObject.Destroy(obj); |
|||
#endif
|
|||
} |
|||
} |
|||
|
|||
public static void Destroy(params UnityObject[] objs) |
|||
{ |
|||
if (objs == null) |
|||
return; |
|||
|
|||
foreach (var o in objs) |
|||
Destroy(o); |
|||
} |
|||
|
|||
public static void SafeRelease(ComputeBuffer buffer) |
|||
{ |
|||
if (buffer != null) |
|||
buffer.Release(); |
|||
} |
|||
|
|||
// Just a sort function that doesn't allocate memory
|
|||
// Note: Shoud be repalc by a radix sort for positive integer
|
|||
public static int Partition(uint[] numbers, int left, int right) |
|||
{ |
|||
uint pivot = numbers[left]; |
|||
while (true) |
|||
{ |
|||
while (numbers[left] < pivot) |
|||
left++; |
|||
|
|||
while (numbers[right] > pivot) |
|||
right--; |
|||
|
|||
if (left < right) |
|||
{ |
|||
uint temp = numbers[right]; |
|||
numbers[right] = numbers[left]; |
|||
numbers[left] = temp; |
|||
} |
|||
else |
|||
{ |
|||
return right; |
|||
} |
|||
} |
|||
} |
|||
|
|||
public static void QuickSort(uint[] arr, int left, int right) |
|||
{ |
|||
// For Recusrion
|
|||
if (left < right) |
|||
{ |
|||
int pivot = Partition(arr, left, right); |
|||
|
|||
if (pivot > 1) |
|||
QuickSort(arr, left, pivot - 1); |
|||
|
|||
if (pivot + 1 < right) |
|||
QuickSort(arr, pivot + 1, right); |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: c86deb7236b4fe146b8b75ab0ac89586 |
|||
timeCreated: 1507041147 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq.Expressions; |
|||
using System.Text; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
public static class CoreEditorUtils |
|||
{ |
|||
// Serialization helpers
|
|||
public static string FindProperty<T, TValue>(Expression<Func<T, TValue>> expr) |
|||
{ |
|||
// Get the field path as a string
|
|||
MemberExpression me; |
|||
switch (expr.Body.NodeType) |
|||
{ |
|||
case ExpressionType.MemberAccess: |
|||
me = expr.Body as MemberExpression; |
|||
break; |
|||
default: |
|||
throw new InvalidOperationException(); |
|||
} |
|||
|
|||
var members = new List<string>(); |
|||
while (me != null) |
|||
{ |
|||
members.Add(me.Member.Name); |
|||
me = me.Expression as MemberExpression; |
|||
} |
|||
|
|||
var sb = new StringBuilder(); |
|||
for (int i = members.Count - 1; i >= 0; i--) |
|||
{ |
|||
sb.Append(members[i]); |
|||
if (i > 0) sb.Append('.'); |
|||
} |
|||
|
|||
return sb.ToString(); |
|||
} |
|||
|
|||
// UI Helpers
|
|||
public static void DrawSplitter() |
|||
{ |
|||
var rect = GUILayoutUtility.GetRect(1f, 1f); |
|||
|
|||
// Splitter rect should be full-width
|
|||
rect.xMin = 0f; |
|||
rect.width += 4f; |
|||
|
|||
if (Event.current.type != EventType.Repaint) |
|||
return; |
|||
|
|||
EditorGUI.DrawRect(rect, !EditorGUIUtility.isProSkin |
|||
? new Color(0.6f, 0.6f, 0.6f, 1.333f) |
|||
: new Color(0.12f, 0.12f, 0.12f, 1.333f)); |
|||
} |
|||
|
|||
public static void DrawHeader(string title) |
|||
{ |
|||
var backgroundRect = GUILayoutUtility.GetRect(1f, 17f); |
|||
|
|||
var labelRect = backgroundRect; |
|||
labelRect.xMin += 16f; |
|||
labelRect.xMax -= 20f; |
|||
|
|||
var foldoutRect = backgroundRect; |
|||
foldoutRect.y += 1f; |
|||
foldoutRect.width = 13f; |
|||
foldoutRect.height = 13f; |
|||
|
|||
// Background rect should be full-width
|
|||
backgroundRect.xMin = 0f; |
|||
backgroundRect.width += 4f; |
|||
|
|||
// Background
|
|||
float backgroundTint = EditorGUIUtility.isProSkin ? 0.1f : 1f; |
|||
EditorGUI.DrawRect(backgroundRect, new Color(backgroundTint, backgroundTint, backgroundTint, 0.2f)); |
|||
|
|||
// Title
|
|||
EditorGUI.LabelField(labelRect, title, EditorStyles.boldLabel); |
|||
} |
|||
|
|||
public static bool DrawHeaderFoldout(string title, bool state) |
|||
{ |
|||
var backgroundRect = GUILayoutUtility.GetRect(1f, 17f); |
|||
|
|||
var labelRect = backgroundRect; |
|||
labelRect.xMin += 16f; |
|||
labelRect.xMax -= 20f; |
|||
|
|||
var foldoutRect = backgroundRect; |
|||
foldoutRect.y += 1f; |
|||
foldoutRect.width = 13f; |
|||
foldoutRect.height = 13f; |
|||
|
|||
// Background rect should be full-width
|
|||
backgroundRect.xMin = 0f; |
|||
backgroundRect.width += 4f; |
|||
|
|||
// Background
|
|||
float backgroundTint = EditorGUIUtility.isProSkin ? 0.1f : 1f; |
|||
EditorGUI.DrawRect(backgroundRect, new Color(backgroundTint, backgroundTint, backgroundTint, 0.2f)); |
|||
|
|||
// Title
|
|||
EditorGUI.LabelField(labelRect, title, EditorStyles.boldLabel); |
|||
|
|||
// Active checkbox
|
|||
state = GUI.Toggle(foldoutRect, state, GUIContent.none, EditorStyles.foldout); |
|||
|
|||
var e = Event.current; |
|||
if (e.type == EventType.MouseDown && backgroundRect.Contains(e.mousePosition) && e.button == 0) |
|||
{ |
|||
state = !state; |
|||
e.Use(); |
|||
} |
|||
|
|||
return state; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 744ceabda269e6c469964dda8c490d0d |
|||
timeCreated: 1507109827 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Linq.Expressions; |
|||
using UnityEngine.Assertions; |
|||
|
|||
namespace UnityEditor.Experimental.Rendering |
|||
{ |
|||
public sealed class PropertyFetcher<T> : IDisposable |
|||
{ |
|||
public readonly SerializedObject obj; |
|||
|
|||
public PropertyFetcher(SerializedObject obj) |
|||
{ |
|||
Assert.IsNotNull(obj); |
|||
this.obj = obj; |
|||
} |
|||
|
|||
public SerializedProperty Find(string str) |
|||
{ |
|||
return obj.FindProperty(str); |
|||
} |
|||
|
|||
public SerializedProperty Find<TValue>(Expression<Func<T, TValue>> expr) |
|||
{ |
|||
string path = CoreEditorUtils.FindProperty(expr); |
|||
return obj.FindProperty(path); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
// Nothing to do here, still needed so we can rely on the using/IDisposable pattern
|
|||
} |
|||
} |
|||
|
|||
public sealed class RelativePropertyFetcher<T> : IDisposable |
|||
{ |
|||
public readonly SerializedProperty obj; |
|||
|
|||
public RelativePropertyFetcher(SerializedProperty obj) |
|||
{ |
|||
Assert.IsNotNull(obj); |
|||
this.obj = obj; |
|||
} |
|||
|
|||
public SerializedProperty Find(string str) |
|||
{ |
|||
return obj.FindPropertyRelative(str); |
|||
} |
|||
|
|||
public SerializedProperty Find<TValue>(Expression<Func<T, TValue>> expr) |
|||
{ |
|||
string path = CoreEditorUtils.FindProperty(expr); |
|||
return obj.FindPropertyRelative(path); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
// Nothing to do here, still needed so we can rely on the using/IDisposable pattern
|
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: ac00489121556c741bc0e67dfb460a8e |
|||
timeCreated: 1507034431 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: edb108228f2caa44ca8154fd4985e101 |
|||
folderAsset: yes |
|||
timeCreated: 1504859102 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEngine.Rendering; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
public struct ProfilingSample : IDisposable |
|||
{ |
|||
public readonly CommandBuffer cmd; |
|||
public readonly string name; |
|||
|
|||
bool m_Disposed; |
|||
|
|||
public ProfilingSample(CommandBuffer cmd, string name) |
|||
{ |
|||
this.cmd = cmd; |
|||
this.name = name; |
|||
m_Disposed = false; |
|||
cmd.BeginSample(name); |
|||
} |
|||
|
|||
// Shortcut to string.Format() using only one argument (reduces Gen0 GC pressure)
|
|||
public ProfilingSample(CommandBuffer cmd, string format, object arg) |
|||
{ |
|||
this.cmd = cmd; |
|||
name = string.Format(format, arg); |
|||
m_Disposed = false; |
|||
cmd.BeginSample(name); |
|||
} |
|||
|
|||
// Shortcut to string.Format() with variable amount of arguments - for performance critical
|
|||
// code you should pre-build & cache the marker name instead of using this
|
|||
public ProfilingSample(CommandBuffer cmd, string format, params object[] args) |
|||
{ |
|||
this.cmd = cmd; |
|||
name = string.Format(format, args); |
|||
m_Disposed = false; |
|||
cmd.BeginSample(name); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
Dispose(true); |
|||
} |
|||
|
|||
// Protected implementation of Dispose pattern.
|
|||
void Dispose(bool disposing) |
|||
{ |
|||
if (m_Disposed) |
|||
return; |
|||
|
|||
// As this is a struct, it could have been initialized using an empty constructor so we
|
|||
// need to make sure `cmd` isn't null to avoid a crash. Switching to a class would fix
|
|||
// this but will generate garbage on every frame (and this struct is used quite a lot).
|
|||
if (disposing && cmd != null) |
|||
cmd.EndSample(name); |
|||
|
|||
m_Disposed = true; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: a9115e9ffa8b6df4ba69fe5eb9b541db |
|||
timeCreated: 1507043252 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: f00a25194233f5c4392fa05f23ecc076 |
|||
folderAsset: yes |
|||
timeCreated: 1507130547 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
// Autogenerated file. Do not edit by hand |
|||
|
|||
#include "../ShaderLibrary/Common.hlsl" |
|||
|
|||
SamplerState sampler_LinearClamp; |
|||
|
|||
CBUFFER_START(cb) |
|||
float4 _Size; |
|||
CBUFFER_END |
|||
|
|||
RWTexture2D<float1> _Result1; |
|||
|
|||
Texture2D<float4> _Source4; |
|||
|
|||
|
|||
#pragma kernel KSampleCopy4_1_x |
|||
[numthreads(8, 8, 1)] |
|||
void KSampleCopy4_1_x(uint2 dispatchThreadId : SV_DispatchThreadID) |
|||
{ |
|||
_Result1[dispatchThreadId] = _Source4.SampleLevel(sampler_LinearClamp, float2(dispatchThreadId) * _Size.zw, 0.0).x; |
|||
} |
|||
|
|||
|
|
|||
fileFormatVersion: 2 |
|||
guid: a68d8aaeb0956234d94e389f196381ee |
|||
timeCreated: 1507123133 |
|||
licenseType: Pro |
|||
ComputeShaderImporter: |
|||
externalObjects: {} |
|||
currentAPIMask: 4 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
// Autogenerated file. Do not edit by hand
|
|||
using System; |
|||
using UnityEngine.Rendering; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
public class GPUCopy |
|||
{ |
|||
ComputeShader m_Shader; |
|||
int k_SampleKernel_xyzw2x; |
|||
|
|||
public GPUCopy(ComputeShader shader) |
|||
{ |
|||
m_Shader = shader; |
|||
k_SampleKernel_xyzw2x = m_Shader.FindKernel("KSampleCopy4_1_x"); |
|||
} |
|||
|
|||
static readonly int _Result1 = Shader.PropertyToID("_Result1"); |
|||
static readonly int _Source4 = Shader.PropertyToID("_Source4"); |
|||
static readonly int _Size = Shader.PropertyToID("_Size"); |
|||
public void SampleCopyChannel_xyzw2x(CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier target, Vector2 size) |
|||
{ |
|||
if (size.x < 8 || size.y < 8) |
|||
Debug.LogWarning("Trying to copy a channel from a texture smaller than 8x* or *x8. ComputeShader cannot perform it."); |
|||
var s = new Vector4(size.x, size.y, 1f / size.x, 1f / size.y); |
|||
cmd.SetComputeVectorParam(m_Shader, _Size, s); |
|||
cmd.SetComputeTextureParam(m_Shader, k_SampleKernel_xyzw2x, _Source4, source); |
|||
cmd.SetComputeTextureParam(m_Shader, k_SampleKernel_xyzw2x, _Result1, target); |
|||
cmd.DispatchCompute(m_Shader, k_SampleKernel_xyzw2x, (int)(size.x) / 8, (int)(size.y) / 8, 1); |
|||
} |
|||
|
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 584fa1be28adb3344ab9eec18571f46b |
|||
timeCreated: 1507123133 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering |
|||
{ |
|||
/// <summary>
|
|||
/// Declares what should be generated in utility code.
|
|||
/// It will generate a compute shader and a C# class to use the compute shader with a ComputeBuffer
|
|||
///
|
|||
/// Exemple:
|
|||
/// - I add a CopyOperation { sourceChannel = 4, targetChannel = 2, subscript = "zx" }
|
|||
/// => a Kernel will be generated to copy from a TextureRGBA the AR channels into a TextureRG
|
|||
/// => A method will be added to call the kernel in the C# class GPUCopy (SampleCopy_xyzw2zx)
|
|||
///
|
|||
/// C# Exemple:
|
|||
/// // Initialize the gpucopy
|
|||
/// var gpuCopy = new CPUCopy(generatedComputeShaderAsset);
|
|||
///
|
|||
/// CommandBuffer cmb = ...
|
|||
/// gpuCopy.SampleCopyChannel_xyzw2x(cmb, _SourceTexture, _TargetTexture, new Vector2(targetWidth, targetHeight));
|
|||
///
|
|||
/// Initialization:
|
|||
/// - You must set the generated ComputeShader as argument of the constructor of the generated GPUCopy C# class
|
|||
/// </summary>
|
|||
public class GPUCopyAsset : ScriptableObject |
|||
{ |
|||
static string[] k_ChannelIDS = { "x", "xy", "xyz", "xyzw" }; |
|||
const int k_KernelSize = 8; |
|||
|
|||
[Serializable] |
|||
public struct CopyOperation |
|||
{ |
|||
public string subscript; |
|||
public int sourceChannel; |
|||
public int targetChannel; |
|||
} |
|||
|
|||
[SerializeField] |
|||
CopyOperation[] m_CopyOperation = new CopyOperation[0]; |
|||
|
|||
public void Generate(out string computeShader, out string csharp) |
|||
{ |
|||
var operations = m_CopyOperation; |
|||
|
|||
var sources = new HashSet<int>(); |
|||
var targets = new HashSet<int>(); |
|||
|
|||
var cc = new StringBuilder(); // Compute Shader out
|
|||
var ccp = new StringBuilder(); // Compute properties
|
|||
var cck = new StringBuilder(); // Compute kernel
|
|||
var cs = new StringBuilder(); // CSharp out
|
|||
var csm = new StringBuilder(); // CSharp methods
|
|||
var csc = new StringBuilder(); // CSharp constructor
|
|||
var csp = new StringBuilder(); // CSharp properties
|
|||
|
|||
for (var i = 0; i < operations.Length; i++) |
|||
{ |
|||
var o = operations[i]; |
|||
sources.Add(o.sourceChannel); |
|||
targets.Add(o.targetChannel); |
|||
} |
|||
|
|||
ccp.AppendLine(); |
|||
foreach (var target in targets) |
|||
{ |
|||
ccp.AppendLine(string.Format("RWTexture2D<float{0}> _Result{0};", target.ToString())); |
|||
csm.AppendLine(string.Format(" static readonly int _Result{0} = Shader.PropertyToID(\"_Result{0}\");", target.ToString())); |
|||
} |
|||
ccp.AppendLine(); |
|||
foreach (var source in sources) |
|||
{ |
|||
ccp.AppendLine(string.Format("Texture2D<float{0}> _Source{0};", source.ToString())); |
|||
csm.AppendLine(string.Format(" static readonly int _Source{0} = Shader.PropertyToID(\"_Source{0}\");", source.ToString())); |
|||
} |
|||
ccp.AppendLine(); |
|||
|
|||
csc.AppendLine(" public GPUCopy(ComputeShader shader)"); |
|||
csc.AppendLine(" {"); |
|||
csc.AppendLine(" m_Shader = shader;"); |
|||
csm.AppendLine(" static readonly int _Size = Shader.PropertyToID(\"_Size\");"); |
|||
for (var i = 0; i < operations.Length; i++) |
|||
{ |
|||
var o = operations[i]; |
|||
|
|||
// Compute kernel
|
|||
var kernelName = string.Format("KSampleCopy{0}_{1}_{2}", o.sourceChannel.ToString(), o.targetChannel.ToString(), o.subscript); |
|||
cck.AppendLine(string.Format("#pragma kernel {0}", kernelName)); |
|||
cck.AppendLine(string.Format(@"[numthreads({0}, {0}, 1)]", |
|||
k_KernelSize.ToString(), k_KernelSize.ToString())); |
|||
cck.AppendLine(string.Format(@"void {0}(uint2 dispatchThreadId : SV_DispatchThreadID)", kernelName)); |
|||
cck.AppendLine("{"); |
|||
cck.AppendLine(string.Format(" _Result{0}[dispatchThreadId] = _Source{1}.SampleLevel(sampler_LinearClamp, float2(dispatchThreadId) * _Size.zw, 0.0).{2};", |
|||
o.targetChannel.ToString(), o.sourceChannel.ToString(), o.subscript)); |
|||
cck.AppendLine("}"); |
|||
cck.AppendLine(); |
|||
|
|||
// CSharp kernel index
|
|||
var channelName = k_ChannelIDS[o.sourceChannel - 1]; |
|||
var kernelIndexName = string.Format("k_SampleKernel_{0}2{1}", channelName, o.subscript); |
|||
csp.AppendLine(string.Format(" int {0};", kernelIndexName)); |
|||
|
|||
// CSharp constructor
|
|||
csc.AppendLine(string.Format(" {0} = m_Shader.FindKernel(\"{1}\");", kernelIndexName, kernelName)); |
|||
|
|||
// CSharp method
|
|||
csm.AppendLine(string.Format(@" public void SampleCopyChannel_{0}2{1}(CommandBuffer cmd, RenderTargetIdentifier source, RenderTargetIdentifier target, Vector2 size)", channelName, o.subscript)); |
|||
csm.AppendLine(" {"); |
|||
csm.AppendLine(string.Format(" if (size.x < {0} || size.y < {0})", k_KernelSize.ToString())); |
|||
csm.AppendLine(" Debug.LogWarning(\"Trying to copy a channel from a texture smaller than 8x* or *x8. ComputeShader cannot perform it.\");"); |
|||
csm.AppendLine(" var s = new Vector4(size.x, size.y, 1f / size.x, 1f / size.y);"); |
|||
csm.AppendLine(" cmd.SetComputeVectorParam(m_Shader, _Size, s);"); |
|||
csm.AppendLine(string.Format(" cmd.SetComputeTextureParam(m_Shader, {0}, _Source{1}, source);", kernelIndexName, o.sourceChannel.ToString())); |
|||
csm.AppendLine(string.Format(" cmd.SetComputeTextureParam(m_Shader, {0}, _Result{1}, target);", kernelIndexName, o.targetChannel.ToString())); |
|||
csm.AppendLine(string.Format(" cmd.DispatchCompute(m_Shader, {0}, (int)(size.x) / {1}, (int)(size.y) / {1}, 1);", kernelIndexName, k_KernelSize.ToString())); |
|||
csm.AppendLine(" }"); |
|||
} |
|||
csc.AppendLine(" }"); |
|||
|
|||
// Compute Shader
|
|||
cc.AppendLine(@"// Autogenerated file. Do not edit by hand"); |
|||
cc.AppendLine(); |
|||
cc.AppendLine(@"#include ""../ShaderLibrary/Common.hlsl"""); |
|||
cc.AppendLine(); |
|||
cc.AppendLine(@"SamplerState sampler_LinearClamp;"); |
|||
cc.AppendLine(); |
|||
cc.AppendLine(@"CBUFFER_START(cb)"); |
|||
cc.AppendLine(@" float4 _Size;"); |
|||
cc.AppendLine(@"CBUFFER_END"); |
|||
cc.AppendLine(ccp.ToString()); // Properties
|
|||
cc.AppendLine(cck.ToString()); // Kernels
|
|||
|
|||
// CSharp
|
|||
cs.AppendLine(@"// Autogenerated file. Do not edit by hand"); |
|||
cs.AppendLine(@"using System;"); |
|||
cs.AppendLine(@"using UnityEngine.Rendering;"); |
|||
cs.AppendLine(); |
|||
cs.AppendLine(@"namespace UnityEngine.Experimental.Rendering"); |
|||
cs.AppendLine("{"); |
|||
cs.AppendLine(" public class GPUCopy"); |
|||
cs.AppendLine(" {"); |
|||
cs.AppendLine(" ComputeShader m_Shader;"); |
|||
cs.AppendLine(csp.ToString()); // Properties
|
|||
cs.AppendLine(csc.ToString()); // Constructor
|
|||
cs.AppendLine(csm.ToString()); // methods
|
|||
cs.AppendLine(" }"); |
|||
cs.AppendLine("}"); |
|||
|
|||
computeShader = cc.ToString(); |
|||
csharp = cs.ToString(); |
|||
} |
|||
|
|||
void OnValidate() |
|||
{ |
|||
for (var i = 0; i < m_CopyOperation.Length; i++) |
|||
{ |
|||
var o = m_CopyOperation[i]; |
|||
o.sourceChannel = Mathf.Clamp(o.sourceChannel, 1, k_ChannelIDS.Length); |
|||
o.targetChannel = Mathf.Clamp(o.targetChannel, 1, k_ChannelIDS.Length); |
|||
m_CopyOperation[i] = o; |
|||
} |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: d6592d54c1ab4694eaabc84e14cc6385 |
|||
timeCreated: 1507119931 |
|||
licenseType: Pro |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
%YAML 1.1 |
|||
%TAG !u! tag:unity3d.com,2011: |
|||
--- !u!114 &11400000 |
|||
MonoBehaviour: |
|||
m_ObjectHideFlags: 0 |
|||
m_PrefabParentObject: {fileID: 0} |
|||
m_PrefabInternal: {fileID: 0} |
|||
m_GameObject: {fileID: 0} |
|||
m_Enabled: 1 |
|||
m_EditorHideFlags: 0 |
|||
m_Script: {fileID: 11500000, guid: d6592d54c1ab4694eaabc84e14cc6385, type: 3} |
|||
m_Name: GPUCopyDefinition |
|||
m_EditorClassIdentifier: |
|||
m_CopyOperation: |
|||
- subscript: x |
|||
sourceChannel: 4 |
|||
targetChannel: 1 |
|
|||
fileFormatVersion: 2 |
|||
guid: 6aece293b43f5fb4fb5ace0d22b0035a |
|||
timeCreated: 1507122722 |
|||
licenseType: Pro |
|||
NativeFormatImporter: |
|||
externalObjects: {} |
|||
mainObjectFileID: 11400000 |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
fileFormatVersion: 2 |
|||
guid: d49f97c73daab8a4a8d389c977c2345f |
|||
folderAsset: yes |
|||
timeCreated: 1491321440 |
|||
licenseType: Pro |
|||
DefaultImporter: |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System; |
|||
using UnityEditor.Experimental.Rendering.LightweightPipeline; |
|||
using UnityEngine; |
|||
|
|||
namespace UnityEditor |
|||
{ |
|||
internal class LightweightStandardGUI : ShaderGUI |
|||
{ |
|||
public enum WorkflowMode : int |
|||
{ |
|||
Specular = 0, |
|||
Metallic |
|||
} |
|||
|
|||
public enum BlendMode : int |
|||
{ |
|||
Opaque, |
|||
Cutout, |
|||
Fade, // Old school alpha-blending mode, fresnel does not affect amount of transparency
|
|||
Transparent // Physically plausible transparency mode, implemented as alpha pre-multiply
|
|||
} |
|||
|
|||
public enum SmoothnessMapChannel : int |
|||
{ |
|||
SpecularMetallicAlpha, |
|||
AlbedoAlpha, |
|||
} |
|||
|
|||
private static class Styles |
|||
{ |
|||
public static GUIContent uvSetLabel = new GUIContent("UV Set"); |
|||
|
|||
public static GUIContent albedoText = new GUIContent("Albedo", "Albedo (RGB) and Transparency (A)"); |
|||
public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff"); |
|||
public static GUIContent specularMapText = new GUIContent("Specular", "Specular (RGB) and Smoothness (A)"); |
|||
public static GUIContent metallicMapText = new GUIContent("Metallic", "Metallic (R) and Smoothness (A)"); |
|||
public static GUIContent smoothnessText = new GUIContent("Smoothness", "Smoothness value"); |
|||
public static GUIContent smoothnessScaleText = new GUIContent("Smoothness", "Smoothness scale factor"); |
|||
public static GUIContent smoothnessMapChannelText = new GUIContent("Source", "Smoothness texture and channel"); |
|||
public static GUIContent highlightsText = new GUIContent("Specular Highlights", "Specular Highlights"); |
|||
public static GUIContent reflectionsText = new GUIContent("Reflections", "Glossy Reflections"); |
|||
public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map"); |
|||
public static GUIContent heightMapText = new GUIContent("Height Map", "Height Map (G)"); |
|||
public static GUIContent occlusionText = new GUIContent("Occlusion", "Occlusion (G)"); |
|||
public static GUIContent emissionText = new GUIContent("Color", "Emission (RGB)"); |
|||
public static GUIContent detailMaskText = new GUIContent("Detail Mask", "Mask for Secondary Maps (A)"); |
|||
public static GUIContent detailAlbedoText = new GUIContent("Detail Albedo x2", "Albedo (RGB) multiplied by 2"); |
|||
public static GUIContent detailNormalMapText = new GUIContent("Normal Map", "Normal Map"); |
|||
|
|||
public static string primaryMapsText = "Main Maps"; |
|||
public static string secondaryMapsText = "Secondary Maps"; |
|||
public static string forwardText = "Forward Rendering Options"; |
|||
public static string workflowModeText = "Workflow Mode"; |
|||
public static string renderingMode = "Rendering Mode"; |
|||
public static string advancedText = "Advanced Options"; |
|||
public static readonly string[] workflowNames = Enum.GetNames(typeof(WorkflowMode)); |
|||
public static readonly string[] blendNames = Enum.GetNames(typeof(BlendMode)); |
|||
public static readonly string[] metallicSmoothnessChannelNames = {"Metallic Alpha", "Albedo Alpha"}; |
|||
public static readonly string[] specularSmoothnessChannelNames = {"Specular Alpha", "Albedo Alpha"}; |
|||
} |
|||
|
|||
#pragma warning disable 0414
|
|||
private MaterialProperty workflowMode = null; |
|||
private MaterialProperty blendMode = null; |
|||
|
|||
private MaterialProperty albedoColor = null; |
|||
private MaterialProperty albedoMap = null; |
|||
private MaterialProperty alphaCutoff = null; |
|||
|
|||
private MaterialProperty smoothness = null; |
|||
private MaterialProperty smoothnessScale = null; |
|||
private MaterialProperty smoothnessMapChannel = null; |
|||
|
|||
private MaterialProperty metallic = null; |
|||
private MaterialProperty specColor = null; |
|||
private MaterialProperty metallicGlossMap = null; |
|||
private MaterialProperty specGlossMap = null; |
|||
private MaterialProperty highlights = null; |
|||
private MaterialProperty reflections = null; |
|||
|
|||
private MaterialProperty bumpScale = null; |
|||
private MaterialProperty bumpMap = null; |
|||
private MaterialProperty occlusionStrength = null; |
|||
private MaterialProperty occlusionMap = null; |
|||
private MaterialProperty heigtMapScale = null; |
|||
private MaterialProperty heightMap = null; |
|||
private MaterialProperty emissionColorForRendering = null; |
|||
private MaterialProperty emissionMap = null; |
|||
private MaterialProperty detailMask = null; |
|||
private MaterialProperty detailAlbedoMap = null; |
|||
private MaterialProperty detailNormalMapScale = null; |
|||
private MaterialProperty detailNormalMap = null; |
|||
private MaterialProperty uvSetSecondary = null; |
|||
|
|||
private MaterialEditor m_MaterialEditor; |
|||
private const float kMaxfp16 = 65536f; // Clamp to a value that fits into fp16.
|
|||
private ColorPickerHDRConfig m_ColorPickerHDRConfig = new ColorPickerHDRConfig(0f, kMaxfp16, 1 / kMaxfp16, 3f); |
|||
|
|||
private bool m_FirstTimeApply = true; |
|||
#pragma warning restore 0414
|
|||
|
|||
public void FindProperties(MaterialProperty[] props) |
|||
{ |
|||
workflowMode = FindProperty("_WorkflowMode", props); |
|||
blendMode = FindProperty("_Mode", props); |
|||
albedoColor = FindProperty("_Color", props); |
|||
albedoMap = FindProperty("_MainTex", props); |
|||
alphaCutoff = FindProperty("_Cutoff", props); |
|||
|
|||
smoothness = FindProperty("_Glossiness", props); |
|||
smoothnessScale = FindProperty("_GlossMapScale", props, false); |
|||
smoothnessMapChannel = FindProperty("_SmoothnessTextureChannel", props, false); |
|||
|
|||
metallic = FindProperty("_Metallic", props); |
|||
specColor = FindProperty("_SpecColor", props); |
|||
metallicGlossMap = FindProperty("_MetallicGlossMap", props); |
|||
specGlossMap = FindProperty("_SpecGlossMap", props); |
|||
highlights = FindProperty("_SpecularHighlights", props); |
|||
reflections = FindProperty("_GlossyReflections", props); |
|||
|
|||
bumpScale = FindProperty("_BumpScale", props); |
|||
bumpMap = FindProperty("_BumpMap", props); |
|||
heigtMapScale = FindProperty("_Parallax", props); |
|||
heightMap = FindProperty("_ParallaxMap", props); |
|||
occlusionStrength = FindProperty("_OcclusionStrength", props); |
|||
occlusionMap = FindProperty("_OcclusionMap", props); |
|||
emissionColorForRendering = FindProperty("_EmissionColor", props); |
|||
emissionMap = FindProperty("_EmissionMap", props); |
|||
detailMask = FindProperty("_DetailMask", props); |
|||
detailAlbedoMap = FindProperty("_DetailAlbedoMap", props); |
|||
detailNormalMapScale = FindProperty("_DetailNormalMapScale", props); |
|||
detailNormalMap = FindProperty("_DetailNormalMap", props); |
|||
uvSetSecondary = FindProperty("_UVSec", props); |
|||
} |
|||
|
|||
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props) |
|||
{ |
|||
FindProperties(props); // MaterialProperties can be animated so we do not cache them but fetch them every event to ensure animated values are updated correctly
|
|||
m_MaterialEditor = materialEditor; |
|||
Material material = materialEditor.target as Material; |
|||
|
|||
// Make sure that needed setup (ie keywords/renderqueue) are set up if we're switching some existing
|
|||
// material to a lightweight shader.
|
|||
if (m_FirstTimeApply) |
|||
{ |
|||
MaterialChanged(material); |
|||
m_FirstTimeApply = false; |
|||
} |
|||
|
|||
ShaderPropertiesGUI(material); |
|||
} |
|||
|
|||
public void ShaderPropertiesGUI(Material material) |
|||
{ |
|||
// Use default labelWidth
|
|||
EditorGUIUtility.labelWidth = 0f; |
|||
|
|||
// Detect any changes to the material
|
|||
EditorGUI.BeginChangeCheck(); |
|||
{ |
|||
DoPopup(Styles.workflowModeText, workflowMode, Styles.workflowNames); |
|||
DoPopup(Styles.renderingMode, blendMode, Styles.blendNames); |
|||
|
|||
// Primary properties
|
|||
GUILayout.Label(Styles.primaryMapsText, EditorStyles.boldLabel); |
|||
DoAlbedoArea(material); |
|||
DoMetallicSpecularArea(); |
|||
DoNormalArea(); |
|||
|
|||
m_MaterialEditor.TexturePropertySingleLine(Styles.occlusionText, occlusionMap, occlusionMap.textureValue != null ? occlusionStrength : null); |
|||
|
|||
DoEmissionArea(material); |
|||
EditorGUI.BeginChangeCheck(); |
|||
m_MaterialEditor.TextureScaleOffsetProperty(albedoMap); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
emissionMap.textureScaleAndOffset = albedoMap.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake
|
|||
|
|||
EditorGUILayout.Space(); |
|||
|
|||
m_MaterialEditor.ShaderProperty(highlights, Styles.highlightsText); |
|||
m_MaterialEditor.ShaderProperty(reflections, Styles.reflectionsText); |
|||
} |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
foreach (var obj in blendMode.targets) |
|||
MaterialChanged((Material)obj); |
|||
} |
|||
|
|||
EditorGUILayout.Space(); |
|||
|
|||
// NB renderqueue editor is not shown on purpose: we want to override it based on blend mode
|
|||
GUILayout.Label(Styles.advancedText, EditorStyles.boldLabel); |
|||
m_MaterialEditor.EnableInstancingField(); |
|||
m_MaterialEditor.DoubleSidedGIField(); |
|||
} |
|||
|
|||
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader) |
|||
{ |
|||
// _Emission property is lost after assigning Standard shader to the material
|
|||
// thus transfer it before assigning the new shader
|
|||
if (material.HasProperty("_Emission")) |
|||
{ |
|||
material.SetColor("_EmissionColor", material.GetColor("_Emission")); |
|||
} |
|||
|
|||
base.AssignNewShaderToMaterial(material, oldShader, newShader); |
|||
|
|||
if (oldShader == null || !oldShader.name.Contains("Legacy Shaders/")) |
|||
{ |
|||
SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode")); |
|||
return; |
|||
} |
|||
|
|||
BlendMode blendMode = BlendMode.Opaque; |
|||
if (oldShader.name.Contains("/Transparent/Cutout/")) |
|||
{ |
|||
blendMode = BlendMode.Cutout; |
|||
} |
|||
else if (oldShader.name.Contains("/Transparent/")) |
|||
{ |
|||
// NOTE: legacy shaders did not provide physically based transparency
|
|||
// therefore Fade mode
|
|||
blendMode = BlendMode.Fade; |
|||
} |
|||
material.SetFloat("_Mode", (float)blendMode); |
|||
|
|||
if (oldShader.name.Equals("Standard (Specular setup)")) |
|||
{ |
|||
material.SetFloat("_WorkflowMode", (float) WorkflowMode.Specular); |
|||
Texture texture = material.GetTexture("_SpecGlossMap"); |
|||
if (texture != null) |
|||
material.SetTexture("_MetallicSpecGlossMap", texture); |
|||
} |
|||
else |
|||
{ |
|||
material.SetFloat("_WorkflowMode", (float) WorkflowMode.Metallic); |
|||
Texture texture = material.GetTexture("_MetallicGlossMap"); |
|||
if (texture != null) |
|||
material.SetTexture("_MetallicSpecGlossMap", texture); |
|||
} |
|||
|
|||
MaterialChanged(material); |
|||
} |
|||
|
|||
private void DoPopup(string label, MaterialProperty property, string[] options) |
|||
{ |
|||
EditorGUI.showMixedValue = property.hasMixedValue; |
|||
|
|||
var mode = property.floatValue; |
|||
EditorGUI.BeginChangeCheck(); |
|||
mode = EditorGUILayout.Popup(label, (int) mode, options); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
{ |
|||
m_MaterialEditor.RegisterPropertyChangeUndo(label); |
|||
property.floatValue = (float)mode; |
|||
} |
|||
|
|||
EditorGUI.showMixedValue = false; |
|||
} |
|||
|
|||
void DoNormalArea() |
|||
{ |
|||
m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMap); |
|||
} |
|||
|
|||
void DoAlbedoArea(Material material) |
|||
{ |
|||
m_MaterialEditor.TexturePropertySingleLine(Styles.albedoText, albedoMap, albedoColor); |
|||
if (((BlendMode)material.GetFloat("_Mode") == BlendMode.Cutout)) |
|||
{ |
|||
m_MaterialEditor.ShaderProperty(alphaCutoff, Styles.alphaCutoffText.text, MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1); |
|||
} |
|||
} |
|||
|
|||
void DoEmissionArea(Material material) |
|||
{ |
|||
// Emission for GI?
|
|||
if (m_MaterialEditor.EmissionEnabledProperty()) |
|||
{ |
|||
bool hadEmissionTexture = emissionMap.textureValue != null; |
|||
|
|||
// Texture and HDR color controls
|
|||
m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionText, emissionMap, emissionColorForRendering, m_ColorPickerHDRConfig, false); |
|||
|
|||
// If texture was assigned and color was black set color to white
|
|||
float brightness = emissionColorForRendering.colorValue.maxColorComponent; |
|||
if (emissionMap.textureValue != null && !hadEmissionTexture && brightness <= 0f) |
|||
emissionColorForRendering.colorValue = Color.white; |
|||
|
|||
// LW does not support RealtimeEmissive. We set it to bake emissive and handle the emissive is black right.
|
|||
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive; |
|||
if (brightness <= 0f) |
|||
material.globalIlluminationFlags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack; |
|||
} |
|||
} |
|||
|
|||
void DoMetallicSpecularArea() |
|||
{ |
|||
string[] metallicSpecSmoothnessChannelName; |
|||
bool hasGlossMap = false; |
|||
if ((WorkflowMode) workflowMode.floatValue == WorkflowMode.Metallic) |
|||
{ |
|||
hasGlossMap = metallicGlossMap.textureValue != null; |
|||
metallicSpecSmoothnessChannelName = Styles.metallicSmoothnessChannelNames; |
|||
m_MaterialEditor.TexturePropertySingleLine(Styles.metallicMapText, metallicGlossMap, |
|||
hasGlossMap ? null : metallic); |
|||
} |
|||
else |
|||
{ |
|||
hasGlossMap = specGlossMap.textureValue != null; |
|||
metallicSpecSmoothnessChannelName = Styles.specularSmoothnessChannelNames; |
|||
m_MaterialEditor.TexturePropertySingleLine(Styles.specularMapText, specGlossMap, |
|||
hasGlossMap ? null : specColor); |
|||
} |
|||
|
|||
bool showSmoothnessScale = hasGlossMap; |
|||
if (smoothnessMapChannel != null) |
|||
{ |
|||
int smoothnessChannel = (int)smoothnessMapChannel.floatValue; |
|||
if (smoothnessChannel == (int)SmoothnessMapChannel.AlbedoAlpha) |
|||
showSmoothnessScale = true; |
|||
} |
|||
|
|||
int indentation = 2; // align with labels of texture properties
|
|||
m_MaterialEditor.ShaderProperty(showSmoothnessScale ? smoothnessScale : smoothness, showSmoothnessScale ? Styles.smoothnessScaleText : Styles.smoothnessText, indentation); |
|||
|
|||
int prevIndentLevel = EditorGUI.indentLevel; |
|||
EditorGUI.indentLevel = 3; |
|||
if (smoothnessMapChannel != null) |
|||
DoPopup(Styles.smoothnessMapChannelText.text, smoothnessMapChannel, metallicSpecSmoothnessChannelName); |
|||
EditorGUI.indentLevel = prevIndentLevel; |
|||
} |
|||
|
|||
public static void SetupMaterialWithBlendMode(Material material, BlendMode blendMode) |
|||
{ |
|||
switch (blendMode) |
|||
{ |
|||
case BlendMode.Opaque: |
|||
material.SetOverrideTag("RenderType", ""); |
|||
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); |
|||
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); |
|||
material.SetInt("_ZWrite", 1); |
|||
material.DisableKeyword("_ALPHATEST_ON"); |
|||
material.DisableKeyword("_ALPHABLEND_ON"); |
|||
material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); |
|||
material.renderQueue = -1; |
|||
break; |
|||
case BlendMode.Cutout: |
|||
material.SetOverrideTag("RenderType", "TransparentCutout"); |
|||
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); |
|||
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); |
|||
material.SetInt("_ZWrite", 1); |
|||
material.EnableKeyword("_ALPHATEST_ON"); |
|||
material.DisableKeyword("_ALPHABLEND_ON"); |
|||
material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); |
|||
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest; |
|||
break; |
|||
case BlendMode.Fade: |
|||
material.SetOverrideTag("RenderType", "Transparent"); |
|||
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); |
|||
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); |
|||
material.SetInt("_ZWrite", 0); |
|||
material.DisableKeyword("_ALPHATEST_ON"); |
|||
material.EnableKeyword("_ALPHABLEND_ON"); |
|||
material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); |
|||
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; |
|||
break; |
|||
case BlendMode.Transparent: |
|||
material.SetOverrideTag("RenderType", "Transparent"); |
|||
material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); |
|||
material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); |
|||
material.SetInt("_ZWrite", 0); |
|||
material.DisableKeyword("_ALPHATEST_ON"); |
|||
material.DisableKeyword("_ALPHABLEND_ON"); |
|||
material.EnableKeyword("_ALPHAPREMULTIPLY_ON"); |
|||
material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
static SmoothnessMapChannel GetSmoothnessMapChannel(Material material) |
|||
{ |
|||
int ch = (int)material.GetFloat("_SmoothnessTextureChannel"); |
|||
if (ch == (int)SmoothnessMapChannel.AlbedoAlpha) |
|||
return SmoothnessMapChannel.AlbedoAlpha; |
|||
else |
|||
return SmoothnessMapChannel.SpecularMetallicAlpha; |
|||
} |
|||
|
|||
static void SetMaterialKeywords(Material material) |
|||
{ |
|||
// Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
|
|||
// (MaterialProperty value might come from renderer material property block)
|
|||
bool isSpecularWorkFlow = (WorkflowMode)material.GetFloat("_WorkflowMode") == WorkflowMode.Specular; |
|||
bool hasGlossMap = false; |
|||
if (isSpecularWorkFlow) |
|||
hasGlossMap = material.GetTexture("_SpecGlossMap"); |
|||
else |
|||
hasGlossMap = material.GetTexture("_MetallicGlossMap"); |
|||
|
|||
LightweightShaderHelper.SetKeyword(material, "_SPECULAR_SETUP", isSpecularWorkFlow); |
|||
LightweightShaderHelper.SetKeyword(material, "_METALLIC_SETUP", !isSpecularWorkFlow); |
|||
|
|||
LightweightShaderHelper.SetKeyword(material, "_METALLICSPECGLOSSMAP", hasGlossMap); |
|||
LightweightShaderHelper.SetKeyword(material, "_SPECGLOSSMAP", hasGlossMap && isSpecularWorkFlow); |
|||
LightweightShaderHelper.SetKeyword(material, "_METALLICGLOSSMAP", hasGlossMap && !isSpecularWorkFlow); |
|||
|
|||
LightweightShaderHelper.SetKeyword(material, "_NORMALMAP", material.GetTexture("_BumpMap")); |
|||
|
|||
LightweightShaderHelper.SetKeyword(material, "_SPECULARHIGHLIGHTS_OFF", material.GetFloat("_SpecularHighlights") == 0.0f); |
|||
LightweightShaderHelper.SetKeyword(material, "_GLOSSYREFLECTIONS_OFF", material.GetFloat("_GlossyReflections") == 0.0f); |
|||
|
|||
LightweightShaderHelper.SetKeyword(material, "_OCCLUSIONMAP", material.GetTexture("_OcclusionMap")); |
|||
LightweightShaderHelper.SetKeyword(material, "_PARALLAXMAP", material.GetTexture("_ParallaxMap")); |
|||
LightweightShaderHelper.SetKeyword(material, "_DETAIL_MULX2", material.GetTexture("_DetailAlbedoMap") || material.GetTexture("_DetailNormalMap")); |
|||
|
|||
// A material's GI flag internally keeps track of whether emission is enabled at all, it's enabled but has no effect
|
|||
// or is enabled and may be modified at runtime. This state depends on the values of the current flag and emissive color.
|
|||
// The fixup routine makes sure that the material is in the correct state if/when changes are made to the mode or color.
|
|||
MaterialEditor.FixupEmissiveFlag(material); |
|||
bool shouldEmissionBeEnabled = (material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.EmissiveIsBlack) == 0; |
|||
LightweightShaderHelper.SetKeyword(material, "_EMISSION", shouldEmissionBeEnabled); |
|||
|
|||
if (material.HasProperty("_SmoothnessTextureChannel")) |
|||
{ |
|||
LightweightShaderHelper.SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A", GetSmoothnessMapChannel(material) == SmoothnessMapChannel.AlbedoAlpha); |
|||
} |
|||
} |
|||
|
|||
static void MaterialChanged(Material material) |
|||
{ |
|||
material.shaderKeywords = null; |
|||
SetupMaterialWithBlendMode(material, (BlendMode)material.GetFloat("_Mode")); |
|||
SetMaterialKeywords(material); |
|||
} |
|||
} |
|||
} |
|
|||
using System; |
|||
using UnityEditor; |
|||
using UnityEngine; |
|||
using UnityEditor.Experimental.Rendering.LightweightPipeline; |
|||
|
|||
public class LightweightStandardSimpleLightingGUI : ShaderGUI |
|||
{ |
|||
private const float kMinShininessValue = 0.01f; |
|||
private MaterialProperty blendModeProp = null; |
|||
private MaterialProperty albedoMapProp = null; |
|||
private MaterialProperty albedoColorProp = null; |
|||
private MaterialProperty alphaCutoffProp = null; |
|||
private MaterialProperty specularSourceProp = null; |
|||
private MaterialProperty glossinessSourceProp = null; |
|||
private MaterialProperty specularGlossMapProp = null; |
|||
private MaterialProperty specularColorProp = null; |
|||
private MaterialProperty shininessProp = null; |
|||
private MaterialProperty bumpMapProp = null; |
|||
private MaterialProperty emissionMapProp = null; |
|||
private MaterialProperty emissionColorProp = null; |
|||
|
|||
private MaterialEditor m_MaterialEditor = null; |
|||
private const float kMaxfp16 = 65536f; // Clamp to a value that fits into fp16.
|
|||
private ColorPickerHDRConfig m_ColorPickerHDRConfig = new ColorPickerHDRConfig(0f, kMaxfp16, 1 / kMaxfp16, 3f); |
|||
|
|||
private static class Styles |
|||
{ |
|||
public static GUIContent[] albedoGlosinessLabels = |
|||
{ |
|||
new GUIContent("Base (RGB) Glossiness (A)", "Base Color (RGB) and Glossiness (A)"), |
|||
new GUIContent("Base (RGB)", "Base Color (RGB)") |
|||
}; |
|||
|
|||
public static GUIContent albedoAlphaLabel = new GUIContent("Base (RGB) Alpha (A)", |
|||
"Base Color (RGB) and Transparency (A)"); |
|||
|
|||
public static GUIContent[] specularGlossMapLabels = |
|||
{ |
|||
new GUIContent("Specular Map (RGB)", "Specular Color (RGB)"), |
|||
new GUIContent("Specular Map (RGB) Glossiness (A)", "Specular Color (RGB) Glossiness (A)") |
|||
}; |
|||
|
|||
public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map"); |
|||
public static GUIContent emissionMapLabel = new GUIContent("Emission Map", "Emission Map"); |
|||
|
|||
public static readonly string[] blendNames = Enum.GetNames(typeof(UpgradeBlendMode)); |
|||
public static readonly string[] glossinessSourceNames = Enum.GetNames(typeof(GlossinessSource)); |
|||
|
|||
public static string renderingModeLabel = "Rendering Mode"; |
|||
public static string specularSourceLabel = "Specular"; |
|||
public static string glossinessSourceLabel = "Glossiness Source"; |
|||
public static string glossinessSource = "Glossiness Source"; |
|||
public static string albedoColorLabel = "Base Color"; |
|||
public static string albedoMapAlphaLabel = "Base(RGB) Alpha(A)"; |
|||
public static string albedoMapGlossinessLabel = "Base(RGB) Glossiness (A)"; |
|||
public static string alphaCutoffLabel = "Alpha Cutoff"; |
|||
public static string shininessLabel = "Shininess"; |
|||
public static string normalMapLabel = "Normal map"; |
|||
public static string emissionColorLabel = "Emission Color"; |
|||
} |
|||
|
|||
private void FindMaterialProperties(MaterialProperty[] properties) |
|||
{ |
|||
blendModeProp = FindProperty("_Mode", properties); |
|||
albedoMapProp = FindProperty("_MainTex", properties); |
|||
albedoColorProp = FindProperty("_Color", properties); |
|||
|
|||
alphaCutoffProp = FindProperty("_Cutoff", properties); |
|||
specularSourceProp = FindProperty("_SpecSource", properties); |
|||
glossinessSourceProp = FindProperty("_GlossinessSource", properties); |
|||
specularGlossMapProp = FindProperty("_SpecGlossMap", properties); |
|||
specularColorProp = FindProperty("_SpecColor", properties); |
|||
shininessProp = FindProperty("_Shininess", properties); |
|||
bumpMapProp = FindProperty("_BumpMap", properties); |
|||
emissionMapProp = FindProperty("_EmissionMap", properties); |
|||
emissionColorProp = FindProperty("_EmissionColor", properties); |
|||
} |
|||
|
|||
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties) |
|||
{ |
|||
Material material = materialEditor.target as Material; |
|||
m_MaterialEditor = materialEditor; |
|||
|
|||
FindMaterialProperties(properties); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
{ |
|||
DoBlendMode(); |
|||
|
|||
EditorGUILayout.Space(); |
|||
DoSpecular(); |
|||
|
|||
EditorGUILayout.Space(); |
|||
m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, bumpMapProp); |
|||
|
|||
EditorGUILayout.Space(); |
|||
DoEmissionArea(material); |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
m_MaterialEditor.TextureScaleOffsetProperty(albedoMapProp); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
emissionMapProp.textureScaleAndOffset = albedoMapProp.textureScaleAndOffset; // Apply the main texture scale and offset to the emission texture as well, for Enlighten's sake
|
|||
} |
|||
if (EditorGUI.EndChangeCheck()) |
|||
LegacyBlinnPhongUpgrader.UpdateMaterialKeywords(material); |
|||
|
|||
EditorGUILayout.Space(); |
|||
EditorGUILayout.Space(); |
|||
|
|||
materialEditor.RenderQueueField(); |
|||
|
|||
EditorGUILayout.Space(); |
|||
EditorGUILayout.Space(); |
|||
} |
|||
|
|||
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader) |
|||
{ |
|||
base.AssignNewShaderToMaterial(material, oldShader, newShader); |
|||
|
|||
// Shininess value cannot be zero since it will produce undefined values for cases where pow(0, 0).
|
|||
float shininess = material.GetFloat("_Shininess"); |
|||
material.SetFloat("_Shininess", Mathf.Clamp(shininess, kMinShininessValue, 1.0f)); |
|||
|
|||
string oldShaderName = oldShader.name; |
|||
string[] shaderStrings = oldShaderName.Split('/'); |
|||
|
|||
if (shaderStrings[0].Equals("Legacy Shaders") || shaderStrings[0].Equals("Mobile")) |
|||
{ |
|||
ConvertFromLegacy(material, oldShaderName); |
|||
} |
|||
|
|||
LegacyBlinnPhongUpgrader.UpdateMaterialKeywords(material); |
|||
} |
|||
|
|||
private void DoBlendMode() |
|||
{ |
|||
int modeValue = (int)blendModeProp.floatValue; |
|||
EditorGUI.BeginChangeCheck(); |
|||
modeValue = EditorGUILayout.Popup(Styles.renderingModeLabel, modeValue, Styles.blendNames); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
blendModeProp.floatValue = modeValue; |
|||
|
|||
UpgradeBlendMode mode = (UpgradeBlendMode)blendModeProp.floatValue; |
|||
|
|||
EditorGUILayout.Space(); |
|||
|
|||
if (mode == UpgradeBlendMode.Opaque) |
|||
{ |
|||
int glossSource = (int)glossinessSourceProp.floatValue; |
|||
m_MaterialEditor.TexturePropertySingleLine(Styles.albedoGlosinessLabels[glossSource], albedoMapProp, |
|||
albedoColorProp); |
|||
m_MaterialEditor.TextureScaleOffsetProperty(albedoMapProp);} |
|||
else |
|||
{ |
|||
m_MaterialEditor.TexturePropertySingleLine(Styles.albedoAlphaLabel, albedoMapProp, albedoColorProp); |
|||
if (mode == UpgradeBlendMode.Cutout) |
|||
m_MaterialEditor.RangeProperty(alphaCutoffProp, "Cutoff"); |
|||
} |
|||
} |
|||
|
|||
private void DoSpecular() |
|||
{ |
|||
EditorGUILayout.Space(); |
|||
|
|||
SpecularSource specularSource = (SpecularSource)specularSourceProp.floatValue; |
|||
EditorGUI.BeginChangeCheck(); |
|||
bool enabled = EditorGUILayout.Toggle(Styles.specularSourceLabel, specularSource == SpecularSource.SpecularTextureAndColor); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
specularSourceProp.floatValue = enabled ? (float)SpecularSource.SpecularTextureAndColor : (float)SpecularSource.NoSpecular; |
|||
|
|||
SpecularSource specSource = (SpecularSource)specularSourceProp.floatValue; |
|||
if (specSource != SpecularSource.NoSpecular) |
|||
{ |
|||
bool hasSpecularMap = specularGlossMapProp.textureValue != null; |
|||
m_MaterialEditor.TexturePropertySingleLine(Styles.specularGlossMapLabels[(int)glossinessSourceProp.floatValue], specularGlossMapProp, hasSpecularMap ? null : specularColorProp); |
|||
|
|||
EditorGUI.indentLevel += 2; |
|||
GUI.enabled = hasSpecularMap; |
|||
int glossinessSource = hasSpecularMap ? (int)glossinessSourceProp.floatValue : (int)GlossinessSource.BaseAlpha; |
|||
EditorGUI.BeginChangeCheck(); |
|||
glossinessSource = EditorGUILayout.Popup(Styles.glossinessSourceLabel, glossinessSource, Styles.glossinessSourceNames); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
glossinessSourceProp.floatValue = glossinessSource; |
|||
GUI.enabled = true; |
|||
|
|||
EditorGUI.BeginChangeCheck(); |
|||
float shininess = EditorGUILayout.Slider(Styles.shininessLabel, shininessProp.floatValue, |
|||
kMinShininessValue, 1.0f); |
|||
if (EditorGUI.EndChangeCheck()) |
|||
shininessProp.floatValue = shininess; |
|||
EditorGUI.indentLevel -= 2; |
|||
} |
|||
} |
|||
|
|||
void DoEmissionArea(Material material) |
|||
{ |
|||
// Emission for GI?
|
|||
if (m_MaterialEditor.EmissionEnabledProperty()) |
|||
{ |
|||
bool hadEmissionTexture = emissionMapProp.textureValue != null; |
|||
|
|||
// Texture and HDR color controls
|
|||
m_MaterialEditor.TexturePropertyWithHDRColor(Styles.emissionMapLabel, emissionMapProp, emissionColorProp, m_ColorPickerHDRConfig, false); |
|||
|
|||
// If texture was assigned and color was black set color to white
|
|||
float brightness = emissionColorProp.colorValue.maxColorComponent; |
|||
if (emissionMapProp.textureValue != null && !hadEmissionTexture && brightness <= 0f) |
|||
emissionColorProp.colorValue = Color.white; |
|||
|
|||
// LW does not support RealtimeEmissive. We set it to bake emissive and handle the emissive is black right.
|
|||
material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive; |
|||
if (brightness <= 0f) |
|||
material.globalIlluminationFlags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack; |
|||
} |
|||
} |
|||
|
|||
private void ConvertFromLegacy(Material material, string oldShaderName) |
|||
{ |
|||
UpgradeParams shaderUpgradeParams; |
|||
|
|||
if (oldShaderName.Contains("Transp")) |
|||
{ |
|||
shaderUpgradeParams.blendMode = UpgradeBlendMode.Alpha; |
|||
shaderUpgradeParams.glosinessSource = GlossinessSource.SpecularAlpha; |
|||
} |
|||
else if (oldShaderName.Contains("Cutout")) |
|||
{ |
|||
shaderUpgradeParams.blendMode = UpgradeBlendMode.Cutout; |
|||
shaderUpgradeParams.glosinessSource = GlossinessSource.SpecularAlpha; |
|||
} |
|||
else |
|||
{ |
|||
shaderUpgradeParams.blendMode = UpgradeBlendMode.Opaque; |
|||
shaderUpgradeParams.glosinessSource = GlossinessSource.BaseAlpha; |
|||
} |
|||
|
|||
if (oldShaderName.Contains("Spec")) |
|||
shaderUpgradeParams.specularSource = SpecularSource.SpecularTextureAndColor; |
|||
else |
|||
shaderUpgradeParams.specularSource = SpecularSource.NoSpecular; |
|||
|
|||
material.SetFloat("_Mode", (float)shaderUpgradeParams.blendMode); |
|||
material.SetFloat("_SpecSource", (float)shaderUpgradeParams.specularSource); |
|||
material.SetFloat("_GlossinessSource", (float)shaderUpgradeParams.glosinessSource); |
|||
|
|||
if (oldShaderName.Contains("Self-Illumin")) |
|||
{ |
|||
material.SetTexture("_EmissionMap", material.GetTexture("_MainTex")); |
|||
material.SetTexture("_MainTex", null); |
|||
material.SetColor("_EmissionColor", Color.white); |
|||
} |
|||
} |
|||
} |
|
|||
using UnityEngine; |
|||
|
|||
namespace UnityEngine.Experimental.Rendering.LightweightPipeline |
|||
{ |
|||
public static class PerFrameBuffer |
|||
{ |
|||
public static int _GlossyEnvironmentColor; |
|||
public static int _AttenuationTexture; |
|||
} |
|||
|
|||
public static class PerCameraBuffer |
|||
{ |
|||
public static int _MainLightPosition; |
|||
public static int _MainLightColor; |
|||
public static int _MainLightAttenuationParams; |
|||
public static int _MainLightSpotDir; |
|||
|
|||
public static int _AdditionalLightCount; |
|||
public static int _AdditionalLightPosition; |
|||
public static int _AdditionalLightColor; |
|||
public static int _AdditionalLightAttenuationParams; |
|||
public static int _AdditionalLightSpotDir; |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 2462b9b2044ad4b62a8c7fcd6f012f8e |
|||
timeCreated: 1506514389 |
|||
licenseType: Free |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "Hidden/LightweightPipeline/Blit" |
|||
{ |
|||
SubShader |
|||
{ |
|||
Tags { "RenderType" = "Opaque" "RenderPipeline" = "LightweightPipeline"} |
|||
LOD 100 |
|||
|
|||
Pass |
|||
{ |
|||
Tags { "LightMode" = "LightweightForward"} |
|||
|
|||
CGPROGRAM |
|||
#pragma vertex Vertex |
|||
#pragma fragment Fragment |
|||
|
|||
struct VertexInput |
|||
{ |
|||
float4 vertex : POSITION; |
|||
float2 uv : TEXCOORD0; |
|||
}; |
|||
|
|||
struct VertexOutput |
|||
{ |
|||
half4 pos : SV_POSITION; |
|||
half2 uv : TEXCOORD0; |
|||
}; |
|||
|
|||
sampler2D _BlitTex; |
|||
|
|||
VertexOutput Vertex(VertexInput i) |
|||
{ |
|||
VertexOutput o; |
|||
o.pos = half4(i.vertex.xyz, 1.0); |
|||
o.uv = i.uv; |
|||
return o; |
|||
} |
|||
|
|||
fixed4 Fragment(VertexOutput i) : SV_Target |
|||
{ |
|||
fixed4 col = tex2D(_BlitTex, i.uv); |
|||
return col; |
|||
} |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: c17132b1f77d20942aa75f8429c0f8bc |
|||
timeCreated: 1505729520 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
Shader "Hidden/LightweightPipeline/CopyDepth" |
|||
{ |
|||
SubShader |
|||
{ |
|||
Tags { "RenderType" = "Opaque" "RenderPipeline" = "LightiweightPipeline"} |
|||
|
|||
Pass |
|||
{ |
|||
ColorMask 0 |
|||
ZTest Always |
|||
ZWrite On |
|||
|
|||
CGPROGRAM |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
|
|||
sampler2D_float _CameraDepthTexture; |
|||
|
|||
struct VertexInput |
|||
{ |
|||
float4 vertex : POSITION; |
|||
float2 uv : TEXCOORD0; |
|||
}; |
|||
|
|||
struct VertexOutput |
|||
{ |
|||
float4 position : SV_POSITION; |
|||
float2 uv : TEXCOORD0; |
|||
}; |
|||
|
|||
VertexOutput vert(VertexInput i) |
|||
{ |
|||
VertexOutput o; |
|||
o.uv = i.uv; |
|||
o.position = UnityObjectToClipPos(i.vertex); |
|||
return o; |
|||
} |
|||
|
|||
float frag(VertexOutput i) : SV_Depth |
|||
{ |
|||
return tex2D(_CameraDepthTexture, i.uv).r; |
|||
} |
|||
ENDCG |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: d6dae50ee9e1bfa4db75f19f99355220 |
|||
timeCreated: 1506692614 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
externalObjects: {} |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#ifndef LIGHTWEIGHT_PIPELINE_CORE_INCLUDED |
|||
#define LIGHTWEIGHT_PIPELINE_CORE_INCLUDED |
|||
|
|||
#include "UnityCG.cginc" |
|||
|
|||
|
|||
#ifdef _SPECULAR_SETUP |
|||
#define SAMPLE_METALLICSPECULAR(uv) tex2D(_SpecGlossMap, uv) |
|||
#else |
|||
#define SAMPLE_METALLICSPECULAR(uv) tex2D(_MetallicGlossMap, uv) |
|||
#endif |
|||
|
|||
half3 TangentToWorldNormal(half3 normalTangent, half3 tangent, half3 binormal, half3 normal) |
|||
{ |
|||
half3x3 tangentToWorld = half3x3(tangent, binormal, normal); |
|||
return normalize(mul(normalTangent, tangentToWorld)); |
|||
} |
|||
|
|||
float ComputeFogFactor(float z) |
|||
{ |
|||
float clipZ_01 = UNITY_Z_0_FAR_FROM_CLIPSPACE(z); |
|||
|
|||
#if defined(FOG_LINEAR) |
|||
// factor = (end-z)/(end-start) = z * (-1/(end-start)) + (end/(end-start)) |
|||
float fogFactor = saturate(clipZ_01 * unity_FogParams.z + unity_FogParams.w); |
|||
return half(fogFactor); |
|||
#elif defined(FOG_EXP) |
|||
// factor = exp(-density*z) |
|||
float unityFogFactor = unity_FogParams.y * clipZ_01; |
|||
return half(saturate(exp2(-unityFogFactor))); |
|||
#elif defined(FOG_EXP2) |
|||
// factor = exp(-(density*z)^2) |
|||
float unityFogFactor = unity_FogParams.x * clipZ_01; |
|||
return half(saturate(exp2(-unityFogFactor*unityFogFactor))); |
|||
#else |
|||
return 0.0h; |
|||
#endif |
|||
} |
|||
|
|||
inline half Alpha(half albedoAlpha) |
|||
{ |
|||
#if defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A) |
|||
half alpha = _Color.a; |
|||
#else |
|||
half alpha = albedoAlpha * _Color.a; |
|||
#endif |
|||
|
|||
#if defined(_ALPHATEST_ON) |
|||
clip(alpha - _Cutoff); |
|||
#endif |
|||
|
|||
return alpha; |
|||
} |
|||
|
|||
half3 Normal(float2 uv) |
|||
{ |
|||
#if _NORMALMAP |
|||
return UnpackNormal(tex2D(_BumpMap, uv)); |
|||
#else |
|||
return half3(0.0h, 0.0h, 1.0h); |
|||
#endif |
|||
} |
|||
|
|||
inline void SpecularGloss(half2 uv, half alpha, out half4 specularGloss) |
|||
{ |
|||
specularGloss = half4(0, 0, 0, 1); |
|||
#ifdef _SPECGLOSSMAP |
|||
specularGloss = tex2D(_SpecGlossMap, uv); |
|||
specularGloss.rgb = LIGHTWEIGHT_GAMMA_TO_LINEAR(specularGloss.rgb); |
|||
#elif defined(_SPECULAR_COLOR) |
|||
specularGloss = _SpecColor; |
|||
#endif |
|||
|
|||
#ifdef _GLOSSINESS_FROM_BASE_ALPHA |
|||
specularGloss.a = alpha; |
|||
#endif |
|||
} |
|||
|
|||
half4 MetallicSpecGloss(float2 uv, half albedoAlpha) |
|||
{ |
|||
half4 specGloss; |
|||
|
|||
#ifdef _METALLICSPECGLOSSMAP |
|||
specGloss = specGloss = SAMPLE_METALLICSPECULAR(uv); |
|||
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A |
|||
specGloss.a = albedoAlpha * _GlossMapScale; |
|||
#else |
|||
specGloss.a *= _GlossMapScale; |
|||
#endif |
|||
|
|||
#else // _METALLICSPECGLOSSMAP |
|||
#if _METALLIC_SETUP |
|||
specGloss.rgb = _Metallic.rrr; |
|||
#else |
|||
specGloss.rgb = _SpecColor.rgb; |
|||
#endif |
|||
|
|||
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A |
|||
specGloss.a = albedoAlpha * _GlossMapScale; |
|||
#else |
|||
specGloss.a = _Glossiness; |
|||
#endif |
|||
#endif |
|||
|
|||
return specGloss; |
|||
} |
|||
|
|||
half OcclusionLW(float2 uv) |
|||
{ |
|||
#ifdef _OCCLUSIONMAP |
|||
#if (SHADER_TARGET < 30) |
|||
// SM20: instruction count limitation |
|||
// SM20: simpler occlusion |
|||
return tex2D(_OcclusionMap, uv).g; |
|||
#else |
|||
half occ = tex2D(_OcclusionMap, uv).g; |
|||
return LerpOneTo(occ, _OcclusionStrength); |
|||
#endif |
|||
#else |
|||
return 1.0; |
|||
#endif |
|||
} |
|||
|
|||
half3 EmissionLW(float2 uv) |
|||
{ |
|||
#ifndef _EMISSION |
|||
return 0; |
|||
#else |
|||
return LIGHTWEIGHT_GAMMA_TO_LINEAR(tex2D(_EmissionMap, uv).rgb) * _EmissionColor.rgb; |
|||
#endif |
|||
} |
|||
|
|||
|
|||
|
|||
#endif |
|
|||
#ifndef LIGHTWEIGHT_LIGHTING_INCLUDED |
|||
#define LIGHTWEIGHT_LIGHTING_INCLUDED |
|||
|
|||
#include "UnityCG.cginc" |
|||
|
|||
#include "UnityStandardInput.cginc" |
|||
|
|||
#include "LightweightShadows.cginc" |
|||
|
|||
#define PI 3.14159265359f |
|||
#define kDieletricSpec half4(0.04, 0.04, 0.04, 1.0 - 0.04) // standard dielectric reflectivity coef at incident angle (= 4%) |
|||
|
|||
#define MAX_VISIBLE_LIGHTS 16 |
|||
|
|||
CBUFFER_START(_PerObject) |
|||
half4 unity_LightIndicesOffsetAndCount; |
|||
half4 unity_4LightIndices0; |
|||
half4 unity_4LightIndices1; |
|||
half _Shininess; |
|||
CBUFFER_END |
|||
|
|||
CBUFFER_START(_PerCamera) |
|||
float4 _MainLightPosition; |
|||
half4 _MainLightColor; |
|||
float4 _MainLightAttenuationParams; |
|||
half4 _MainLightSpotDir; |
|||
|
|||
half4 _AdditionalLightCount; |
|||
float4 _AdditionalLightPosition[MAX_VISIBLE_LIGHTS]; |
|||
half4 _AdditionalLightColor[MAX_VISIBLE_LIGHTS]; |
|||
float4 _AdditionalLightAttenuationParams[MAX_VISIBLE_LIGHTS]; |
|||
half4 _AdditionalLightSpotDir[MAX_VISIBLE_LIGHTS]; |
|||
CBUFFER_END |
|||
|
|||
CBUFFER_START(_PerFrame) |
|||
half4 _GlossyEnvironmentColor; |
|||
sampler2D _AttenuationTexture; |
|||
CBUFFER_END |
|||
|
|||
#if defined(UNITY_COLORSPACE_GAMMA) |
|||
#define LIGHTWEIGHT_GAMMA_TO_LINEAR(gammaColor) gammaColor * gammaColor |
|||
#define LIGHTWEIGHT_LINEAR_TO_GAMMA(linColor) sqrt(color) |
|||
#else |
|||
#define LIGHTWEIGHT_GAMMA_TO_LINEAR(color) color |
|||
#define LIGHTWEIGHT_LINEAR_TO_GAMMA(color) color |
|||
#endif |
|||
|
|||
// Main light initialized without indexing |
|||
#define INITIALIZE_MAIN_LIGHT(light) \ |
|||
light.pos = _MainLightPosition; \ |
|||
light.color = _MainLightColor; \ |
|||
light.atten = _MainLightAttenuationParams; \ |
|||
light.spotDir = _MainLightSpotDir; |
|||
|
|||
// Indexing might have a performance hit for old mobile hardware |
|||
#define INITIALIZE_LIGHT(light, i) \ |
|||
half4 indices = (i < 4) ? unity_4LightIndices0 : unity_4LightIndices1; \ |
|||
int index = (i < 4) ? i : i - 4; \ |
|||
int lightIndex = indices[index]; \ |
|||
light.pos = _AdditionalLightPosition[lightIndex]; \ |
|||
light.color = _AdditionalLightColor[lightIndex]; \ |
|||
light.atten = _AdditionalLightAttenuationParams[lightIndex]; \ |
|||
light.spotDir = _AdditionalLightSpotDir[lightIndex] |
|||
|
|||
struct LightInput |
|||
{ |
|||
float4 pos; |
|||
half4 color; |
|||
float4 atten; |
|||
half4 spotDir; |
|||
}; |
|||
|
|||
struct SurfaceData |
|||
{ |
|||
half3 albedo; |
|||
half3 specular; |
|||
half metallic; |
|||
half smoothness; |
|||
half3 normal; |
|||
half3 emission; |
|||
half occlusion; |
|||
half alpha; |
|||
}; |
|||
|
|||
struct SurfaceInput |
|||
{ |
|||
float4 lightmapUV; |
|||
half3 normalWS; |
|||
half3 tangentWS; |
|||
half3 bitangentWS; |
|||
float3 positionWS; |
|||
half3 viewDirectionWS; |
|||
half fogFactor; |
|||
}; |
|||
|
|||
struct BRDFData |
|||
{ |
|||
half3 diffuse; |
|||
half3 specular; |
|||
half perceptualRoughness; |
|||
half roughness; |
|||
half grazingTerm; |
|||
}; |
|||
|
|||
inline void InitializeSurfaceData(out SurfaceData outSurfaceData) |
|||
{ |
|||
outSurfaceData.albedo = half3(1.0h, 1.0h, 1.0h); |
|||
outSurfaceData.specular = half3(0.0h, 0.0h, 0.0h); |
|||
outSurfaceData.metallic = 1.0h; |
|||
outSurfaceData.smoothness = 0.5h; |
|||
outSurfaceData.normal = half3(0.0h, 0.0h, 1.0h); |
|||
outSurfaceData.occlusion = 1.0h; |
|||
outSurfaceData.emission = half3(0.0h, 0.0h, 0.0h); |
|||
outSurfaceData.alpha = 1.0h; |
|||
} |
|||
|
|||
half SpecularReflectivity(half3 specular) |
|||
{ |
|||
#if (SHADER_TARGET < 30) |
|||
// SM2.0: instruction count limitation |
|||
// SM2.0: simplified SpecularStrength |
|||
return specular.r; // Red channel - because most metals are either monocrhome or with redish/yellowish tint |
|||
#else |
|||
return max(max(specular.r, specular.g), specular.b); |
|||
#endif |
|||
} |
|||
|
|||
void ApplyFog(inout half3 color, half fogFactor) |
|||
{ |
|||
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2) |
|||
color = lerp(unity_FogColor, color, fogFactor); |
|||
#endif |
|||
} |
|||
|
|||
inline void InitializeBRDFData(half3 albedo, half metallic, half3 specular, half smoothness, half alpha, out BRDFData outBRDFData) |
|||
{ |
|||
// BRDF SETUP |
|||
#ifdef _METALLIC_SETUP |
|||
// We'll need oneMinusReflectivity, so |
|||
// 1-reflectivity = 1-lerp(dielectricSpec, 1, metallic) = lerp(1-dielectricSpec, 0, metallic) |
|||
// store (1-dielectricSpec) in kDieletricSpec.a, then |
|||
// 1-reflectivity = lerp(alpha, 0, metallic) = alpha + metallic*(0 - alpha) = |
|||
// = alpha - metallic * alpha |
|||
half oneMinusDielectricSpec = kDieletricSpec.a; |
|||
half oneMinusReflectivity = oneMinusDielectricSpec - metallic * oneMinusDielectricSpec; |
|||
half reflectivity = 1.0 - oneMinusReflectivity; |
|||
|
|||
outBRDFData.diffuse = albedo * oneMinusReflectivity; |
|||
outBRDFData.specular = lerp(kDieletricSpec.rgb, albedo, metallic); |
|||
#else |
|||
half reflectivity = SpecularReflectivity(specular); |
|||
|
|||
outBRDFData.diffuse = albedo * (half3(1.0h, 1.0h, 1.0h) - specular); |
|||
outBRDFData.specular = specular; |
|||
#endif |
|||
|
|||
outBRDFData.grazingTerm = saturate(smoothness + reflectivity); |
|||
outBRDFData.perceptualRoughness = 1.0h - smoothness; |
|||
outBRDFData.roughness = outBRDFData.perceptualRoughness * outBRDFData.perceptualRoughness; |
|||
|
|||
#ifdef _ALPHAPREMULTIPLY_ON |
|||
outBRDFData.diffuse *= alpha; |
|||
alpha = reflectivity + alpha * (1.0 - reflectivity); |
|||
#endif |
|||
} |
|||
|
|||
// Based on Minimalist CookTorrance BRDF |
|||
// Implementation is slightly different from original derivation: http://www.thetenthplanet.de/archives/255 |
|||
// |
|||
// * NDF [Modified] GGX |
|||
// * Modified Kelemen and Szirmay-Kalos for Visibility term |
|||
// * Fresnel approximated with 1/LdotH |
|||
half3 LightweightBDRF(BRDFData brdfData, half roughness2, half3 normal, half3 lightDirection, half3 viewDir) |
|||
{ |
|||
#ifndef _SPECULARHIGHLIGHTS_OFF |
|||
half3 halfDir = Unity_SafeNormalize(lightDirection + viewDir); |
|||
|
|||
half NoH = saturate(dot(normal, halfDir)); |
|||
half LoH = saturate(dot(lightDirection, halfDir)); |
|||
|
|||
// GGX Distribution multiplied by combined approximation of Visibility and Fresnel |
|||
// See "Optimizing PBR for Mobile" from Siggraph 2015 moving mobile graphics course |
|||
// https://community.arm.com/events/1155 |
|||
half d = NoH * NoH * (roughness2 - 1.h) + 1.00001h; |
|||
|
|||
half LoH2 = LoH * LoH; |
|||
half specularTerm = roughness2 / ((d * d) * max(0.1h, LoH2) * (brdfData.roughness + 0.5h) * 4); |
|||
|
|||
// on mobiles (where half actually means something) denominator have risk of overflow |
|||
// clamp below was added specifically to "fix" that, but dx compiler (we convert bytecode to metal/gles) |
|||
// sees that specularTerm have only non-negative terms, so it skips max(0,..) in clamp (leaving only min(100,...)) |
|||
#if defined (SHADER_API_MOBILE) |
|||
specularTerm = specularTerm - 1e-4h; |
|||
#endif |
|||
|
|||
#if defined (SHADER_API_MOBILE) |
|||
specularTerm = clamp(specularTerm, 0.0, 100.0); // Prevent FP16 overflow on mobiles |
|||
#endif |
|||
|
|||
half3 color = specularTerm * brdfData.specular + brdfData.diffuse; |
|||
return color; |
|||
#else |
|||
return brdfData.diffuse; |
|||
#endif |
|||
} |
|||
|
|||
half3 LightweightBRDFIndirect(BRDFData brdfData, UnityIndirect indirect, half roughness2, half fresnelTerm) |
|||
{ |
|||
half3 c = indirect.diffuse * brdfData.diffuse; |
|||
float surfaceReduction = 1.0 / (roughness2 + 1.0); |
|||
c += surfaceReduction * indirect.specular * lerp(brdfData.specular, brdfData.grazingTerm, fresnelTerm); |
|||
return c; |
|||
} |
|||
|
|||
UnityIndirect LightweightGI(float4 lightmapUV, half3 normalWorld, half3 reflectVec, half occlusion, half perceptualRoughness) |
|||
{ |
|||
UnityIndirect o = (UnityIndirect)0; |
|||
|
|||
#ifdef LIGHTMAP_ON |
|||
o.diffuse += (DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, lightmapUV.xy))) * occlusion; |
|||
#else |
|||
o.diffuse = ShadeSH9(half4(normalWorld, 1.0)) * occlusion; |
|||
#endif |
|||
|
|||
#ifndef _GLOSSYREFLECTIONS_OFF |
|||
Unity_GlossyEnvironmentData g; |
|||
g.roughness = perceptualRoughness; |
|||
g.reflUVW = reflectVec; |
|||
o.specular = Unity_GlossyEnvironment(UNITY_PASS_TEXCUBE(unity_SpecCube0), unity_SpecCube0_HDR, g) * occlusion; |
|||
#else |
|||
o.specular = _GlossyEnvironmentColor * occlusion; |
|||
#endif |
|||
|
|||
return o; |
|||
} |
|||
|
|||
half SpotAttenuation(half3 spotDirection, half3 lightDirection, float4 attenuationParams) |
|||
{ |
|||
// Spot Attenuation with a linear falloff can be defined as |
|||
// (SdotL - cosOuterAngle) / (cosInnerAngle - cosOuterAngle) |
|||
// This can be rewritten as |
|||
// invAngleRange = 1.0 / (cosInnerAngle - cosOuterAngle) |
|||
// SdotL * invAngleRange + (-cosOuterAngle * invAngleRange) |
|||
// If we precompute the terms in a MAD instruction |
|||
half SdotL = dot(spotDirection, lightDirection); |
|||
|
|||
// attenuationParams.x = invAngleRange |
|||
// attenuationParams.y = (-cosOuterAngle invAngleRange) |
|||
return saturate(SdotL * attenuationParams.x + attenuationParams.y); |
|||
} |
|||
|
|||
// In per-vertex falloff there's no smooth falloff to light range. A hard cut will be noticed |
|||
inline half ComputeVertexLightAttenuation(LightInput lightInput, half3 normal, float3 worldPos, out half3 lightDirection) |
|||
{ |
|||
float4 attenuationParams = lightInput.atten; |
|||
float3 posToLightVec = lightInput.pos - worldPos * lightInput.pos.w; |
|||
float distanceSqr = max(dot(posToLightVec, posToLightVec), 0.001); |
|||
|
|||
// normalized light dir |
|||
lightDirection = half3(posToLightVec * rsqrt(distanceSqr)); |
|||
|
|||
// attenuationParams.z = kQuadFallOff = (25.0) / (lightRange * lightRange) |
|||
// attenuationParams.w = lightRange * lightRange |
|||
half lightAtten = half(1.0 / (1.0 + distanceSqr * attenuationParams.z)); |
|||
lightAtten *= SpotAttenuation(lightInput.spotDir.xyz, lightDirection, attenuationParams); |
|||
return lightAtten; |
|||
} |
|||
|
|||
// In per-pixel falloff attenuation smoothly decreases to light range. |
|||
inline half ComputePixelLightAttenuation(LightInput lightInput, half3 normal, float3 worldPos, out half3 lightDirection) |
|||
{ |
|||
float4 attenuationParams = lightInput.atten; |
|||
float3 posToLightVec = lightInput.pos.xyz - worldPos * lightInput.pos.w; |
|||
float distanceSqr = max(dot(posToLightVec, posToLightVec), 0.001); |
|||
|
|||
// normalized light dir |
|||
lightDirection = half3(posToLightVec * rsqrt(distanceSqr)); |
|||
|
|||
float u = (distanceSqr * attenuationParams.z) / attenuationParams.w; |
|||
half lightAtten = tex2D(_AttenuationTexture, float2(u, 0.0)).a; |
|||
lightAtten *= SpotAttenuation(lightInput.spotDir.xyz, lightDirection, attenuationParams); |
|||
return lightAtten; |
|||
} |
|||
|
|||
inline half ComputeMainLightAttenuation(LightInput lightInput, half3 normal, float3 worldPos, out half3 lightDirection) |
|||
{ |
|||
#ifdef _MAIN_DIRECTIONAL_LIGHT |
|||
// Light pos holds normalized light dir |
|||
lightDirection = lightInput.pos; |
|||
return 1.0; |
|||
#else |
|||
return ComputePixelLightAttenuation(lightInput, normal, worldPos, lightDirection); |
|||
#endif |
|||
} |
|||
|
|||
inline half3 LightingLambert(half3 diffuseColor, half3 lightDir, half3 normal, half atten) |
|||
{ |
|||
half NdotL = saturate(dot(normal, lightDir)); |
|||
return diffuseColor * (NdotL * atten); |
|||
} |
|||
|
|||
inline half3 LightingBlinnPhong(half3 diffuseColor, half4 specularGloss, half3 lightDir, half3 normal, half3 viewDir, half atten) |
|||
{ |
|||
half NdotL = saturate(dot(normal, lightDir)); |
|||
half3 diffuse = diffuseColor * NdotL; |
|||
|
|||
half3 halfVec = normalize(lightDir + viewDir); |
|||
half NdotH = saturate(dot(normal, halfVec)); |
|||
half3 specular = specularGloss.rgb * pow(NdotH, _Shininess * 128.0) * specularGloss.a; |
|||
return (diffuse + specular) * atten; |
|||
} |
|||
|
|||
half3 TangentToWorldNormal(half3 normalTangent, half3 tangent, half3 binormal, half3 normal) |
|||
{ |
|||
half3x3 tangentToWorld = half3x3(tangent, binormal, normal); |
|||
return normalize(mul(normalTangent, tangentToWorld)); |
|||
} |
|||
|
|||
half4 OutputColor(half3 color, half alpha) |
|||
{ |
|||
#if defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON) |
|||
return half4(LIGHTWEIGHT_LINEAR_TO_GAMMA(color), alpha); |
|||
#else |
|||
return half4(LIGHTWEIGHT_LINEAR_TO_GAMMA(color), 1); |
|||
#endif |
|||
} |
|||
|
|||
half4 LightweightFragmentPBR(half4 lightmapUV, float3 positionWS, half3 normalWS, half3 tangentWS, half3 bitangentWS, |
|||
half3 viewDirectionWS, half fogFactor, half3 albedo, half metallic, half3 specular, half smoothness, |
|||
half3 normalTS, half ambientOcclusion, half3 emission, half alpha) |
|||
{ |
|||
BRDFData brdfData; |
|||
InitializeBRDFData(albedo, metallic, specular, smoothness, alpha, brdfData); |
|||
|
|||
half3 vertexNormal = normalWS; |
|||
#if _NORMALMAP |
|||
normalWS = TangentToWorldNormal(normalTS, tangentWS, bitangentWS, normalWS); |
|||
#else |
|||
normalWS = normalize(normalWS); |
|||
#endif |
|||
|
|||
half3 reflectVec = reflect(-viewDirectionWS, normalWS); |
|||
half roughness2 = brdfData.roughness * brdfData.roughness; |
|||
UnityIndirect indirectLight = LightweightGI(lightmapUV, normalWS, reflectVec, ambientOcclusion, brdfData.perceptualRoughness); |
|||
|
|||
// PBS |
|||
half fresnelTerm = Pow4(1.0 - saturate(dot(normalWS, viewDirectionWS))); |
|||
half3 color = LightweightBRDFIndirect(brdfData, indirectLight, roughness2, fresnelTerm); |
|||
half3 lightDirectionWS; |
|||
|
|||
LightInput light; |
|||
INITIALIZE_MAIN_LIGHT(light); |
|||
half lightAtten = ComputeMainLightAttenuation(light, normalWS, positionWS, lightDirectionWS); |
|||
lightAtten *= LIGHTWEIGHT_SHADOW_ATTENUATION(positionWS, normalize(vertexNormal), _ShadowLightDirection.xyz); |
|||
|
|||
half NdotL = saturate(dot(normalWS, lightDirectionWS)); |
|||
half3 radiance = light.color * (lightAtten * NdotL); |
|||
color += LightweightBDRF(brdfData, roughness2, normalWS, lightDirectionWS, viewDirectionWS) * radiance; |
|||
|
|||
#ifdef _ADDITIONAL_LIGHTS |
|||
int pixelLightCount = min(_AdditionalLightCount.x, unity_LightIndicesOffsetAndCount.y); |
|||
for (int lightIter = 0; lightIter < pixelLightCount; ++lightIter) |
|||
{ |
|||
LightInput light; |
|||
INITIALIZE_LIGHT(light, lightIter); |
|||
half lightAtten = ComputePixelLightAttenuation(light, normalWS, positionWS, lightDirectionWS); |
|||
|
|||
half NdotL = saturate(dot(normalWS, lightDirectionWS)); |
|||
half3 radiance = light.color * (lightAtten * NdotL); |
|||
color += LightweightBDRF(brdfData, roughness2, normalWS, lightDirectionWS, viewDirectionWS) * radiance; |
|||
} |
|||
#endif |
|||
|
|||
color += emission; |
|||
|
|||
// Computes fog factor per-vertex |
|||
ApplyFog(color, fogFactor); |
|||
return OutputColor(color, alpha); |
|||
} |
|||
#endif |
|
|||
#ifndef LIGHTWEIGHT_PASS_LIT_INCLUDED |
|||
#define LIGHTWEIGHT_PASS_LIT_INCLUDED |
|||
|
|||
#include "LightweightLighting.cginc" |
|||
|
|||
struct LightweightVertexInput |
|||
{ |
|||
float4 vertex : POSITION; |
|||
float3 normal : NORMAL; |
|||
float4 tangent : TANGENT; |
|||
float2 texcoord : TEXCOORD0; |
|||
float2 lightmapUV : TEXCOORD1; |
|||
UNITY_VERTEX_INPUT_INSTANCE_ID |
|||
}; |
|||
|
|||
struct LightweightVertexOutput |
|||
{ |
|||
float2 uv : TEXCOORD0; |
|||
float4 ambientOrLightmapUV : TEXCOORD1; // xy: lightmapUV, zw: dynamicLightmapUV OR color from SH |
|||
float4 posWS : TEXCOORD2; |
|||
#if _NORMALMAP |
|||
half3 tangent : TEXCOORD3; |
|||
half3 binormal : TEXCOORD4; |
|||
half3 normal : TEXCOORD5; |
|||
#else |
|||
half3 normal : TEXCOORD3; |
|||
#endif |
|||
half4 viewDir : TEXCOORD6; // xyz: viewDir |
|||
half4 fogFactorAndVertexLight : TEXCOORD7; // x: fogFactor, yzw: vertex light |
|||
float4 clipPos : SV_POSITION; |
|||
UNITY_VERTEX_OUTPUT_STEREO |
|||
}; |
|||
|
|||
inline void InitializeStandardLitSurfaceData(LightweightVertexOutput IN, out SurfaceData outSurfaceData) |
|||
{ |
|||
float2 uv = IN.uv; |
|||
half4 albedoAlpha = tex2D(_MainTex, uv); |
|||
|
|||
half4 specGloss = MetallicSpecGloss(uv, albedoAlpha); |
|||
outSurfaceData.albedo = LIGHTWEIGHT_GAMMA_TO_LINEAR(albedoAlpha.rgb) * _Color.rgb; |
|||
|
|||
#if _METALLIC_SETUP |
|||
outSurfaceData.metallic = specGloss.r; |
|||
outSurfaceData.specular = half3(0.0h, 0.0h, 0.0h); |
|||
#else |
|||
outSurfaceData.metallic = 1.0h; |
|||
outSurfaceData.specular = specGloss.rgb; |
|||
#endif |
|||
|
|||
outSurfaceData.smoothness = specGloss.a; |
|||
outSurfaceData.normal = Normal(uv); |
|||
outSurfaceData.occlusion = OcclusionLW(uv); |
|||
outSurfaceData.emission = EmissionLW(uv); |
|||
outSurfaceData.emission += IN.fogFactorAndVertexLight.yzw; |
|||
outSurfaceData.alpha = Alpha(albedoAlpha.a); |
|||
} |
|||
|
|||
void InitializeSurfaceInput(LightweightVertexOutput IN, out SurfaceInput outSurfaceInput) |
|||
{ |
|||
#if LIGHTMAP_ON |
|||
outSurfaceInput.lightmapUV = float4(IN.ambientOrLightmapUV.xy, 0.0, 0.0); |
|||
#else |
|||
outSurfaceInput.lightmapUV = float4(0.0, 0.0, 0.0, 0.0); |
|||
#endif |
|||
|
|||
#if _NORMALMAP |
|||
outSurfaceInput.tangentWS = IN.tangent; |
|||
outSurfaceInput.bitangentWS = IN.binormal; |
|||
#else |
|||
outSurfaceInput.tangentWS = half3(1.0h, 0.0h, 0.0h); |
|||
outSurfaceInput.bitangentWS = half3(0.0h, 1.0h, 0.0h); |
|||
#endif |
|||
|
|||
outSurfaceInput.normalWS = IN.normal; |
|||
outSurfaceInput.positionWS = IN.posWS; |
|||
outSurfaceInput.viewDirectionWS = IN.viewDir; |
|||
outSurfaceInput.fogFactor = IN.fogFactorAndVertexLight.x; |
|||
} |
|||
|
|||
LightweightVertexOutput LitPassVertex(LightweightVertexInput v) |
|||
{ |
|||
LightweightVertexOutput o = (LightweightVertexOutput)0; |
|||
|
|||
UNITY_SETUP_INSTANCE_ID(v); |
|||
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); |
|||
|
|||
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); |
|||
|
|||
float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; |
|||
o.posWS.xyz = worldPos; |
|||
|
|||
half3 viewDir = normalize(_WorldSpaceCameraPos - worldPos); |
|||
o.viewDir.xyz = viewDir; |
|||
|
|||
half3 normal = normalize(UnityObjectToWorldNormal(v.normal)); |
|||
|
|||
#if _NORMALMAP |
|||
half sign = v.tangent.w * unity_WorldTransformParams.w; |
|||
o.tangent = normalize(mul((half3x3)unity_ObjectToWorld, v.tangent.xyz)); |
|||
o.binormal = cross(normal, o.tangent) * sign; |
|||
o.normal = normal; |
|||
#else |
|||
o.normal = normal; |
|||
#endif |
|||
|
|||
#ifdef LIGHTMAP_ON |
|||
o.ambientOrLightmapUV.xy = v.lightmapUV * unity_LightmapST.xy + unity_LightmapST.zw; |
|||
// TODO: Dynamic Lightmap |
|||
o.ambientOrLightmapUV.zw = float2(0.0, 0.0); |
|||
|
|||
// TODO: Currently there's no way to pass in ambient contribution to fragmentPBR. |
|||
// We should allow to create custom ambient computation for things like SH evaluation, lightmap, ambient color etc. |
|||
//#else |
|||
// o.ambientOrLightmapUV = half4(SHEvalLinearL2(half4(normal, 1.0)), 0.0h); |
|||
#endif |
|||
|
|||
o.fogFactorAndVertexLight.yzw = half3(0.0h, 0.0h, 0.0h); |
|||
#if defined(_VERTEX_LIGHTS) |
|||
half3 diffuse = half3(1.0, 1.0, 1.0); |
|||
int vertexLightStart = _AdditionalLightCount.x; |
|||
int vertexLightEnd = min(_AdditionalLightCount.y, unity_LightIndicesOffsetAndCount.y); |
|||
for (int lightIter = vertexLightStart; lightIter < vertexLightEnd; ++lightIter) |
|||
{ |
|||
LightInput lightData; |
|||
INITIALIZE_LIGHT(lightData, lightIter); |
|||
|
|||
half3 lightDirection; |
|||
half atten = ComputeVertexLightAttenuation(lightData, normal, worldPos, lightDirection); |
|||
o.fogFactorAndVertexLight.yzw += LightingLambert(diffuse, lightDirection, normal, atten) * lightData.color; |
|||
} |
|||
#endif |
|||
|
|||
float4 clipPos = UnityObjectToClipPos(v.vertex); |
|||
o.fogFactorAndVertexLight.x = ComputeFogFactor(clipPos.z); |
|||
o.clipPos = clipPos; |
|||
return o; |
|||
} |
|||
|
|||
half4 LitPassFragment(LightweightVertexOutput IN) : SV_Target |
|||
{ |
|||
SurfaceData surfaceData; |
|||
InitializeStandardLitSurfaceData(IN, surfaceData); |
|||
|
|||
SurfaceInput surfaceInput; |
|||
InitializeSurfaceInput(IN, surfaceInput); |
|||
|
|||
return LightweightFragmentPBR(surfaceInput.lightmapUV, surfaceInput.positionWS, surfaceInput.normalWS, surfaceInput.tangentWS, surfaceInput.bitangentWS, surfaceInput.viewDirectionWS, surfaceInput.fogFactor, surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.normal, surfaceData.occlusion, surfaceData.emission, surfaceData.alpha); |
|||
} |
|||
|
|||
half4 LitPassFragmentSimple(LightweightVertexOutput IN) : SV_Target |
|||
{ |
|||
float2 uv = IN.uv; |
|||
|
|||
half4 diffuseAlpha = tex2D(_MainTex, uv); |
|||
half3 diffuse = LIGHTWEIGHT_GAMMA_TO_LINEAR(diffuseAlpha.rgb) * _Color.rgb; |
|||
|
|||
#ifdef _GLOSSINESS_FROM_BASE_ALPHA |
|||
half alpha = _Color.a; |
|||
#else |
|||
half alpha = diffuseAlpha.a * _Color.a; |
|||
#endif |
|||
|
|||
// Keep for compatibility reasons. Shader Inpector throws a warning when using cutoff |
|||
// due overdraw performance impact. |
|||
#ifdef _ALPHATEST_ON |
|||
clip(alpha - _Cutoff); |
|||
#endif |
|||
|
|||
#if _NORMALMAP |
|||
half3 normalTangent = Normal(uv); |
|||
half3 normalWorld = TangentToWorldNormal(normalTangent, IN.tangent, IN.binormal, IN.normal); |
|||
#else |
|||
half3 normalWorld = normalize(IN.normal); |
|||
#endif |
|||
|
|||
half4 specularGloss; |
|||
SpecularGloss(uv, alpha, specularGloss); |
|||
|
|||
half3 viewDir = IN.viewDir.xyz; |
|||
float3 worldPos = IN.posWS.xyz; |
|||
|
|||
half3 lightDirection; |
|||
|
|||
#if defined(LIGHTMAP_ON) |
|||
half3 color = DecodeLightmap(UNITY_SAMPLE_TEX2D(unity_Lightmap, IN.ambientOrLightmapUV.xy)) * diffuse; |
|||
#else |
|||
half3 color = (ShadeSH9(half4(normalWorld, 1.0)) + IN.ambientOrLightmapUV.xyz) * diffuse; |
|||
#endif |
|||
|
|||
LightInput lightInput; |
|||
INITIALIZE_MAIN_LIGHT(lightInput); |
|||
half lightAtten = ComputeMainLightAttenuation(lightInput, normalWorld, worldPos, lightDirection); |
|||
lightAtten *= LIGHTWEIGHT_SHADOW_ATTENUATION(worldPos, normalize(IN.normal), _ShadowLightDirection.xyz); |
|||
|
|||
#if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR) |
|||
color += LightingBlinnPhong(diffuse, specularGloss, lightDirection, normalWorld, viewDir, lightAtten) * lightInput.color; |
|||
#else |
|||
color += LightingLambert(diffuse, lightDirection, normalWorld, lightAtten) * lightInput.color; |
|||
#endif |
|||
|
|||
#ifdef _ADDITIONAL_LIGHTS |
|||
int pixelLightCount = min(_AdditionalLightCount.x, unity_LightIndicesOffsetAndCount.y); |
|||
for (int lightIter = 0; lightIter < pixelLightCount; ++lightIter) |
|||
{ |
|||
LightInput lightData; |
|||
INITIALIZE_LIGHT(lightData, lightIter); |
|||
half lightAtten = ComputePixelLightAttenuation(lightData, normalWorld, worldPos, lightDirection); |
|||
|
|||
#if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR) |
|||
color += LightingBlinnPhong(diffuse, specularGloss, lightDirection, normalWorld, viewDir, lightAtten) * lightData.color; |
|||
#else |
|||
color += LightingLambert(diffuse, lightDirection, normalWorld, lightAtten) * lightData.color; |
|||
#endif |
|||
} |
|||
|
|||
#endif // _ADDITIONAL_LIGHTS |
|||
|
|||
color += EmissionLW(uv); |
|||
color += IN.fogFactorAndVertexLight.yzw; |
|||
|
|||
// Computes Fog Factor per vextex |
|||
ApplyFog(color, IN.fogFactorAndVertexLight.x); |
|||
return OutputColor(color, alpha); |
|||
}; |
|||
|
|||
#endif |
|
|||
fileFormatVersion: 2 |
|||
guid: 116bd973269b9f741b7177c8523b9e50 |
|||
timeCreated: 1488965025 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#ifndef LIGHTWEIGHT_PASS_SHADOW_INCLUDED |
|||
#define LIGHTWEIGHT_PASS_SHADOW_INCLUDED |
|||
|
|||
float4 ShadowPassVertex(float4 pos : POSITION) : SV_POSITION |
|||
{ |
|||
float4 clipPos = UnityObjectToClipPos(pos); |
|||
#if defined(UNITY_REVERSED_Z) |
|||
clipPos.z = min(clipPos.z, UNITY_NEAR_CLIP_VALUE); |
|||
#else |
|||
clipPos.z = max(clipPos.z, UNITY_NEAR_CLIP_VALUE); |
|||
#endif |
|||
return clipPos; |
|||
} |
|||
|
|||
half4 ShadowPassFragment() : SV_TARGET |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
#endif |
|
|||
fileFormatVersion: 2 |
|||
guid: 9a48a2987a0e11645adf07fe4a8d5ec9 |
|||
timeCreated: 1488965025 |
|||
licenseType: Pro |
|||
ShaderImporter: |
|||
defaultTextures: [] |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
#ifndef LIGHTWEIGHT_SHADOWS_INCLUDED |
|||
#define LIGHTWEIGHT_SHADOWS_INCLUDED |
|||
#define MAX_SHADOW_CASCADES 4 |
|||
|
|||
#if defined(_HARD_SHADOWS) || defined(_SOFT_SHADOWS) || defined(_HARD_SHADOWS_CASCADES) || defined(_SOFT_SHADOWS_CASCADES) |
|||
#define _SHADOWS |
|||
#endif |
|||
|
|||
#if defined(_HARD_SHADOWS_CASCADES) || defined(_SOFT_SHADOWS_CASCADES) |
|||
#define _SHADOW_CASCADES |
|||
#endif |
|||
|
|||
#ifdef _SHADOWS |
|||
#define LIGHTWEIGHT_SHADOW_ATTENUATION(posWorld, vertexNormal, shadowDir) ComputeShadowAttenuation(posWorld, vertexNormal, shadowDir) |
|||
#else |
|||
#define LIGHTWEIGHT_SHADOW_ATTENUATION(posWorld, vertexNormal, shadowDir) 1.0h |
|||
#endif |
|||
|
|||
sampler2D_float _ShadowMap; |
|||
float _PCFKernel[8]; |
|||
float4x4 _WorldToShadow[MAX_SHADOW_CASCADES]; |
|||
float4 _DirShadowSplitSpheres[MAX_SHADOW_CASCADES]; |
|||
half4 _ShadowData; |
|||
half4 _ShadowLightDirection; |
|||
|
|||
inline half ShadowAttenuation(float3 shadowCoord) |
|||
{ |
|||
if (shadowCoord.x <= 0 || shadowCoord.x >= 1 || shadowCoord.y <= 0 || shadowCoord.y >= 1) |
|||
return 1; |
|||
|
|||
float depth = tex2D(_ShadowMap, shadowCoord).r; |
|||
|
|||
#if defined(UNITY_REVERSED_Z) |
|||
return step(depth - _ShadowData.y, shadowCoord.z); |
|||
#else |
|||
return step(shadowCoord.z, depth + _ShadowData.y); |
|||
#endif |
|||
} |
|||
|
|||
inline half ComputeCascadeIndex(float3 wpos) |
|||
{ |
|||
float3 fromCenter0 = wpos.xyz - _DirShadowSplitSpheres[0].xyz; |
|||
float3 fromCenter1 = wpos.xyz - _DirShadowSplitSpheres[1].xyz; |
|||
float3 fromCenter2 = wpos.xyz - _DirShadowSplitSpheres[2].xyz; |
|||
float3 fromCenter3 = wpos.xyz - _DirShadowSplitSpheres[3].xyz; |
|||
float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3)); |
|||
|
|||
float4 vDirShadowSplitSphereSqRadii; |
|||
vDirShadowSplitSphereSqRadii.x = _DirShadowSplitSpheres[0].w; |
|||
vDirShadowSplitSphereSqRadii.y = _DirShadowSplitSpheres[1].w; |
|||
vDirShadowSplitSphereSqRadii.z = _DirShadowSplitSpheres[2].w; |
|||
vDirShadowSplitSphereSqRadii.w = _DirShadowSplitSpheres[3].w; |
|||
fixed4 weights = fixed4(distances2 < vDirShadowSplitSphereSqRadii); |
|||
weights.yzw = saturate(weights.yzw - weights.xyz); |
|||
return 4 - dot(weights, fixed4(4, 3, 2, 1)); |
|||
} |
|||
|
|||
inline half ShadowPCF(half3 shadowCoord) |
|||
{ |
|||
// TODO: simulate textureGatherOffset not available, simulate it |
|||
half2 offset = half2(0, 0); |
|||
half attenuation = ShadowAttenuation(half3(shadowCoord.xy + half2(_PCFKernel[0], _PCFKernel[1]) + offset, shadowCoord.z)) + |
|||
ShadowAttenuation(half3(shadowCoord.xy + half2(_PCFKernel[2], _PCFKernel[3]) + offset, shadowCoord.z)) + |
|||
ShadowAttenuation(half3(shadowCoord.xy + half2(_PCFKernel[4], _PCFKernel[5]) + offset, shadowCoord.z)) + |
|||
ShadowAttenuation(half3(shadowCoord.xy + half2(_PCFKernel[6], _PCFKernel[7]) + offset, shadowCoord.z)); |
|||
return attenuation * 0.25; |
|||
} |
|||
|
|||
inline half ComputeShadowAttenuation(float3 posWorld, half3 vertexNormal, half3 shadowDir) |
|||
{ |
|||
half NdotL = dot(vertexNormal, shadowDir); |
|||
half bias = saturate(1.0 - NdotL) * _ShadowData.z; |
|||
|
|||
float3 posWorldOffsetNormal = posWorld + vertexNormal * bias; |
|||
|
|||
int cascadeIndex = 0; |
|||
#ifdef _SHADOW_CASCADES |
|||
cascadeIndex = ComputeCascadeIndex(posWorldOffsetNormal); |
|||
if (cascadeIndex >= MAX_SHADOW_CASCADES) |
|||
return 1.0; |
|||
#endif |
|||
float4 shadowCoord = mul(_WorldToShadow[cascadeIndex], float4(posWorldOffsetNormal, 1.0)); |
|||
shadowCoord.xyz /= shadowCoord.w; |
|||
shadowCoord.z = saturate(shadowCoord.z); |
|||
|
|||
#if defined(_SOFT_SHADOWS) || defined(_SOFT_SHADOWS_CASCADES) |
|||
return ShadowPCF(shadowCoord.xyz); |
|||
#else |
|||
return ShadowAttenuation(shadowCoord.xyz); |
|||
#endif |
|||
} |
|||
|
|||
#endif |
|
|||
Shader "LightweightPipeline/Standard (Physically Based)" |
|||
{ |
|||
Properties |
|||
{ |
|||
// Specular vs Metallic workflow |
|||
[HideInInspector] _WorkflowMode("WorkflowMode", Float) = 1.0 |
|||
|
|||
_Color("Color", Color) = (1,1,1,1) |
|||
_MainTex("Albedo", 2D) = "white" {} |
|||
|
|||
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 |
|||
|
|||
_Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5 |
|||
_GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0 |
|||
_SmoothnessTextureChannel("Smoothness texture channel", Float) = 0 |
|||
|
|||
[Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0 |
|||
_MetallicGlossMap("Metallic", 2D) = "white" {} |
|||
|
|||
_SpecColor("Specular", Color) = (0.2, 0.2, 0.2) |
|||
_SpecGlossMap("Specular", 2D) = "white" {} |
|||
|
|||
[Toggle] _SpecularHighlights("Specular Highlights", Float) = 1.0 |
|||
[Toggle] _GlossyReflections("Glossy Reflections", Float) = 1.0 |
|||
|
|||
_BumpScale("Scale", Float) = 1.0 |
|||
_BumpMap("Normal Map", 2D) = "bump" {} |
|||
|
|||
_Parallax("Height Scale", Range(0.005, 0.08)) = 0.02 |
|||
_ParallaxMap("Height Map", 2D) = "black" {} |
|||
|
|||
_OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0 |
|||
_OcclusionMap("Occlusion", 2D) = "white" {} |
|||
|
|||
_EmissionColor("Color", Color) = (0,0,0) |
|||
_EmissionMap("Emission", 2D) = "white" {} |
|||
|
|||
_DetailMask("Detail Mask", 2D) = "white" {} |
|||
|
|||
_DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {} |
|||
_DetailNormalMapScale("Scale", Float) = 1.0 |
|||
_DetailNormalMap("Normal Map", 2D) = "bump" {} |
|||
|
|||
[Enum(UV0,0,UV1,1)] _UVSec("UV Set for secondary textures", Float) = 0 |
|||
|
|||
// Blending state |
|||
[HideInInspector] _Mode("__mode", Float) = 0.0 |
|||
[HideInInspector] _SrcBlend("__src", Float) = 1.0 |
|||
[HideInInspector] _DstBlend("__dst", Float) = 0.0 |
|||
[HideInInspector] _ZWrite("__zw", Float) = 1.0 |
|||
} |
|||
|
|||
SubShader |
|||
{ |
|||
Tags{"RenderType" = "Opaque" "RenderPipeline" = "LightweightPipeline"} |
|||
LOD 300 |
|||
|
|||
// ------------------------------------------------------------------ |
|||
// Base forward pass (directional light, emission, lightmaps, ...) |
|||
Pass |
|||
{ |
|||
Tags{"LightMode" = "LightweightForward"} |
|||
|
|||
Blend[_SrcBlend][_DstBlend] |
|||
ZWrite[_ZWrite] |
|||
|
|||
CGPROGRAM |
|||
#pragma target 3.0 |
|||
|
|||
// ------------------------------------- |
|||
#pragma shader_feature _METALLIC_SETUP _SPECULAR_SETUP |
|||
#pragma shader_feature _NORMALMAP |
|||
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON |
|||
#pragma shader_feature _EMISSION |
|||
#pragma shader_feature _METALLICSPECGLOSSMAP |
|||
#pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A |
|||
#pragma shader_feature _SPECULARHIGHLIGHTS_OFF |
|||
#pragma shader_feature _GLOSSYREFLECTIONS_OFF |
|||
#pragma shader_feature _OCCLUSIONMAP |
|||
|
|||
#pragma multi_compile _MAIN_DIRECTIONAL_LIGHT _MAIN_SPOT_LIGHT _MAIN_POINT_LIGHT |
|||
#pragma multi_compile _ _ADDITIONAL_LIGHTS |
|||
#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON |
|||
#pragma multi_compile _ LIGHTMAP_ON |
|||
#pragma multi_compile _ _HARD_SHADOWS _SOFT_SHADOWS _HARD_SHADOWS_CASCADES _SOFT_SHADOWS_CASCADES |
|||
#pragma multi_compile _ _VERTEX_LIGHTS |
|||
|
|||
#pragma multi_compile_fog |
|||
#pragma multi_compile_instancing |
|||
|
|||
#pragma vertex LitPassVertex |
|||
#pragma fragment LitPassFragment |
|||
#include "UnityStandardInput.cginc" |
|||
#include "LightweightPassLit.cginc" |
|||
ENDCG |
|||
} |
|||
|
|||
Pass |
|||
{ |
|||
Tags{"Lightmode" = "ShadowCaster"} |
|||
|
|||
ZWrite On ZTest LEqual |
|||
|
|||
CGPROGRAM |
|||
#pragma target 2.0 |
|||
#pragma vertex ShadowPassVertex |
|||
#pragma fragment ShadowPassFragment |
|||
|
|||
#include "UnityCG.cginc" |
|||
#include "LightweightPassShadow.cginc" |
|||
ENDCG |
|||
} |
|||
|
|||
Pass |
|||
{ |
|||
Tags{"Lightmode" = "DepthOnly"} |
|||
|
|||
ZWrite On |
|||
|
|||
CGPROGRAM |
|||
#pragma target 2.0 |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
|
|||
#include "UnityCG.cginc" |
|||
|
|||
float4 vert(float4 pos : POSITION) : SV_POSITION |
|||
{ |
|||
return UnityObjectToClipPos(pos); |
|||
} |
|||
|
|||
half4 frag() : SV_TARGET |
|||
{ |
|||
return 0; |
|||
} |
|||
ENDCG |
|||
} |
|||
} |
|||
FallBack "Standard" |
|||
CustomEditor "LightweightStandardGUI" |
|||
} |
|||
|
|
|||
// Shader targeted for low end devices. Single Pass Forward Rendering. Shader Model 2 |
|||
Shader "LightweightPipeline/Standard (Simple Lighting)" |
|||
{ |
|||
// Keep properties of StandardSpecular shader for upgrade reasons. |
|||
Properties |
|||
{ |
|||
_Color("Color", Color) = (1,1,1,1) |
|||
_MainTex("Base (RGB) Glossiness / Alpha (A)", 2D) = "white" {} |
|||
|
|||
_Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 |
|||
|
|||
_Shininess("Shininess", Range(0.01, 1.0)) = 1.0 |
|||
_GlossMapScale("Smoothness Factor", Range(0.0, 1.0)) = 1.0 |
|||
|
|||
_Glossiness("Glossiness", Range(0.0, 1.0)) = 0.5 |
|||
[Enum(Specular Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel("Smoothness texture channel", Float) = 0 |
|||
|
|||
[HideInInspector] _SpecSource("Specular Color Source", Float) = 0.0 |
|||
_SpecColor("Specular", Color) = (1.0, 1.0, 1.0) |
|||
_SpecGlossMap("Specular", 2D) = "white" {} |
|||
[HideInInspector] _GlossinessSource("Glossiness Source", Float) = 0.0 |
|||
[ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0 |
|||
[ToggleOff] _GlossyReflections("Glossy Reflections", Float) = 1.0 |
|||
|
|||
[HideInInspector] _BumpScale("Scale", Float) = 1.0 |
|||
[NoScaleOffset] _BumpMap("Normal Map", 2D) = "bump" {} |
|||
|
|||
_Parallax("Height Scale", Range(0.005, 0.08)) = 0.02 |
|||
_ParallaxMap("Height Map", 2D) = "black" {} |
|||
|
|||
_EmissionColor("Emission Color", Color) = (0,0,0) |
|||
_EmissionMap("Emission", 2D) = "white" {} |
|||
|
|||
_DetailMask("Detail Mask", 2D) = "white" {} |
|||
|
|||
_DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {} |
|||
_DetailNormalMapScale("Scale", Float) = 1.0 |
|||
_DetailNormalMap("Normal Map", 2D) = "bump" {} |
|||
|
|||
[Enum(UV0,0,UV1,1)] _UVSec("UV Set for secondary textures", Float) = 0 |
|||
|
|||
// Blending state |
|||
[HideInInspector] _Mode("__mode", Float) = 0.0 |
|||
[HideInInspector] _SrcBlend("__src", Float) = 1.0 |
|||
[HideInInspector] _DstBlend("__dst", Float) = 0.0 |
|||
[HideInInspector] _ZWrite("__zw", Float) = 1.0 |
|||
} |
|||
|
|||
SubShader |
|||
{ |
|||
Tags { "RenderType" = "Opaque" "RenderPipeline" = "LightweightPipeline" } |
|||
LOD 300 |
|||
|
|||
Pass |
|||
{ |
|||
Tags { "LightMode" = "LightweightForward" } |
|||
|
|||
// Use same blending / depth states as Standard shader |
|||
Blend[_SrcBlend][_DstBlend] |
|||
ZWrite[_ZWrite] |
|||
|
|||
CGPROGRAM |
|||
#pragma target 3.0 |
|||
#pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON |
|||
#pragma shader_feature _ _SPECGLOSSMAP _SPECULAR_COLOR |
|||
#pragma shader_feature _ _GLOSSINESS_FROM_BASE_ALPHA |
|||
#pragma shader_feature _NORMALMAP |
|||
#pragma shader_feature _EMISSION |
|||
|
|||
#pragma multi_compile _MAIN_DIRECTIONAL_LIGHT _MAIN_SPOT_LIGHT _MAIN_POINT_LIGHT |
|||
#pragma multi_compile _ _ADDITIONAL_LIGHTS |
|||
#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON |
|||
#pragma multi_compile _ LIGHTMAP_ON |
|||
#pragma multi_compile _ _HARD_SHADOWS _SOFT_SHADOWS _HARD_SHADOWS_CASCADES _SOFT_SHADOWS_CASCADES |
|||
#pragma multi_compile _ _VERTEX_LIGHTS |
|||
#pragma multi_compile_fog |
|||
#pragma multi_compile_instancing |
|||
|
|||
#pragma vertex LitPassVertex |
|||
#pragma fragment LitPassFragmentSimple |
|||
#include "UnityStandardInput.cginc" |
|||
#include "LightweightPassLit.cginc" |
|||
ENDCG |
|||
} |
|||
|
|||
Pass |
|||
{ |
|||
Tags{"Lightmode" = "ShadowCaster"} |
|||
|
|||
ZWrite On ZTest LEqual |
|||
|
|||
CGPROGRAM |
|||
#pragma target 2.0 |
|||
#pragma vertex ShadowPassVertex |
|||
#pragma fragment ShadowPassFragment |
|||
|
|||
#include "UnityCG.cginc" |
|||
#include "LightweightPassShadow.cginc" |
|||
ENDCG |
|||
} |
|||
|
|||
Pass |
|||
{ |
|||
Tags{"Lightmode" = "DepthOnly"} |
|||
|
|||
ZWrite On |
|||
|
|||
CGPROGRAM |
|||
#pragma target 2.0 |
|||
#pragma vertex vert |
|||
#pragma fragment frag |
|||
|
|||
#include "UnityCG.cginc" |
|||
|
|||
float4 vert(float4 pos : POSITION) : SV_POSITION |
|||
{ |
|||
return UnityObjectToClipPos(pos); |
|||
} |
|||
|
|||
half4 frag() : SV_TARGET |
|||
{ |
|||
return 0; |
|||
} |
|||
ENDCG |
|||
} |
|||
|
|||
// This pass it not used during regular rendering, only for lightmap baking. |
|||
Pass |
|||
{ |
|||
Tags{ "LightMode" = "Meta" } |
|||
|
|||
Cull Off |
|||
|
|||
CGPROGRAM |
|||
#define UNITY_SETUP_BRDF_INPUT SpecularSetup |
|||
#pragma vertex vert_meta |
|||
#pragma fragment frag_meta_ld |
|||
|
|||
#pragma shader_feature _EMISSION |
|||
#pragma shader_feature _SPECGLOSSMAP |
|||
#pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A |
|||
#pragma shader_feature ___ _DETAIL_MULX2 |
|||
#pragma shader_feature EDITOR_VISUALIZATION |
|||
|
|||
#include "UnityStandardMeta.cginc" |
|||
#include "LightweightCore.cginc" |
|||
|
|||
fixed4 frag_meta_ld(v2f_meta i) : SV_Target |
|||
{ |
|||
UnityMetaInput o; |
|||
UNITY_INITIALIZE_OUTPUT(UnityMetaInput, o); |
|||
|
|||
o.Albedo = Albedo(i.uv); |
|||
|
|||
half4 specularColor; |
|||
SpecularGloss(i.uv.xy, 1.0, specularColor); |
|||
o.SpecularColor = specularColor; |
|||
|
|||
#ifdef _EMISSION |
|||
o.Emission += LIGHTWEIGHT_GAMMA_TO_LINEAR(tex2D(_EmissionMap, i.uv).rgb) * _EmissionColor; |
|||
#else |
|||
o.Emission += _EmissionColor; |
|||
#endif |
|||
|
|||
return UnityMetaFragment(o); |
|||
} |
|||
ENDCG |
|||
} |
|||
} |
|||
Fallback "Standard (Specular setup)" |
|||
CustomEditor "LightweightStandardSimpleLightingGUI" |
|||
} |
|
|||
# Unity stuff |
|||
/[Ll]ibrary/ |
|||
/[Tt]emp/ |
|||
/[Oo]bj/ |
|||
/[Bb]uild/ |
|||
/[Bb]uilds/ |
|||
/Assets/AssetStoreTools* |
|||
|
|||
# Autogenerated VS/MD solution and project files |
|||
[Ee]xported[Oo]bj/ |
|||
*.csproj |
|||
*.unityproj |
|||
*.sln* |
|||
*.suo |
|||
*.tmp |
|||
*.user |
|||
*.userprefs |
|||
*.pidb |
|||
*.booproj |
|||
*.svd |
|||
|
|||
# Unity3D generated meta files |
|||
*.pidb.meta |
|||
LICENSE.meta |
|||
PostProcessing.meta |
|||
README.md.meta |
|||
package.json.meta |
|||
|
|||
# Unity3D Generated File On Crash Reports |
|||
sysinfo.txt |
|||
|
|||
# OS generated |
|||
.DS_Store* |
|||
._* |
|||
.Spotlight-V100 |
|||
.Trashes |
|||
Icon? |
|||
ehthumbs.db |
|||
[Tt]humbs.db |
|
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2014-2017, Unity Technologies |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to deal |
|||
in the Software without restriction, including without limitation the rights |
|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in |
|||
all copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
THE SOFTWARE. |
|
|||
fileFormatVersion: 2 |
|||
guid: d92c086ad7fe8fc408422746b8052530 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
部分文件因为文件数量过多而无法显示
撰写
预览
正在加载...
取消
保存
Reference in new issue