fixing d3d11 depth buffers, adding depth buffer clear support

This commit is contained in:
Noel Berry 2021-02-21 23:00:37 -08:00
parent a72cd5cab6
commit 2de541fb18
10 changed files with 198 additions and 27 deletions

View File

@ -14,6 +14,15 @@ namespace Blah
class FrameBuffer; class FrameBuffer;
typedef std::shared_ptr<FrameBuffer> FrameBufferRef; typedef std::shared_ptr<FrameBuffer> FrameBufferRef;
enum class ClearMask
{
None = 0,
Color = 1,
Depth = 2,
Stencil = 4,
All = (int)Color | (int)Depth | (int)Stencil
};
class FrameBuffer class FrameBuffer
{ {
protected: protected:
@ -56,7 +65,7 @@ namespace Blah
virtual int height() const = 0; virtual int height() const = 0;
// Clears the FrameBuffer // Clears the FrameBuffer
virtual void clear(Color color) = 0; virtual void clear(Color color = Color::black, float depth = 1.0f, uint8_t stencil = 0, ClearMask mask = ClearMask::All) = 0;
}; };
} }

View File

@ -61,6 +61,8 @@ namespace Blah
float cos(float x); float cos(float x);
float tan(float x);
float atan2(float y, float x); float atan2(float y, float x);
float pow(float x, float n); float pow(float x, float n);

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "vec3.h"
namespace Blah namespace Blah
{ {
@ -36,8 +37,11 @@ namespace Blah
static Mat4x4 create_ortho(float width, float height, float z_near_plane, float z_far_plane); static Mat4x4 create_ortho(float width, float height, float z_near_plane, float z_far_plane);
static Mat4x4 create_ortho_offcenter(float left, float right, float bottom, float top, float z_near_plane, float z_far_plane); static Mat4x4 create_ortho_offcenter(float left, float right, float bottom, float top, float z_near_plane, float z_far_plane);
static Mat4x4 create_perspective(float field_of_view, float ratio, float z_near_plane, float z_far_plane);
static Mat4x4 create_translation(float x, float y, float z); static Mat4x4 create_translation(float x, float y, float z);
static Mat4x4 create_scale(float x, float y, float z); static Mat4x4 create_scale(float x, float y, float z);
static Mat4x4 create_lookat(Vec3 position, Vec3 target, Vec3 up);
Mat4x4 operator* (const Mat4x4& rhs); Mat4x4 operator* (const Mat4x4& rhs);
}; };

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "calc.h"
namespace Blah namespace Blah
{ {
@ -19,5 +20,37 @@ namespace Blah
, y(y) , y(y)
, z(z) , z(z)
{} {}
inline Vec3 operator +(const Vec3 rhs) const
{
return Vec3(x + rhs.x, y + rhs.y, z + rhs.z);
}
inline Vec3 operator -(const Vec3 rhs) const
{
return Vec3(x + rhs.x, y + rhs.y, z + rhs.z);
}
inline Vec3 normal() const
{
float ls = x * x + y * y + z * z;
float length = (float)Calc::sqrt(ls);
return Vec3(x / length, y / length, z / length);
}
static inline float dot(Vec3 a, Vec3 b)
{
return a.x * b.x +
a.y * b.y +
a.z * b.z;
}
static inline Vec3 cross(Vec3 a, Vec3 b)
{
return Vec3(
a.y * b.z - a.z * b.y,
a.z * b.x - a.x * b.z,
a.x * b.y - a.y * b.x);
}
}; };
} }

View File

@ -300,9 +300,9 @@ namespace
return App::draw_height(); return App::draw_height();
} }
virtual void clear(Color color) override virtual void clear(Color color, float depth, uint8_t stencil, ClearMask mask) override
{ {
GraphicsBackend::clear_backbuffer(color); GraphicsBackend::clear_backbuffer(color, depth, stencil, mask);
} }
}; };

View File

@ -39,7 +39,7 @@ namespace Blah
void render(const RenderPass& pass); void render(const RenderPass& pass);
// Clears the backbuffer // Clears the backbuffer
void clear_backbuffer(Color color); void clear_backbuffer(Color color, float depth, uint8_t stencil, ClearMask mask);
// Creates a new Texture. // Creates a new Texture.
// if the Texture is invalid, this should return an empty reference. // if the Texture is invalid, this should return an empty reference.

