浏览代码

Fix some bugs in new nodes (bad conversion to HLSLSnippet node) + Add ability to hide slots at the slot level (i.e. hide implicit inputs for function node)

/main
Tim Cooper 7 年前
当前提交
b44a8aea
共有 32 个文件被更改,包括 72 次插入89 次删除
  1. 4
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/NodeInspectors/BasicNodeInspector.cs
  2. 5
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/Presenters/GraphNodePresenter.cs
  3. 15
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Implementation/SerializableSlot.cs
  4. 1
      MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/ISlot.cs
  5. 8
      MaterialGraphProject/Assets/NewNodes/WIP/AACheckerBoard3dNode.cs
  6. 4
      MaterialGraphProject/Assets/NewNodes/WIP/AACheckerBoardNode.cs
  7. 4
      MaterialGraphProject/Assets/NewNodes/WIP/ConstantsNode.cs
  8. 2
      MaterialGraphProject/Assets/NewNodes/WIP/SamplerStateNode.cs
  9. 7
      MaterialGraphProject/Assets/NewNodes/WIP/SphericalIndentationNode.cs
  10. 2
      MaterialGraphProject/Assets/NewNodes/WIP/Texture2DNode.cs
  11. 2
      MaterialGraphProject/Assets/SphereDent.ShaderGraph
  12. 7
      MaterialGraphProject/Assets/SphereDent.ShaderGraph.meta
  13. 4
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeInspectors/SubgraphInputNodeInspector.cs
  14. 4
      MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeInspectors/SubgraphOutputNodeInspector.cs
  15. 24
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Graphs/MaterialSlot.cs
  16. 21
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/HLSLNode.cs
  17. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Input/SceneData/DepthTextureNode.cs
  18. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Input/SceneData/MotionVectorTextureNode.cs
  19. 2
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Input/Texture/CubemapNode.cs
  20. 6
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Input/Texture/TextureLODNode.cs
  21. 15
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphInputNode.cs
  22. 11
      MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphOutputNode.cs
  23. 9
      MaterialGraphProject/Assets/Andre.meta
  24. 0
      /MaterialGraphProject/Assets/TestAssets/an_gradient.png
  25. 0
      /MaterialGraphProject/Assets/TestAssets/an_gradient.png.meta
  26. 0
      /MaterialGraphProject/Assets/TestAssets/ground_cracked_ground_basecolor.png
  27. 0
      /MaterialGraphProject/Assets/TestAssets/ground_cracked_ground_basecolor.png.meta
  28. 0
      /MaterialGraphProject/Assets/TestAssets/ground_cracked_ground_height.png
  29. 0
      /MaterialGraphProject/Assets/TestAssets/ground_cracked_ground_height.png.meta
  30. 0
      /MaterialGraphProject/Assets/TestAssets/ground_cracked_ground_roughness.png
  31. 0
      /MaterialGraphProject/Assets/TestAssets/ground_cracked_ground_roughness.png.meta

4
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/NodeInspectors/BasicNodeInspector.cs


protected virtual ModificationScope DoSlotsUI()
{
var slots = node.GetSlots<MaterialSlot>().Where(x => x.showValue);
var slots = node.GetSlots<MaterialSlot>();
if (!slots.Any())
return ModificationScope.Nothing;

foreach (var slot in node.GetSlots<MaterialSlot>().Where(x => x.showValue))
foreach (var slot in node.GetSlots<MaterialSlot>())
slot.currentValue = EditorGUILayout.Vector4Field(slot.displayName, slot.currentValue);
GUILayout.Space(10);

5
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Editor/Drawing/Presenters/GraphNodePresenter.cs


{
foreach (var slot in slots)
{
if (slot.hidden)
continue;
data.capabilities &= ~Capabilities.Movable;
data.capabilities &= ~Capabilities.Movable;
data.Initialize(slot);
if (slot.isOutputSlot)

15
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Implementation/SerializableSlot.cs


[SerializeField]
private int m_Priority = int.MaxValue;
[SerializeField]
private bool m_Hidden;
public SlotReference slotReference
{
get { return new SlotReference(owner.guid, m_Id); }

public bool hidden
{
get { return m_Hidden; }
set { m_Hidden = value; }
}
public int id
{

public SerializableSlot()
{}
public SerializableSlot(int id, string displayName, SlotType slotType, int priority)
public SerializableSlot(int id, string displayName, SlotType slotType, int priority, bool hidden = false)
m_Hidden = hidden;
public SerializableSlot(int id, string displayName, SlotType slotType)
public SerializableSlot(int id, string displayName, SlotType slotType, bool hidden = false)
m_Hidden = hidden;
}
}
}

1
MaterialGraphProject/Assets/GraphFramework/SerializableGraph/Runtime/Interfaces/ISlot.cs


int priority { get; set; }
SlotReference slotReference { get; }
INode owner { get; set; }
bool hidden { get; set; }
}
}

