Sort and render transparent objects last (#277)

This commit is contained in:
Anders Jenbo 2025-06-11 02:15:26 +02:00 committed by GitHub
parent 2c9d9ba920
commit b2354a85d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 89 additions and 15 deletions

View File

@ -439,6 +439,11 @@ HRESULT OpenGL1Renderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
return DD_OK; return DD_OK;
} }
void OpenGL1Renderer::EnableTransparency()
{
glDepthMask(GL_FALSE);
}
void OpenGL1Renderer::SubmitDraw( void OpenGL1Renderer::SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& worldMatrix, const D3DRMMATRIX4D& worldMatrix,
@ -524,6 +529,7 @@ void OpenGL1Renderer::SubmitDraw(
HRESULT OpenGL1Renderer::FinalizeFrame() HRESULT OpenGL1Renderer::FinalizeFrame()
{ {
glDepthMask(GL_TRUE);
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels); glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);

View File

@ -735,6 +735,11 @@ HRESULT Direct3DRMSDL3GPURenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
return DD_OK; return DD_OK;
} }
void Direct3DRMSDL3GPURenderer::EnableTransparency()
{
SDL_BindGPUGraphicsPipeline(m_renderPass, m_transparentPipeline);
}
void Direct3DRMSDL3GPURenderer::SubmitDraw( void Direct3DRMSDL3GPURenderer::SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& worldMatrix, const D3DRMMATRIX4D& worldMatrix,
@ -742,9 +747,6 @@ void Direct3DRMSDL3GPURenderer::SubmitDraw(
const Appearance& appearance const Appearance& appearance
) )
{ {
// TODO only switch piplinen after all opaque's have been rendered
SDL_BindGPUGraphicsPipeline(m_renderPass, appearance.color.a == 255 ? m_opaquePipeline : m_transparentPipeline);
D3DRMMATRIX4D worldViewMatrix; D3DRMMATRIX4D worldViewMatrix;
MultiplyMatrix(worldViewMatrix, worldMatrix, m_viewMatrix); MultiplyMatrix(worldViewMatrix, worldMatrix, m_viewMatrix);
memcpy(&m_uniforms.worldViewMatrix, worldViewMatrix, sizeof(D3DRMMATRIX4D)); memcpy(&m_uniforms.worldViewMatrix, worldViewMatrix, sizeof(D3DRMMATRIX4D));

View File

@ -554,6 +554,10 @@ HRESULT Direct3DRMSoftwareRenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
return DD_OK; return DD_OK;
} }
void Direct3DRMSoftwareRenderer::EnableTransparency()
{
}
void Direct3DRMSoftwareRenderer::SubmitDraw( void Direct3DRMSoftwareRenderer::SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& worldMatrix, const D3DRMMATRIX4D& worldMatrix,

View File

@ -216,6 +216,23 @@ bool IsMeshInFrustum(Direct3DRMMeshImpl* mesh, const D3DRMMATRIX4D& worldMatrix)
return true; return true;
} }
inline D3DRMVECTOR4D TransformPoint4(const D3DRMVECTOR4D& p, const D3DRMMATRIX4D& m)
{
return {
p.x * m[0][0] + p.y * m[1][0] + p.z * m[2][0] + p.w * m[3][0],
p.x * m[0][1] + p.y * m[1][1] + p.z * m[2][1] + p.w * m[3][1],
p.x * m[0][2] + p.y * m[1][2] + p.z * m[2][2] + p.w * m[3][2],
p.x * m[0][3] + p.y * m[1][3] + p.z * m[2][3] + p.w * m[3][3]
};
}
float CalculateDepth(const D3DRMMATRIX4D& viewProj, const D3DRMMATRIX4D& worldMatrix)
{
D3DRMVECTOR4D position = {worldMatrix[3][0], worldMatrix[3][1], worldMatrix[3][2], 1.0f};
D3DRMVECTOR4D clipPos = TransformPoint4(position, viewProj);
return (clipPos.z / clipPos.w + 1.0f) * 0.5f;
}
void Direct3DRMViewportImpl::CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix) void Direct3DRMViewportImpl::CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix)
{ {
Direct3DRMFrameImpl* frameImpl = static_cast<Direct3DRMFrameImpl*>(frame); Direct3DRMFrameImpl* frameImpl = static_cast<Direct3DRMFrameImpl*>(frame);
@ -251,15 +268,33 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3D
DWORD groupCount = mesh->GetGroupCount(); DWORD groupCount = mesh->GetGroupCount();
for (DWORD gi = 0; gi < groupCount; ++gi) { for (DWORD gi = 0; gi < groupCount; ++gi) {
const MeshGroup& meshGroup = mesh->GetGroup(gi); const MeshGroup& meshGroup = mesh->GetGroup(gi);
m_renderer->SubmitDraw(
m_renderer->GetMeshId(mesh, &meshGroup), Appearance appearance = {
worldMatrix, meshGroup.color,
worldMatrixInvert, meshGroup.material ? meshGroup.material->GetPower() : 0.0f,
{meshGroup.color, meshGroup.texture ? m_renderer->GetTextureId(meshGroup.texture) : NO_TEXTURE_ID,
meshGroup.material ? meshGroup.material->GetPower() : 0.0f, meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT
meshGroup.texture ? m_renderer->GetTextureId(meshGroup.texture) : NO_TEXTURE_ID, };
meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT}
); if (appearance.color.a != 255) {
m_deferredDraws.push_back(
{m_renderer->GetMeshId(mesh, &meshGroup),
{},
{},
appearance,
CalculateDepth(m_viewProjectionwMatrix, worldMatrix)}
);
memcpy(m_deferredDraws.back().worldMatrix, worldMatrix, sizeof(D3DRMMATRIX4D));
memcpy(m_deferredDraws.back().normalMatrix, worldMatrixInvert, sizeof(Matrix3x3));
}
else {
m_renderer->SubmitDraw(
m_renderer->GetMeshId(mesh, &meshGroup),
worldMatrix,
worldMatrixInvert,
appearance
);
}
} }
} }
mesh->Release(); mesh->Release();
@ -274,10 +309,10 @@ HRESULT Direct3DRMViewportImpl::RenderScene()
m_backgroundColor = static_cast<Direct3DRMFrameImpl*>(m_rootFrame)->m_backgroundColor; m_backgroundColor = static_cast<Direct3DRMFrameImpl*>(m_rootFrame)->m_backgroundColor;
// Compute view-projection matrix // Compute view-projection matrix
D3DRMMATRIX4D cameraWorld, viewProj; D3DRMMATRIX4D cameraWorld;
ComputeFrameWorldMatrix(m_camera, cameraWorld); ComputeFrameWorldMatrix(m_camera, cameraWorld);
D3DRMMatrixInvertOrthogonal(m_viewMatrix, cameraWorld); D3DRMMatrixInvertOrthogonal(m_viewMatrix, cameraWorld);
D3DRMMatrixMultiply(viewProj, m_viewMatrix, m_projectionMatrix); D3DRMMatrixMultiply(m_viewProjectionwMatrix, m_viewMatrix, m_projectionMatrix);
D3DRMMATRIX4D identity = {{1.f, 0.f, 0.f, 0.f}, {0.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 0.f}, {0.f, 0.f, 0.f, 1.f}}; D3DRMMATRIX4D identity = {{1.f, 0.f, 0.f, 0.f}, {0.f, 1.f, 0.f, 0.f}, {0.f, 0.f, 1.f, 0.f}, {0.f, 0.f, 0.f, 1.f}};
@ -289,8 +324,20 @@ HRESULT Direct3DRMViewportImpl::RenderScene()
return status; return status;
} }
ExtractFrustumPlanes(viewProj); ExtractFrustumPlanes(m_viewProjectionwMatrix);
CollectMeshesFromFrame(m_rootFrame, identity); CollectMeshesFromFrame(m_rootFrame, identity);
std::sort(
m_deferredDraws.begin(),
m_deferredDraws.end(),
[](const DeferredDrawCommand& a, const DeferredDrawCommand& b) { return a.depth > b.depth; }
);
m_renderer->EnableTransparency();
for (const DeferredDrawCommand& cmd : m_deferredDraws) {
m_renderer->SubmitDraw(cmd.meshId, cmd.worldMatrix, cmd.normalMatrix, cmd.appearance);
}
m_deferredDraws.clear();
return m_renderer->FinalizeFrame(); return m_renderer->FinalizeFrame();
} }

