浏览代码

Tidy up transforms so that graphs have a 'prefered' space to work in.

/main
Tim Cooper 7 年前
当前提交
66cf728c
共有 15 个文件被更改,包括 337 次插入231 次删除
  1. 2
      MaterialGraphProject/Assets/NewNodes/Editor/Keep/ParallaxNode.cs
  2. 2
      MaterialGraphProject/Assets/NewNodes/Editor/Kill/MultiLayerParallaxNode.cs
  3. 84
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/AbstractMaterialGraph.cs
  4. 33
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Interfaces/NeededCoordinateSpace.cs
  5. 6
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/LightweightPipeline/AbstractLightweightMasterNode.cs
  6. 4
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/LightweightPipeline/LightweightMetallicMasterNode.cs
  7. 40
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/HLSLNode.cs
  8. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Geometry/BitangentNode.cs
  9. 4
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Geometry/NormalNode.cs
  10. 6
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs
  11. 6
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Geometry/WorldSpacePositionNode.cs
  12. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Geometry/WorldSpaceTangentNode.cs
  13. 24
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/SubGraph/LayeredShaderGraph.cs
  14. 341
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Util/ShaderGenerator.cs
  15. 12
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Templates/lightweightSubshaderPBR.template

2
MaterialGraphProject/Assets/NewNodes/Editor/Keep/ParallaxNode.cs


return GetFunctionName() + " (" +
inputValue1 + ", " +
channel.GetUVName() + ", " +
ShaderGeneratorNames.TangentSpaceViewDirection + ")";
CoordinateSpace.View.ToVariableName(InterpolatorType.Tangent) + ")";
}
public bool RequiresMeshUV(UVChannel channel)

2
MaterialGraphProject/Assets/NewNodes/Editor/Kill/MultiLayerParallaxNode.cs


layerCountValue + ", " +
texValue + ", " +
UVChannel.uv0.GetUVName() + ", " +
ShaderGeneratorNames.TangentSpaceViewDirection + ")";
CoordinateSpace.View.ToVariableName(InterpolatorType.Tangent) + ")";
}
public bool RequiresMeshUV(UVChannel channel)

84
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Graphs/AbstractMaterialGraph.cs


return reqs;
}
protected static void GenerateSpaceTranslationSurfaceInputs(
NeededCoordinateSpace neededSpaces,
ShaderGenerator surfaceInputs,
string objectSpaceName,
string viewSpaceName,
string worldSpaceName,
string tangentSpaceName)
{
if ((neededSpaces & NeededCoordinateSpace.Object) > 0)
surfaceInputs.AddShaderChunk(string.Format("float3 {0};", objectSpaceName), false);
if ((neededSpaces & NeededCoordinateSpace.World) > 0)
surfaceInputs.AddShaderChunk(string.Format("float3 {0};", worldSpaceName), false);
if ((neededSpaces & NeededCoordinateSpace.View) > 0)
surfaceInputs.AddShaderChunk(string.Format("float3 {0};", viewSpaceName), false);
if ((neededSpaces & NeededCoordinateSpace.Tangent) > 0)
surfaceInputs.AddShaderChunk(string.Format("float3 {0};", tangentSpaceName), false);
}
public string GetPreviewShader(AbstractMaterialNode node, out PreviewMode previewMode)
{

surfaceDescriptionFunction.Indent();
if ((requirements.requiresNormal & NeededCoordinateSpace.Object) > 0)
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ObjectSpaceNormal), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Object.ToVariableName(InterpolatorType.Normal)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ViewSpaceNormal), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.View.ToVariableName(InterpolatorType.Normal)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.WorldSpaceNormal), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.World.ToVariableName(InterpolatorType.Normal)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.TangentSpaceNormal), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Tangent.ToVariableName(InterpolatorType.Normal)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ObjectSpaceTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Object.ToVariableName(InterpolatorType.Tangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ViewSpaceTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.View.ToVariableName(InterpolatorType.Tangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.WorldSpaceTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.World.ToVariableName(InterpolatorType.Tangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.TangentSpaceTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Tangent.ToVariableName(InterpolatorType.Tangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ObjectSpaceBiTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Object.ToVariableName(InterpolatorType.BiTangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ViewSpaceBiTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.View.ToVariableName(InterpolatorType.BiTangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.WorldSpaceBiTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.World.ToVariableName(InterpolatorType.BiTangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.TangentSpaceBiTangent), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Tangent.ToVariableName(InterpolatorType.BiTangent)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ObjectSpaceViewDirection), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Object.ToVariableName(InterpolatorType.ViewDirection)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ViewSpaceViewDirection), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.View.ToVariableName(InterpolatorType.ViewDirection)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.WorldSpaceViewDirection), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.World.ToVariableName(InterpolatorType.ViewDirection)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.TangentSpaceViewDirection), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Tangent.ToVariableName(InterpolatorType.ViewDirection)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ObjectSpacePosition), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Object.ToVariableName(InterpolatorType.Position)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.ViewSpacePosition), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.View.ToVariableName(InterpolatorType.Position)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.WorldSpacePosition), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.World.ToVariableName(InterpolatorType.Position)), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", ShaderGeneratorNames.TangentSpacePosition), false);
surfaceDescriptionFunction.AddShaderChunk(string.Format("float3 {0} = IN.{0};", CoordinateSpace.Tangent.ToVariableName(InterpolatorType.Position)), false);
if (requirements.requiresScreenPosition)
surfaceDescriptionFunction.AddShaderChunk(string.Format("float4 {0} = IN.{0};", ShaderGeneratorNames.ScreenPosition), false);