View File

@ -25,7 +25,8 @@ namespace Blah
ID3D11Device* device = nullptr; ID3D11Device* device = nullptr;
ID3D11DeviceContext* context = nullptr; ID3D11DeviceContext* context = nullptr;
IDXGISwapChain* swap_chain = nullptr; IDXGISwapChain* swap_chain = nullptr;
ID3D11RenderTargetView* backbuffer = nullptr; ID3D11RenderTargetView* backbuffer_view = nullptr;
ID3D11DepthStencilView* backbuffer_depth_view = nullptr;
// supported renderer features // supported renderer features
RendererFeatures features; RendererFeatures features;
@ -120,12 +121,10 @@ namespace Blah
desc.SampleDesc.Count = 1; desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0; desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT; desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0; desc.CPUAccessFlags = 0;
desc.MiscFlags = 0; desc.MiscFlags = 0;
if (is_framebuffer) bool is_depth_stencil = false;
desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
switch (format) switch (format)
{ {
@ -144,9 +143,18 @@ namespace Blah
case TextureFormat::DepthStencil: case TextureFormat::DepthStencil:
desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
m_size = width * height * 4; m_size = width * height * 4;
is_depth_stencil = true;
break; break;
} }
if (!is_depth_stencil)
desc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
else
desc.BindFlags |= D3D11_BIND_DEPTH_STENCIL;
if (is_framebuffer && !is_depth_stencil)
desc.BindFlags |= D3D11_BIND_RENDER_TARGET;
m_dxgi_format = desc.Format; m_dxgi_format = desc.Format;
auto hr = state.device->CreateTexture2D(&desc, NULL, &texture); auto hr = state.device->CreateTexture2D(&desc, NULL, &texture);
@ -158,11 +166,14 @@ namespace Blah
return; return;
} }
hr = state.device->CreateShaderResourceView(texture, NULL, &view); if (!is_depth_stencil)
if (!SUCCEEDED(hr))
{ {
texture->Release(); hr = state.device->CreateShaderResourceView(texture, NULL, &view);
texture = nullptr; if (!SUCCEEDED(hr))
{
texture->Release();
texture = nullptr;
}
} }
} }
@ -347,12 +358,27 @@ namespace Blah
return m_attachments[0]->height(); return m_attachments[0]->height();
} }
virtual void clear(Color color) override virtual void clear(Color color, float depth, uint8_t stencil, ClearMask mask) override
{ {
float col[4] = { color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f }; float col[4] = { color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f };
for (int i = 0; i < m_attachments.size(); i++) if (((int)mask & (int)ClearMask::Color) == (int)ClearMask::Color)
state.context->ClearRenderTargetView(color_views[i], col); {
for (int i = 0; i < m_attachments.size() - 1; i++)
state.context->ClearRenderTargetView(color_views[i], col);
}
if (depth_view)
{
UINT flags = 0;
if (((int)mask & (int)ClearMask::Depth) == (int)ClearMask::Depth)
flags |= D3D11_CLEAR_DEPTH;
if (((int)mask & (int)ClearMask::Stencil) == (int)ClearMask::Stencil)
flags |= D3D11_CLEAR_STENCIL;
if (flags != 0)
state.context->ClearDepthStencilView(depth_view, flags, depth, stencil);
}
} }
}; };
@ -722,10 +748,13 @@ namespace Blah
state.swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&frame_buffer); state.swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&frame_buffer);
if (frame_buffer) if (frame_buffer)
{ {
state.device->CreateRenderTargetView(frame_buffer, nullptr, &state.backbuffer); state.device->CreateRenderTargetView(frame_buffer, nullptr, &state.backbuffer_view);
frame_buffer->Release(); frame_buffer->Release();
} }
// TODO:
// create a depth backbuffer
// Store Features // Store Features
state.features.instancing = true; state.features.instancing = true;
state.features.max_texture_size = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; state.features.max_texture_size = D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
@ -802,8 +831,8 @@ namespace Blah
if (state.last_size != next_size) if (state.last_size != next_size)
{ {
// release old buffer // release old buffer
if (state.backbuffer) if (state.backbuffer_view)
state.backbuffer->Release(); state.backbuffer_view->Release();
// perform resize // perform resize
hr = state.swap_chain->ResizeBuffers(0, next_size.x, next_size.y, DXGI_FORMAT_B8G8R8A8_UNORM, 0); hr = state.swap_chain->ResizeBuffers(0, next_size.x, next_size.y, DXGI_FORMAT_B8G8R8A8_UNORM, 0);
@ -815,7 +844,7 @@ namespace Blah
hr = state.swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&frame_buffer); hr = state.swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&frame_buffer);
if (SUCCEEDED(hr) && frame_buffer) if (SUCCEEDED(hr) && frame_buffer)
{ {
hr = state.device->CreateRenderTargetView(frame_buffer, nullptr, &state.backbuffer); hr = state.device->CreateRenderTargetView(frame_buffer, nullptr, &state.backbuffer_view);
BLAH_ASSERT(SUCCEEDED(hr), "Failed to update Backbuffer on Resize"); BLAH_ASSERT(SUCCEEDED(hr), "Failed to update Backbuffer on Resize");
frame_buffer->Release(); frame_buffer->Release();
} }
@ -870,7 +899,7 @@ namespace Blah
// Set the Target // Set the Target
if (pass.target == App::backbuffer || !pass.target) if (pass.target == App::backbuffer || !pass.target)
{ {
ctx->OMSetRenderTargets(1, &state.backbuffer, nullptr); ctx->OMSetRenderTargets(1, &state.backbuffer_view, state.backbuffer_depth_view);
} }
else else
{ {
@ -1036,10 +1065,25 @@ namespace Blah
} }
} }
void GraphicsBackend::clear_backbuffer(Color color) void GraphicsBackend::clear_backbuffer(Color color, float depth, uint8_t stencil, ClearMask mask)
{ {
float clear[4] = { color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f }; if (((int)mask & (int)ClearMask::Color) == (int)ClearMask::Color)
state.context->ClearRenderTargetView(state.backbuffer, clear); {
float clear[4] = { color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f };
state.context->ClearRenderTargetView(state.backbuffer_view, clear);
}
if (state.backbuffer_depth_view)
{
UINT flags = 0;
if (((int)mask & (int)ClearMask::Depth) == (int)ClearMask::Depth)
flags |= D3D11_CLEAR_DEPTH;
if (((int)mask & (int)ClearMask::Stencil) == (int)ClearMask::Stencil)
flags |= D3D11_CLEAR_STENCIL;
if (flags != 0)
state.context->ClearDepthStencilView(state.backbuffer_depth_view, flags, depth, stencil);
}
} }
// Utility Methods // Utility Methods