View File

@ -42,6 +42,7 @@ public:
virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0; virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0;
virtual const char* GetName() = 0; virtual const char* GetName() = 0;
virtual HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) = 0; virtual HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) = 0;
virtual void EnableTransparency() = 0;
virtual void SubmitDraw( virtual void SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& worldMatrix, const D3DRMMATRIX4D& worldMatrix,

View File

@ -48,6 +48,7 @@ public:
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override; const char* GetName() override;
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override; HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
void EnableTransparency() override;
void SubmitDraw( void SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& worldMatrix, const D3DRMMATRIX4D& worldMatrix,

View File

@ -55,6 +55,7 @@ public:
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override; const char* GetName() override;
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override; HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
void EnableTransparency() override;
void SubmitDraw( void SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& worldMatrix, const D3DRMMATRIX4D& worldMatrix,

View File

@ -36,6 +36,7 @@ public:
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override; const char* GetName() override;
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override; HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
void EnableTransparency() override;
void SubmitDraw( void SubmitDraw(
DWORD meshId, DWORD meshId,
const D3DRMMATRIX4D& worldMatrix, const D3DRMMATRIX4D& worldMatrix,

View File

@ -5,6 +5,15 @@
#include "miniwin/d3drm.h" #include "miniwin/d3drm.h"
#include <SDL3/SDL.h> #include <SDL3/SDL.h>
#include <vector>
struct DeferredDrawCommand {
DWORD meshId;
D3DRMMATRIX4D worldMatrix;
Matrix3x3 normalMatrix;
Appearance appearance;
float depth;
};
class Direct3DRMDeviceImpl; class Direct3DRMDeviceImpl;
class Direct3DRMFrameImpl; class Direct3DRMFrameImpl;
@ -40,9 +49,11 @@ private:
void CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix); void CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix);
void UpdateProjectionMatrix(); void UpdateProjectionMatrix();
Direct3DRMRenderer* m_renderer; Direct3DRMRenderer* m_renderer;
std::vector<DeferredDrawCommand> m_deferredDraws;
D3DCOLOR m_backgroundColor = 0xFF000000; D3DCOLOR m_backgroundColor = 0xFF000000;
DWORD m_width; DWORD m_width;
DWORD m_height; DWORD m_height;
D3DRMMATRIX4D m_viewProjectionwMatrix;
D3DRMMATRIX4D m_viewMatrix; D3DRMMATRIX4D m_viewMatrix;
D3DRMMATRIX4D m_projectionMatrix; D3DRMMATRIX4D m_projectionMatrix;
D3DRMMATRIX4D m_inverseProjectionMatrix; D3DRMMATRIX4D m_inverseProjectionMatrix;