8
MaterialGraphProject/Assets/NewNodes/WIP/AACheckerBoard3dNode.cs


}
static string Unity_AACheckerboard3d(
[Slot(0, Binding.MeshUV0)] Vector2 uv,
[Slot(0, Binding.MeshUV0)] Vector3 uv,
[Slot(1, Binding.None, 0.2f, 0.2f, 0.2f, 0.2f)] Vector4 colorA,
[Slot(2, Binding.None, 0.7f, 0.7f, 0.7f, 0.7f)] Vector4 colorB,
[Slot(3, Binding.None, 0.5f, 3f, 0f, 0f)] Vector3 aaTweak,

return
@"
{
float3 dx = ddx(inUVs);
float3 dy = ddy(inUVs);
float3 dx = ddx(uv);
float3 dy = ddy(uv);
float3 distance3 = 2.0f * abs(frac((inUVs.xyz + 0.5f) * frequency.xyz) - 0.5f) - 0.5f;
float3 distance3 = 2.0f * abs(frac((uv.xyz + 0.5f) * frequency.xyz) - 0.5f) - 0.5f;
float3 scale = aaTweak.xxx / float3(du, dv, dw);
float3 blend_out = saturate((scale - aaTweak.zzz) / (aaTweak.yyy - aaTweak.zzz));
float3 vectorAlpha = clamp(distance3 * scale.xyz * blend_out.xyz, -1.0f, 1.0f);

4
MaterialGraphProject/Assets/NewNodes/WIP/AACheckerBoardNode.cs


return
@"
{
float4 derivatives = float4(ddx(inUVs), ddy(inUVs));
float4 derivatives = float4(ddx(uv), ddy(uv));
float2 distance3 = 2.0f * abs(frac(inUVs.xy * frequency) - 0.5f) - width;
float2 distance3 = 2.0f * abs(frac(uv.xy * frequency) - 0.5f) - width;
float2 scale = aaTweak.x / duv_length.xy;
float2 blend_out = saturate((scale - aaTweak.zz) / (aaTweak.yy - aaTweak.zz));
float2 vector_alpha = clamp(distance3 * scale.xy * blend_out.xy, -1.0f, 1.0f);

4
MaterialGraphProject/Assets/NewNodes/WIP/ConstantsNode.cs


[Title("Math/Constants")]
public class ConstantsNode : PropertyNode, IGeneratesBodyCode
{
static Dictionary<ConstantType, float> m_constantList = new Dictionary<ConstantType, float>
{
{ConstantType.PI, 3.1415926f },

public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector1, Vector4.zero, false));
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}

2
MaterialGraphProject/Assets/NewNodes/WIP/SamplerStateNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.SamplerState, Vector4.zero, false));
AddSlot(new MaterialSlot(kOutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.SamplerState, Vector4.zero));
RemoveSlotsNameNotMatching(new[] { kOutputSlotId });
}

7
MaterialGraphProject/Assets/NewNodes/WIP/SphericalIndentationNode.cs


