Skip to content

Commit

Permalink
fix: improve material serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
sinnwrig committed Oct 1, 2024
1 parent 555e2a6 commit 5cf8e82
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 81 deletions.
18 changes: 9 additions & 9 deletions Prowl.Editor/Assets/Importers/ModelImporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,10 @@ private void LoadMaterials(SerializedAsset ctx, Assimp.Scene? scene, DirectoryIn
if (FindTextureFromPath(m.TextureDiffuse.FilePath, parentDir, out var file))
LoadTextureIntoMesh("_AlbedoTex", ctx, file, mat);
else
mat.SetProperty("_AlbedoTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/grid.png")).Res);
mat.SetProperty("_AlbedoTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/grid.png")));
}
else
mat.SetProperty("_AlbedoTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/grid.png")).Res);
mat.SetProperty("_AlbedoTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/grid.png")));

// Normal Texture
if (m.HasTextureNormal)
Expand All @@ -277,10 +277,10 @@ private void LoadMaterials(SerializedAsset ctx, Assimp.Scene? scene, DirectoryIn
if (FindTextureFromPath(m.TextureNormal.FilePath, parentDir, out var file))
LoadTextureIntoMesh("_NormalTex", ctx, file, mat);
else
mat.SetProperty("_NormalTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/default_normal.png")).Res);
mat.SetProperty("_NormalTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/default_normal.png")));
}
else
mat.SetProperty("_NormalTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/default_normal.png")).Res);
mat.SetProperty("_NormalTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/default_normal.png")));

//AO, Roughness, Metallic Texture
if (m.GetMaterialTexture(TextureType.Unknown, 0, out var surface))
Expand All @@ -289,10 +289,10 @@ private void LoadMaterials(SerializedAsset ctx, Assimp.Scene? scene, DirectoryIn
if (FindTextureFromPath(surface.FilePath, parentDir, out var file))
LoadTextureIntoMesh("_SurfaceTex", ctx, file, mat);
else
mat.SetProperty("_SurfaceTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/default_surface.png")).Res);
mat.SetProperty("_SurfaceTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/default_surface.png")));
}
else
mat.SetProperty("_SurfaceTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/default_surface.png")).Res);
mat.SetProperty("_SurfaceTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/default_surface.png")));

// Emissive Texture
if (m.HasTextureEmissive)
Expand All @@ -304,10 +304,10 @@ private void LoadMaterials(SerializedAsset ctx, Assimp.Scene? scene, DirectoryIn
LoadTextureIntoMesh("_EmissiveTex", ctx, file, mat);
}
else
mat.SetProperty("_EmissiveTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/default_emission.png")).Res);
mat.SetProperty("_EmissiveTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/default_emission.png")));
}
else
mat.SetProperty("_EmissionTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/default_emission.png")).Res);
mat.SetProperty("_EmissionTex", new AssetRef<Texture2D>(AssetDatabase.GuidFromRelativePath("Defaults/default_emission.png")));

