Componentified Camera

This commit is contained in:
Simon Lübeß
2021-05-17 20:07:58 +02:00
parent 3e0c4b2eb7
commit 7fb1f30303
6 changed files with 234 additions and 34 deletions
@@ -0,0 +1,98 @@
using GlitchyEngine.Math;
namespace GlitchyEngine.Renderer
{
public struct CameraComponent
{
public enum Projection
{
/**
* A perspective projection with near and far plane.
*/
Perspective,
/**
* A perspective projection with near and far plane,
* except that the closer a pixel is to the far plane the smaller its depth-value gets.
*/
PerspectiveReversed,
/**
* A perspective projection with a near plane and a far plane at infinite distance.
*/
PerspectiveInfinite,
/**
* A perspective projection with a near plane and a far plane at infinite distance,
* except that the closer a pixel is to the far plane the smaller its depth-value gets.
*/
PerspectiveReversedInfinite,
/**
* An orthographic projection.
*/
Orthographic
}
float _nearPlane;
float _farPlane;
Projection _projectionType;
float _fovY;
float _aspect;
public float NearPlane
{
get => _nearPlane;
set mut => _nearPlane = value;
}
public float FarPlane
{
get => _farPlane;
set mut => _farPlane = value;
}
public Projection ProjectionType
{
get => _projectionType;
set mut => _projectionType = value;
}
public float FovY
{
get => _fovY;
set mut => _fovY = value;
}
public float FovX
{
get => _fovY * _aspect;
set mut => _fovY = value / _aspect;
}
public float Aspect
{
get => _aspect;
set mut => _aspect = value;
}
public Matrix Projection => CalculateProjection();
public Matrix CalculateProjection()
{
Log.EngineLogger.Assert(_nearPlane < _farPlane, "The near plane must be smaller than the far plane.");
switch(_projectionType)
{
case .Perspective:
return Matrix.PerspectiveProjection(_fovY, _aspect, _nearPlane, _farPlane);
case .PerspectiveReversed:
return Matrix.ReversedPerspectiveProjection(_fovY, _aspect, _nearPlane, _farPlane);
case .PerspectiveInfinite:
return Matrix.InfinitePerspectiveProjection(_fovY, _aspect, _nearPlane);
case .PerspectiveReversedInfinite:
return Matrix.ReversedInfinitePerspectiveProjection(_fovY, _aspect, _nearPlane);
default:
Log.EngineLogger.Assert(false, "Unknown projection type.");
}
return .Identity;
}
}
}
@@ -0,0 +1,7 @@
namespace GlitchyEngine.Renderer
{
public struct MeshComponent
{
public GeometryBinding Mesh;
}
}
+13
View File
@@ -1,4 +1,5 @@
using GlitchyEngine.Math;
using GlitchyEngine.World;
namespace GlitchyEngine.Renderer
{
@@ -36,6 +37,18 @@ namespace GlitchyEngine.Renderer
RenderCommand.Init();
}
public static void BeginScene(EcsWorld world, Entity cameraEntity)
{
var camera = world.GetComponent<CameraComponent>(cameraEntity);
var transform = world.GetComponent<TransformComponent>(cameraEntity);
var trans = transform.Transform;
var view = trans.Invert();
var proj = camera.Projection;
_sceneConstants.ViewProjection = proj * view;
}
public static void BeginScene(Camera camera)
{
_sceneConstants.ViewProjection = camera.ViewProjection;
+56 -5
View File
@@ -4,16 +4,67 @@ namespace GlitchyEngine.World
{
public struct TransformComponent
{
static int _id;
Vector3 _position = .Zero;
Vector3 _rotation = .Zero;
Vector3 _scale = .One;
public static int ID {get => _id; set => _id = value; }
internal Matrix _transform;
Matrix _transform;
bool _dirty;
public Matrix Transform
{
get => _transform;
get mut
{
return _transform;
}
set mut => _transform = value;
}
public Vector3 Position
{
get => _position;
set mut
{
if(_position == value)
return;
_position = value;
_dirty = true;
}
}
public Vector3 Rotation
{
get => _rotation;
set mut
{
if(_rotation == value)
return;
_rotation = value;
_dirty = true;
}
}
public Vector3 Scale
{
get => _scale;
set mut
{
if(_scale == value)
return;
_scale = value;
_dirty = true;
}
}
public void Update() mut
{
if(!_dirty)
return;
_transform = .Translation(_position) * .RotationX(_rotation.X) *
.RotationY(_rotation.Y) * .RotationZ(_rotation.Z) * .Scaling(_scale);
_dirty = false;
}
}
}
+59 -28
View File
@@ -7,13 +7,12 @@ using GlitchyEngine.ImGui;
using ImGui;
using GlitchyEngine.Renderer;
using GlitchyEngine.Math;
using GlitchyEngine.World;
namespace Sandbox
{
class ExampleLayer : Layer
{
private OrthographicCamera _camera ~ delete _; // PerspectiveCamera
[Ordered]
struct VertexColorTexture : IVertexData
{
@@ -69,6 +68,8 @@ namespace Sandbox
EffectLibrary _effectLibrary ~ delete _;
EcsWorld _world = new EcsWorld() ~ delete _;
private Vector3 CircleCoord(float angle)
{
return .(Math.Cos(angle), Math.Sin(angle), 0);
@@ -159,18 +160,6 @@ namespace Sandbox
GlitchyEngine.Renderer.RasterizerStateDescription rsDesc = .(.Solid, .Back, true);
_rasterizerState = new RasterizerState(_context, rsDesc);
// Camera
_camera = new OrthographicCamera();
_camera.NearPlane = -1;
_camera.FarPlane = 1;
/*
_camera = new PerspectiveCamera();
_camera.NearPlane = 0.1f;
_camera.FarPlane = 10.0f;
_camera.FovY = Math.PI_f / 4;
_camera.Position = .(0, -1, -5);
*/
_texture = new Texture2D(_context, "content/Textures/Checkerboard.dds");
_ge_logo = new Texture2D(_context, "content/Textures/GE_Logo.dds");
@@ -189,10 +178,45 @@ namespace Sandbox
blendDesc.RenderTarget[0] = .(true, .SourceAlpha, .InvertedSourceAlpha, .Add, .SourceAlpha, .InvertedSourceAlpha, .Add, .All);
_alphaBlendState = new BlendState(_context, blendDesc);
_opaqueBlendState = new BlendState(_context, .Default);
InitEcs();
}
Entity _cameraEntity;
void InitEcs()
{
_world.Register<TransformComponent>();
_world.Register<MeshComponent>();
_world.Register<CameraComponent>();
// Create camera entity
_cameraEntity = _world.NewEntity();
var cameraTransform = _world.AssignComponent<TransformComponent>(_cameraEntity);
var camera = _world.AssignComponent<CameraComponent>(_cameraEntity);
*cameraTransform = TransformComponent();
camera.NearPlane = 0.1f;
camera.FarPlane = 10.0f;
camera.FovY = Math.PI_f / 4;
cameraTransform.Position = .(0, -1, -5);
for(int x < 20)
for(int y < 20)
{
Entity entity = _world.NewEntity();
var transform = _world.AssignComponent<TransformComponent>(entity);
transform.Transform = Matrix.Translation(x * 0.2f, y * 0.2f, 0) * Matrix.Scaling(0.1f);
var mesh = _world.AssignComponent<MeshComponent>(entity);
mesh.Mesh = _quadGeometryBinding;
}
}
public override void Update(GameTime gameTime)
{
var cameraTransform = _world.GetComponent<TransformComponent>(_cameraEntity);
if(Application.Get().Window.IsActive)
{
Vector2 movement = .();
@@ -220,16 +244,13 @@ namespace Sandbox
movement *= (float)(gameTime.FrameTime.TotalSeconds);
_camera.Position += .(movement, 0);
cameraTransform.Position += .(movement, 0);
cameraTransform.Update();
}
_camera.Width = _context.SwapChain.BackbufferViewport.Width / 256;
_camera.Height = _context.SwapChain.BackbufferViewport.Height / 256;
//_camera.AspectRatio = Application.Get().Window.Context.SwapChain.BackbufferViewport.Width /
// Application.Get().Window.Context.SwapChain.BackbufferViewport.Height;
_camera.Update();
var camera = _world.GetComponent<CameraComponent>(_cameraEntity);
camera.Aspect = Application.Get().Window.Context.SwapChain.BackbufferViewport.Width /
Application.Get().Window.Context.SwapChain.BackbufferViewport.Height;
RenderCommand.Clear(null, .(0.2f, 0.2f, 0.2f));
@@ -241,23 +262,33 @@ namespace Sandbox
_context.SetViewport(_context.SwapChain.BackbufferViewport);
Renderer.BeginScene(_camera);
Renderer.BeginScene(_world, _cameraEntity);
_opaqueBlendState.Bind();
var basicEffect = _effectLibrary.Get("basicShader");
var textureEffect = _effectLibrary.Get("textureShader");
for(int x < 20)
for(int y < 20)
for(var entity in _world.Enumerate(typeof(TransformComponent)))
{
if((x + y) % 2 == 0)
var transform = _world.GetComponent<TransformComponent>(entity);
transform.Update();
}
int i = 0;
for(var entity in _world.Enumerate(typeof(TransformComponent), typeof(MeshComponent)))
{
i++;
if(i % 2 == 0)
basicEffect.Variables["BaseColor"].SetData(_squareColor0);
else
basicEffect.Variables["BaseColor"].SetData(_squareColor1);
Matrix transform = Matrix.Translation(x * 0.2f, y * 0.2f, 0) * Matrix.Scaling(0.1f);
Renderer.Submit(_quadGeometryBinding, basicEffect, transform);
var transform = _world.GetComponent<TransformComponent>(entity);
var mesh = _world.GetComponent<MeshComponent>(entity);
Renderer.Submit(mesh.Mesh, basicEffect, transform.Transform);
}
basicEffect.Variables["BaseColor"].SetData(_squareColor1);