[Slot(2, Binding.None)] Vector1 height,
[Slot(3, Binding.None, 1f, 1f, 1f, 1f)] Vector1 radius,
[Slot(4, Binding.None)] out Vector3 resultUV,
[Slot(5, Binding.None)] out Vector2 resultNormal)
[Slot(5, Binding.None)] out Vector3 resultNormal,
[Slot(6, Binding.ViewDirectionTangentSpace, true)] Vector3 tangentSpaceViewDirection)
{
resultUV = Vector3.zero;
resultNormal = Vector3.up;

float3 sphereCenter = float3(center, height);
float3 edgeA = sphereCenter - cur;
float a2 = dot(edgeA, edgeA);
outUVs= float3(inUVs.xy, 0.0f);
outNormal= float3(0.0f, 0.0f, 1.0f);
resultUV= float3(uv.xy, 0.0f);
resultNormal= float3(0.0f, 0.0f, 1.0f);
if (a2 < radius2)
{
float a = sqrt(a2);

2
MaterialGraphProject/Assets/NewNodes/WIP/Texture2DNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(textureID, textureName, textureName, SlotType.Output, SlotValueType.Texture2D, Vector4.zero, false));
AddSlot(new MaterialSlot(textureID, textureName, textureName, SlotType.Output, SlotValueType.Texture2D, Vector4.zero));
RemoveSlotsNameNotMatching(validSlots);
}

2
MaterialGraphProject/Assets/SphereDent.ShaderGraph
文件差异内容过多而无法显示
查看文件

7
MaterialGraphProject/Assets/SphereDent.ShaderGraph.meta


fileFormatVersion: 2
guid: b63da350811f7ba48914e852a299204c
timeCreated: 1495747830
timeCreated: 1500715026
ScriptedImporter:
ShaderImporter:
defaultTextures: []
nonModifiableTextures: []
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}

4
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeInspectors/SubgraphInputNodeInspector.cs


protected override ModificationScope DoSlotsUI()
{
var slots = node.GetSlots<MaterialSlot>().Where(x => x.showValue);
var slots = node.GetSlots<MaterialSlot>();
if (!slots.Any())
return ModificationScope.Node;

bool typeChanged = false;
foreach (var slot in node.GetSlots<MaterialSlot>().Where(x => x.showValue))
foreach (var slot in node.GetSlots<MaterialSlot>())
{
EditorGUI.BeginChangeCheck();
GUILayout.Label(slot.displayName);

4
MaterialGraphProject/Assets/UnityShaderEditor/Editor/Drawing/NodeInspectors/SubgraphOutputNodeInspector.cs


protected override ModificationScope DoSlotsUI()
{
var slots = node.GetSlots<MaterialSlot>().Where(x => x.showValue);
var slots = node.GetSlots<MaterialSlot>();
if (!slots.Any())
return ModificationScope.Node;

foreach (var slot in node.GetSlots<MaterialSlot>().Where(x => x.showValue))
foreach (var slot in node.GetSlots<MaterialSlot>())
{
EditorGUI.BeginChangeCheck();
var result = (UISlotValueType)EditorGUILayout.EnumPopup(ToUISlot(slot.valueType));

24
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Graphs/MaterialSlot.cs


[SerializeField]
private string m_ShaderOutputName;
[SerializeField]
private bool m_ShowValue;
public MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, SlotValueType valueType, Vector4 defaultValue)
: base(slotId, displayName, slotType)
{
SharedInitialize(shaderOutputName, valueType, true, defaultValue);
}
public MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, SlotValueType valueType, Vector4 defaultValue, bool usesDefaultValue)
: base(slotId, displayName, slotType)
public MaterialSlot(int slotId, string displayName, string shaderOutputName, SlotType slotType, SlotValueType valueType, Vector4 defaultValue, bool hidden = false)
: base(slotId, displayName, slotType, hidden)
SharedInitialize(shaderOutputName, valueType, usesDefaultValue, defaultValue);
SharedInitialize(shaderOutputName, valueType, defaultValue);
private void SharedInitialize(string inShaderOutputName, SlotValueType inValueType, bool usesDefaultValue, Vector4 inDefaultValue)
private void SharedInitialize(string inShaderOutputName, SlotValueType inValueType, Vector4 inDefaultValue)
m_ShowValue = usesDefaultValue;
}
private static string ConcreteSlotValueTypeAsString(ConcreteSlotValueType type)

{
get { return m_ShaderOutputName; }
private set { m_ShaderOutputName = value; }
}
public bool showValue
{
get { return m_ShowValue; }
set { m_ShowValue = value; }
}
public void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode)

21
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/HLSLNode.cs


