mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Start of 3d renderer integration
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,73 @@
|
||||
cbuffer SceneConstants
|
||||
{
|
||||
float4x4 ViewProjection = float4x4(1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
cbuffer ObjectConstants
|
||||
{
|
||||
float4x4 Transform;
|
||||
}
|
||||
|
||||
cbuffer Constants
|
||||
{
|
||||
float4 BaseColor = float4(1, 0, 1, 1);
|
||||
//float3 LightDir = float3(0, 1, 0);
|
||||
}
|
||||
|
||||
struct VS_IN
|
||||
{
|
||||
float3 Position : POSITION;
|
||||
float3 Normal : NORMAL;
|
||||
};
|
||||
|
||||
struct PS_IN
|
||||
{
|
||||
float4 Position : SV_POSITION;
|
||||
float3 WorldPosition : TEXCOORD0;
|
||||
float3 Normal : NORMAL;
|
||||
};
|
||||
|
||||
PS_IN VS(VS_IN input)
|
||||
{
|
||||
PS_IN output;
|
||||
|
||||
float4 worldPosition = mul(Transform, float4(input.Position, 1));
|
||||
|
||||
output.Position = mul(ViewProjection, worldPosition);
|
||||
output.WorldPosition = worldPosition.xyz / worldPosition.w;
|
||||
output.Normal = mul((float3x3)Transform, input.Normal);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
struct PS_OUT
|
||||
{
|
||||
float4 Color : SV_TARGET0;
|
||||
float4 Normal : SV_TARGET1;
|
||||
float4 Position : SV_TARGET2;
|
||||
};
|
||||
|
||||
PS_OUT PS(PS_IN input)
|
||||
{
|
||||
input.Normal = normalize(input.Normal);
|
||||
|
||||
float f = distance(input.Normal, input.Normal);
|
||||
|
||||
//float shading = dot(LightDir, input.Normal);
|
||||
//float shading = dot(LightDir, LightDir) + 1;
|
||||
//shading = clamp(shading, 0.0f, 1.0f);
|
||||
|
||||
//return float4(BaseColor.rgb * shading, 1.0f);
|
||||
|
||||
PS_OUT output = (PS_OUT)0;
|
||||
output.Color = BaseColor;
|
||||
output.Normal = float4(input.Normal, 1);
|
||||
output.Position = float4(input.WorldPosition, 1);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#effect[VS=VS,PS=PS]
|
||||
@@ -0,0 +1,46 @@
|
||||
Texture2D Colors : register(t0);
|
||||
Texture2D<float3> Normals : register(t1);
|
||||
Texture2D Positions : register(t2);
|
||||
|
||||
SamplerState Sampler : register(s0);
|
||||
|
||||
cbuffer Constants
|
||||
{
|
||||
float3 LightDir = float3(0, 1, 0);
|
||||
}
|
||||
|
||||
struct VS_IN
|
||||
{
|
||||
float2 Position : POSITION;
|
||||
float2 TexCoord : TEXCOORD0;
|
||||
};
|
||||
|
||||
struct PS_IN
|
||||
{
|
||||
float4 Position : SV_POSITION;
|
||||
float2 TexCoord : TEXCOORD;
|
||||
};
|
||||
|
||||
PS_IN VS(VS_IN input)
|
||||
{
|
||||
PS_IN output;
|
||||
|
||||
output.Position = float4(input.Position, 0, 1);
|
||||
output.TexCoord = input.TexCoord;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 PS(PS_IN input) : SV_TARGET
|
||||
{
|
||||
float4 color = Colors.Sample(Sampler, input.TexCoord);
|
||||
float3 normal = Normals.Sample(Sampler, input.TexCoord);
|
||||
|
||||
//float shading = dot(LightDir, normal) + 100;
|
||||
float shading = dot(float3(0, 1, 0), normal);
|
||||
shading = clamp(shading, 0.0f, 1.0f);
|
||||
|
||||
return float4(color.rgb * shading, 1);
|
||||
}
|
||||
|
||||
#effect[VS=VS,PS=PS]
|
||||
@@ -0,0 +1,52 @@
|
||||
Texture2D Texture : register(t0);
|
||||
SamplerState Sampler : register(s0);
|
||||
|
||||
cbuffer Constants
|
||||
{
|
||||
float4x4 ViewProjection;
|
||||
|
||||
float ColorOffset = 0.5f;
|
||||
float AlphaOffset = 0.0f;
|
||||
float ColorScale = 0.5f;
|
||||
float AlphaScale = 1.0f;
|
||||
|
||||
float2 TextureSizeInPixels;
|
||||
}
|
||||
|
||||
struct VS_Input
|
||||
{
|
||||
float2 Position : POSITION;
|
||||
float2 Texcoord : TEXCOORD0;
|
||||
float4x4 Transform : TRANSFORM;
|
||||
float4 Color : COLOR;
|
||||
float4 UVTransform : TEXCOORD1;
|
||||
};
|
||||
|
||||
struct PS_Input
|
||||
{
|
||||
float4 Position : SV_Position;
|
||||
float2 Texcoord : TEXCOORD0;
|
||||
float4 Color : COLOR;
|
||||
};
|
||||
|
||||
PS_Input VS(VS_Input input)
|
||||
{
|
||||
PS_Input output;
|
||||
|
||||
output.Position = mul(ViewProjection, mul(input.Transform, float4(input.Position, 0.0f, 1.0f)));
|
||||
output.Texcoord = input.UVTransform.xy + input.UVTransform.zw * input.Texcoord;
|
||||
output.Color = input.Color;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 PS(PS_Input input) : SV_Target0
|
||||
{
|
||||
float4 color = Texture.Sample(Sampler, input.Texcoord);
|
||||
|
||||
float4 final = float4(ColorOffset.xxx, AlphaOffset) + color * float4(ColorScale.xxx, AlphaScale);
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
#effect[VS=VS, PS=PS]
|
||||
@@ -7,6 +7,9 @@ using GlitchyEngine.ImGui;
|
||||
using GlitchyEngine.Math;
|
||||
using GlitchyEngine.Renderer;
|
||||
using GlitchyEngine.World;
|
||||
using GlitchyEngine.Content;
|
||||
using System.Collections;
|
||||
using GlitchyEngine.Renderer.Animation;
|
||||
|
||||
namespace GlitchyEditor
|
||||
{
|
||||
@@ -83,6 +86,7 @@ namespace GlitchyEditor
|
||||
camera.Camera.SetPerspective(MathHelper.ToRadians(75), 0.1f, 10000.0f);
|
||||
camera.Primary = true;
|
||||
camera.FixedAspectRatio = false;
|
||||
camera.RenderTarget = _viewportTarget;
|
||||
let transform = _cameraEntity.GetComponent<TransformComponent>();
|
||||
transform.Position = .(0, 0, -5);
|
||||
|
||||
@@ -96,6 +100,7 @@ namespace GlitchyEditor
|
||||
camera.Camera.SetPerspective(MathHelper.ToRadians(45), 0.1f, 1000.0f);
|
||||
camera.Primary = false;
|
||||
camera.FixedAspectRatio = false;
|
||||
camera.RenderTarget = _viewportTarget;
|
||||
let transform = _otherCameraEntity.GetComponent<TransformComponent>();
|
||||
transform.Position = .(0, 0, -5);
|
||||
|
||||
@@ -104,6 +109,31 @@ namespace GlitchyEditor
|
||||
}
|
||||
|
||||
InitEditor();
|
||||
|
||||
TestEntitiesWithModels();
|
||||
}
|
||||
|
||||
private void TestEntitiesWithModels()
|
||||
{
|
||||
Effect myEffect = new Effect("content/Shaders/myEffect.hlsl")..ReleaseRefNoDelete();
|
||||
|
||||
Material mat = new Material(myEffect)..ReleaseRefNoDelete();
|
||||
mat.SetVariable("BaseColor", Vector4(1, 0, 1, 1));
|
||||
//mat.SetVariable("LightDir", Vector3(1, 1, 0).Normalized());
|
||||
|
||||
List<AnimationClip> clips = scope .();
|
||||
|
||||
ModelLoader.LoadModel("content/Models/plane.glb", myEffect, mat, _scene.[Friend]_ecsWorld, clips);
|
||||
|
||||
mat = new Material(myEffect)..ReleaseRefNoDelete();
|
||||
mat.SetVariable("BaseColor", Vector4(1, 1, 0, 1));
|
||||
//mat.SetVariable("LightDir", Vector3(0, 1, 0).Normalized());
|
||||
|
||||
clips = scope .();
|
||||
|
||||
ModelLoader.LoadModel("content/Models/plane.glb", myEffect, mat, _scene.[Friend]_ecsWorld, clips);
|
||||
|
||||
ClearAndReleaseItems!(clips);
|
||||
}
|
||||
|
||||
private void InitGraphics()
|
||||
@@ -184,9 +214,13 @@ namespace GlitchyEditor
|
||||
}
|
||||
|
||||
ImGui.ID _mainDockspaceId;
|
||||
|
||||
TextureViewer viewer = new TextureViewer() ~ delete _;
|
||||
|
||||
private bool OnImGuiRender(ImGuiRenderEvent event)
|
||||
{
|
||||
viewer.ViewTexture(Renderer.[Friend]_gBuffer.Normal);
|
||||
|
||||
ImGui.Begin("Test");
|
||||
|
||||
static bool cameraA = true;
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
using GlitchyEngine.Renderer;
|
||||
using GlitchyEngine;
|
||||
using ImGui;
|
||||
using GlitchyEngine.Math;
|
||||
using System;
|
||||
|
||||
namespace GlitchyEditor
|
||||
{
|
||||
class TextureViewer
|
||||
{
|
||||
enum BackgroundMode : int32
|
||||
{
|
||||
White,
|
||||
Black,
|
||||
Checkerboard
|
||||
}
|
||||
|
||||
enum SampleMode : int32
|
||||
{
|
||||
Point,
|
||||
Linear
|
||||
}
|
||||
|
||||
GraphicsContext _context ~ _.ReleaseRef();
|
||||
|
||||
Effect _effect ~ _.ReleaseRef();
|
||||
|
||||
float _zoom = 1.0f;
|
||||
|
||||
BackgroundMode _backgroundMode = .Checkerboard;
|
||||
|
||||
SampleMode _sampleMode = .Linear;
|
||||
|
||||
RenderTarget2D _target ~ _?.ReleaseRef();
|
||||
// TODO: we don't need depth!
|
||||
DepthStencilTarget _depth ~ _?.ReleaseRef();
|
||||
|
||||
SamplerState _samplerPoint ~ _.ReleaseRef();
|
||||
SamplerState _samplerLinear ~ _.ReleaseRef();
|
||||
|
||||
public this()
|
||||
{
|
||||
_context = Renderer.[Friend]_context..AddRef();
|
||||
|
||||
InitEffect();
|
||||
InitState();
|
||||
// TODO: rasterizerstate and depthstencilstate
|
||||
}
|
||||
|
||||
private void InitEffect()
|
||||
{
|
||||
_effect = new Effect("content\\Shaders\\textureViewerShader.hlsl");
|
||||
}
|
||||
|
||||
private void InitState()
|
||||
{
|
||||
SamplerStateDescription desc = .();
|
||||
desc.MagFilter = .Linear;
|
||||
desc.MinFilter = .Linear;
|
||||
_samplerLinear = SamplerStateManager.GetSampler(desc);
|
||||
|
||||
desc.MagFilter = .Point;
|
||||
desc.MinFilter = .Point;
|
||||
_samplerPoint = SamplerStateManager.GetSampler(desc);
|
||||
}
|
||||
|
||||
Vector2 _position;
|
||||
|
||||
bool _moving;
|
||||
|
||||
float _colorOffset = 0;
|
||||
float _colorScale = 1;
|
||||
float _alphaOffset = 0;
|
||||
float _alphaScale = 1;
|
||||
|
||||
public void ViewTexture(Texture viewedTexture)
|
||||
{
|
||||
ImGui.Begin("Texture Viewer");
|
||||
|
||||
ImGui.SliderFloat("Zoom", &_zoom, 0.01f, 100.0f);
|
||||
|
||||
char8*[] items = scope .("White", "Black", "Checkerboard");
|
||||
|
||||
ImGui.Combo("Background", (.)&_backgroundMode, items.Ptr, (.)items.Count);
|
||||
|
||||
items = scope .("Point", "Linear");
|
||||
|
||||
ImGui.Combo("Sampler", (.)&_sampleMode, items.Ptr, (.)items.Count);
|
||||
|
||||
ImGui.SliderFloat2("Color offset and scale", *(float[2]*)&_colorOffset, -1.0f, 1.0f);
|
||||
ImGui.SliderFloat2("Alpha offset and scale", *(float[2]*)&_alphaOffset, -1.0f, 1.0f);
|
||||
|
||||
ImGui.SliderFloat2("Position", *(float[2]*)&_position, 2 * -Math.Max(viewedTexture.Width, viewedTexture.Height) * _zoom, 2 * Math.Max(viewedTexture.Width, viewedTexture.Height) * _zoom);
|
||||
|
||||
ImGui.BeginChild("imageChild");
|
||||
|
||||
UpdateInput();
|
||||
|
||||
var viewportSize = ImGui.GetContentRegionAvail();
|
||||
|
||||
viewportSize.x = Math.Max(viewportSize.x, 1);
|
||||
viewportSize.y = Math.Max(viewportSize.y, 1);
|
||||
|
||||
if(_target == null || viewportSize.x != _target.Width || viewportSize.y != _target.Height)
|
||||
{
|
||||
_target?.ReleaseRef();
|
||||
_target = new RenderTarget2D(.(.R8G8B8A8_UNorm, (.)viewportSize.x, (.)viewportSize.y));
|
||||
_depth?.ReleaseRef();
|
||||
_depth = new DepthStencilTarget((.)viewportSize.x, (.)viewportSize.y, .D16_UNorm);
|
||||
}
|
||||
|
||||
RenderTexture(viewedTexture);
|
||||
|
||||
ImGui.Image(_target, viewportSize);
|
||||
|
||||
ImGui.EndChild();
|
||||
|
||||
ImGui.End();
|
||||
}
|
||||
|
||||
float lastWheel;
|
||||
|
||||
private void UpdateInput()
|
||||
{
|
||||
var windowPos = ImGui.GetWindowPos();
|
||||
var mousePos = ImGui.GetIO().MousePos;
|
||||
Vector2 mouseInWindow = .(mousePos.x - windowPos.x, mousePos.y - windowPos.y);
|
||||
|
||||
bool windowHovered = ImGui.IsWindowHovered();
|
||||
|
||||
if(windowHovered && Input.IsMouseButtonPressing(.MiddleButton))
|
||||
{
|
||||
_moving = true;
|
||||
}
|
||||
else if(Input.IsMouseButtonReleased(.MiddleButton))
|
||||
{
|
||||
_moving = false;
|
||||
}
|
||||
|
||||
if(windowHovered || _moving)
|
||||
{
|
||||
float mouseWheel = ImGui.GetIO().MouseWheel;
|
||||
|
||||
float delta = mouseWheel - lastWheel;
|
||||
|
||||
if(delta != 0)
|
||||
{
|
||||
_position -= mouseInWindow;
|
||||
_position /= _zoom;
|
||||
|
||||
_zoom *= Math.Pow(1.1f, delta);
|
||||
|
||||
_position *= _zoom;
|
||||
_position += mouseInWindow;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(_moving)
|
||||
{
|
||||
Point movement = Input.GetMouseMovement();
|
||||
|
||||
_position.X += movement.X;
|
||||
_position.Y += movement.Y;
|
||||
}
|
||||
}
|
||||
|
||||
OrthographicCamera _camera = new OrthographicCamera() ~ delete _;
|
||||
|
||||
private void RenderTexture(Texture viewedTexture)
|
||||
{
|
||||
Viewport vp = .(0, 0, _target.Width, _target.Height);
|
||||
RenderCommand.SetViewport(vp);
|
||||
|
||||
// TODO: don't clear pink!
|
||||
RenderCommand.Clear(_target, .Pink);
|
||||
RenderCommand.Clear(_depth, .Depth, 1.0f, 0);
|
||||
|
||||
//_target.Bind();
|
||||
_context.SetRenderTarget(_target);
|
||||
_context.SetDepthStencilTarget(_depth);
|
||||
_context.BindRenderTargets();
|
||||
|
||||
Vector2 textureSize = Vector2(viewedTexture.Width, viewedTexture.Height);
|
||||
Vector2 zoomedTextureSize = textureSize * _zoom;
|
||||
|
||||
Vector2 targetSize = Vector2(_target.Width, _target.Height);
|
||||
|
||||
_effect.Variables["ColorOffset"].SetData(_colorOffset);
|
||||
_effect.Variables["ColorScale"].SetData(_colorScale);
|
||||
_effect.Variables["AlphaOffset"].SetData(_alphaOffset);
|
||||
_effect.Variables["AlphaScale"].SetData(_alphaScale);
|
||||
|
||||
_camera.Left = 0;
|
||||
_camera.Top = 0;
|
||||
_camera.Right = targetSize.X;
|
||||
_camera.Bottom = -targetSize.Y;
|
||||
_camera.NearPlane = -5;
|
||||
_camera.FarPlane = 5;
|
||||
_camera.Update();
|
||||
|
||||
Renderer2D.BeginScene(_camera);
|
||||
|
||||
switch(_backgroundMode)
|
||||
{
|
||||
case .Black:
|
||||
Renderer2D.DrawQuadPivotCorner(Vector3(0, 0, 1), targetSize, 0, .Black);
|
||||
case .White:
|
||||
Renderer2D.DrawQuadPivotCorner(Vector3(0, 0, 1), targetSize, 0, .White);
|
||||
case .Checkerboard:
|
||||
float quadSize = 50.0f;
|
||||
|
||||
Vector2 numQuads = (targetSize / 500f) * 10f;
|
||||
|
||||
for(float x = 0; x < numQuads.X; x++)
|
||||
{
|
||||
for(float y = 0; y < numQuads.Y; y++)
|
||||
{
|
||||
Renderer2D.DrawQuadPivotCorner(Vector3(x * quadSize, -y * quadSize, 1), quadSize.XX, 0, ((x + y) % 2 == 0) ? .White : .Gray);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
Renderer2D.EndScene();
|
||||
|
||||
var sampler = viewedTexture.SamplerState;
|
||||
|
||||
switch(_sampleMode)
|
||||
{
|
||||
case .Point:
|
||||
viewedTexture.SamplerState = _samplerPoint;
|
||||
case .Linear:
|
||||
viewedTexture.SamplerState = _samplerLinear;
|
||||
}
|
||||
|
||||
Renderer2D.BeginScene(_camera, .SortByTexture, _effect);
|
||||
|
||||
Renderer2D.DrawQuad(Vector3(_position * .(1, -1), 0), zoomedTextureSize, 0, viewedTexture);
|
||||
|
||||
Renderer2D.EndScene();
|
||||
|
||||
viewedTexture.SamplerState = sampler;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user