View File

@ -749,13 +749,24 @@ namespace Blah
return m_height; return m_height;
} }
virtual void clear(Color color) override virtual void clear(Color color, float depth, uint8_t stencil, ClearMask mask) override
{ {
int clear = 0;
if (((int)mask & (int)ClearMask::Color) == (int)ClearMask::Color)
clear |= GL_COLOR_BUFFER_BIT;
if (((int)mask & (int)ClearMask::Depth) == (int)ClearMask::Depth)
clear |= GL_DEPTH_BUFFER_BIT;
if (((int)mask & (int)ClearMask::Stencil) == (int)ClearMask::Stencil)
clear |= GL_STENCIL_BUFFER_BIT;
gl.BindFramebuffer(GL_FRAMEBUFFER, m_id); gl.BindFramebuffer(GL_FRAMEBUFFER, m_id);
gl.Disable(GL_SCISSOR_TEST); gl.Disable(GL_SCISSOR_TEST);
gl.ColorMask(true, true, true, true); gl.ColorMask(true, true, true, true);
gl.ClearColor(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f); gl.ClearColor(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f);
gl.Clear(GL_COLOR_BUFFER_BIT); gl.ClearDepth(depth);
gl.ClearStencil(stencil);
gl.Clear(clear);
} }
}; };
@ -1485,13 +1496,24 @@ namespace Blah
} }
} }
void GraphicsBackend::clear_backbuffer(Color color) void GraphicsBackend::clear_backbuffer(Color color, float depth, uint8_t stencil, ClearMask mask)
{ {
int clear = 0;
if (((int)mask & (int)ClearMask::Color) == (int)ClearMask::Color)
clear |= GL_COLOR_BUFFER_BIT;
if (((int)mask & (int)ClearMask::Depth) == (int)ClearMask::Depth)
clear |= GL_DEPTH_BUFFER_BIT;
if (((int)mask & (int)ClearMask::Stencil) == (int)ClearMask::Stencil)
clear |= GL_STENCIL_BUFFER_BIT;
gl.BindFramebuffer(GL_FRAMEBUFFER, 0); gl.BindFramebuffer(GL_FRAMEBUFFER, 0);
gl.Disable(GL_SCISSOR_TEST); gl.Disable(GL_SCISSOR_TEST);
gl.ColorMask(true, true, true, true); gl.ColorMask(true, true, true, true);
gl.ClearColor(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f); gl.ClearColor(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f);
gl.Clear(GL_COLOR_BUFFER_BIT); gl.ClearDepth(depth);
gl.ClearStencil(stencil);
gl.Clear(clear);
} }
} }

