|
|
|
|
|
|
}, |
|
|
|
}; |
|
|
|
|
|
|
|
private static string GetVariantDefines(PBRMasterNode masterNode) |
|
|
|
private static HashSet<string> GetActiveFieldsFromMasterNode(INode iMasterNode, Pass pass) |
|
|
|
ShaderGenerator defines = new ShaderGenerator(); |
|
|
|
HashSet<string> activeFields = new HashSet<string>(); |
|
|
|
// TODO:
|
|
|
|
// _MATERIAL_FEATURE_SUBSURFACE_SCATTERING
|
|
|
|
// _MATERIAL_FEATURE_TRANSMISSION
|
|
|
|
// _MATERIAL_FEATURE_ANISOTROPY
|
|
|
|
// _MATERIAL_FEATURE_CLEAR_COAT
|
|
|
|
// _MATERIAL_FEATURE_IRIDESCENCE
|
|
|
|
PBRMasterNode masterNode = iMasterNode as PBRMasterNode; |
|
|
|
if (masterNode == null) |
|
|
|
{ |
|
|
|
return activeFields; |
|
|
|
} |
|
|
|
|
|
|
|
if (masterNode.twoSided.isOn) |
|
|
|
{ |
|
|
|
activeFields.Add("DoubleSided"); |
|
|
|
if (pass.ShaderPassName != "SHADERPASS_VELOCITY") // HACK to get around lack of a good interpolator dependency system
|
|
|
|
{ // we need to be able to build interpolators using multiple input structs
|
|
|
|
// also: should only require isFrontFace if Normals are required...
|
|
|
|
activeFields.Add("DoubleSided.Mirror"); // TODO: change this depending on what kind of normal flip you want..
|
|
|
|
activeFields.Add("FragInputs.isFrontFace"); // will need this for determining normal flip mode
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
switch (masterNode.model) |
|
|
|
{ |
|
|
|
|
|
|
defines.AddShaderChunk("#define _MATERIAL_FEATURE_SPECULAR_COLOR 1", true); |
|
|
|
activeFields.Add("Material.SpecularColor"); |
|
|
|
break; |
|
|
|
default: |
|
|
|
// TODO: error!
|
|
|
|
|
|
|
// #pragma shader_feature _ALPHATEST_ON
|
|
|
|
defines.AddShaderChunk("#define _ALPHATEST_ON 1", true); |
|
|
|
activeFields.Add("AlphaTest"); |
|
|
|
} |
|
|
|
|
|
|
|
// if (kTesselationMode != TessellationMode.None)
|
|
|
|
|
|
|
// #pragma shader_feature _ _MAPPING_PLANAR _MAPPING_TRIPLANAR // MOVE to a node
|
|
|
|
// #pragma shader_feature _NORMALMAP_TANGENT_SPACE
|
|
|
|
// #pragma shader_feature _ _REQUIRE_UV2 _REQUIRE_UV3
|
|
|
|
//
|
|
|
|
// #pragma shader_feature _NORMALMAP
|
|
|
|
if (masterNode.IsSlotConnected(PBRMasterNode.NormalSlotId)) |
|
|
|
{ |
|
|
|
defines.AddShaderChunk("#define _NORMALMAP 1", true); |
|
|
|
} |
|
|
|
|
|
|
|
// #pragma shader_feature _MASKMAP
|
|
|
|
// #pragma shader_feature _BENTNORMALMAP
|
|
|
|
|
|
|
if (masterNode.surfaceType != SurfaceType.Opaque) |
|
|
|
{ |
|
|
|
// transparent-only defines
|
|
|
|
defines.AddShaderChunk("#define _SURFACE_TYPE_TRANSPARENT 1", true); |
|
|
|
activeFields.Add("SurfaceType.Transparent"); |
|
|
|
defines.AddShaderChunk("#define _BLENDMODE_ALPHA 1", true); |
|
|
|
activeFields.Add("BlendMode.Alpha"); |
|
|
|
defines.AddShaderChunk("#define _BLENDMODE_ADD 1", true); |
|
|
|
activeFields.Add("BlendMode.Add"); |
|
|
|
} |
|
|
|
// else if (masterNode.alphaMode == PBRMasterNode.AlphaMode.PremultiplyAlpha) // TODO
|
|
|
|
// {
|
|
|
|
|
|
|
// opaque-only defines
|
|
|
|
} |
|
|
|
|
|
|
|
// MaterialId are used as shader feature to allow compiler to optimize properly
|
|
|
|
// Note _MATID_STANDARD is not define as there is always the default case "_". We assign default as _MATID_STANDARD, so we never test _MATID_STANDARD
|
|
|
|
// #pragma shader_feature _ _MATID_SSS _MATID_ANISO _MATID_SPECULAR _MATID_CLEARCOAT
|
|
|
|
|
|
|
|
return defines.GetShaderString(2); |
|
|
|
return activeFields; |
|
|
|
private static bool GenerateShaderPassLit(PBRMasterNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions, ShaderGenerator result, List<string> sourceAssetDependencyPaths) |
|
|
|
private static bool GenerateShaderPassLit(AbstractMaterialNode masterNode, Pass pass, GenerationMode mode, SurfaceMaterialOptions materialOptions, ShaderGenerator result, List<string> sourceAssetDependencyPaths) |
|
|
|
{ |
|
|
|
var templateLocation = Path.Combine(Path.Combine(Path.Combine(HDEditorUtils.GetHDRenderPipelinePath(), "Editor"), "ShaderGraph"), pass.TemplateName); |
|
|
|
if (!File.Exists(templateLocation)) |
|
|
|
|
|
|
sourceAssetDependencyPaths.Add(templateLocation); |
|
|
|
|
|
|
|
// grab all of the active nodes (for pixel and vertex graphs)
|
|
|
|
var vertexNodes = ListPool<AbstractMaterialNode>.Get(); |
|
|
|
var vertexNodes = ListPool<INode>.Get(); |
|
|
|
NodeUtils.DepthFirstCollectNodesFromNode(vertexNodes, masterNode, NodeUtils.IncludeSelf.Include, pass.VertexShaderSlots); |
|
|
|
|
|
|
|
var pixelNodes = ListPool<INode>.Get(); |
|
|
|
|
|
|
ShaderStringBuilder pixelGraphOutputs = new ShaderStringBuilder(); |
|
|
|
|
|
|
|
// dependency tracker -- set of active fields
|
|
|
|
HashSet<string> activeFields = new HashSet<string>(); |
|
|
|
HashSet<string> activeFields = GetActiveFieldsFromMasterNode(masterNode, pass); |
|
|
|
|
|
|
|
// build initial requirements
|
|
|
|
HDRPShaderStructs.AddActiveFieldsFromPixelGraphRequirements(activeFields, pixelRequirements); |
|
|
|
|
|
|
var colorMaskCode = new ShaderStringBuilder(); |
|
|
|
HDSubShaderUtilities.BuildRenderStatesFromPassAndMaterialOptions(pass, materialOptions, blendCode, cullCode, zTestCode, zWriteCode, stencilCode, colorMaskCode); |
|
|
|
|
|
|
|
if (masterNode.twoSided.isOn) |
|
|
|
{ |
|
|
|
activeFields.Add("DoubleSided"); |
|
|
|
if (pass.ShaderPassName != "SHADERPASS_VELOCITY") // HACK to get around lack of a good interpolator dependency system
|
|
|
|
{ // we need to be able to build interpolators using multiple input structs
|
|
|
|
// also: should only require isFrontFace if Normals are required...
|
|
|
|
activeFields.Add("DoubleSided.Mirror"); // TODO: change this depending on what kind of normal flip you want..
|
|
|
|
activeFields.Add("FragInputs.isFrontFace"); // will need this for determining normal flip mode
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
HDRPShaderStructs.AddRequiredFields(pass.RequiredFields, activeFields); |
|
|
|
|
|
|
|
// apply dependencies to the active fields, and build interpolators (TODO: split this function)
|
|
|
|
|
|
|
namedFragments.Add("${Stencil}", stencilCode.ToString()); |
|
|
|
namedFragments.Add("${ColorMask}", colorMaskCode.ToString()); |
|
|
|
namedFragments.Add("${LOD}", materialOptions.lod.ToString()); |
|
|
|
namedFragments.Add("${VariantDefines}", GetVariantDefines(masterNode)); |
|
|
|
|
|
|
|
// process the template to generate the shader code for this pass TODO: could make this a shared function
|
|
|
|
string[] templateLines = File.ReadAllLines(templateLocation); |
|
|
|