You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

317 lines
15 KiB

using System;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UIElements;
using UnityEngine.Rendering.HighDefinition;
using UnityEditor.ShaderGraph;
using UnityEditor.ShaderGraph.Internal;
using static UnityEditor.Rendering.HighDefinition.HDFields;
namespace UnityEditor.Rendering.HighDefinition.ShaderGraph
{
class PBRSkyData : HDTargetData
{
public NormalDropOffSpace normalDropOffSpace = NormalDropOffSpace.Tangent;
public bool groundShading = false;
public bool debugSymbols = false;
}
sealed class PBRSkySubTarget : SubTarget<HDTarget>, IRequiresData<PBRSkyData>
{
class Styles
{
public static GUIContent groundShadingText = new GUIContent("Ground Shading", "When enabled, HDRP uses more controls for the shading of the planet.");
}
public PBRSkySubTarget() => displayName = "Physically Based Sky";
static readonly string kTemplateDirectory = $"{HDUtils.GetHDRenderPipelinePath()}/Editor/Material/PBRSky/ShaderGraph/";
static readonly string kTemplatePath = $"{kTemplateDirectory}/ShaderPass.template";
static readonly GUID kSubTargetSourceCodeGuid = new GUID("f7d870597a428d646b08e894b1d9b741"); // PBRSkySubTarget.cs
static readonly string[] kSharedTemplateDirectories = new string[] { GenerationUtils.GetDefaultSharedTemplateDirectories()[0], kTemplateDirectory };
static readonly string kBSDF = $"{HDUtils.GetCorePath()}/ShaderLibrary/BSDF.hlsl";
static readonly string kTexture = $"{HDUtils.GetCorePath()}/ShaderLibrary/Texture.hlsl";
static readonly string kCommonMaterial = $"{HDUtils.GetCorePath()}/ShaderLibrary/CommonMaterial.hlsl";
static readonly string kFunctions = "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl";
static readonly string kShaderPass = $"{HDUtils.GetHDRenderPipelinePath()}/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl";
static readonly string kPBRSkyRendering = $"{HDUtils.GetHDRenderPipelinePath()}/Runtime/Sky/PhysicallyBasedSky/PhysicallyBasedSkyRendering.hlsl";
static readonly string kPBRSkyEvaluation = $"{HDUtils.GetHDRenderPipelinePath()}/Runtime/Sky/PhysicallyBasedSky/PhysicallyBasedSkyEvaluation.hlsl";
PBRSkyData m_SkyData;
PBRSkyData IRequiresData<PBRSkyData>.data
{
get => m_SkyData;
set => m_SkyData = value;
}
public PBRSkyData skyData
{
get => m_SkyData;
set => m_SkyData = value;
}
public override void Setup(ref TargetSetupContext context)
{
context.AddAssetDependency(kSubTargetSourceCodeGuid, AssetCollection.Flags.SourceDependency);
context.AddSubShader(GenerateSubShader());
}
public override bool IsActive() => true;
public override void GetFields(ref TargetFieldContext context)
{
context.AddField(Fields.GraphPixel);
}
public struct SurfaceDescriptionInputs
{
public static string name = "SurfaceDescriptionInputs";
public static FieldDescriptor renderSunDisk = new FieldDescriptor(name, "renderSunDisk", "", ShaderValueType.Boolean, subscriptOptions: StructFieldOptions.Static);
public static FieldDescriptor radiance = new FieldDescriptor(name, "radiance", "", ShaderValueType.Float3, subscriptOptions: StructFieldOptions.Static);
public static FieldDescriptor intersectAtmosphere = new FieldDescriptor(name, "intersectAtmosphere", "", ShaderValueType.Boolean, subscriptOptions: StructFieldOptions.Static);
public static FieldDescriptor tFrag = new FieldDescriptor(name, "tFrag", "", ShaderValueType.Float, subscriptOptions: StructFieldOptions.Static);
public static FieldDescriptor tGround = new FieldDescriptor(name, "tGround", "", ShaderValueType.Float, subscriptOptions: StructFieldOptions.Static);
public static FieldDescriptor hitGround = new FieldDescriptor(name, "hitGround", "", ShaderValueType.Boolean, subscriptOptions: StructFieldOptions.Static);
}
[GenerateBlocks]
public struct PBRSkyBlocks
{
// Water specific block descriptors
public static BlockFieldDescriptor GroundColor = new BlockFieldDescriptor(kMaterial, "GroundColor", "Ground Color", "", new ColorControl(Color.white, false), ShaderStage.Fragment);
public static BlockFieldDescriptor GroundEmission = new BlockFieldDescriptor(kMaterial, "GroundEmission", "Ground Emission", "", new ColorControl(Color.black, true), ShaderStage.Fragment);
public static BlockFieldDescriptor GroundNormalOS = new BlockFieldDescriptor(kMaterial, "GroundNormalOS", "Ground Normal (Object Space)", "", new NormalControl(CoordinateSpace.Object), ShaderStage.Fragment);
public static BlockFieldDescriptor GroundNormalTS = new BlockFieldDescriptor(kMaterial, "GroundNormalTS", "Ground Normal (Tangent Space)", "", new NormalControl(CoordinateSpace.Tangent), ShaderStage.Fragment);
public static BlockFieldDescriptor GroundNormalWS = new BlockFieldDescriptor(kMaterial, "GroundNormalWS", "Ground Normal (World Space)", "", new NormalControl(CoordinateSpace.World), ShaderStage.Fragment);
public static BlockFieldDescriptor GroundSmoothness = new BlockFieldDescriptor(kMaterial, "GroundSmoothness", "Ground Smoothness", "", new FloatControl(0.0f), ShaderStage.Fragment);
public static BlockFieldDescriptor SpaceColor = new BlockFieldDescriptor(kMaterial, "SpaceColor", "Space Color", "", new ColorControl(Color.black, true), ShaderStage.Fragment);
}
public static KeywordDescriptor LocalSky = new KeywordDescriptor
{
displayName = "Local Sky",
referenceName = "LOCAL_SKY",
type = KeywordType.Boolean,
definition = KeywordDefinition.MultiCompile,
scope = KeywordScope.Global,
stages = KeywordShaderStage.Fragment,
};
public override void GetActiveBlocks(ref TargetActiveBlockContext context)
{
if (skyData.groundShading)
{
context.AddBlock(PBRSkyBlocks.GroundColor);
context.AddBlock(PBRSkyBlocks.GroundEmission);
context.AddBlock(PBRSkyBlocks.GroundNormalOS, skyData.normalDropOffSpace == NormalDropOffSpace.Object);
context.AddBlock(PBRSkyBlocks.GroundNormalTS, skyData.normalDropOffSpace == NormalDropOffSpace.Tangent);
context.AddBlock(PBRSkyBlocks.GroundNormalWS, skyData.normalDropOffSpace == NormalDropOffSpace.World);
context.AddBlock(PBRSkyBlocks.GroundSmoothness);
}
context.AddBlock(PBRSkyBlocks.SpaceColor);
}
void AddProperty<F, T>(ref TargetPropertyGUIContext context, Action onChange, Action<string> registerUndo, GUIContent style, BaseField<F> field, Func<T> getter, Action<T> setter)
{
field.value = (F)(object)getter();
context.AddProperty(style.text, style.tooltip, 0, field, (evt) =>
{
if (Equals(getter(), evt.newValue))
return;
registerUndo(style.text);
setter((T)(object)evt.newValue);
onChange();
});
}
public override void GetPropertiesGUI(ref TargetPropertyGUIContext context, Action onChange, Action<String> registerUndo)
{
AddProperty(ref context, onChange, registerUndo, SurfaceOptionUIBlock.Styles.fragmentNormalSpace,
new EnumField(skyData.normalDropOffSpace), () => skyData.normalDropOffSpace, (v) => { skyData.normalDropOffSpace = v; });
AddProperty(ref context, onChange, registerUndo, Styles.groundShadingText,
new Toggle(), () => skyData.groundShading, (v) => { skyData.groundShading = v; });
if (Unsupported.IsDeveloperMode())
AddProperty(ref context, onChange, registerUndo, AdvancedOptionsPropertyBlock.Styles.debugSymbolsText,
new Toggle(), () => skyData.debugSymbols, (v) => { skyData.debugSymbols = v; });
}
SubShaderDescriptor GenerateSubShader()
{
var result = new SubShaderDescriptor()
{
generatesPreview = false,
passes = new PassCollection(),
pipelineTag = HDRenderPipeline.k_ShaderTagName,
};
result.passes.Add(GeneratePass(true));
result.passes.Add(GeneratePass(false));
return result;
}
public RenderStateCollection GetRenderState(bool cubemap)
{
return new RenderStateCollection()
{
RenderState.ZWrite(ZWrite.Off),
RenderState.ZTest(cubemap ? ZTest.Always : ZTest.LEqual),
RenderState.Cull(Cull.Off),
};
}
public PassDescriptor GeneratePass(bool cubemap)
{
var fullscreenPass = new PassDescriptor
{
// Definition
displayName = "PBR Sky" + (cubemap ? " cubemap" : ""),
referenceName = "SHADERPASS_PBRSKY",
useInPreview = false,
// Template
passTemplatePath = kTemplatePath,
sharedTemplateDirectories = kSharedTemplateDirectories,
// Port Mask
validVertexBlocks = null,
validPixelBlocks = new BlockFieldDescriptor[]
{
PBRSkyBlocks.GroundColor,
PBRSkyBlocks.GroundEmission,
PBRSkyBlocks.GroundNormalOS,
PBRSkyBlocks.GroundNormalTS,
PBRSkyBlocks.GroundNormalWS,
PBRSkyBlocks.GroundSmoothness,
PBRSkyBlocks.SpaceColor,
},
// Fields
structs = new StructCollection
{
new StructDescriptor() {
name = "Attributes",
packFields = false,
fields = new FieldDescriptor[]
{
StructFields.Attributes.vertexID,
StructFields.Attributes.instanceID,
}
},
new StructDescriptor()
{
name = "SurfaceDescriptionInputs",
packFields = false,
populateWithCustomInterpolators = true,
fields = new FieldDescriptor[]
{
StructFields.SurfaceDescriptionInputs.WorldSpaceViewDirection,
StructFields.SurfaceDescriptionInputs.WorldSpacePosition,
StructFields.SurfaceDescriptionInputs.TangentSpaceNormal,
StructFields.SurfaceDescriptionInputs.ObjectSpaceNormal,
StructFields.SurfaceDescriptionInputs.WorldSpaceNormal,
StructFields.SurfaceDescriptionInputs.TimeParameters,
SurfaceDescriptionInputs.renderSunDisk,
SurfaceDescriptionInputs.radiance,
SurfaceDescriptionInputs.intersectAtmosphere,
SurfaceDescriptionInputs.tFrag,
SurfaceDescriptionInputs.tGround,
SurfaceDescriptionInputs.hitGround,
}
},
new StructDescriptor()
{
name = "Varyings",
packFields = true,
populateWithCustomInterpolators = false,
fields = new FieldDescriptor[]
{
StructFields.Varyings.positionCS,
StructFields.Varyings.instanceID,
StructFields.Varyings.stereoTargetEyeIndexAsBlendIdx0,
StructFields.Varyings.stereoTargetEyeIndexAsRTArrayIdx,
}
},
},
fieldDependencies = FieldDependencies.Default,
requiredFields = new FieldCollection
{
StructFields.SurfaceDescriptionInputs.WorldSpaceViewDirection,
StructFields.SurfaceDescriptionInputs.WorldSpacePosition,
StructFields.SurfaceDescriptionInputs.WorldSpaceNormal,
StructFields.Attributes.vertexID,
},
keywords = new KeywordCollection { { LocalSky } },
renderStates = GetRenderState(cubemap),
pragmas = new PragmaCollection
{
{ Pragma.Target(ShaderModel.Target45) },
{ Pragma.Vertex("Vert") },
{ Pragma.Fragment(cubemap ? "FragBaking" : "Frag") },
{ Pragma.EditorSyncCompilation },
},
includes = new IncludeCollection
{
{ kBSDF, IncludeLocation.Pregraph },
{ kTexture, IncludeLocation.Pregraph },
{ kCommonMaterial, IncludeLocation.Pregraph },
{ kFunctions, IncludeLocation.Pregraph },
{ kShaderPass, IncludeLocation.Pregraph },
{ kPBRSkyRendering, IncludeLocation.Pregraph },
{ kPBRSkyEvaluation, IncludeLocation.Pregraph },
{ CoreIncludes.kShaderGraphFunctions, IncludeLocation.Pregraph },
},
};
if (skyData.debugSymbols)
fullscreenPass.pragmas.Add(Pragma.DebugSymbols);
return fullscreenPass;
}
class DoCreatePBRSkyShaderGraph : ProjectWindowCallback.EndNameEditAction
{
public override void Action(int instanceId, string pathName, string resourceFile)
{
var material = GraphicsSettings.GetRenderPipelineSettings<HDRenderPipelineRuntimeMaterials>().pbrSkyMaterial;
AssetDatabase.CopyAsset(AssetDatabase.GetAssetPath(material), pathName);
}
}
[MenuItem("Assets/Create/Shader Graph/HDRP/PBR Sky Shader Graph", priority = CoreUtils.Priorities.assetsCreateShaderMenuPriority + 7)]
static void CreatePBRSkyGraph()
{
/*
// Create an empty graph from scratch
var target = (HDTarget)Activator.CreateInstance(typeof(HDTarget));
target.TrySetActiveSubTarget(typeof(PBRSkySubTarget));
var blockDescriptors = new[]
{
PBRSkyBlocks.SpaceColor,
};
GraphUtil.CreateNewGraphWithOutputs(new[] { target }, blockDescriptors);
*/
// Copy the default graph from the package
ProjectWindowUtil.StartNameEditingIfProjectWindowExists(0, ScriptableObject.CreateInstance<DoCreatePBRSkyShaderGraph>(), "PBR Sky Shader Graph.shadergraph", ShaderGraphImporter.GetIcon(), null);
}
}
}