{
public int slotId { get; private set; }
public Binding binding { get; private set; }
public bool hidden { get; private set; }
public SlotAttribute(int mslotId, Binding mImplicitBinding)
public SlotAttribute(int mSlotId, Binding mImplicitBinding)
{
slotId = mSlotId;
binding = mImplicitBinding;
defaultValue = null;
}
public SlotAttribute(int mSlotId, Binding mImplicitBinding, bool mHidden)
slotId = mslotId;
slotId = mSlotId;
hidden = mHidden;
public SlotAttribute(int mslotId, Binding mImplicitBinding, float defaultX, float defaultY, float defaultZ, float defaultW)
public SlotAttribute(int mSlotId, Binding mImplicitBinding, float defaultX, float defaultY, float defaultZ, float defaultW)
slotId = mslotId;
slotId = mSlotId;
binding = mImplicitBinding;
defaultValue = new Vector4(defaultX, defaultY, defaultZ, defaultW);
}

// validate no duplicates
var slotAtributes = method.GetParameters().Select(GetSlotAttribute).ToList();
if (slotAtributes.Any(x => x == null))
throw new ArgumentException("Missing SlotAttribute does not exist on " + method.Name);
throw new ArgumentException("Missing SlotAttribute on " + method.Name);
if(slotAtributes.GroupBy(x=>x.slotId).Any(x => x.Count() > 1))
throw new ArgumentException("Duplicate SlotAttribute on " + method.Name);

var attribute = GetSlotAttribute(par);
slots.Add(new MaterialSlot(attribute.slotId, par.Name, par.Name, par.IsOut ? SlotType.Output : SlotType.Input,
ConvertTypeToSlotValueType(par), attribute.defaultValue ?? Vector4.zero));
ConvertTypeToSlotValueType(par), attribute.defaultValue ?? Vector4.zero, attribute.hidden));
m_Slots.Add(attribute);

2
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Input/SceneData/DepthTextureNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(UvSlotId, kUVSlotName, kUVSlotName, SlotType.Input, SlotValueType.Vector2, Vector4.zero, false));
AddSlot(new MaterialSlot(UvSlotId, kUVSlotName, kUVSlotName, SlotType.Input, SlotValueType.Vector2, Vector4.zero));
RemoveSlotsNameNotMatching(validSlots);
}

2
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Input/SceneData/MotionVectorTextureNode.cs