View File

@ -113,6 +113,11 @@ float Calc::cos(float x)
return cosf(x); return cosf(x);
} }
float Calc::tan(float x)
{
return tanf(x);
}
float Calc::atan2(float y, float x) float Calc::atan2(float y, float x)
{ {
return atan2f(y, x); return atan2f(y, x);

View File

@ -1,4 +1,5 @@
#include <blah/math/mat4x4.h> #include <blah/math/mat4x4.h>
#include <blah/core/log.h>
using namespace Blah; using namespace Blah;
@ -59,6 +60,29 @@ Mat4x4 Mat4x4::create_ortho_offcenter(float left, float right, float bottom, flo
return result; return result;
} }
Mat4x4 Mat4x4::create_perspective(float field_of_view, float ratio, float z_near_plane, float z_far_plane)
{
float yScale = 1.0f / (float)Calc::tan(field_of_view * 0.5f);
float xScale = yScale / ratio;
Mat4x4 result;
result.m11 = xScale;
result.m12 = result.m13 = result.m14 = 0.0f;
result.m22 = yScale;
result.m21 = result.m23 = result.m24 = 0.0f;
result.m31 = result.m32 = 0.0f;
result.m33 = z_far_plane / (z_near_plane - z_far_plane);
result.m34 = -1.0f;
result.m41 = result.m42 = result.m44 = 0.0f;
result.m43 = z_near_plane * z_far_plane / (z_near_plane - z_far_plane);
return result;
}
Mat4x4 Mat4x4::create_translation(float x, float y, float z) Mat4x4 Mat4x4::create_translation(float x, float y, float z)
{ {
Mat4x4 result = identity; Mat4x4 result = identity;
@ -81,6 +105,34 @@ Mat4x4 Mat4x4::create_scale(float x, float y, float z)
return result; return result;
} }
Mat4x4 Mat4x4::create_lookat(Vec3 position, Vec3 target, Vec3 up)
{
Vec3 zaxis = (position - target).normal();
Vec3 xaxis = Vec3::cross(up, zaxis).normal();
Vec3 yaxis = Vec3::cross(zaxis, xaxis);
Mat4x4 result;
result.m11 = xaxis.x;
result.m12 = yaxis.x;
result.m13 = zaxis.x;
result.m14 = 0.0f;
result.m21 = xaxis.y;
result.m22 = yaxis.y;
result.m23 = zaxis.y;
result.m24 = 0.0f;
result.m31 = xaxis.z;
result.m32 = yaxis.z;
result.m33 = zaxis.z;
result.m34 = 0.0f;
result.m41 = -Vec3::dot(xaxis, position);
result.m42 = -Vec3::dot(yaxis, position);
result.m43 = -Vec3::dot(zaxis, position);
result.m44 = 1.0f;
return result;
}
Mat4x4 Mat4x4::operator*(const Mat4x4& rhs) Mat4x4 Mat4x4::operator*(const Mat4x4& rhs)
{ {
Mat4x4 m; Mat4x4 m;