name ??= "StandardMat";
mat.Name = name;
Expand Down Expand Up @@ -589,7 +589,7 @@ private static void LoadTextureIntoMesh(string name, SerializedAsset ctx, FileIn
if (AssetDatabase.TryGetGuid(file, out var guid))
{
// We have this texture as an asset, Juse use the asset we dont need to load it
mat.SetProperty(name, new AssetRef<Texture2D>(guid).Res);
mat.SetProperty(name, new AssetRef<Texture2D>(guid));
}
else
{
Expand Down
63 changes: 19 additions & 44 deletions Prowl.Runtime/Rendering/Material.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public AssetRef<Shader> Shader
}

[SerializeField]
internal List<SerializedShaderProperty> _serializedProperties;
internal List<ShaderProperty> _serializedProperties;

[NonSerialized]
private Dictionary<string, int> _propertyLookup;
Expand Down Expand Up @@ -90,38 +90,13 @@ public Material(AssetRef<Shader> shader, PropertyState? properties = null, Keywo
public void SetColorArray(string name, Color[] values) => _properties.SetColorArray(name, values);
public void SetMatrixArray(string name, Matrix4x4F[] values) => _properties.SetMatrixArray(name, values);


public void SetProperty(string name, double value)
=> SetPropertyInternal(name, value);

public void SetProperty(string name, Vector2 value)
=> SetPropertyInternal(name, value);

public void SetProperty(string name, Vector3 value)
=> SetPropertyInternal(name, value);

public void SetProperty(string name, Vector4 value)
=> SetPropertyInternal(name, value);

public void SetProperty(string name, Color value)
=> SetPropertyInternal(name, value);

public void SetProperty(string name, Matrix4x4 value)
=> SetPropertyInternal(name, value);

public void SetProperty(string name, AssetRef<Texture2D> value)
=> SetPropertyInternal(name, value);

public void SetProperty(string name, AssetRef<Texture3D> value)
=> SetPropertyInternal(name, value);

private void SetPropertyInternal(string name, object? value)
public void SetProperty(string name, ShaderProperty value)
{
if (_propertyLookup.TryGetValue(name, out int val))
{
SerializedShaderProperty prop = _serializedProperties[val];
ShaderProperty prop = _serializedProperties[val];

prop.defaultProperty = value;
prop.Set(value);

UpdatePropertyState(prop);

Expand All @@ -132,45 +107,45 @@ private void SetPropertyInternal(string name, object? value)

public void SyncPropertyBlock()
{
foreach (SerializedShaderProperty prop in _serializedProperties)
foreach (ShaderProperty prop in _serializedProperties)
UpdatePropertyState(prop);
}


private void UpdatePropertyState(SerializedShaderProperty property)
private void UpdatePropertyState(ShaderProperty property)
{
switch (property.propertyType)
switch (property.PropertyType)
{
case ShaderPropertyType.Texture2D:
_properties.SetTexture(property.name, ((AssetRef<Texture2D>)property.defaultProperty).Res);
_properties.SetTexture(property.Name, property.Texture2DValue.Res);
break;

case ShaderPropertyType.Texture3D:
_properties.SetTexture(property.name, ((AssetRef<Texture3D>)property.defaultProperty).Res);
_properties.SetTexture(property.Name, property.Texture3DValue.Res);
break;

case ShaderPropertyType.Float:
_properties.SetFloat(property.name, (float)property.defaultProperty);
_properties.SetFloat(property.Name, (float)property);
break;

case ShaderPropertyType.Vector2:
_properties.SetVector(property.name, (Vector2)property.defaultProperty);
_properties.SetVector(property.Name, (Vector2)property);
break;

case ShaderPropertyType.Vector3:
_properties.SetVector(property.name, (Vector3)property.defaultProperty);
_properties.SetVector(property.Name, (Vector3)property);
break;

case ShaderPropertyType.Vector4:
_properties.SetVector(property.name, (Vector4)property.defaultProperty);
_properties.SetVector(property.Name, (Vector4)property);
break;

case ShaderPropertyType.Color:
_properties.SetColor(property.name, (Color)property.defaultProperty);
_properties.SetColor(property.Name, (Color)property);
break;

case ShaderPropertyType.Matrix:
_properties.SetMatrix(property.name, ((Matrix4x4)property.defaultProperty).ToFloat());
_properties.SetMatrix(property.Name, ((Matrix4x4)property).ToFloat());
break;
}
}
Expand All @@ -186,10 +161,10 @@ internal void SetShader(AssetRef<Shader> shader)
_serializedProperties.Clear();
_propertyLookup.Clear();

foreach (SerializedShaderProperty prop in shader.Res.Properties)
foreach (ShaderProperty prop in shader.Res.Properties)
{
_serializedProperties.Add(prop);
_propertyLookup.Add(prop.name, _serializedProperties.Count - 1);
_propertyLookup.Add(prop.Name, _serializedProperties.Count - 1);
}
}

Expand All @@ -200,8 +175,8 @@ public void OnAfterDeserialize()
{
_propertyLookup ??= [];

foreach (SerializedShaderProperty prop in Shader.Res.Properties)
_propertyLookup.Add(prop.name, _serializedProperties.Count - 1);
foreach (ShaderProperty prop in _serializedProperties)
_propertyLookup.Add(prop.Name, _serializedProperties.Count - 1);

SyncPropertyBlock();
}
Expand Down
33 changes: 5 additions & 28 deletions Prowl.Runtime/Rendering/Shader/Shader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,11 @@

namespace Prowl.Runtime;


public enum ShaderPropertyType
{
Float,
Vector2,
Vector3,
Vector4,
Color,
Matrix,
Texture2D,
Texture3D
}


public struct SerializedShaderProperty
{
public string name;
public string displayName;
public ShaderPropertyType propertyType;
public object defaultProperty;
}


public sealed class Shader : EngineObject, ISerializationCallbackReceiver
{
[SerializeField, HideInInspector]
private readonly SerializedShaderProperty[] _properties;
public IEnumerable<SerializedShaderProperty> Properties => _properties;
private readonly ShaderProperty[] _properties;
public IEnumerable<ShaderProperty> Properties => _properties;


[SerializeField, HideInInspector]
Expand All @@ -50,7 +27,7 @@ public sealed class Shader : EngineObject, ISerializationCallbackReceiver

internal Shader() : base("New Shader") { }

public Shader(string name, SerializedShaderProperty[] properties, ShaderPass[] passes) : base(name)
public Shader(string name, ShaderProperty[] properties, ShaderPass[] passes) : base(name)
{
this._properties = properties;
this._passes = passes;
Expand Down Expand Up @@ -128,9 +105,9 @@ public string GetStringRepresentation()

builder.Append("Properties\n{\n");

foreach (SerializedShaderProperty property in Properties)
foreach (ShaderProperty property in Properties)
{
builder.Append($"\t{property.name}(\"{property.displayName}\", {property.propertyType})\n");
builder.Append($"\t{property.Name}(\"{property.DisplayName}\", {property.PropertyType})\n");
}

builder.Append("}\n\n");
Expand Down
144 changes: 144 additions & 0 deletions Prowl.Runtime/Rendering/Shader/ShaderProperty.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// This file is part of the Prowl Game Engine
// Licensed under the MIT License. See the LICENSE file in the project root for details.
using System;

using Vortice.Direct3D11;

namespace Prowl.Runtime;


public enum ShaderPropertyType
{
Float,
Vector2,
Vector3,
Vector4,
Color,
Matrix,
Texture2D,
Texture3D
}


public struct ShaderProperty
{
public string Name;
public string DisplayName;

[field: SerializeField]
public ShaderPropertyType PropertyType { get; private set; }

public Vector4 Value;
public Matrix4x4 MatrixValue;

public AssetRef<Texture2D> Texture2DValue;
public AssetRef<Texture3D> Texture3DValue;


public void Set(ShaderProperty other)
{
if (other.PropertyType != PropertyType)
return;

Value = other.Value;
MatrixValue = other.MatrixValue;
Texture2DValue = other.Texture2DValue;
Texture3DValue = other.Texture3DValue;
}

public ShaderProperty(double value)
{
Value = new(value);
PropertyType = ShaderPropertyType.Float;
}

public static implicit operator ShaderProperty(double value)
=> new ShaderProperty(value);

public static implicit operator double(ShaderProperty value)
=> value.Value.x;

public ShaderProperty(Vector2 value)
{
Value = new(value);
PropertyType = ShaderPropertyType.Vector2;
}

public static implicit operator ShaderProperty(Vector2 value)
=> new ShaderProperty(value);

public static implicit operator Vector2(ShaderProperty value)
=> new Vector2(value.Value.x, value.Value.y);

public ShaderProperty(Vector3 value)
{
Value = new(value);
PropertyType = ShaderPropertyType.Vector3;
}

public static implicit operator ShaderProperty(Vector3 value)
=> new ShaderProperty(value);

public static implicit operator Vector3(ShaderProperty value)
=> new Vector3(value.Value.x, value.Value.y, value.Value.z);

public ShaderProperty(Vector4 value)
{
Value = value;
PropertyType = ShaderPropertyType.Vector4;
}

public static implicit operator ShaderProperty(Vector4 value)
=> new ShaderProperty(value);

public static implicit operator Vector4(ShaderProperty value)
=> value.Value;

public ShaderProperty(Color value)
{
Value = new(value.r, value.g, value.b, value.a);
PropertyType = ShaderPropertyType.Color;
}

public static implicit operator ShaderProperty(Color value)
=> new ShaderProperty(value);

public static implicit operator Color(ShaderProperty value)
=> new Color((float)value.Value.x, (float)value.Value.y, (float)value.Value.z, (float)value.Value.w);

public ShaderProperty(Matrix4x4 value)
{
MatrixValue = value;
PropertyType = ShaderPropertyType.Matrix;
}

public static implicit operator ShaderProperty(Matrix4x4 value)
=> new ShaderProperty(value);

public static implicit operator Matrix4x4(ShaderProperty value)
=> value.MatrixValue;

public ShaderProperty(AssetRef<Texture2D> value)
{
Texture2DValue = value;
PropertyType = ShaderPropertyType.Texture2D;
}

public static implicit operator ShaderProperty(AssetRef<Texture2D> value)
=> new ShaderProperty(value);

public static implicit operator AssetRef<Texture2D>(ShaderProperty value)
=> value.Texture2DValue;

public ShaderProperty(AssetRef<Texture3D> value)
{
Texture3DValue = value;
PropertyType = ShaderPropertyType.Texture3D;
}

public static implicit operator ShaderProperty(AssetRef<Texture3D> value)
=> new ShaderProperty(value);

public static implicit operator AssetRef<Texture3D>(ShaderProperty value)
=> value.Texture3DValue;
}

0 comments on commit 5cf8e82

Please sign in to comment.