using System; using GlitchyEngine; using GlitchyEngine.Events; using System.Diagnostics; using GlitchLog; using GlitchyEngine.ImGui; using ImGui; using GlitchyEngine.Renderer; using GlitchyEngine.Math; using GlitchyEngine.World; using System.Collections; using GlitchyEngine.Content; using GlitchyEngine.Renderer.Animation; 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 _; // OrthographicCameraController _cameraController ~ 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 OrthographicCameraController(Application.Get().Window.Context.SwapChain.BackbufferViewport.Width / // Application.Get().Window.Context.SwapChain.BackbufferViewport.Height); _cameraController = new .(Application.Get().Window.Context.SwapChain.BackbufferViewport.Width / Application.Get().Window.Context.SwapChain.BackbufferViewport.Height); _cameraController.CameraPosition = .(0, 0, -5); _cameraController.TranslationSpeed = 10; TestLoadModel(); } List Clips = new List() ~ 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\\Figure\\Figure.gltf", testEffect, materialTestMaterial, _world, Clips); materialTestMaterial.ReleaseRef(); testEffect.ReleaseRef(); for(var (entity, transform, mesh, meshRenderer) in _world.Enumerate()) { var animation = _world.AssignComponent(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(); _world.Register(); _world.Register(); _world.Register(); _world.Register(); _world.Register(); _world.Register(); _world.Register(); 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(entity); *transform = TransformComponent(); transform.LocalTransform = Matrix.Translation(x * 0.2f, y * 0.2f, 0) * Matrix.Scaling(0.1f); var mesh = _world.AssignComponent(entity); mesh.Mesh = _quadGeometryBinding; i++; var meshRenderer = _world.AssignComponent(entity); if(i % 2 == 0) meshRenderer.Material = testMaterial1; else meshRenderer.Material = testMaterial2; } crazyParent = _world.NewEntity(); evenCrazierParent = _world.NewEntity(); var crazyTransform = _world.AssignComponent(evenCrazierParent); crazyTransform.Position = .Zero; crazyTransform.Scale = .One; crazyTransform.Rotation = .Identity; var pp = _world.AssignComponent(crazyParent); pp.Entity = evenCrazierParent; crazyTransform = _world.AssignComponent(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(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()) { Renderer.Submit(mesh.Mesh, meshRenderer.Material, transform.WorldTransform); } for(var (entity, transform, mesh, meshRenderer, animation) in _world.Enumerate()) { 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.RotationZ(f) * .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(scope (e) => OnImGuiRender(e)); dispatcher.Dispatch(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; } } class SandboxApp : Application { public this() { #if SANDBOX_2D PushLayer(new ExampleLayer2D()); #else PushLayer(new ExampleLayer()); #endif } [Export, LinkName("CreateApplication")] public static Application CreateApplication() { return new SandboxApp(); } } }