Start of 3d renderer integration

This commit is contained in:
Simon Lübeß
2022-05-04 18:38:59 +02:00
parent 412d0ea965
commit 2817c5b1a1
16 changed files with 733 additions and 14 deletions
+2 -2
View File
@@ -37,7 +37,7 @@ namespace GlitchyEngine.Content
{
EcsEntity entity = world.NewEntity();
#if DEBUG
//#if DEBUG
var nameComponent = world.AssignComponent<DebugNameComponent>(entity);
if (node.Name != null)
@@ -48,7 +48,7 @@ namespace GlitchyEngine.Content
{
nameComponent.SetName("Unnamed Node");
}
#endif
//#endif
if(parentEntity.HasValue)
{
@@ -129,6 +129,14 @@ namespace GlitchyEngine.Renderer
SetDepthStencilTarget((renderTarget ?? _swapChain.BackBuffer).DepthStencilTarget);
}
}
public override void UnbindRenderTargets()
{
for (var rt in ref _renderTargets)
{
rt = null;
}
}
public override void BindRenderTargets()
{
@@ -193,7 +201,7 @@ namespace GlitchyEngine.Renderer
for(let entry in shader.Textures)
{
_textures[entry.Index] = entry.Texture?.nativeResourceView;
_textures[entry.Index] = entry.Texture?._nativeResourceView;
_samplers[entry.Index] = entry.Texture?.SamplerState?.nativeSamplerState;
if(entry.Index >= _textureCount)
@@ -75,6 +75,13 @@ namespace GlitchyEngine.Renderer
_context.SetDepthStencilTarget(target);
}
public override void UnbindRenderTargets()
{
Debug.Profiler.ProfileRendererFunction!();
_context.UnbindRenderTargets();
}
public override void BindRenderTargets()
{
Debug.Profiler.ProfileRendererFunction!();
@@ -49,6 +49,8 @@ namespace GlitchyEngine.Renderer
StringView str = StringView((char8*)errorBlob.GetBufferPointer(), (int)errorBlob.GetBufferSize());
Log.EngineLogger.Error($"Failed to compile Shader: Error Code({(int)result}): {result} | Error Message: {str}");
}
Log.EngineLogger.Assert(shaderBlob != null, "Shader compilation failed.");
}
protected internal void Reflect(ID3DBlob* shaderCode)
@@ -34,6 +34,11 @@ namespace GlitchyEngine.Renderer
* @param setDepthTarget If set to true the depth stencil target of the given renderTarget will be bound (only applies if slot is 0).
*/
public extern void SetRenderTarget(RenderTarget2D renderTarget, int slot = 0, bool setDepthTarget = true);
/**
* Unbinds all rendertargets.
*/
public extern void UnbindRenderTargets();
/**
* Binds all.
@@ -63,6 +63,11 @@ namespace GlitchyEngine.Renderer
_rendererAPI.SetDepthStencilTarget(target);
}
public static void UnbindRenderTargets()
{
_rendererAPI.UnbindRenderTargets();
}
public static void BindRenderTargets()
{
_rendererAPI.BindRenderTargets();
+217 -7
View File
@@ -1,5 +1,7 @@
using GlitchyEngine.Math;
using GlitchyEngine.World;
using System.Collections;
using System;
namespace GlitchyEngine.Renderer
{
@@ -8,6 +10,8 @@ namespace GlitchyEngine.Renderer
struct SceneConstants
{
public Matrix ViewProjection;
public Vector3 CameraPosition;
public RenderTarget2D CameraTarget;
}
struct ObjectConstants
@@ -15,6 +19,57 @@ namespace GlitchyEngine.Renderer
public Matrix Transform;
}
class GBuffer
{
private uint32 _width;
private uint32 _height;
public DepthStencilTarget DepthStencil;
public RenderTarget2D Color ~ _?.ReleaseRef();
public RenderTarget2D Normal ~ _?.ReleaseRef();
public RenderTarget2D Position ~ _?.ReleaseRef();
public void EnsureSize(uint32 width, uint32 height)
{
if (width <= _width && height <= _height)
return;
if (_width == 0 || _height == 0)
{
// Note: Depth-Buffer in Color-Target for convenience
RenderTarget2DDescription colorDesc = .(.R8G8B8A8_UNorm, width, height, 1, 1, .D24_UNorm_S8_UInt);
Color = new RenderTarget2D(colorDesc);
RenderTarget2DDescription normalDesc = .(.R32G32B32A32_Float, width, height);
Normal = new RenderTarget2D(normalDesc);
RenderTarget2DDescription positionDesc = .(.R32G32B32A32_Float, width, height);
Position = new RenderTarget2D(positionDesc);
}
_width = width;
_height = height;
Color.Resize(_width, _height);
Normal.Resize(_width, _height);
Position.Resize(_width, _height);
DepthStencil = Color.DepthStencilTarget;
}
public void Bind()
{
RenderCommand.SetDepthStencilTarget(DepthStencil);
RenderCommand.UnbindRenderTargets();
RenderCommand.SetRenderTarget(Color, 0);
RenderCommand.SetRenderTarget(Normal, 1);
RenderCommand.SetRenderTarget(Position, 2);
RenderCommand.BindRenderTargets();
}
}
static internal GraphicsContext _context ~ _?.ReleaseRef();
//static Buffer<SceneConstants> _sceneConstants ~ _?.ReleaseRef();
@@ -27,6 +82,9 @@ namespace GlitchyEngine.Renderer
static VertexBuffer LineVertices ~ _?.ReleaseRef();
static GeometryBinding LineGeometry ~ _?.ReleaseRef();
static GBuffer _gBuffer ~ delete _;
static Effect TestFullscreenEffect ~ _?.ReleaseRef();
public static void Init(GraphicsContext context, EffectLibrary effectLibrary)
{
Debug.Profiler.ProfileFunction!();
@@ -44,6 +102,9 @@ namespace GlitchyEngine.Renderer
Renderer2D.Init();
InitLineRenderer(effectLibrary);
InitDeferredRenderer(effectLibrary);
_gBuffer = new GBuffer();
}
public static void Deinit()
@@ -78,6 +139,50 @@ namespace GlitchyEngine.Renderer
VertexLayout layout = new VertexLayout(vertexElements, true, LineEffect.VertexShader);
LineGeometry.SetVertexLayout(layout..ReleaseRefNoDelete());
}
private static GeometryBinding s_quadGeometry ~ _?.ReleaseRef();
static void InitDeferredRenderer(EffectLibrary effectLibrary)
{
TestFullscreenEffect = effectLibrary.Load("content\\Shaders\\simpleLight.hlsl");
s_quadGeometry = new GeometryBinding();
s_quadGeometry.SetPrimitiveTopology(.TriangleList);
using(var quadVertices = new VertexBuffer(typeof(Vector4), 4, .Immutable))
{
Vector4[4] vertices = .(
.(-0.5f,-0.5f, 0, 1),
.(-0.5f, 0.5f, 0, 0),
.( 0.5f, 0.5f, 1, 0),
.( 0.5f,-0.5f, 1, 1)
);
quadVertices.SetData(vertices);
s_quadGeometry.SetVertexBufferSlot(quadVertices, 0);
}
using(var quadIndices = new IndexBuffer(6, .Immutable))
{
uint16[6] indices = .(
0, 1, 2,
2, 3, 0
);
quadIndices.SetData(indices);
s_quadGeometry.SetIndexBuffer(quadIndices);
}
VertexElement[] vertexElements = new .(
VertexElement(.R32G32_Float, "POSITION", false, 0, 0, 0, .PerVertexData, 0),
VertexElement(.R32G32_Float, "TEXCOORD", false, 0, 0, (.)-1, .PerVertexData, 0)
);
using (var quadBatchLayout = new VertexLayout(vertexElements, true, TestFullscreenEffect.VertexShader))
{
s_quadGeometry.SetVertexLayout(quadBatchLayout);
}
}
// TODO
/*public static void BeginScene(EcsWorld world, EcsEntity cameraEntity)
@@ -103,9 +208,98 @@ namespace GlitchyEngine.Renderer
//_sceneConstants.Update();
}
public static void BeginScene(Camera camera, Matrix transform, RenderTarget2D renderTarget)
{
Debug.Profiler.ProfileRendererFunction!();
Matrix viewProjection = camera.Projection * Matrix.Invert(transform);
_sceneConstants.ViewProjection = viewProjection;
_sceneConstants.CameraPosition = transform.Translation;
_sceneConstants.CameraTarget = renderTarget;
}
public static int SortMeshes(SubmittedMesh left, SubmittedMesh right)
{
// TODO: Once Material "inheritance" is ready we could perhaps check how similar materials are (e.g. shared textures/variables/etc...)
// Similar thing could be done for Meshes. Both would probably require a different way to sort howerver?...
int cmp = (int)Internal.UnsafeCastToPtr(left.Material) <=> (int)Internal.UnsafeCastToPtr(right.Material);
// Material equal: Sort by Mesh
if (cmp == 0)
{
cmp = (int)Internal.UnsafeCastToPtr(left.Mesh) <=> (int)Internal.UnsafeCastToPtr(right.Mesh);
// Material and Mesh equal: sort by distance
if (cmp == 0)
{
float distLeftSq = Vector3.DistanceSquared(_sceneConstants.CameraPosition, left.Transform.Translation);
float distRightSq = Vector3.DistanceSquared(_sceneConstants.CameraPosition, right.Transform.Translation);
// Whether or not the values are squared doesn't affect the order (because square(-root) is a monotonic function)
cmp = distLeftSq <=> distRightSq;
}
}
return 0;
}
public static void EndScene()
{
Debug.Profiler.ProfileRendererFunction!();
_queue.Sort(scope => SortMeshes);
// Deferred renderer:
// TODO: foreach light: draw shadow map
// foreach camera:
// {
_gBuffer.EnsureSize(_sceneConstants.CameraTarget.Width, _sceneConstants.CameraTarget.Height);
_gBuffer.Bind();
RenderCommand.Clear(_gBuffer.Color, .Color | .Depth, .Blue, 1, 0);
RenderCommand.Clear(_gBuffer.Normal, Color.Beige);
RenderCommand.Clear(_gBuffer.Position, Color.Black);
/*RenderCommand.UnbindRenderTargets();
RenderCommand.SetRenderTarget(_sceneConstants.CameraTarget, 0, true);
RenderCommand.BindRenderTargets();*/
// TODO: Draw into GBuffer
for (SubmittedMesh entry in _queue)
{
entry.Material.SetVariable("ViewProjection", _sceneConstants.ViewProjection);
entry.Material.SetVariable("Transform", entry.Transform);
entry.Material.Bind(_context);
entry.Mesh.Bind();
RenderCommand.DrawIndexed(entry.Mesh);
}
RenderCommand.UnbindRenderTargets();
RenderCommand.SetRenderTarget(_sceneConstants.CameraTarget, 0, true);
RenderCommand.BindRenderTargets();
_gBuffer.Color.SamplerState = SamplerStateManager.PointClamp;
TestFullscreenEffect.SetTexture("Colors", _gBuffer.Color);
TestFullscreenEffect.SetTexture("Normals", _gBuffer.Normal);
//TestFullscreenEffect.SetTexture("Positions", _gBuffer.Position);
//TestFullscreenEffect.SetVariable("LightDir");
TestFullscreenEffect.Bind(_context);
s_quadGeometry.Bind();
RenderCommand.DrawIndexed(s_quadGeometry);
// TODO: Draw lights to camera target
// }
// Queue entries increase the reference counter of the mesh/material thus we have to dispose of them.
ClearAndDisposeItems!(_queue);
}
public static void Submit(GeometryBinding geometry, Effect effect, Matrix transform = .Identity)
@@ -130,17 +324,33 @@ namespace GlitchyEngine.Renderer
RenderCommand.DrawIndexed(geometry);
}
struct SubmittedMesh : IDisposable
{
public GeometryBinding Mesh;
public Material Material;
public Matrix Transform;
public this(GeometryBinding mesh, Material material, Matrix transform)
{
Mesh = mesh..AddRef();
Material = material..AddRef();
Transform = transform;
}
public void Dispose()
{
Mesh.ReleaseRef();
Material.ReleaseRef();
}
}
private static List<SubmittedMesh> _queue = new .(10000) ~ DeleteContainerAndDisposeItems!(_);
public static void Submit(GeometryBinding geometry, Material material, Matrix transform = .Identity)
{
Debug.Profiler.ProfileRendererFunction!();
material.SetVariable("ViewProjection", _sceneConstants.ViewProjection);
material.SetVariable("Transform", transform);
material.Bind(_context);
geometry.Bind();
RenderCommand.DrawIndexed(geometry);
_queue.Add(SubmittedMesh(geometry, material, transform));
}
/** @brief Draws a line.
@@ -38,6 +38,8 @@ namespace GlitchyEngine.Renderer
public extern void SetDepthStencilTarget(DepthStencilTarget target);
public extern void UnbindRenderTargets();
public extern void BindRenderTargets();
public extern void SetRasterizerState(RasterizerState rasterizerState);
+17 -2
View File
@@ -249,16 +249,31 @@ namespace GlitchyEngine.World
}
}
struct CameraComponent
struct CameraComponent : IDisposableComponent
{
public SceneCamera Camera;
public bool Primary = true; // Todo: probably move into scene
public bool FixedAspectRatio = false;
private RenderTarget2D _renderTarget = null;
public RenderTarget2D RenderTarget
{
get => _renderTarget;
set mut
{
SetReference!(_renderTarget, value);
}
}
public this()
{
Camera = .();
}
}
public void Dispose()
{
_renderTarget?.ReleaseRef();
}
}
struct NativeScriptComponent : IDisposableComponent
+16 -2
View File
@@ -52,6 +52,7 @@ namespace GlitchyEngine.World
Camera* primaryCamera = null;
Matrix primaryCameraTransform = default;
RenderTarget2D renderTarget = null;
for (var (entity, transform, camera) in _ecsWorld.Enumerate<TransformComponent, CameraComponent>())
{
@@ -59,12 +60,23 @@ namespace GlitchyEngine.World
{
primaryCamera = &camera.Camera;
primaryCameraTransform = transform.WorldTransform;
renderTarget = camera.RenderTarget..AddRef();
}
}
// Sprite renderer
if (primaryCamera != null)
{
{
// 3D render
Renderer.BeginScene(*primaryCamera, primaryCameraTransform, renderTarget);
for (var (entity, transform, mesh, meshRenderer) in _ecsWorld.Enumerate<TransformComponent, MeshComponent, MeshRendererComponent>())
{
Renderer.Submit(mesh.Mesh, meshRenderer.Material, transform.WorldTransform);
}
Renderer.EndScene();
// Sprite renderer
Renderer2D.BeginScene(*primaryCamera, primaryCameraTransform);
for (var (entity, transform, sprite) in _ecsWorld.Enumerate<TransformComponent, SpriterRendererComponent>())
@@ -73,6 +85,8 @@ namespace GlitchyEngine.World
}
Renderer2D.EndScene();
renderTarget?.ReleaseRef();
}
}