public sealed override void UpdateNodeAfterDeserialization()
{
AddSlot(new MaterialSlot(OutputSlotId, kOutputSlotName, kOutputSlotName, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
AddSlot(new MaterialSlot(UvSlotId, kUVSlotName, kUVSlotName, SlotType.Input, SlotValueType.Vector2, Vector4.zero, false));
AddSlot(new MaterialSlot(UvSlotId, kUVSlotName, kUVSlotName, SlotType.Input, SlotValueType.Vector2, Vector4.zero));
RemoveSlotsNameNotMatching(validSlots);
}

2
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Input/Texture/CubemapNode.cs


AddSlot(new MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(RefDirSlot, kUVSlotName, kUVSlotName, SlotType.Input, SlotValueType.Vector3, Vector3.zero, false));
AddSlot(new MaterialSlot(RefDirSlot, kUVSlotName, kUVSlotName, SlotType.Input, SlotValueType.Vector3, Vector3.zero));
AddSlot (new MaterialSlot(InputSlotLod, kInputSlotLodName, kInputSlotLodName, SlotType.Input, SlotValueType.Vector1, Vector2.zero));
RemoveSlotsNameNotMatching(validSlots);
}

6
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/Nodes/Input/Texture/TextureLODNode.cs


AddSlot(new MaterialSlot(OutputSlotGId, kOutputSlotGName, kOutputSlotGName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotBId, kOutputSlotBName, kOutputSlotBName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(OutputSlotAId, kOutputSlotAName, kOutputSlotAName, SlotType.Output, SlotValueType.Vector1, Vector4.zero));
AddSlot(new MaterialSlot(UvSlotId, kUVSlotName, kUVSlotName, SlotType.Input, SlotValueType.Vector2, Vector4.zero, false));
AddSlot(new MaterialSlot(LODSlotId, kLODSlotName, kLODSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero, false));
AddSlot(new MaterialSlot(UvSlotId, kUVSlotName, kUVSlotName, SlotType.Input, SlotValueType.Vector2, Vector4.zero));
AddSlot(new MaterialSlot(LODSlotId, kLODSlotName, kLODSlotName, SlotType.Input, SlotValueType.Vector1, Vector4.zero));
RemoveSlotsNameNotMatching(validSlots);
}

{
var uvSlot = FindInputSlot<MaterialSlot>(UvSlotId);
var lodSlot = FindInputSlot<MaterialSlot>(LODSlotId);
if (uvSlot == null)
return;

15
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphInputNode.cs


public override int AddSlot()
{
var nextSlotId = GetOutputSlots<ISlot>().Count() + 1;
AddSlot(new MaterialSlot(-nextSlotId, "Input " + nextSlotId, "Input" + nextSlotId, SlotType.Output, SlotValueType.Vector4, Vector4.zero, true));
AddSlot(new MaterialSlot(-nextSlotId, "Input " + nextSlotId, "Input" + nextSlotId, SlotType.Output, SlotValueType.Vector4, Vector4.zero));
return -nextSlotId;
}

}
public override void UpdateNodeAfterDeserialization()
{
base.UpdateNodeAfterDeserialization();
foreach (var slot in GetOutputSlots<MaterialSlot>())
{
slot.showValue = true;
}
}
public override void GeneratePropertyUsages(ShaderGenerator visitor, GenerationMode generationMode)
{
if (generationMode == GenerationMode.ForReals)

public override void CollectPreviewMaterialProperties(List<PreviewProperty> properties)
{
base.CollectPreviewMaterialProperties(properties);
foreach (var s in GetOutputSlots<MaterialSlot>())
foreach (var s in GetOutputSlots<MaterialSlot>())
new PreviewProperty
new PreviewProperty
{
m_Name = GetVariableNameForSlot (s.id),
m_PropType = ConvertConcreteSlotValueTypeToPropertyType (s.concreteValueType),

11
MaterialGraphProject/Assets/UnityShaderEditor/Runtime/SubGraph/SubGraphOutputNode.cs


public override int AddSlot()
{
var index = GetInputSlots<ISlot>().Count() + 1;
AddSlot(new MaterialSlot(index, "Output " + index, "Output" + index, SlotType.Input, SlotValueType.Vector4, Vector4.zero, true));
AddSlot(new MaterialSlot(index, "Output " + index, "Output" + index, SlotType.Input, SlotValueType.Vector4, Vector4.zero));
public override void UpdateNodeAfterDeserialization()
{
base.UpdateNodeAfterDeserialization();
foreach (var slot in GetInputSlots<MaterialSlot>())
{
slot.showValue = true;
}
}
public override void RemoveSlot()
{

9
MaterialGraphProject/Assets/Andre.meta


fileFormatVersion: 2
guid: cd5688ca09d4248698f2b43253441000
folderAsset: yes
timeCreated: 1495479128
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

/MaterialGraphProject/Assets/Andre/an_gradient.png → /MaterialGraphProject/Assets/TestAssets/an_gradient.png

/MaterialGraphProject/Assets/Andre/an_gradient.png.meta → /MaterialGraphProject/Assets/TestAssets/an_gradient.png.meta

/MaterialGraphProject/Assets/Andre/ground_cracked_ground_basecolor.png → /MaterialGraphProject/Assets/TestAssets/ground_cracked_ground_basecolor.png

/MaterialGraphProject/Assets/Andre/ground_cracked_ground_basecolor.png.meta → /MaterialGraphProject/Assets/TestAssets/ground_cracked_ground_basecolor.png.meta

/MaterialGraphProject/Assets/Andre/ground_cracked_ground_height.png → /MaterialGraphProject/Assets/TestAssets/ground_cracked_ground_height.png

/MaterialGraphProject/Assets/Andre/ground_cracked_ground_height.png.meta → /MaterialGraphProject/Assets/TestAssets/ground_cracked_ground_height.png.meta

/MaterialGraphProject/Assets/Andre/ground_cracked_ground_roughness.png → /MaterialGraphProject/Assets/TestAssets/ground_cracked_ground_roughness.png

/MaterialGraphProject/Assets/Andre/ground_cracked_ground_roughness.png.meta → /MaterialGraphProject/Assets/TestAssets/ground_cracked_ground_roughness.png.meta

正在加载...
取消
保存