Files
glitchy-engine-beef/Sandbox/src/ExampleLayer.bf
T
2022-02-13 02:14:56 +01:00

521 lines
15 KiB
Beef

using GlitchyEngine.Renderer;
using GlitchyEngine.Events;
using GlitchyEngine.ImGui;
using GlitchyEngine.Math;
using GlitchyEngine;
using System;
using GlitchyEngine.World;
using GlitchyEngine.Renderer.Animation;
using GlitchyEngine.Content;
using System.Collections;
namespace Sandbox
{
class ExampleLayer : Layer
{
[Ordered]
struct VertexColorTexture : IVertexData
{
public Vector3 Position;
public Color Color;
public Vector2 TexCoord;
public this() => this = default;
public this(Vector3 pos, Color color)
{
Position = pos;
Color = color;
TexCoord = .();
}
public this(Vector3 pos, Color color, Vector2 texCoord)
{
Position = pos;
Color = color;
TexCoord = texCoord;
}
public static readonly VertexElement[] VertexElements ~ delete _;
public static VertexElement[] IVertexData.VertexElements => VertexElements;
static this()
{
VertexElements = new VertexElement[](
VertexElement(.R32G32B32_Float, "POSITION"),
VertexElement(.R8G8B8A8_UNorm, "COLOR"),
VertexElement(.R32G32_Float, "TEXCOORD"),
);
}
}
GeometryBinding _geometryBinding ~ _?.ReleaseRef();
GeometryBinding _quadGeometryBinding ~ _?.ReleaseRef();
RasterizerState _rasterizerState ~ _?.ReleaseRef();
RasterizerState _rasterizerStateClockWise ~ _?.ReleaseRef();
GraphicsContext _context ~ _?.ReleaseRef();
DepthStencilTarget _depthTarget ~ _?.ReleaseRef();
Material _checkerMaterial ~ _?.ReleaseRef();
Material _logoMaterial ~ _?.ReleaseRef();
Texture2D _texture ~ _?.ReleaseRef();
Texture2D _ge_logo ~ _?.ReleaseRef();
BlendState _alphaBlendState ~ _?.ReleaseRef();
BlendState _opaqueBlendState ~ _?.ReleaseRef();
EcsWorld _world = new EcsWorld() ~ delete _;
PerspectiveCameraController _cameraController ~ delete _;
private Vector3 CircleCoord(float angle)
{
return .(Math.Cos(angle), Math.Sin(angle), 0);
}
[AllowAppend]
public this() : base("Example")
{
Application.Get().Window.IsVSync = false;
_context = Application.Get().Window.Context..AddRef();
var effectLibrary = Application.Get().EffectLibrary;
effectLibrary.LoadNoRefInc("content\\Shaders\\basicShader.hlsl");
effectLibrary.LoadNoRefInc("content\\Shaders\\testShader.hlsl");
var textureEffect = effectLibrary.Load("content\\Shaders\\textureShader.hlsl");
_depthTarget = new DepthStencilTarget(_context.SwapChain.Width, _context.SwapChain.Height);
// Create Input Layout
VertexLayout vertexLayout = new VertexLayout(VertexColorTexture.VertexElements, false, textureEffect.VertexShader);
textureEffect.ReleaseRef();
// Create hexagon
{
_geometryBinding = new GeometryBinding();
_geometryBinding.SetPrimitiveTopology(.TriangleList);
_geometryBinding.SetVertexLayout(vertexLayout);
float pO3 = Math.PI_f / 3.0f;
VertexColorTexture[?] vertices = .(
VertexColorTexture(.Zero, Color(255,255,255)),
VertexColorTexture(CircleCoord(0), Color(255, 0, 0)),
VertexColorTexture(CircleCoord(pO3), Color(255,255, 0)),
VertexColorTexture(CircleCoord(pO3*2), Color( 0,255, 0)),
VertexColorTexture(CircleCoord(Math.PI_f), Color( 0,255,255)),
VertexColorTexture(CircleCoord(-pO3*2), Color( 0, 0,255)),
VertexColorTexture(CircleCoord(-pO3), Color(255, 0,255)),
);
let vb = new VertexBuffer(typeof(VertexColorTexture), (.)vertices.Count, .Immutable);
vb.SetData(vertices);
_geometryBinding.SetVertexBufferSlot(vb, 0);
vb.ReleaseRef();
uint16[?] indices = .(
0, 1, 2,
0, 2, 3,
0, 3, 4,
0, 4, 5,
0, 5, 6,
0, 6, 1);
let ib = new IndexBuffer((.)indices.Count, .Immutable);
ib.SetData(indices);
_geometryBinding.SetIndexBuffer(ib);
ib.ReleaseRef();
}
// Create Quad
{
_quadGeometryBinding = new GeometryBinding();
_quadGeometryBinding.SetPrimitiveTopology(.TriangleList);
_quadGeometryBinding.SetVertexLayout(vertexLayout);
VertexColorTexture[?] vertices = .(
VertexColorTexture(Vector3(-0.75f, 0.75f, 0), Color.White, .(0, 0)),
VertexColorTexture(Vector3(-0.75f, -0.75f, 0), Color.White, .(0, 1)),
VertexColorTexture(Vector3(0.75f, -0.75f, 0), Color.White, .(1, 1)),
VertexColorTexture(Vector3(0.75f, 0.75f, 0), Color.White, .(1, 0)),
);
let qvb = new VertexBuffer(typeof(VertexColorTexture), (.)vertices.Count, .Immutable);
qvb.SetData(vertices);
_quadGeometryBinding.SetVertexBufferSlot(qvb, 0);
qvb.ReleaseRef();
uint16[?] indices = .(
0, 1, 2,
2, 3, 0);
let qib = new IndexBuffer((.)indices.Count, .Immutable);
qib.SetData(indices);
_quadGeometryBinding.SetIndexBuffer(qib);
qib.ReleaseRef();
}
vertexLayout.ReleaseRef();
// Create rasterizer state
RasterizerStateDescription rsDesc = .(.Solid, .Back, true);
_rasterizerState = new RasterizerState(rsDesc);
rsDesc.FrontCounterClockwise = false;
_rasterizerStateClockWise = new RasterizerState(rsDesc);
_texture = new Texture2D("content/Textures/Checkerboard.dds");
_ge_logo = new Texture2D("content/Textures/GE_Logo.dds");
let sampler = SamplerStateManager.GetSampler(
SamplerStateDescription()
{
MagFilter = .Point
});
_texture.SamplerState = sampler;
_ge_logo.SamplerState = sampler;
sampler.ReleaseRef();
_logoMaterial = new Material(textureEffect);
_logoMaterial.SetTexture("ColorTexture", _ge_logo);
_checkerMaterial = new Material(textureEffect);
_checkerMaterial.SetTexture("ColorTexture", _texture);
BlendStateDescription blendDesc = .();
blendDesc.RenderTarget[0] = .(true, .SourceAlpha, .InvertedSourceAlpha, .Add, .SourceAlpha, .InvertedSourceAlpha, .Add, .All);
_alphaBlendState = new BlendState(blendDesc);
_opaqueBlendState = new BlendState(.Default);
InitEcs();
_cameraController = new .(_context.SwapChain.AspectRatio);
_cameraController.CameraPosition = .(0, 0, -5);
_cameraController.TranslationSpeed = 10;
TestLoadModel();
}
List<AnimationClip> Clips = new List<AnimationClip>() ~ DeleteContainerAndReleaseItems!(_);
Material animationMat;
void TestLoadModel()
{
var testEffect = Application.Get().EffectLibrary.Get("testShader");
var materialTestMaterial = new Material(testEffect);
animationMat = materialTestMaterial;
Matrix[] matrices = scope Matrix[255];
Matrix3x3[] matrices2 = scope Matrix3x3[255];
for(int i < 255)
{
matrices[i] = .Identity;
matrices2[i] = .Identity;
}
materialTestMaterial.SetVariable("SkinningMatrices", matrices);
materialTestMaterial.SetVariable("InvTransSkinningMatrices", matrices2);
materialTestMaterial.SetVariable("BaseColor", Color.White);
materialTestMaterial.SetVariable("LightDir", Vector3(1, 1, -0.5f).Normalized());
ModelLoader.LoadModel("content\\Models\\RiggedFigure\\RiggedFigure.glb", testEffect, materialTestMaterial, _world, Clips);
materialTestMaterial.ReleaseRef();
testEffect.ReleaseRef();
for(var (entity, transform, mesh, meshRenderer) in _world.Enumerate<TransformComponent, MeshComponent, SkinnedMeshRendererComponent>())
{
var animation = _world.AssignComponent<AnimationComponent>(entity);
animation.AnimationClip = Clips[0];
animation.TimeScale = 1.0f;
animation.IsPlaying = true;
animation.[Friend]_pose = new SkeletonPose(meshRenderer.Skeleton);
}
}
Entity evenCrazierParent;
Entity crazyParent;
Material testMaterial1 ~ _?.ReleaseRef();
Material testMaterial2 ~ _?.ReleaseRef();
void InitEcs()
{
_world.Register<DebugNameComponent>();
_world.Register<TransformComponent>();
_world.Register<ParentComponent>();
_world.Register<MeshComponent>();
_world.Register<MeshRendererComponent>();
_world.Register<SkinnedMeshRendererComponent>();
_world.Register<CameraComponent>();
_world.Register<AnimationComponent>();
var basicEffect = Application.Get().EffectLibrary.Get("basicShader");
testMaterial1 = new Material(basicEffect);
testMaterial1.SetVariable("BaseColor", _squareColor0);
testMaterial2 = new Material(basicEffect);
testMaterial2.SetVariable("BaseColor", _squareColor1);
basicEffect.ReleaseRef();
/*
Entity[20][20] entities;
int i = 0;
for(int x < 20)
for(int y < 20)
{
Entity entity = _world.NewEntity();
entities[x][y] = entity;
var transform = _world.AssignComponent<TransformComponent>(entity);
*transform = TransformComponent();
transform.LocalTransform = Matrix.Translation(x * 0.2f, y * 0.2f, 0) * Matrix.Scaling(0.1f);
var mesh = _world.AssignComponent<MeshComponent>(entity);
mesh.Mesh = _quadGeometryBinding;
i++;
var meshRenderer = _world.AssignComponent<MeshRendererComponent>(entity);
if(i % 2 == 0)
meshRenderer.Material = testMaterial1;
else
meshRenderer.Material = testMaterial2;
}
crazyParent = _world.NewEntity();
evenCrazierParent = _world.NewEntity();
var crazyTransform = _world.AssignComponent<TransformComponent>(evenCrazierParent);
crazyTransform.Position = .Zero;
crazyTransform.Scale = .One;
crazyTransform.Rotation = .Identity;
var pp = _world.AssignComponent<ParentComponent>(crazyParent);
pp.Entity = evenCrazierParent;
crazyTransform = _world.AssignComponent<TransformComponent>(crazyParent);
crazyTransform.Position = .Zero;
crazyTransform.Scale = .(2.0f, 2.0f, 2.0f);
crazyTransform.Rotation = .Identity;
for(int x < 20)
for(int y < 20)
{
var parent = _world.AssignComponent<ParentComponent>(entities[x][y]);
parent.Entity = crazyParent;
}
*/
}
float f = 0.0f;
bool playAnimation = false;
public override void Update(GameTime gameTime)
{
f += (float)gameTime.FrameTime.TotalSeconds;
_cameraController.Update(gameTime);
RenderCommand.Clear(null, .(0.2f, 0.2f, 0.2f));
RenderCommand.Clear(_depthTarget, .Depth, 1.0f, 0);
// Draw test geometry
RenderCommand.SetRenderTarget(null);
RenderCommand.SetDepthStencilTarget(_depthTarget);
RenderCommand.BindRenderTargets();
RenderCommand.SetViewport(_context.SwapChain.BackbufferViewport);
Renderer.BeginScene(_cameraController.Camera);
RenderCommand.SetBlendState(_opaqueBlendState);
var basicEffect = Application.Get().EffectLibrary.Get("basicShader");
RenderCommand.SetRasterizerState(_rasterizerState);
TransformSystem.Update(_world);
for(var (entity, transform, mesh, meshRenderer) in _world.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>())
{
Renderer.Submit(mesh.Mesh, meshRenderer.Material, transform.WorldTransform);
}
for(var (entity, transform, mesh, meshRenderer, animation) in _world.Enumerate<TransformComponent, MeshComponent, SkinnedMeshRendererComponent, AnimationComponent>())
{
var material = meshRenderer.Material;
var timeIndex = ref animation.TimeIndex;
var currentClip = animation.AnimationClip;
var pose = animation.Pose;
// Only advance time index if animation is playing
if(animation.IsPlaying)
{
timeIndex += (float)gameTime.FrameTime.TotalSeconds * animation.TimeScale;
if(currentClip.IsLooping && currentClip.Duration != 0)
{
timeIndex %= currentClip.Duration;
// modulo can result in negative numbers
if(timeIndex < 0)
timeIndex += currentClip.Duration;
}
}
var skeleton = currentClip.Skeleton;
// Update joints
for(int i < skeleton.Joints.Count)
{
ref JointPose localPose = ref pose.LocalPose[i];
localPose = currentClip.JointAnimations[i].GetCurrentPose(timeIndex);
Matrix jointToParent =
Matrix.Translation(localPose.Translation) *
Matrix.RotationQuaternion(localPose.Rotation) *
Matrix.Scaling(localPose.Scale);
uint8 parentIndex = skeleton.Joints[i].ParentID;
ref Matrix globalPose = ref pose.GlobalPose[i];
if(parentIndex == uint8.MaxValue)
{
globalPose = jointToParent;
}
else
{
globalPose = pose.GlobalPose[parentIndex] * jointToParent;
}
pose.SkinningMatricies[i] = globalPose * skeleton.Joints[i].InverseBindPose;
pose.InvTransSkinningMatricies[i] = ((Matrix3x3)pose.SkinningMatricies[i]).Inverse().Transpose();
}
int i = 0;
for(var globalPose in pose.GlobalPose)
{
Joint currentJoint = meshRenderer.Skeleton.Joints[i];
Matrix bindPose = currentJoint.InverseBindPose.Invert();
// Draw skeleton
Matrix mat = pose.SkinningMatricies[i] * bindPose;
uint8 parentId = currentJoint.ParentID;
if(parentId != uint8.MaxValue)
{
Vector3 start = mat.Translation;
Joint parent = meshRenderer.Skeleton.Joints[parentId];
Matrix parentBindPose = parent.InverseBindPose.Invert();
Matrix parentMatrix = pose.SkinningMatricies[parentId] * parentBindPose;
Vector3 end = parentMatrix.Translation;
Renderer.DrawLine(start, end, .Black, transform.WorldTransform);
}
DebugRenderer.DrawCoordinateCross(transform.WorldTransform * mat, 0.5f);
i++;
}
material.SetVariable("SkinningMatrices", pose.SkinningMatricies);
material.SetVariable("InvTransSkinningMatrices", pose.InvTransSkinningMatricies);
// non engine
material.SetVariable("BaseColor", Color.White);
material.SetVariable("LightDir", Vector3(1, 1, -0.5f).Normalized());
Renderer.Submit(mesh.Mesh, material, transform.WorldTransform);
}
basicEffect.Variables["BaseColor"].SetData(_squareColor1);
_checkerMaterial.SetVariable("BaseColor", Color.White);
Renderer.Submit(_quadGeometryBinding, _checkerMaterial, Matrix.RotationY(f) * Matrix.RotationX(MathHelper.PiOverTwo) * .Scaling(1.5f));
RenderCommand.SetBlendState(_alphaBlendState);
_logoMaterial.SetVariable("BaseColor", Color.Pink);
Renderer.Submit(_quadGeometryBinding, _logoMaterial, .Translation(0, 0, -1) * .Scaling(2f));
DebugRenderer.Render(_world);
Renderer.EndScene();
basicEffect.ReleaseRef();
}
ColorRGBA _squareColor0 = ColorRGBA.CornflowerBlue;
ColorRGBA _squareColor1;
public override void OnEvent(Event event)
{
_cameraController.OnEvent(event);
EventDispatcher dispatcher = EventDispatcher(event);
dispatcher.Dispatch<ImGuiRenderEvent>(scope (e) => OnImGuiRender(e));
dispatcher.Dispatch<WindowResizeEvent>(scope (e) => OnWindowResize(e));
}
private bool OnImGuiRender(ImGuiRenderEvent e)
{
/*
ImGui.Begin("Test");
var v = ImGui.ColorEdit3("Square Color", ref _squareColor0);
if(v)
{
testMaterial1.SetVariable("BaseColor", _squareColor0);
testMaterial2.SetVariable("BaseColor", ColorRGBA.White - _squareColor0);
}
ImGui.End();
*/
return false;
}
private bool OnWindowResize(WindowResizeEvent e)
{
_depthTarget.ReleaseRef();
_depthTarget = new DepthStencilTarget(_context.SwapChain.Width, _context.SwapChain.Height);
return false;
}
}
}