surfaceInputs.AddShaderChunk("struct SurfaceInputs{", false);
surfaceInputs.Indent();
var requirements = GetRequierments(node);
GenerateSpaceTranslationSurfaceInputs(requirements.requiresNormal, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceNormal, ShaderGeneratorNames.ViewSpaceNormal,
ShaderGeneratorNames.WorldSpaceNormal, ShaderGeneratorNames.TangentSpaceNormal);
GenerateSpaceTranslationSurfaceInputs(requirements.requiresTangent, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceTangent, ShaderGeneratorNames.ViewSpaceTangent,
ShaderGeneratorNames.WorldSpaceTangent, ShaderGeneratorNames.TangentSpaceTangent);
GenerateSpaceTranslationSurfaceInputs(requirements.requiresBitangent, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceBiTangent, ShaderGeneratorNames.ViewSpaceBiTangent,
ShaderGeneratorNames.WorldSpaceBiTangent, ShaderGeneratorNames.TangentSpaceBiTangent);
GenerateSpaceTranslationSurfaceInputs(requirements.requiresViewDir, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceViewDirection, ShaderGeneratorNames.ViewSpaceViewDirection,
ShaderGeneratorNames.WorldSpaceViewDirection, ShaderGeneratorNames.TangentSpaceViewDirection);
GenerateSpaceTranslationSurfaceInputs(requirements.requiresPosition, surfaceInputs,
ShaderGeneratorNames.ObjectSpacePosition, ShaderGeneratorNames.ViewSpacePosition,
ShaderGeneratorNames.WorldSpacePosition, ShaderGeneratorNames.TangentSpacePosition);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresNormal, InterpolatorType.Normal, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresTangent, InterpolatorType.Tangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresBitangent, InterpolatorType.BiTangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresPosition, InterpolatorType.Position, surfaceInputs);
if (requirements.requiresVertexColor)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.VertexColor), false);

33
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Interfaces/NeededCoordinateSpace.cs


public enum NeededCoordinateSpace
{
None = 0,
Object = 1<<0,
View = 1<<1,
World = 1<<2,
Tangent = 1<<3
Object = 1 << 0,
View = 1 << 1,
World = 1 << 2,
Tangent = 1 << 3
}
public enum CoordinateSpace
{
Object,
View,
World,
Tangent
}
public enum InterpolatorType
{
Normal,
BiTangent,
Tangent,
ViewDirection,
Position
}
public static class CoordinateSpaceNameExtensions
{
public static string ToVariableName(this CoordinateSpace space, InterpolatorType type)
{
return string.Format("{0}Space{1}", space, type);
}
}
}

6
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/LightweightPipeline/AbstractLightweightMasterNode.cs


