Interact with Materials from scripts

This commit is contained in:
Simon Lübeß
2025-02-14 11:54:07 +01:00
parent e5437c6ff6
commit aaed4199d3
24 changed files with 739 additions and 64 deletions
@@ -109,6 +109,26 @@ namespace GlitchyEngine.Renderer
#endif
}
public enum TypematchResult
{
Ok,
MatrixDimensionMismatch,
ElementTypeMismatch,
}
public TypematchResult CheckTypematch(int rows, int cols, ShaderVariableType type)
{
Debug.Profiler.ProfileRendererFunction!();
if (rows != _rows || cols != _columns)
return .MatrixDimensionMismatch;
if (type != _elementType)
return .ElementTypeMismatch;
return .Ok;
}
public void EnsureTypeMatch<T>()
{
switch(typeof(T))
+62 -25
View File
@@ -196,7 +196,7 @@ public class Material : Asset
}
}
private mixin SetVariable(String name, var value)
private mixin SetVariable(StringView name, var value)
{
if(_variables.TryGetValue(name, let entry))
{
@@ -204,35 +204,72 @@ public class Material : Asset
}
}
public void SetVariable(String name, bool value) => SetVariable!(name, value);
public void SetVariable(String name, bool2 value) => SetVariable!(name, value);
public void SetVariable(String name, bool3 value) => SetVariable!(name, value);
public void SetVariable(String name, bool4 value) => SetVariable!(name, value);
public void SetVariable(String name, int32 value) => SetVariable!(name, value);
public void SetVariable(String name, int2 value) => SetVariable!(name, value);
public void SetVariable(String name, int3 value) => SetVariable!(name, value);
public void SetVariable(String name, int4 value) => SetVariable!(name, value);
public enum SetVariableError
{
VariableNotFound,
ElementTypeMismatch,
MatrixDimensionMismatch,
ProvidedBufferTooShort,
}
public void SetVariable(String name, uint32 value) => SetVariable!(name, value);
public void SetVariable(String name, uint2 value) => SetVariable!(name, value);
public void SetVariable(String name, uint3 value) => SetVariable!(name, value);
public void SetVariable(String name, uint4 value) => SetVariable!(name, value);
internal Result<void, SetVariableError> SetVariableRaw(StringView name, ShaderVariableType elementType, int32 rows, int32 columns, int32 arrayLength, Span<uint8> rawData)
{
if(!_variables.TryGetValue(name, let variable))
{
return .Err(.VariableNotFound);
}
public void SetVariable(String name, float value) => SetVariable!(name, value);
public void SetVariable(String name, float2 value) => SetVariable!(name, value);
public void SetVariable(String name, float3 value) => SetVariable!(name, value);
public void SetVariable(String name, float4 value) => SetVariable!(name, value);
let matchResult = variable.CheckTypematch(rows, columns, elementType);
public void SetVariable(String name, Color value) => SetVariable!(name, value);
public void SetVariable(String name, ColorRGB value) => SetVariable!(name, value);
public void SetVariable(String name, ColorRGBA value) => SetVariable!(name, value);
switch (matchResult)
{
case .Ok:
// Nothing went wrong.
case .ElementTypeMismatch:
return .Err(.ElementTypeMismatch);
case .MatrixDimensionMismatch:
return .Err(.MatrixDimensionMismatch);
}
public void SetVariable(String name, Matrix3x3 value) => SetVariable!(name, value);
public void SetVariable(String name, Matrix4x3 value) => SetVariable!(name, value);
public void SetVariable(String name, Matrix value) => SetVariable!(name, value);
if (rawData.Length < variable._sizeInBytes)
return .Err(.ProvidedBufferTooShort);
public void GetVariable<T>(String name, out T value) where T : struct
// TODO: This method is very stupid atm.
// We could e.g. allow array length mismatches by simply copying the smaller amount of elements.
variable.SetRawData(rawData.Ptr);
return .Ok;
}
public void SetVariable(StringView name, bool value) => SetVariable!(name, value);
public void SetVariable(StringView name, bool2 value) => SetVariable!(name, value);
public void SetVariable(StringView name, bool3 value) => SetVariable!(name, value);
public void SetVariable(StringView name, bool4 value) => SetVariable!(name, value);
public void SetVariable(StringView name, int32 value) => SetVariable!(name, value);
public void SetVariable(StringView name, int2 value) => SetVariable!(name, value);
public void SetVariable(StringView name, int3 value) => SetVariable!(name, value);
public void SetVariable(StringView name, int4 value) => SetVariable!(name, value);
public void SetVariable(StringView name, uint32 value) => SetVariable!(name, value);
public void SetVariable(StringView name, uint2 value) => SetVariable!(name, value);
public void SetVariable(StringView name, uint3 value) => SetVariable!(name, value);
public void SetVariable(StringView name, uint4 value) => SetVariable!(name, value);
public void SetVariable(StringView name, float value) => SetVariable!(name, value);
public void SetVariable(StringView name, float2 value) => SetVariable!(name, value);
public void SetVariable(StringView name, float3 value) => SetVariable!(name, value);
public void SetVariable(StringView name, float4 value) => SetVariable!(name, value);
public void SetVariable(StringView name, Color value) => SetVariable!(name, value);
public void SetVariable(StringView name, ColorRGB value) => SetVariable!(name, value);
public void SetVariable(StringView name, ColorRGBA value) => SetVariable!(name, value);
public void SetVariable(StringView name, Matrix3x3 value) => SetVariable!(name, value);
public void SetVariable(StringView name, Matrix4x3 value) => SetVariable!(name, value);
public void SetVariable(StringView name, Matrix value) => SetVariable!(name, value);
public void GetVariable<T>(StringView name, out T value) where T : struct
{
Debug.Profiler.ProfileRendererFunction!();
+45 -17
View File
@@ -98,6 +98,7 @@ namespace GlitchyEngine.Renderer
static GBuffer _gBuffer;
static AssetHandle<Effect> TestFullscreenEffect;
static Material TestDeferredMaterial ~ _?.ReleaseRef();
static AssetHandle<Effect> s_tonemappingEffect;
static BlendState _gBufferBlend;
@@ -179,6 +180,9 @@ namespace GlitchyEngine.Renderer
static void InitDeferredRenderer()
{
TestFullscreenEffect = Content.LoadAsset("Resources/Shaders/simpleLight.fx", null, true);
TestDeferredMaterial = new Material(TestFullscreenEffect);
s_tonemappingEffect = Content.LoadAsset("Resources/Shaders/SimpleTonemapping.fx", null, true);
_gBuffer = new GBuffer();
@@ -362,32 +366,56 @@ namespace GlitchyEngine.Renderer
{
Debug.Profiler.ProfileRendererScope!("Draw Light");
Effect fsEffect = TestFullscreenEffect.Get();
//Effect fsEffect = TestFullscreenEffect.Get();
if (fsEffect == null)
if (TestDeferredMaterial == null)
continue;
float3 lightDir = -light.Transform.Forward;
fsEffect.SetTexture("GBuffer_Albedo", _gBuffer.Target, 0);
fsEffect.SetTexture("GBuffer_Normal", _gBuffer.Target, 1);
fsEffect.SetTexture("GBuffer_Tangent", _gBuffer.Target, 2);
fsEffect.SetTexture("GBuffer_Position", _gBuffer.Target, 3);
fsEffect.SetTexture("GBuffer_Emissive", _gBuffer.Target, 4);
fsEffect.SetTexture("GBuffer_Material", _gBuffer.Target, 5);
/*TestDeferredMaterial.SetTexture("GBuffer_Albedo", _gBuffer.Target, 0);
TestDeferredMaterial.SetTexture("GBuffer_Normal", _gBuffer.Target, 1);
TestDeferredMaterial.SetTexture("GBuffer_Tangent", _gBuffer.Target, 2);
TestDeferredMaterial.SetTexture("GBuffer_Position", _gBuffer.Target, 3);
TestDeferredMaterial.SetTexture("GBuffer_Emissive", _gBuffer.Target, 4);
TestDeferredMaterial.SetTexture("GBuffer_Material", _gBuffer.Target, 5);*/
fsEffect.Variables["LightColor"].SetData(light.Light.Color);
fsEffect.Variables["Illuminance"].SetData(light.Light.Illuminance);
fsEffect.Variables["LightDir"].SetData(lightDir);
TestDeferredMaterial.SetVariable("LightColor", light.Light.Color);
TestDeferredMaterial.SetVariable("Illuminance", light.Light.Illuminance);
TestDeferredMaterial.SetVariable("LightDir", lightDir);
fsEffect.Variables["CameraPos"].SetData(_sceneConstants.CameraPosition);
TestDeferredMaterial.SetVariable("CameraPos", _sceneConstants.CameraPosition);
fsEffect.Variables["Scaling"].SetData(scaling);
TestDeferredMaterial.SetVariable("Scaling", scaling);
fsEffect.ApplyChanges();
fsEffect.Bind();
//RenderCommand.BindEffect(TestFullscreenEffect);
TestDeferredMaterial.Bind();
// TODO: Don't do that please...
using (let vb = _gBuffer.Target.GetViewBinding(0))
{
RenderCommand.BindTexture(vb, 0, .Pixel);
}
using (let vb = _gBuffer.Target.GetViewBinding(1))
{
RenderCommand.BindTexture(vb, 1, .Pixel);
}
using (let vb = _gBuffer.Target.GetViewBinding(2))
{
RenderCommand.BindTexture(vb, 2, .Pixel);
}
using (let vb = _gBuffer.Target.GetViewBinding(3))
{
RenderCommand.BindTexture(vb, 3, .Pixel);
}
using (let vb = _gBuffer.Target.GetViewBinding(4))
{
RenderCommand.BindTexture(vb, 4, .Pixel);
}
using (let vb = _gBuffer.Target.GetViewBinding(5))
{
RenderCommand.BindTexture(vb, 5, .Pixel);
}
FullscreenQuad.Draw();
}
+5 -5
View File
@@ -640,9 +640,9 @@ namespace GlitchyEngine.Renderer
return;
s_quadInstanceBuffer.SetData<QuadBatchVertex>(s_rawQuadInstances.Ptr, s_setQuadInstances, 0, .WriteDiscard);
//s_currentQuadEffect.ApplyChanges();
//s_currentQuadEffect.Bind();
// TODO: Bind scene buffer
material.SetVariable("ViewProjection", sceneViewProjection);
material.Bind();
using (TextureViewBinding tvb = texture.GetViewBinding())
@@ -1151,8 +1151,8 @@ namespace GlitchyEngine.Renderer
uvTransform = sprite.TextureCoordinates;
}
// TODO: Material for Sprite renderer
DrawQuad(transform, spriteTexture ?? s_whiteTexture, null, spriteRenderer.Color, uvTransform, entityId);
Material material = spriteRenderer.Material.Get();
DrawQuad(transform, spriteTexture ?? s_whiteTexture, material, spriteRenderer.Color, uvTransform, entityId);
}
public static void DrawCircle(Matrix transform, CircleRendererComponent* spriteRenderer, uint32 entityId)
+176 -2
View File
@@ -12,15 +12,18 @@ using GlitchyEngine.Scripting;
using GlitchyEngine.Serialization;
using GlitchyEngine.Editor;
using GlitchyEngine.World.Components;
using GlitchyEngine.Content;
using GlitchyEngine.Renderer;
using static GlitchyEngine.Renderer.Text.FontRenderer;
namespace GlitchyEngine.Scripting;
using internal GlitchyEngine.Scripting;
using internal GlitchyEngine.Content;
class MessageOrigin
{
private String _fileName;
private String _fileName ~ delete:append _;
private int _lineNumber;
public StringView FileName => _fileName;
@@ -91,8 +94,11 @@ static class ScriptGlue
RegisterComponent<TransformComponent>("GlitchyEngine.Core.Transform");
RegisterComponent<Rigidbody2DComponent>("GlitchyEngine.Physics.Rigidbody2D");
RegisterComponent<CameraComponent>("GlitchyEngine.Core.Camera");
RegisterComponent<SpriteRendererComponent>("GlitchyEngine.Graphics.SpriteRenderer");
RegisterComponent<CircleRendererComponent>("GlitchyEngine.Graphics.CircleRenderer");
RegisterComponent<TextRendererComponent>("GlitchyEngine.Graphics.Text.TextRenderer");
RegisterComponent<MeshComponent>("GlitchyEngine.Graphics.Mesh");
RegisterComponent<MeshRendererComponent>("GlitchyEngine.Graphics.MeshRenderer");
}
[RegisterMethod]
@@ -211,13 +217,29 @@ static class ScriptGlue
#region Exception Helpers
/// Throws an argument exception.
/// Throws an ArgumentException in the mono runtime.
[NoReturn]
static void ThrowArgumentException(char8* argument, char8* message)
{
MonoException* exception = Mono.mono_get_exception_argument(argument, message);
Mono.mono_raise_exception(exception);
}
/// Throws an InvalidOperationException in the mono runtime.
[NoReturn]
static void ThrowInvalidOperationException(char8* message)
{
MonoException* exception = Mono.mono_get_exception_invalid_operation(message);
Mono.mono_raise_exception(exception);
}
/// Throws an NotImplementedException in the mono runtime.
[NoReturn]
static void ThrowNotImplementedException(char8* message)
{
MonoException* exception = Mono.mono_get_exception_invalid_operation(message);
Mono.mono_raise_exception(exception);
}
#endregion
@@ -998,6 +1020,53 @@ static class ScriptGlue
#endregion
#region SpriteRenderer
[RegisterCall("ScriptGlue::SpriteRenderer_GetColor")]
static void SpriteRenderer_GetColor(UUID entityId, out ColorRGBA color)
{
SpriteRendererComponent* spriteRenderer = GetComponentSafe<SpriteRendererComponent>(entityId);
color = spriteRenderer.Color;
}
[RegisterCall("ScriptGlue::SpriteRenderer_SetColor")]
static void SpriteRenderer_SetColor(UUID entityId, ColorRGBA color)
{
SpriteRendererComponent* spriteRenderer = GetComponentSafe<SpriteRendererComponent>(entityId);
spriteRenderer.Color = color;
}
[RegisterCall("ScriptGlue::SpriteRenderer_GetUvTransform")]
static void SpriteRenderer_GetUvTransform(UUID entityId, out float4 uvTransform)
{
SpriteRendererComponent* spriteRenderer = GetComponentSafe<SpriteRendererComponent>(entityId);
uvTransform = spriteRenderer.UvTransform;
}
[RegisterCall("ScriptGlue::SpriteRenderer_SetUvTransform")]
static void SpriteRenderer_SetUvTransform(UUID entityId, float4 uvTransform)
{
SpriteRendererComponent* spriteRenderer = GetComponentSafe<SpriteRendererComponent>(entityId);
spriteRenderer.UvTransform = uvTransform;
}
[RegisterCall("ScriptGlue::SpriteRenderer_GetMaterial")]
static void SpriteRenderer_GetMaterial(UUID entityId, out AssetHandle assetId)
{
SpriteRendererComponent* spriteRenderer = GetComponentSafe<SpriteRendererComponent>(entityId);
assetId = spriteRenderer.Material;
}
[RegisterCall("ScriptGlue::SpriteRenderer_SetMaterial")]
static void SpriteRenderer_SetMaterial(UUID entityId, AssetHandle assetId)
{
SpriteRendererComponent* spriteRenderer = GetComponentSafe<SpriteRendererComponent>(entityId);
spriteRenderer.Material = assetId;
}
#endregion
#region TextRenderer
[RegisterCall("ScriptGlue::TextRenderer_SetIsRichText")]
@@ -1084,6 +1153,27 @@ static class ScriptGlue
#endregion
#region Mesh
#endregion
#region MeshRenderer
[RegisterCall("ScriptGlue::MeshRenderer_GetMaterial")]
static void MeshRenderer_GetMaterial(UUID entityId, out AssetHandle assetId)
{
MeshRendererComponent* meshRenderer = GetComponentSafe<MeshRendererComponent>(entityId);
assetId = meshRenderer.Material;
}
[RegisterCall("ScriptGlue::MeshRenderer_SetMaterial")]
static void MeshRenderer_SetMaterial(UUID entityId, AssetHandle assetId)
{
MeshRendererComponent* meshRenderer = GetComponentSafe<MeshRendererComponent>(entityId);
meshRenderer.Material = assetId;
}
#endregion
#region Math
private static void RegisterMathFunctions()
@@ -1234,6 +1324,89 @@ static class ScriptGlue
#endregion
#region Asset
/*static mixin GetAssetOrThrow(UUID assetId)
{
AssetHandle handle = .(assetId);
Asset asset = Content.GetAsset(handle, blocking: true);
if (asset == null)
{
ThrowInvalidOperationException(scope $"No asset exists for AssetHandle \"{assetId}\".");
}
asset
}*/
static mixin GetAssetOrThrow<T>(UUID assetId) where T : Asset
{
AssetHandle handle = .(assetId);
T asset = Content.GetAsset<T>(handle, blocking: true);
if (asset == null)
{
ThrowInvalidOperationException(scope $"No asset exists for AssetHandle \"{assetId}\".");
}
asset
}
static mixin GetAssetOrThrow<T>(AssetHandle assetHandle) where T : Asset
{
T asset = Content.GetAsset<T>(assetHandle, blocking: true);
if (asset == null)
{
ThrowInvalidOperationException(scope $"No asset exists for AssetHandle \"{assetHandle}\".");
}
asset
}
[RegisterCall("ScriptGlue::Asset_GetIdentifier")]
static void Asset_GetIdentifier(UUID assetId, out MonoString* text)
{
Asset asset = GetAssetOrThrow!<Asset>(assetId);
text = Mono.mono_string_new_len(ScriptEngine.[Friend]s_AppDomain, asset.Identifier.Ptr, (uint32)asset.Identifier.Length);
}
[RegisterCall("ScriptGlue::Asset_SetIdentifier")]
static void Asset_GetIdentifier(UUID assetId, MonoString* text)
{
ThrowNotImplementedException("Asset.GetIdentifier is not implemented.");
/*AssetHandle handle = .(assetId);
Asset asset = Content.GetAsset(handle, blocking: true);
char8* rawText = Mono.mono_string_to_utf8(text);
// TODO: I think it's not THAT easy.
asset.Identifier = StringView(rawText);
Mono.mono_free(rawText);*/
}
#endregion
#region Material
[RegisterCall("ScriptGlue::Material_SetVariable")]
static void Material_SetVariable(AssetHandle assetHandle, MonoString* managedVariableName, ShaderVariableType elementType, int32 rows, int32 columns, int32 arrayLength, uint8* rawData, int32 dataLength)
{
Material material = GetAssetOrThrow!<Material>(assetHandle);
char8* rawVariableName = Mono.mono_string_to_utf8(managedVariableName);
defer Mono.mono_free(rawVariableName);
StringView variableName = StringView(rawVariableName);
material.[Friend]SetVariableRaw(variableName, elementType, rows, columns , arrayLength, Span<uint8>(rawData, dataLength));
}
#endregion
#region ImGui Extension
[RegisterCall("ScriptGlue::ImGuiExtension_ListElementGrabber")]
@@ -1242,6 +1415,7 @@ static class ScriptGlue
ImGui.ImGui.ListElementGrabber();
}
#endregion
private static void RegisterCall<T>(String name, T method) where T : var
@@ -49,6 +49,8 @@ namespace GlitchyEngine.World
public ColorRGBA Color = .White;
public float4 UvTransform = .(0, 0, 1, 1);
public AssetHandle<Material> Material = .Invalid;
public this()
{
-2
View File
@@ -233,8 +233,6 @@ class SceneRenderer
FontRenderer.DrawText(text.PreparedText, transform.WorldTransform, text.Color, entity.Index);
}
//FontRenderer.DrawText(_smallLinesInfo, 0, 0);
Renderer2D.EndScene();
Renderer2D.BeginScene(camera, .BackToFront);