From 0ac7fee23cde82f83eae26c67bdedee2e270a95d Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Wed, 4 Jun 2025 02:21:06 +0200 Subject: [PATCH 1/2] Renderer clean up (#228) --- .../src/d3drm/backends/opengl15/renderer.cpp | 9 ++------ .../src/d3drm/backends/sdl3gpu/renderer.cpp | 7 +------ .../src/d3drm/backends/software/renderer.cpp | 21 +++++++------------ miniwin/src/d3drm/d3drmviewport.cpp | 1 - miniwin/src/internal/d3drmrenderer.h | 1 - miniwin/src/internal/d3drmrenderer_opengl15.h | 2 -- miniwin/src/internal/d3drmrenderer_sdl3gpu.h | 2 -- miniwin/src/internal/d3drmrenderer_software.h | 2 -- 8 files changed, 11 insertions(+), 34 deletions(-) diff --git a/miniwin/src/d3drm/backends/opengl15/renderer.cpp b/miniwin/src/d3drm/backends/opengl15/renderer.cpp index 14bb7cd0..d193fe76 100644 --- a/miniwin/src/d3drm/backends/opengl15/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengl15/renderer.cpp @@ -92,11 +92,6 @@ OpenGL15Renderer::~OpenGL15Renderer() } } -void OpenGL15Renderer::SetBackbuffer(SDL_Surface* surface) -{ - m_backbuffer = surface; -} - void OpenGL15Renderer::PushVertices(const PositionColorVertex* verts, size_t count) { m_vertices.assign(verts, verts + count); @@ -148,7 +143,7 @@ const char* OpenGL15Renderer::GetName() HRESULT OpenGL15Renderer::Render() { - if (!m_backbuffer) { + if (!DDBackBuffer) { return DDERR_GENERIC; } SDL_GL_MakeCurrent(DDWindow, m_context); @@ -251,7 +246,7 @@ HRESULT OpenGL15Renderer::Render() glBindFramebuffer(GL_FRAMEBUFFER, 0); // Composite onto SDL backbuffer - SDL_BlitSurface(m_renderedImage, nullptr, m_backbuffer, nullptr); + SDL_BlitSurface(m_renderedImage, nullptr, DDBackBuffer, nullptr); return DD_OK; } diff --git a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp index f72c1e87..471b0113 100644 --- a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp +++ b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp @@ -200,11 +200,6 @@ Direct3DRMSDL3GPURenderer::~Direct3DRMSDL3GPURenderer() SDL_DestroyGPUDevice(m_device); } -void Direct3DRMSDL3GPURenderer::SetBackbuffer(SDL_Surface* buf) -{ - m_backbuffer = buf; -} - void Direct3DRMSDL3GPURenderer::PushLights(const SceneLight* vertices, size_t count) { if (count > 3) { @@ -388,7 +383,7 @@ HRESULT Direct3DRMSDL3GPURenderer::Render() SDL_DestroySurface(m_renderedImage); SDL_UnmapGPUTransferBuffer(m_device, m_downloadTransferBuffer); m_renderedImage = convertedRender; - SDL_BlitSurface(m_renderedImage, nullptr, m_backbuffer, nullptr); + SDL_BlitSurface(m_renderedImage, nullptr, DDBackBuffer, nullptr); return DD_OK; } diff --git a/miniwin/src/d3drm/backends/software/renderer.cpp b/miniwin/src/d3drm/backends/software/renderer.cpp index ce6f03ac..f7a09aad 100644 --- a/miniwin/src/d3drm/backends/software/renderer.cpp +++ b/miniwin/src/d3drm/backends/software/renderer.cpp @@ -14,11 +14,6 @@ Direct3DRMSoftwareRenderer::Direct3DRMSoftwareRenderer(DWORD width, DWORD height m_zBuffer.resize(m_width * m_height); } -void Direct3DRMSoftwareRenderer::SetBackbuffer(SDL_Surface* buf) -{ - m_backbuffer = buf; -} - void Direct3DRMSoftwareRenderer::PushLights(const SceneLight* lights, size_t count) { m_lights.assign(lights, lights + count); @@ -292,8 +287,8 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected( } } - Uint8* pixels = (Uint8*) m_backbuffer->pixels; - int pitch = m_backbuffer->pitch; + Uint8* pixels = (Uint8*) DDBackBuffer->pixels; + int pitch = DDBackBuffer->pitch; for (int y = minY; y <= maxY; ++y) { for (int x = minX; x <= maxX; ++x) { @@ -409,7 +404,7 @@ Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture) if (texRef.version != texture->m_version) { // Update animated textures SDL_DestroySurface(texRef.cached); - texRef.cached = SDL_ConvertSurface(surface->m_surface, m_backbuffer->format); + texRef.cached = SDL_ConvertSurface(surface->m_surface, DDBackBuffer->format); SDL_LockSurface(texRef.cached); texRef.version = texture->m_version; } @@ -417,7 +412,7 @@ Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture) } } - SDL_Surface* convertedRender = SDL_ConvertSurface(surface->m_surface, m_backbuffer->format); + SDL_Surface* convertedRender = SDL_ConvertSurface(surface->m_surface, DDBackBuffer->format); SDL_LockSurface(convertedRender); // Reuse freed slot @@ -468,17 +463,17 @@ const char* Direct3DRMSoftwareRenderer::GetName() HRESULT Direct3DRMSoftwareRenderer::Render() { - if (!m_backbuffer || m_vertexBuffer.size() % 3 != 0 || !SDL_LockSurface(m_backbuffer)) { + if (!DDBackBuffer || m_vertexBuffer.size() % 3 != 0 || !SDL_LockSurface(DDBackBuffer)) { return DDERR_GENERIC; } ClearZBuffer(); - m_format = SDL_GetPixelFormatDetails(m_backbuffer->format); - m_palette = SDL_GetSurfacePalette(m_backbuffer); + m_format = SDL_GetPixelFormatDetails(DDBackBuffer->format); + m_palette = SDL_GetSurfacePalette(DDBackBuffer); m_bytesPerPixel = m_format->bits_per_pixel / 8; for (size_t i = 0; i + 2 < m_vertexBuffer.size(); i += 3) { DrawTriangleClipped(m_vertexBuffer[i], m_vertexBuffer[i + 1], m_vertexBuffer[i + 2]); } - SDL_UnlockSurface(m_backbuffer); + SDL_UnlockSurface(DDBackBuffer); m_vertexBuffer.clear(); diff --git a/miniwin/src/d3drm/d3drmviewport.cpp b/miniwin/src/d3drm/d3drmviewport.cpp index 581669f5..3e65d48a 100644 --- a/miniwin/src/d3drm/d3drmviewport.cpp +++ b/miniwin/src/d3drm/d3drmviewport.cpp @@ -334,7 +334,6 @@ HRESULT Direct3DRMViewportImpl::CollectSceneData() m_renderer->PushLights(lights.data(), lights.size()); m_renderer->PushVertices(verts.data(), verts.size()); - m_renderer->SetBackbuffer(DDBackBuffer); return D3DRM_OK; } diff --git a/miniwin/src/internal/d3drmrenderer.h b/miniwin/src/internal/d3drmrenderer.h index 20b44051..074dacb5 100644 --- a/miniwin/src/internal/d3drmrenderer.h +++ b/miniwin/src/internal/d3drmrenderer.h @@ -35,7 +35,6 @@ static_assert(sizeof(SceneLight) == 48); class Direct3DRMRenderer : public IDirect3DDevice2 { public: - virtual void SetBackbuffer(SDL_Surface* backbuffer) = 0; virtual void PushVertices(const PositionColorVertex* vertices, size_t count) = 0; virtual void PushLights(const SceneLight* vertices, size_t count) = 0; virtual void SetProjection(D3DRMMATRIX4D perspective, D3DVALUE front, D3DVALUE back) = 0; diff --git a/miniwin/src/internal/d3drmrenderer_opengl15.h b/miniwin/src/internal/d3drmrenderer_opengl15.h index d3d1b0c8..c5bc02ad 100644 --- a/miniwin/src/internal/d3drmrenderer_opengl15.h +++ b/miniwin/src/internal/d3drmrenderer_opengl15.h @@ -15,7 +15,6 @@ class OpenGL15Renderer : public Direct3DRMRenderer { static Direct3DRMRenderer* Create(DWORD width, DWORD height); OpenGL15Renderer(int width, int height, SDL_GLContext context, GLuint fbo, GLuint colorTex, GLuint depthRb); ~OpenGL15Renderer() override; - void SetBackbuffer(SDL_Surface* surface) override; void PushVertices(const PositionColorVertex* verts, size_t count) override; void PushLights(const SceneLight* lightsArray, size_t count) override; void SetProjection(D3DRMMATRIX4D perspective, D3DVALUE front, D3DVALUE back) override; @@ -29,7 +28,6 @@ class OpenGL15Renderer : public Direct3DRMRenderer { private: SDL_GLContext m_context; D3DRMMATRIX4D m_projection; - SDL_Surface* m_backbuffer = nullptr; SDL_Surface* m_renderedImage; int m_width, m_height; std::vector m_vertices; diff --git a/miniwin/src/internal/d3drmrenderer_sdl3gpu.h b/miniwin/src/internal/d3drmrenderer_sdl3gpu.h index 20fe0451..2375ab1a 100644 --- a/miniwin/src/internal/d3drmrenderer_sdl3gpu.h +++ b/miniwin/src/internal/d3drmrenderer_sdl3gpu.h @@ -20,7 +20,6 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer { public: static Direct3DRMRenderer* Create(DWORD width, DWORD height); ~Direct3DRMSDL3GPURenderer() override; - void SetBackbuffer(SDL_Surface* backbuffer) override; void PushVertices(const PositionColorVertex* vertices, size_t count) override; void PushLights(const SceneLight* vertices, size_t count) override; Uint32 GetTextureId(IDirect3DRMTexture* texture) override; @@ -52,7 +51,6 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer { ViewportUniforms m_uniforms; SceneLights m_lights; D3DDEVICEDESC m_desc; - SDL_Surface* m_backbuffer = nullptr; SDL_GPUDevice* m_device; SDL_GPUGraphicsPipeline* m_pipeline; SDL_GPUTexture* m_transferTexture; diff --git a/miniwin/src/internal/d3drmrenderer_software.h b/miniwin/src/internal/d3drmrenderer_software.h index 7ad5e80c..18ffb795 100644 --- a/miniwin/src/internal/d3drmrenderer_software.h +++ b/miniwin/src/internal/d3drmrenderer_software.h @@ -19,7 +19,6 @@ struct TextureCache { class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer { public: Direct3DRMSoftwareRenderer(DWORD width, DWORD height); - void SetBackbuffer(SDL_Surface* backbuffer) override; void PushVertices(const PositionColorVertex* vertices, size_t count) override; void PushLights(const SceneLight* vertices, size_t count) override; Uint32 GetTextureId(IDirect3DRMTexture* texture) override; @@ -45,7 +44,6 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer { DWORD m_width; DWORD m_height; - SDL_Surface* m_backbuffer = nullptr; SDL_Palette* m_palette; const SDL_PixelFormatDetails* m_format; int m_bytesPerPixel; From 72eb992af47e7e563ce74cead1cc51a3aaa33bb7 Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Wed, 4 Jun 2025 05:42:42 +0200 Subject: [PATCH 2/2] Make Lego Islan Fully playable (#230) --- miniwin/src/d3drm/d3drmviewport.cpp | 102 +++++++++++++++++++--- miniwin/src/internal/d3drmviewport_impl.h | 3 + 2 files changed, 93 insertions(+), 12 deletions(-) diff --git a/miniwin/src/d3drm/d3drmviewport.cpp b/miniwin/src/d3drm/d3drmviewport.cpp index 3e65d48a..3b9b6586 100644 --- a/miniwin/src/d3drm/d3drmviewport.cpp +++ b/miniwin/src/d3drm/d3drmviewport.cpp @@ -122,9 +122,9 @@ HRESULT Direct3DRMViewportImpl::CollectSceneData() std::vector verts; // Compute camera matrix - D3DRMMATRIX4D cameraWorld, viewMatrix; + D3DRMMATRIX4D cameraWorld; ComputeFrameWorldMatrix(m_camera, cameraWorld); - D3DRMMatrixInvertOrthogonal(viewMatrix, cameraWorld); + D3DRMMatrixInvertOrthogonal(m_viewMatrix, cameraWorld); std::function recurseFrame; std::function recurseChildren; @@ -270,12 +270,12 @@ HRESULT Direct3DRMViewportImpl::CollectSceneData() // View transform D3DVECTOR viewPos; - viewPos.x = worldPos.x * viewMatrix[0][0] + worldPos.y * viewMatrix[1][0] + - worldPos.z * viewMatrix[2][0] + viewMatrix[3][0]; - viewPos.y = worldPos.x * viewMatrix[0][1] + worldPos.y * viewMatrix[1][1] + - worldPos.z * viewMatrix[2][1] + viewMatrix[3][1]; - viewPos.z = worldPos.x * viewMatrix[0][2] + worldPos.y * viewMatrix[1][2] + - worldPos.z * viewMatrix[2][2] + viewMatrix[3][2]; + viewPos.x = worldPos.x * m_viewMatrix[0][0] + worldPos.y * m_viewMatrix[1][0] + + worldPos.z * m_viewMatrix[2][0] + m_viewMatrix[3][0]; + viewPos.y = worldPos.x * m_viewMatrix[0][1] + worldPos.y * m_viewMatrix[1][1] + + worldPos.z * m_viewMatrix[2][1] + m_viewMatrix[3][1]; + viewPos.z = worldPos.x * m_viewMatrix[0][2] + worldPos.y * m_viewMatrix[1][2] + + worldPos.z * m_viewMatrix[2][2] + m_viewMatrix[3][2]; // View transform D3DVECTOR viewNorm; @@ -440,14 +440,23 @@ void Direct3DRMViewportImpl::UpdateProjectionMatrix() float f = m_front / m_field; float depth = m_back - m_front; - D3DRMMATRIX4D perspective = { + D3DRMMATRIX4D projection = { {f, 0, 0, 0}, {0, f * aspect, 0, 0}, {0, 0, m_back / depth, 1}, {0, 0, (-m_front * m_back) / depth, 0}, }; + memcpy(m_projectionMatrix, projection, sizeof(D3DRMMATRIX4D)); - m_renderer->SetProjection(perspective, m_front, m_back); + m_renderer->SetProjection(projection, m_front, m_back); + + D3DRMMATRIX4D inverseProjectionMatrix = { + {1.0f / f, 0, 0, 0}, + {0, 1.0f / (f * aspect), 0, 0}, + {0, 0, 0, depth / (-m_front * m_back)}, + {0, 0, 1, -(m_back / depth) * depth / (-m_front * m_back)}, + }; + memcpy(m_inverseProjectionMatrix, inverseProjectionMatrix, sizeof(D3DRMMATRIX4D)); } D3DVALUE Direct3DRMViewportImpl::GetField() @@ -467,13 +476,82 @@ DWORD Direct3DRMViewportImpl::GetHeight() HRESULT Direct3DRMViewportImpl::Transform(D3DRMVECTOR4D* screen, D3DVECTOR* world) { - MINIWIN_NOT_IMPLEMENTED(); + D3DRMVECTOR4D worldVec = {world->x, world->y, world->z, 1.0f}; + + D3DRMVECTOR4D viewVec; + viewVec.x = m_viewMatrix[0][0] * worldVec.x + m_viewMatrix[1][0] * worldVec.y + m_viewMatrix[2][0] * worldVec.z + + m_viewMatrix[3][0] * worldVec.w; + viewVec.y = m_viewMatrix[0][1] * worldVec.x + m_viewMatrix[1][1] * worldVec.y + m_viewMatrix[2][1] * worldVec.z + + m_viewMatrix[3][1] * worldVec.w; + viewVec.z = m_viewMatrix[0][2] * worldVec.x + m_viewMatrix[1][2] * worldVec.y + m_viewMatrix[2][2] * worldVec.z + + m_viewMatrix[3][2] * worldVec.w; + viewVec.w = m_viewMatrix[0][3] * worldVec.x + m_viewMatrix[1][3] * worldVec.y + m_viewMatrix[2][3] * worldVec.z + + m_viewMatrix[3][3] * worldVec.w; + + screen->x = viewVec.x * m_projectionMatrix[0][0] + viewVec.y * m_projectionMatrix[1][0] + + viewVec.z * m_projectionMatrix[2][0] + viewVec.w * m_projectionMatrix[3][0]; + screen->y = viewVec.x * m_projectionMatrix[0][1] + viewVec.y * m_projectionMatrix[1][1] + + viewVec.z * m_projectionMatrix[2][1] + viewVec.w * m_projectionMatrix[3][1]; + screen->z = viewVec.x * m_projectionMatrix[0][2] + viewVec.y * m_projectionMatrix[1][2] + + viewVec.z * m_projectionMatrix[2][2] + viewVec.w * m_projectionMatrix[3][2]; + screen->w = viewVec.x * m_projectionMatrix[0][3] + viewVec.y * m_projectionMatrix[1][3] + + viewVec.z * m_projectionMatrix[2][3] + viewVec.w * m_projectionMatrix[3][3]; + + float invW = 1.0f / screen->w; + float ndcX = screen->x * invW; + float ndcY = screen->y * invW; + + screen->x = (ndcX * 0.5f + 0.5f) * m_width; + screen->y = (1.0f - (ndcY * 0.5f + 0.5f)) * m_height; + + // Undo perspective divide + screen->x *= screen->z; + screen->y *= screen->w; + return DD_OK; } HRESULT Direct3DRMViewportImpl::InverseTransform(D3DVECTOR* world, D3DRMVECTOR4D* screen) { - MINIWIN_NOT_IMPLEMENTED(); + // Convert to screen coordinates + float screenX = screen->x / screen->z; + float screenY = screen->y / screen->w; + + // Convert screen coordinates to NDC + float ndcX = screenX / m_width * 2.0f - 1.0f; + float ndcY = 1.0f - (screenY / m_height) * 2.0f; + + float clipVec[4] = {ndcX * screen->w, ndcY * screen->w, screen->z, screen->w}; + + float viewVec[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + viewVec[j] += m_inverseProjectionMatrix[i][j] * clipVec[i]; + } + } + + float invViewMatrix[4][4]; + D3DRMMatrixInvertOrthogonal(invViewMatrix, m_viewMatrix); + + float worldVec[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + worldVec[j] += invViewMatrix[i][j] * viewVec[i]; + } + } + + // Perspective divide + if (worldVec[3] != 0.0f) { + world->x = worldVec[0] / worldVec[3]; + world->y = worldVec[1] / worldVec[3]; + world->z = worldVec[2] / worldVec[3]; + } + else { + world->x = worldVec[0]; + world->y = worldVec[1]; + world->z = worldVec[2]; + } + return DD_OK; } diff --git a/miniwin/src/internal/d3drmviewport_impl.h b/miniwin/src/internal/d3drmviewport_impl.h index 1f819734..162230d1 100644 --- a/miniwin/src/internal/d3drmviewport_impl.h +++ b/miniwin/src/internal/d3drmviewport_impl.h @@ -41,6 +41,9 @@ struct Direct3DRMViewportImpl : public Direct3DRMObjectBaseImpl