{
public abstract class AbstractLightweightMasterNode : MasterNode
{
private const int kMaxInterpolators = 8;
protected abstract IEnumerable<int> masterSurfaceInputs { get; }
protected abstract IEnumerable<int> masterVertexInputs { get; }
protected abstract string GetTemplateName();

ShaderGenerator.GenerateStandardTransforms(
GetInterpolatorStartIndex(),
10,
GetNodeSpecificRequirements());
GetNodeSpecificRequirements(),
CoordinateSpace.World);
ShaderGenerator defines = new ShaderGenerator();
ShaderGenerator surfaceOutputRemap = new ShaderGenerator();

4
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/LightweightPipeline/LightweightMetallicMasterNode.cs


AddSlot(new Vector3MaterialSlot(NormalSlotId, NormalSlotName, NormalSlotName, SlotType.Input, new Vector3(0,0,1), ShaderStage.Fragment));
AddSlot(new Vector3MaterialSlot(EmissionSlotId, EmissionSlotName, EmissionSlotName, SlotType.Input, Vector3.zero, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(MetallicSlotId, MetallicSlotName, MetallicSlotName, SlotType.Input,0, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(SmoothnessSlotId, SmoothnessSlotName, SmoothnessSlotName, SlotType.Input, 0, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(OcclusionSlotId, OcclusionSlotName, OcclusionSlotName, SlotType.Input, 0, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(SmoothnessSlotId, SmoothnessSlotName, SmoothnessSlotName, SlotType.Input, 0.5f, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(OcclusionSlotId, OcclusionSlotName, OcclusionSlotName, SlotType.Input, 1f, ShaderStage.Fragment));
AddSlot(new Vector1MaterialSlot(AlphaSlotId, AlphaSlotName, AlphaSlotName, SlotType.Input, 0, ShaderStage.Fragment));
// clear out slot names that do not match the slots

40
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/HLSLNode.cs


case Binding.None:
return "ERROR!";
case Binding.ObjectSpaceNormal:
return ShaderGeneratorNames.ObjectSpaceNormal;
return CoordinateSpace.Object.ToVariableName(InterpolatorType.Normal);
return ShaderGeneratorNames.ObjectSpaceTangent;
return CoordinateSpace.Object.ToVariableName(InterpolatorType.Tangent);
return ShaderGeneratorNames.ObjectSpaceBiTangent;
return CoordinateSpace.Object.ToVariableName(InterpolatorType.BiTangent);
return ShaderGeneratorNames.ObjectSpacePosition;
return CoordinateSpace.Object.ToVariableName(InterpolatorType.Position);
return ShaderGeneratorNames.ViewSpaceNormal;
return CoordinateSpace.View.ToVariableName(InterpolatorType.Normal);
return ShaderGeneratorNames.ViewSpaceTangent;
return CoordinateSpace.View.ToVariableName(InterpolatorType.Tangent);
return ShaderGeneratorNames.ViewSpaceBiTangent;
return CoordinateSpace.View.ToVariableName(InterpolatorType.BiTangent);
return ShaderGeneratorNames.ViewSpacePosition;
return CoordinateSpace.View.ToVariableName(InterpolatorType.Position);
return ShaderGeneratorNames.WorldSpaceNormal;
return CoordinateSpace.World.ToVariableName(InterpolatorType.Normal);
return ShaderGeneratorNames.WorldSpaceTangent;
return CoordinateSpace.World.ToVariableName(InterpolatorType.Tangent);
return ShaderGeneratorNames.WorldSpaceBiTangent;
return CoordinateSpace.World.ToVariableName(InterpolatorType.BiTangent);
return ShaderGeneratorNames.WorldSpacePosition;
return CoordinateSpace.World.ToVariableName(InterpolatorType.Position);
return ShaderGeneratorNames.TangentSpaceNormal;
return CoordinateSpace.Tangent.ToVariableName(InterpolatorType.Normal);
return ShaderGeneratorNames.TangentSpaceTangent;
return CoordinateSpace.Tangent.ToVariableName(InterpolatorType.Tangent);
return ShaderGeneratorNames.TangentSpaceBiTangent;
return CoordinateSpace.Tangent.ToVariableName(InterpolatorType.BiTangent);
return ShaderGeneratorNames.TangentSpacePosition;
return CoordinateSpace.Tangent.ToVariableName(InterpolatorType.Position);
case Binding.MeshUV0:
return UVChannel.uv0.GetUVName();
case Binding.MeshUV1:

case Binding.ScreenPosition:
return ShaderGeneratorNames.ScreenPosition;
case Binding.ObjectSpaceViewDirection:
return ShaderGeneratorNames.ObjectSpaceViewDirection;
return CoordinateSpace.Object.ToVariableName(InterpolatorType.ViewDirection);
return ShaderGeneratorNames.ViewSpaceViewDirection;
return CoordinateSpace.View.ToVariableName(InterpolatorType.ViewDirection);
return ShaderGeneratorNames.WorldSpaceViewDirection;
return CoordinateSpace.View.ToVariableName(InterpolatorType.ViewDirection);
return ShaderGeneratorNames.TangentSpaceViewDirection;
return CoordinateSpace.View.ToVariableName(InterpolatorType.ViewDirection);
case Binding.VertexColor:
return ShaderGeneratorNames.VertexColor;
default:

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Geometry/BitangentNode.cs


public override string GetVariableNameForSlot(int slotId)
{
return ShaderGeneratorNames.WorldSpaceBiTangent;
return CoordinateSpace.World.ToVariableName(InterpolatorType.BiTangent);
}
public NeededCoordinateSpace RequiresBitangent()

4
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Geometry/NormalNode.cs


public override string GetVariableNameForSlot(int slotId)
{
return ShaderGeneratorNames.ObjectSpaceNormal;
return CoordinateSpace.World.ToVariableName(InterpolatorType.Normal);
return NeededCoordinateSpace.Object;
return NeededCoordinateSpace.World;
}
}
}

6
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Geometry/ViewDirectionNode.cs


{
AddSlot(new Vector3MaterialSlot(
kOutputSlotId,
ShaderGeneratorNames.WorldSpaceViewDirection,
ShaderGeneratorNames.WorldSpaceViewDirection,
CoordinateSpace.World.ToVariableName(InterpolatorType.ViewDirection),
CoordinateSpace.World.ToVariableName(InterpolatorType.ViewDirection),
SlotType.Output,
Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });

{
return ShaderGeneratorNames.WorldSpaceViewDirection;
return CoordinateSpace.World.ToVariableName(InterpolatorType.ViewDirection);
}
public NeededCoordinateSpace RequiresViewDirection()

6
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Geometry/WorldSpacePositionNode.cs


{
AddSlot(new Vector3MaterialSlot(
kOutputSlotId,
ShaderGeneratorNames.WorldSpacePosition,
ShaderGeneratorNames.WorldSpacePosition,
CoordinateSpace.World.ToVariableName(InterpolatorType.Position),
CoordinateSpace.World.ToVariableName(InterpolatorType.Position),
SlotType.Output,
Vector3.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });

{
return ShaderGeneratorNames.WorldSpacePosition;
return CoordinateSpace.World.ToVariableName(InterpolatorType.Position);
}
public NeededCoordinateSpace RequiresPosition()

2
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Nodes/Input/Geometry/WorldSpaceTangentNode.cs


public override string GetVariableNameForSlot(int slotId)
{
return ShaderGeneratorNames.ObjectSpaceTangent;
return CoordinateSpace.World.ToVariableName(InterpolatorType.Tangent);
}
public NeededCoordinateSpace RequiresTangent()

24
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/SubGraph/LayeredShaderGraph.cs


requirements = requirements.Union(GetRequierments(outputNode));
GenerateSpaceTranslationSurfaceInputs(requirements.requiresNormal, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceNormal, ShaderGeneratorNames.ViewSpaceNormal,
ShaderGeneratorNames.WorldSpaceNormal, ShaderGeneratorNames.TangentSpaceNormal);
GenerateSpaceTranslationSurfaceInputs(requirements.requiresTangent, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceTangent, ShaderGeneratorNames.ViewSpaceTangent,
ShaderGeneratorNames.WorldSpaceTangent, ShaderGeneratorNames.TangentSpaceTangent);
GenerateSpaceTranslationSurfaceInputs(requirements.requiresBitangent, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceBiTangent, ShaderGeneratorNames.ViewSpaceBiTangent,
ShaderGeneratorNames.WorldSpaceBiTangent, ShaderGeneratorNames.TangentSpaceBiTangent);
GenerateSpaceTranslationSurfaceInputs(requirements.requiresViewDir, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceViewDirection, ShaderGeneratorNames.ViewSpaceViewDirection,
ShaderGeneratorNames.WorldSpaceViewDirection, ShaderGeneratorNames.TangentSpaceViewDirection);
GenerateSpaceTranslationSurfaceInputs(requirements.requiresPosition, surfaceInputs,
ShaderGeneratorNames.ObjectSpacePosition, ShaderGeneratorNames.ViewSpacePosition,
ShaderGeneratorNames.WorldSpacePosition, ShaderGeneratorNames.TangentSpacePosition);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresNormal, InterpolatorType.Normal, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresTangent, InterpolatorType.Tangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresBitangent, InterpolatorType.BiTangent, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresViewDir, InterpolatorType.ViewDirection, surfaceInputs);
ShaderGenerator.GenerateSpaceTranslationSurfaceInputs(requirements.requiresPosition, InterpolatorType.Position, surfaceInputs);
if (requirements.requiresVertexColor)
surfaceInputs.AddShaderChunk(string.Format("float4 {0};", ShaderGeneratorNames.VertexColor), false);

341
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Data/Util/ShaderGenerator.cs


{
private static string[] UV = {"uv0", "uv1", "uv2", "uv3"};
public static int UVCount = 4;
public const string ObjectSpaceNormal = "objectSpaceNormal";
public const string ViewSpaceNormal = "viewSpaceNormal";
public const string WorldSpaceNormal = "worldSpaceNormal";
public const string TangentSpaceNormal = "tangentSpaceNormal";
public const string ObjectSpaceBiTangent = "objectSpaceBiTangent";
public const string ViewSpaceBiTangent = "viewSpaceBiTangent";
public const string WorldSpaceBiTangent = "worldSpaceBiTangent";
public const string TangentSpaceBiTangent = "TangentSpaceBitangent";
public const string ObjectSpaceTangent = "objectSpaceTangent";
public const string ViewSpaceTangent = "viewSpaceTangent";
public const string WorldSpaceTangent = "worldSpaceTangent";
public const string TangentSpaceTangent = "tangentSpaceTangent";
public const string ObjectSpaceViewDirection = "objectSpaceViewDirection";
public const string ViewSpaceViewDirection = "viewSpaceViewDirection";
public const string WorldSpaceViewDirection = "worldSpaceViewDirection";
public const string TangentSpaceViewDirection = "tangentSpaceViewDirection";
public const string ObjectSpacePosition = "objectSpacePosition";
public const string ViewSpacePosition = "viewSpaceVPosition";
public const string WorldSpacePosition = "worldSpacePosition";
public const string TangentSpacePosition = "tangentSpacePosition";
public const string ScreenPosition = "screenPosition";
public const string VertexColor = "vertexColor";

get { return m_ShaderChunks.Count; }
}
public enum InputType
{
Position,
Vector,
Normal
}
public static string EmitTransform(string[] matrices, string[] invMatrices, string variable, bool isAffine, bool inverseTranspose)
{
if (inverseTranspose)
matrices = invMatrices;
if (isAffine)
{
variable = string.Format("float4({0},1.0)", variable);
}
foreach (var m in matrices)
{
var matrix = m;
if (!isAffine)
{
matrix = "(float3x3)" + matrix;
}
variable = inverseTranspose
? string.Format("mul({1},{0})", matrix, variable)
: string.Format("mul({0},{1})", matrix, variable);
}
return variable;
}
public static string EmitTransform(string matrix, string invMatrix, string variable, bool isAffine, bool inverseTranspose)
{
return EmitTransform(new[] { matrix }, new[] { invMatrix }, variable, isAffine, inverseTranspose);
}
public static string ConvertBetweenSpace(
string variable,
CoordinateSpace from,
CoordinateSpace to,
InputType inputType,
CoordinateSpace tangentMatrixSpace = CoordinateSpace.Object)
{
if (from == to)
{
// nothing to do
return variable;
}
bool isNormal = false;
bool affine = (inputType == InputType.Position);
if (inputType == InputType.Normal)
isNormal = true;
if (from == CoordinateSpace.Tangent)
{
// if converting from tangent space, reuse the object space code for now
from = tangentMatrixSpace;
variable = EmitTransform("tangentSpaceTransform", "transpose(tangentSpaceTransform)", variable, affine, !isNormal);
if (to == tangentMatrixSpace)
{
return variable;
}
}
switch (from)
{
case CoordinateSpace.Object:
{
switch (to)
{
case CoordinateSpace.View:
return EmitTransform(new string[] { "unity_ObjectToWorld", "UNITY_MATRIX_V" }
, new string[] { "UNITY_MATRIX_I_V", "unity_WorldToObject" }
, variable, affine, isNormal);
case CoordinateSpace.World:
return EmitTransform("unity_ObjectToWorld", "unity_WorldToObject", variable, affine, isNormal);
case CoordinateSpace.Tangent:
return EmitTransform("tangentSpaceTransform", "transpose(tangentSpaceTransform)", variable, affine, isNormal);
default:
throw new ArgumentOutOfRangeException("from", @from, null);
}
}
case CoordinateSpace.View:
{
switch (to)
{
case CoordinateSpace.Object:
return EmitTransform(new string[] { "UNITY_MATRIX_I_V", "unity_WorldToObject" }
, new string[] { "unity_ObjectToWorld", "UNITY_MATRIX_V" }
, variable, affine, isNormal);
case CoordinateSpace.World:
return EmitTransform("UNITY_MATRIX_I_V", "UNITY_MATRIX_V", variable, affine, isNormal);
case CoordinateSpace.Tangent:
return EmitTransform(new string[] { "UNITY_MATRIX_I_V", "unity_WorldToObject", "tangentSpaceTransform" },
new string[] { "transpose(tangentSpaceTransform)", "unity_ObjectToWorld", "UNITY_MATRIX_V" },
variable, affine, isNormal);
default:
throw new ArgumentOutOfRangeException("from", @from, null);
}
}
case CoordinateSpace.World:
{
switch (to)
{
case CoordinateSpace.Object:
return EmitTransform("unity_WorldToObject", "unity_ObjectToWorld", variable, affine, isNormal);
case CoordinateSpace.View:
return EmitTransform("UNITY_MATRIX_V", "UNITY_MATRIX_I_V", variable, affine, isNormal);
case CoordinateSpace.Tangent:
return EmitTransform(new string[] { "unity_WorldToObject", "tangentSpaceTransform" },
new string[] { "transpose(tangentSpaceTransform)", "unity_ObjectToWorld" },
variable, affine, isNormal);
default:
throw new ArgumentOutOfRangeException("from", @from, null);
}
}
default:
throw new ArgumentOutOfRangeException("from", @from, null);
}
}
public static void GenerateSpaceTranslationSurfaceInputs(
NeededCoordinateSpace neededSpaces,
InterpolatorType interpolatorType,
ShaderGenerator surfaceInputs,
string toReplace = "float3 {0};")
{
if ((neededSpaces & NeededCoordinateSpace.Object) > 0)
surfaceInputs.AddShaderChunk(string.Format(toReplace, CoordinateSpace.Object.ToVariableName(interpolatorType)), false);
if ((neededSpaces & NeededCoordinateSpace.World) > 0)
surfaceInputs.AddShaderChunk(string.Format(toReplace, CoordinateSpace.World.ToVariableName(interpolatorType)), false);
if ((neededSpaces & NeededCoordinateSpace.View) > 0)
surfaceInputs.AddShaderChunk(string.Format(toReplace, CoordinateSpace.View.ToVariableName(interpolatorType)), false);
if ((neededSpaces & NeededCoordinateSpace.Tangent) > 0)
surfaceInputs.AddShaderChunk(string.Format(toReplace, CoordinateSpace.Tangent.ToVariableName(interpolatorType)), false);
}
int maxInterpolators,
ShaderGraphRequirements externalGraphRequiements,
ShaderGraphRequirements modelRequiements)
ShaderGraphRequirements graphRequiements,
ShaderGraphRequirements modelRequiements,
CoordinateSpace preferedCoordinateSpace)
if (preferedCoordinateSpace == CoordinateSpace.Tangent)
preferedCoordinateSpace = CoordinateSpace.World;
var combinedRequierments = graphRequiements.Union(modelRequiements);
var combinedRequierments = externalGraphRequiements.Union(modelRequiements);
int interpolatorIndex = interpolatorStartIndex;
interpolators.AddShaderChunk(string.Format("float3 {0} : NORMAL;", ShaderGeneratorNames.ObjectSpaceNormal), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = v.normal;", ShaderGeneratorNames.ObjectSpaceNormal), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = normalize(IN.{0});", ShaderGeneratorNames.ObjectSpaceNormal), false);
var name = preferedCoordinateSpace.ToVariableName(InterpolatorType.Normal);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = {1};", name, ConvertBetweenSpace("v.normal", CoordinateSpace.Object, preferedCoordinateSpace, InputType.Normal)), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = normalize(IN.{0});", name), false);
interpolatorIndex++;
interpolators.AddShaderChunk(string.Format("float4 {0} : TANGENT;", ShaderGeneratorNames.ObjectSpaceTangent), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = v.tangent;", ShaderGeneratorNames.ObjectSpaceTangent), false);
pixelShader.AddShaderChunk(string.Format("float4 {0} = IN.{0};", ShaderGeneratorNames.ObjectSpaceTangent), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = normalize(cross(normalize(IN.{1}), normalize(IN.{2}.xyz)) * IN.{2}.w);",
ShaderGeneratorNames.ObjectSpaceBiTangent,
ShaderGeneratorNames.ObjectSpaceNormal,
ShaderGeneratorNames.ObjectSpaceTangent), false);
var name = preferedCoordinateSpace.ToVariableName(InterpolatorType.Tangent);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = {1};", name, ConvertBetweenSpace("v.tangent", CoordinateSpace.Object, preferedCoordinateSpace, InputType.Vector)), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = IN.{0};", name), false);
interpolatorIndex++;
}
if (combinedRequierments.requiresBitangent > 0)
{
var name = preferedCoordinateSpace.ToVariableName(InterpolatorType.BiTangent);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = normalize(cross(o.{1}, o.{2}.xyz) * {3});",
name,
preferedCoordinateSpace.ToVariableName(InterpolatorType.Normal),
preferedCoordinateSpace.ToVariableName(InterpolatorType.Tangent),
"v.tangent.w"), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = IN.{0};", name), false);
interpolatorIndex++;
int interpolatorIndex = interpolatorStartIndex;
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", ShaderGeneratorNames.ObjectSpaceViewDirection, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = ObjSpaceViewDir(v.vertex);", ShaderGeneratorNames.ObjectSpaceViewDirection), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = normalize(IN.{0});", ShaderGeneratorNames.ObjectSpaceViewDirection), false);
var name = preferedCoordinateSpace.ToVariableName(InterpolatorType.ViewDirection);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = {1};", name, ConvertBetweenSpace("ObjSpaceViewDir(v.vertex)", CoordinateSpace.Object, preferedCoordinateSpace, InputType.Vector)), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = normalize(IN.{0});", name), false);
interpolators.AddShaderChunk(string.Format("float4 {0} : TEXCOORD{1};", ShaderGeneratorNames.ObjectSpacePosition, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = v.vertex;", ShaderGeneratorNames.ObjectSpacePosition), false);
pixelShader.AddShaderChunk(string.Format("float4 {0} = IN.{0};", ShaderGeneratorNames.ObjectSpacePosition), false);
var name = preferedCoordinateSpace.ToVariableName(InterpolatorType.Position);
interpolators.AddShaderChunk(string.Format("float3 {0} : TEXCOORD{1};", name, interpolatorIndex), false);
vertexShader.AddShaderChunk(string.Format("o.{0} = {1};", name, ConvertBetweenSpace("v.vertex", CoordinateSpace.Object, preferedCoordinateSpace, InputType.Vector)), false);
pixelShader.AddShaderChunk(string.Format("float3 {0} = IN.{0};", name), false);
interpolatorIndex++;
}

ShaderGeneratorNames.ObjectSpaceTangent, ShaderGeneratorNames.ObjectSpaceBiTangent, ShaderGeneratorNames.ObjectSpaceNormal), false);
preferedCoordinateSpace.ToVariableName(InterpolatorType.Tangent), preferedCoordinateSpace.ToVariableName(InterpolatorType.BiTangent), preferedCoordinateSpace.ToVariableName(InterpolatorType.Normal)), false);
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresNormal, pixelShader,
ShaderGeneratorNames.ObjectSpaceNormal, ShaderGeneratorNames.ViewSpaceNormal,
ShaderGeneratorNames.WorldSpaceNormal, ShaderGeneratorNames.TangentSpaceNormal, Dimension.Three, true);
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresTangent, pixelShader,
ShaderGeneratorNames.ObjectSpaceTangent, ShaderGeneratorNames.ViewSpaceTangent,
ShaderGeneratorNames.WorldSpaceTangent, ShaderGeneratorNames.TangentSpaceTangent, Dimension.Three);
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresBitangent, pixelShader,
ShaderGeneratorNames.ObjectSpaceBiTangent, ShaderGeneratorNames.ViewSpaceBiTangent,
ShaderGeneratorNames.WorldSpaceBiTangent, ShaderGeneratorNames.TangentSpaceBiTangent, Dimension.Three);
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresViewDir, pixelShader,
ShaderGeneratorNames.ObjectSpaceViewDirection, ShaderGeneratorNames.ViewSpaceViewDirection,
ShaderGeneratorNames.WorldSpaceViewDirection, ShaderGeneratorNames.TangentSpaceViewDirection, Dimension.Three);
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresNormal, InterpolatorType.Normal, preferedCoordinateSpace,
InputType.Normal, pixelShader, Dimension.Three);
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresTangent, InterpolatorType.Tangent, preferedCoordinateSpace,
InputType.Vector, pixelShader, Dimension.Three);
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresBitangent, InterpolatorType.BiTangent, preferedCoordinateSpace,
InputType.Vector, pixelShader, Dimension.Three);
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresPosition, pixelShader,
ShaderGeneratorNames.ObjectSpacePosition, ShaderGeneratorNames.ViewSpacePosition,
ShaderGeneratorNames.WorldSpacePosition, ShaderGeneratorNames.TangentSpacePosition, Dimension.Three);
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresViewDir, InterpolatorType.ViewDirection, preferedCoordinateSpace,
InputType.Vector, pixelShader, Dimension.Three);
ShaderGenerator.GenerateSpaceTranslationPixelShader(combinedRequierments.requiresPosition, InterpolatorType.Position, preferedCoordinateSpace,
InputType.Position, pixelShader, Dimension.Three);
if (combinedRequierments.requiresVertexColor)
{

// structure using the requirements for ONLY the shader graph
// additional requirements have come from the lighting model
// and are not needed in the shader graph
ShaderGenerator.GenerateCopyToSurfaceInputs(externalGraphRequiements.requiresNormal, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceNormal, ShaderGeneratorNames.ViewSpaceNormal,
ShaderGeneratorNames.WorldSpaceNormal, ShaderGeneratorNames.TangentSpaceNormal);
ShaderGenerator.GenerateCopyToSurfaceInputs(externalGraphRequiements.requiresTangent, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceTangent, ShaderGeneratorNames.ViewSpaceTangent,
ShaderGeneratorNames.WorldSpaceTangent, ShaderGeneratorNames.TangentSpaceTangent);
var replaceString = "surfaceInput.{0} = {0};";
GenerateSpaceTranslationSurfaceInputs(graphRequiements.requiresNormal, InterpolatorType.Normal, surfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(graphRequiements.requiresTangent, InterpolatorType.Tangent, surfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(graphRequiements.requiresBitangent, InterpolatorType.BiTangent, surfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(graphRequiements.requiresViewDir, InterpolatorType.ViewDirection, surfaceInputs, replaceString);
GenerateSpaceTranslationSurfaceInputs(graphRequiements.requiresPosition, InterpolatorType.Position, surfaceInputs, replaceString);
ShaderGenerator.GenerateCopyToSurfaceInputs(externalGraphRequiements.requiresBitangent, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceBiTangent, ShaderGeneratorNames.ViewSpaceBiTangent,
ShaderGeneratorNames.WorldSpaceBiTangent, ShaderGeneratorNames.TangentSpaceBiTangent);
ShaderGenerator.GenerateCopyToSurfaceInputs(externalGraphRequiements.requiresViewDir, surfaceInputs,
ShaderGeneratorNames.ObjectSpaceViewDirection, ShaderGeneratorNames.ViewSpaceViewDirection,
ShaderGeneratorNames.WorldSpaceViewDirection, ShaderGeneratorNames.TangentSpaceViewDirection);
ShaderGenerator.GenerateCopyToSurfaceInputs(externalGraphRequiements.requiresPosition, surfaceInputs,
ShaderGeneratorNames.ObjectSpacePosition, ShaderGeneratorNames.ViewSpacePosition,
ShaderGeneratorNames.WorldSpacePosition, ShaderGeneratorNames.TangentSpacePosition);
if (externalGraphRequiements.requiresVertexColor)
if (graphRequiements.requiresVertexColor)
if (externalGraphRequiements.requiresScreenPosition)
if (graphRequiements.requiresScreenPosition)
surfaceInputs.AddShaderChunk(string.Format("surfaceInput.{0} = {0};", ShaderGeneratorNames.ScreenPosition), false);
foreach (var channel in combinedRequierments.requiresMeshUVs.Distinct())

public static void GenerateSpaceTranslationPixelShader(
NeededCoordinateSpace neededSpaces,
InterpolatorType type,
CoordinateSpace from,
InputType inputType,
string objectSpaceName,
string viewSpaceName,
string worldSpaceName,
string tangentSpaceName,
Dimension dimension,
bool isNormal = false)
Dimension dimension)
if ((neededSpaces & NeededCoordinateSpace.World) > 0)
{
if (isNormal)
pixelShader.AddShaderChunk(string.Format("float{0} {1} = UnityObjectToWorldNormal({2});", DimensionToString(dimension), worldSpaceName, objectSpaceName), false);
else
pixelShader.AddShaderChunk(string.Format("float{0} {1} = UnityObjectToWorldDir({2});", DimensionToString(dimension), worldSpaceName, objectSpaceName), false);
}
if ((neededSpaces & NeededCoordinateSpace.Object) > 0 && from != CoordinateSpace.Object)
pixelShader.AddShaderChunk(
string.Format("float{0} {1} = {2};", DimensionToString(dimension),
CoordinateSpace.Object.ToVariableName(type), ConvertBetweenSpace(from.ToVariableName(type), from, CoordinateSpace.Object, inputType, from)), false);
if ((neededSpaces & NeededCoordinateSpace.View) > 0)
{
pixelShader.AddShaderChunk(string.Format("float{0} {1} = UnityObjectToViewPos({2});", DimensionToString(dimension), viewSpaceName, objectSpaceName), false);
}
if ((neededSpaces & NeededCoordinateSpace.World) > 0 && from != CoordinateSpace.World)
pixelShader.AddShaderChunk(
string.Format("float{0} {1} = {2};", DimensionToString(dimension),
CoordinateSpace.World.ToVariableName(type), ConvertBetweenSpace(from.ToVariableName(type), from, CoordinateSpace.World, inputType, from)), false);
if ((neededSpaces & NeededCoordinateSpace.View) > 0 && from != CoordinateSpace.View)
pixelShader.AddShaderChunk(
string.Format("float{0} {1} = {2};", DimensionToString(dimension),
CoordinateSpace.View.ToVariableName(type),
ConvertBetweenSpace(from.ToVariableName(type), from, CoordinateSpace.View, inputType, from)), false);
if ((neededSpaces & NeededCoordinateSpace.Tangent) > 0)
{
pixelShader.AddShaderChunk(string.Format("float{0} {1} = mul(tangentSpaceTransform, {2})", DimensionToString(dimension), tangentSpaceName, objectSpaceName), false);
}
if ((neededSpaces & NeededCoordinateSpace.Tangent) > 0 && from != CoordinateSpace.Tangent)
pixelShader.AddShaderChunk(
string.Format("float{0} {1} = {2};", DimensionToString(dimension),
CoordinateSpace.Tangent.ToVariableName(type),
ConvertBetweenSpace(from.ToVariableName(type), from, CoordinateSpace.Tangent, inputType, from)), false);
}
public static void GenerateCopyToSurfaceInputs(

ShaderGenerator.GenerateStandardTransforms(
0,
16,
ShaderGraphRequirements.none);
ShaderGraphRequirements.none,
CoordinateSpace.World);
var outputs = new ShaderGenerator();
var outputSlot = node.GetOutputSlots<MaterialSlot>().FirstOrDefault();

12
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Templates/lightweightSubshaderPBR.template


float Metallic = 0;
float3 Normal = float3(0, 0, 1);
float3 Emission = 0;
float Smoothness = 0;
float Smoothness = 0.5;
float Occlusion = 1;
float Alpha = 1;

return LightweightFragmentPBR(
IN.lwCustom,
worldSpacePosition,
worldSpaceNormal,
worldSpaceTangent,
worldSpaceBiTangent,
worldSpaceViewDirection,
WorldSpacePosition,
WorldSpaceNormal,
WorldSpaceTangent,
WorldSpaceBiTangent,
WorldSpaceViewDirection,
IN.fogCoord.x,
Albedo,

正在加载...
取消
保存