From 2828452b35112d3bd21efab634991453c47129df Mon Sep 17 00:00:00 2001 From: Anders Jenbo Date: Mon, 16 Jun 2025 04:28:32 +0200 Subject: [PATCH] Clean up rendering (#301) --- miniwin/include/miniwin/d3drm.h | 2 +- .../src/d3drm/backends/opengl1/renderer.cpp | 23 +-- .../src/d3drm/backends/sdl3gpu/renderer.cpp | 16 +- .../src/d3drm/backends/software/renderer.cpp | 154 ++++++++++-------- miniwin/src/d3drm/d3drmviewport.cpp | 69 ++++---- miniwin/src/ddraw/ddsurface.cpp | 17 +- miniwin/src/internal/d3drmmesh_impl.h | 2 +- miniwin/src/internal/d3drmrenderer.h | 10 +- miniwin/src/internal/d3drmrenderer_opengl1.h | 8 +- miniwin/src/internal/d3drmrenderer_sdl3gpu.h | 6 +- miniwin/src/internal/d3drmrenderer_software.h | 13 +- miniwin/src/internal/d3drmviewport_impl.h | 4 +- miniwin/src/internal/meshutils.cpp | 2 +- miniwin/src/internal/meshutils.h | 2 +- 14 files changed, 184 insertions(+), 144 deletions(-) diff --git a/miniwin/include/miniwin/d3drm.h b/miniwin/include/miniwin/d3drm.h index 28260a41..6d2e5395 100644 --- a/miniwin/include/miniwin/d3drm.h +++ b/miniwin/include/miniwin/d3drm.h @@ -145,10 +145,10 @@ struct D3DRMVERTEX { D3DVECTOR position; D3DVECTOR normal; union { + TexCoord texCoord; struct { D3DVALUE tu, tv; }; - TexCoord texCoord; }; }; diff --git a/miniwin/src/d3drm/backends/opengl1/renderer.cpp b/miniwin/src/d3drm/backends/opengl1/renderer.cpp index 36ba5fa1..7e8ba241 100644 --- a/miniwin/src/d3drm/backends/opengl1/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengl1/renderer.cpp @@ -109,6 +109,10 @@ void OpenGL1Renderer::PushLights(const SceneLight* lightsArray, size_t count) m_lights.assign(lightsArray, lightsArray + count); } +void OpenGL1Renderer::SetFrustumPlanes(const Plane* frustumPlanes) +{ +} + void OpenGL1Renderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) { memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D)); @@ -217,7 +221,10 @@ GLMeshCacheEntry GLUploadMesh(const MeshGroup& meshGroup, bool useVBOs) } else { vertices = meshGroup.vertices; - cache.indices = meshGroup.indices; + cache.indices.resize(meshGroup.indices.size()); + std::transform(meshGroup.indices.begin(), meshGroup.indices.end(), cache.indices.begin(), [](DWORD index) { + return static_cast(index); + }); } if (meshGroup.texture != nullptr) { @@ -354,14 +361,12 @@ const char* OpenGL1Renderer::GetName() return "OpenGL 1.2 HAL"; } -HRESULT OpenGL1Renderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix) +HRESULT OpenGL1Renderer::BeginFrame() { if (!DDBackBuffer) { return DDERR_GENERIC; } - memcpy(m_viewMatrix, viewMatrix, sizeof(D3DRMMATRIX4D)); - SDL_GL_MakeCurrent(DDWindow, m_context); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glViewport(0, 0, m_width, m_height); @@ -454,7 +459,7 @@ void OpenGL1Renderer::EnableTransparency() void OpenGL1Renderer::SubmitDraw( DWORD meshId, - const D3DRMMATRIX4D& worldMatrix, + const D3DRMMATRIX4D& modelViewMatrix, const Matrix3x3& normalMatrix, const Appearance& appearance ) @@ -462,9 +467,7 @@ void OpenGL1Renderer::SubmitDraw( glMatrixMode(GL_MODELVIEW); glPushMatrix(); - D3DRMMATRIX4D mvMatrix; - MultiplyMatrix(mvMatrix, worldMatrix, m_viewMatrix); - glLoadMatrixf(&mvMatrix[0][0]); + glLoadMatrixf(&modelViewMatrix[0][0]); glEnable(GL_NORMALIZE); glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a); @@ -517,7 +520,7 @@ void OpenGL1Renderer::SubmitDraw( } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ibo); - glDrawElements(GL_TRIANGLES, static_cast(mesh.indices.size()), GL_UNSIGNED_INT, nullptr); + glDrawElements(GL_TRIANGLES, static_cast(mesh.indices.size()), GL_UNSIGNED_SHORT, nullptr); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); @@ -529,7 +532,7 @@ void OpenGL1Renderer::SubmitDraw( glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords.data()); } - glDrawElements(GL_TRIANGLES, static_cast(mesh.indices.size()), GL_UNSIGNED_INT, mesh.indices.data()); + glDrawElements(GL_TRIANGLES, static_cast(mesh.indices.size()), GL_UNSIGNED_SHORT, mesh.indices.data()); } glPopMatrix(); diff --git a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp index 7ec0ff35..8ede7580 100644 --- a/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp +++ b/miniwin/src/d3drm/backends/sdl3gpu/renderer.cpp @@ -355,6 +355,10 @@ void Direct3DRMSDL3GPURenderer::PushLights(const SceneLight* vertices, size_t co m_fragmentShadingData.lightCount = count; } +void Direct3DRMSDL3GPURenderer::SetFrustumPlanes(const Plane* frustumPlanes) +{ +} + void Direct3DRMSDL3GPURenderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) { m_front = front; @@ -507,7 +511,7 @@ SDL3MeshCache Direct3DRMSDL3GPURenderer::UploadMesh(const MeshGroup& meshGroup) std::vector finalIndices; if (meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT) { - std::vector newIndices; + std::vector newIndices; FlattenSurfaces( meshGroup.vertices.data(), meshGroup.vertices.size(), @@ -703,14 +707,12 @@ SDL_GPUTransferBuffer* Direct3DRMSDL3GPURenderer::GetUploadBuffer(size_t size) return m_uploadBuffer; } -HRESULT Direct3DRMSDL3GPURenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix) +HRESULT Direct3DRMSDL3GPURenderer::BeginFrame() { if (!DDBackBuffer) { return DDERR_GENERIC; } - memcpy(&m_viewMatrix, viewMatrix, sizeof(D3DRMMATRIX4D)); - // Clear color and depth targets SDL_GPUColorTargetInfo colorTargetInfo = {}; colorTargetInfo.texture = m_transferTexture; @@ -742,14 +744,12 @@ void Direct3DRMSDL3GPURenderer::EnableTransparency() void Direct3DRMSDL3GPURenderer::SubmitDraw( DWORD meshId, - const D3DRMMATRIX4D& worldMatrix, + const D3DRMMATRIX4D& modelViewMatrix, const Matrix3x3& normalMatrix, const Appearance& appearance ) { - D3DRMMATRIX4D worldViewMatrix; - MultiplyMatrix(worldViewMatrix, worldMatrix, m_viewMatrix); - memcpy(&m_uniforms.worldViewMatrix, worldViewMatrix, sizeof(D3DRMMATRIX4D)); + memcpy(&m_uniforms.worldViewMatrix, modelViewMatrix, sizeof(D3DRMMATRIX4D)); PackNormalMatrix(normalMatrix, m_uniforms.normalMatrix); m_fragmentShadingData.color = appearance.color; m_fragmentShadingData.shininess = appearance.shininess; diff --git a/miniwin/src/d3drm/backends/software/renderer.cpp b/miniwin/src/d3drm/backends/software/renderer.cpp index 8882098e..6b5df06b 100644 --- a/miniwin/src/d3drm/backends/software/renderer.cpp +++ b/miniwin/src/d3drm/backends/software/renderer.cpp @@ -33,6 +33,11 @@ void Direct3DRMSoftwareRenderer::PushLights(const SceneLight* lights, size_t cou m_lights.assign(lights, lights + count); } +void Direct3DRMSoftwareRenderer::SetFrustumPlanes(const Plane* frustumPlanes) +{ + memcpy(m_frustumPlanes, frustumPlanes, sizeof(m_frustumPlanes)); +} + void Direct3DRMSoftwareRenderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) { m_front = front; @@ -82,16 +87,12 @@ void Direct3DRMSoftwareRenderer::ClearZBuffer() } } -void Direct3DRMSoftwareRenderer::ProjectVertex(const D3DRMVERTEX& v, D3DRMVECTOR4D& p) const +void Direct3DRMSoftwareRenderer::ProjectVertex(const D3DVECTOR& v, D3DRMVECTOR4D& p) const { - float px = m_projection[0][0] * v.position.x + m_projection[1][0] * v.position.y + - m_projection[2][0] * v.position.z + m_projection[3][0]; - float py = m_projection[0][1] * v.position.x + m_projection[1][1] * v.position.y + - m_projection[2][1] * v.position.z + m_projection[3][1]; - float pz = m_projection[0][2] * v.position.x + m_projection[1][2] * v.position.y + - m_projection[2][2] * v.position.z + m_projection[3][2]; - float pw = m_projection[0][3] * v.position.x + m_projection[1][3] * v.position.y + - m_projection[2][3] * v.position.z + m_projection[3][3]; + float px = m_projection[0][0] * v.x + m_projection[1][0] * v.y + m_projection[2][0] * v.z + m_projection[3][0]; + float py = m_projection[0][1] * v.x + m_projection[1][1] * v.y + m_projection[2][1] * v.z + m_projection[3][1]; + float pz = m_projection[0][2] * v.x + m_projection[1][2] * v.y + m_projection[2][2] * v.z + m_projection[3][2]; + float pw = m_projection[0][3] * v.x + m_projection[1][3] * v.y + m_projection[2][3] * v.z + m_projection[3][3]; p.w = pw; @@ -128,6 +129,27 @@ D3DRMVERTEX SplitEdge(D3DRMVERTEX a, const D3DRMVERTEX& b, float plane) return a; } +bool IsTriangleOutsideViewCone( + const D3DVECTOR& v0, + const D3DVECTOR& v1, + const D3DVECTOR& v2, + const Plane* frustumPlanes +) +{ + for (int i = 0; i < 4; ++i) { + const Plane& plane = frustumPlanes[i]; + + float d0 = DotProduct(plane.normal, v0) + plane.d; + float d1 = DotProduct(plane.normal, v1) + plane.d; + float d2 = DotProduct(plane.normal, v2) + plane.d; + + if (d0 < 0 && d1 < 0 && d2 < 0) { + return true; + } + } + return false; +} + void Direct3DRMSoftwareRenderer::DrawTriangleClipped(const D3DRMVERTEX (&v)[3], const Appearance& appearance) { bool in0 = v[0].position.z >= m_front; @@ -136,7 +158,10 @@ void Direct3DRMSoftwareRenderer::DrawTriangleClipped(const D3DRMVERTEX (&v)[3], int insideCount = in0 + in1 + in2; - if (insideCount == 0) { + if (insideCount == 0 || v[0].position.z > m_back && v[1].position.z > m_back && v[2].position.z > m_back) { + return; // Outside clipping + } + if (IsTriangleOutsideViewCone(v[0].position, v[1].position, v[2].position, m_frustumPlanes)) { return; } @@ -203,13 +228,15 @@ Uint32 Direct3DRMSoftwareRenderer::BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g SDL_Color Direct3DRMSoftwareRenderer::ApplyLighting( const D3DVECTOR& position, - const D3DVECTOR& normal, + const D3DVECTOR& oNormal, const Appearance& appearance ) { FColor specular = {0, 0, 0, 0}; FColor diffuse = {0, 0, 0, 0}; + D3DVECTOR normal = Normalize(TransformNormal(oNormal, m_normalMatrix)); + for (const auto& light : m_lights) { FColor lightColor = light.color; @@ -291,6 +318,18 @@ VertexXY InterpolateVertex(float y, const VertexXY& v0, const VertexXY& v1) return r; } +inline D3DVECTOR Subtract(const D3DVECTOR& a, const D3DVECTOR& b) +{ + return {a.x - b.x, a.y - b.y, a.z - b.z}; +} + +inline bool IsBackface(const D3DVECTOR& v0, const D3DVECTOR& v1, const D3DVECTOR& v2) +{ + D3DVECTOR normal = CrossProduct(Subtract(v1, v0), Subtract(v2, v0)); + + return DotProduct(normal, v0) >= 0.0f; +} + void Direct3DRMSoftwareRenderer::DrawTriangleProjected( const D3DRMVERTEX& v0, const D3DRMVERTEX& v1, @@ -298,26 +337,14 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected( const Appearance& appearance ) { + if (IsBackface(v0.position, v1.position, v2.position)) { + return; + } + D3DRMVECTOR4D p0, p1, p2; - ProjectVertex(v0, p0); - ProjectVertex(v1, p1); - ProjectVertex(v2, p2); - - // Skip triangles outside the frustum - if ((p0.z < m_front && p1.z < m_front && p2.z < m_front) || (p0.z > m_back && p1.z > m_back && p2.z > m_back)) { - return; - } - - // Skip offscreen triangles - if ((p0.x < 0 && p1.x < 0 && p2.x < 0) || (p0.x >= m_width && p1.x >= m_width && p2.x >= m_width) || - (p0.y < 0 && p1.y < 0 && p2.y < 0) || (p0.y >= m_height && p1.y >= m_height && p2.y >= m_height)) { - return; - } - - // Cull backfaces - if ((p2.x - p0.x) * (p1.y - p0.y) - (p2.y - p0.y) * (p1.x - p0.x) >= 0) { - return; - } + ProjectVertex(v0.position, p0); + ProjectVertex(v1.position, p1); + ProjectVertex(v2.position, p2); Uint8 r, g, b; SDL_Color c0 = ApplyLighting(v0.position, v0.normal, appearance); @@ -327,6 +354,15 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected( c2 = ApplyLighting(v2.position, v2.normal, appearance); } + Uint8* pixels = (Uint8*) DDBackBuffer->pixels; + int pitch = DDBackBuffer->pitch; + + VertexXY verts[3] = { + {p0.x, p0.y, p0.z, p0.w, c0, v0.texCoord.u, v0.texCoord.v}, + {p1.x, p1.y, p1.z, p1.w, c1, v1.texCoord.u, v1.texCoord.v}, + {p2.x, p2.y, p2.z, p2.w, c2, v2.texCoord.u, v2.texCoord.v} + }; + Uint32 textureId = appearance.textureId; int texturePitch; Uint8* texels = nullptr; @@ -340,29 +376,20 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected( texWidthScale = texture->w - 1; texHeightScale = texture->h - 1; } + + verts[0].u_over_w = v0.texCoord.u / p0.w; + verts[0].v_over_w = v0.texCoord.v / p0.w; + verts[0].one_over_w = 1.0f / p0.w; + + verts[1].u_over_w = v1.texCoord.u / p1.w; + verts[1].v_over_w = v1.texCoord.v / p1.w; + verts[1].one_over_w = 1.0f / p1.w; + + verts[2].u_over_w = v2.texCoord.u / p2.w; + verts[2].v_over_w = v2.texCoord.v / p2.w; + verts[2].one_over_w = 1.0f / p2.w; } - Uint8* pixels = (Uint8*) DDBackBuffer->pixels; - int pitch = DDBackBuffer->pitch; - - VertexXY verts[3] = { - {p0.x, p0.y, p0.z, p0.w, c0, v0.texCoord.u, v0.texCoord.v}, - {p1.x, p1.y, p1.z, p1.w, c1, v1.texCoord.u, v1.texCoord.v}, - {p2.x, p2.y, p2.z, p2.w, c2, v2.texCoord.u, v2.texCoord.v} - }; - - verts[0].u_over_w = v0.texCoord.u / p0.w; - verts[0].v_over_w = v0.texCoord.v / p0.w; - verts[0].one_over_w = 1.0f / p0.w; - - verts[1].u_over_w = v1.texCoord.u / p1.w; - verts[1].v_over_w = v1.texCoord.v / p1.w; - verts[1].one_over_w = 1.0f / p1.w; - - verts[2].u_over_w = v2.texCoord.u / p2.w; - verts[2].v_over_w = v2.texCoord.v / p2.w; - verts[2].one_over_w = 1.0f / p2.w; - // Sort verts if (verts[0].y > verts[1].y) { std::swap(verts[0], verts[1]); @@ -559,7 +586,6 @@ MeshCache UploadMesh(const MeshGroup& meshGroup) cache.flat = meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT; - std::vector vertices; if (cache.flat) { FlattenSurfaces( meshGroup.vertices.data(), @@ -653,14 +679,13 @@ const char* Direct3DRMSoftwareRenderer::GetName() return "Miniwin Emulation"; } -HRESULT Direct3DRMSoftwareRenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix) +HRESULT Direct3DRMSoftwareRenderer::BeginFrame() { if (!DDBackBuffer || !SDL_LockSurface(DDBackBuffer)) { return DDERR_GENERIC; } ClearZBuffer(); - memcpy(m_viewMatrix, viewMatrix, sizeof(D3DRMMATRIX4D)); m_format = SDL_GetPixelFormatDetails(DDBackBuffer->format); m_palette = SDL_GetSurfacePalette(DDBackBuffer); m_bytesPerPixel = m_format->bits_per_pixel / 8; @@ -674,33 +699,32 @@ void Direct3DRMSoftwareRenderer::EnableTransparency() void Direct3DRMSoftwareRenderer::SubmitDraw( DWORD meshId, - const D3DRMMATRIX4D& worldMatrix, + const D3DRMMATRIX4D& modelViewMatrix, const Matrix3x3& normalMatrix, const Appearance& appearance ) { - D3DRMMATRIX4D mvMatrix; - MultiplyMatrix(mvMatrix, worldMatrix, m_viewMatrix); + memcpy(m_normalMatrix, normalMatrix, sizeof(Matrix3x3)); auto& mesh = m_meshs[meshId]; // Pre-transform all vertex positions and normals - std::vector transformedVerts(mesh.vertices.size()); + m_transformedVerts.clear(); + m_transformedVerts.reserve(mesh.vertices.size()); for (size_t i = 0; i < mesh.vertices.size(); ++i) { const D3DRMVERTEX& src = mesh.vertices[i]; - D3DRMVERTEX& dst = transformedVerts[i]; - dst.position = TransformPoint(src.position, mvMatrix); - // TODO defer normal transformation til lighting to allow culling first - dst.normal = Normalize(TransformNormal(src.normal, normalMatrix)); + D3DRMVERTEX& dst = m_transformedVerts[i]; + dst.position = TransformPoint(src.position, modelViewMatrix); + dst.normal = src.normal; dst.texCoord = src.texCoord; } // Assemble triangles using index buffer for (size_t i = 0; i + 2 < mesh.indices.size(); i += 3) { DrawTriangleClipped( - {transformedVerts[mesh.indices[i]], - transformedVerts[mesh.indices[i + 1]], - transformedVerts[mesh.indices[i + 2]]}, + {m_transformedVerts[mesh.indices[i]], + m_transformedVerts[mesh.indices[i + 1]], + m_transformedVerts[mesh.indices[i + 2]]}, appearance ); } diff --git a/miniwin/src/d3drm/d3drmviewport.cpp b/miniwin/src/d3drm/d3drmviewport.cpp index c87866a7..a6523f1b 100644 --- a/miniwin/src/d3drm/d3drmviewport.cpp +++ b/miniwin/src/d3drm/d3drmviewport.cpp @@ -148,39 +148,25 @@ void Direct3DRMViewportImpl::CollectLightsFromFrame( children->Release(); } -struct Plane { - D3DVECTOR normal; - float d; -}; - -void NormalizePlane(Plane& plane) +void Direct3DRMViewportImpl::BuildViewFrustumPlanes() { - float len = - sqrtf(plane.normal.x * plane.normal.x + plane.normal.y * plane.normal.y + plane.normal.z * plane.normal.z); - if (len > 0.0f) { - float invLen = 1.0f / len; - plane.normal.x *= invLen; - plane.normal.y *= invLen; - plane.normal.z *= invLen; - plane.d *= invLen; - } + + float aspect = (float) m_width / (float) m_height; + float tanFovX = m_field; + float tanFovY = m_field / aspect; + + // View-space frustum planes + m_frustumPlanes[0] = {Normalize({tanFovX, 0.0f, 1.0f}), 0.0f}; // Left + m_frustumPlanes[1] = {Normalize({-tanFovX, 0.0f, 1.0f}), 0.0f}; // Right + m_frustumPlanes[2] = {Normalize({0.0f, -tanFovY, 1.0f}), 0.0f}; // Top + m_frustumPlanes[3] = {Normalize({0.0f, tanFovY, 1.0f}), 0.0f}; // Bottom + + // Near and far planes + m_frustumPlanes[4] = {{0.0f, 0.0f, 1.0f}, -m_front}; // Near (Z >= m_front) + m_frustumPlanes[5] = {{0.0f, 0.0f, -1.0f}, m_back}; // Far (Z <= m_back) } -Plane frustumPlanes[6]; - -void ExtractFrustumPlanes(const D3DRMMATRIX4D& m) -{ - static const int idx[][2] = {{0, 1}, {0, -1}, {1, 1}, {1, -1}, {2, 1}, {2, -1}}; - for (int i = 0; i < 6; ++i) { - int axis = idx[i][0], sign = idx[i][1]; - frustumPlanes[i] - .normal = {m[0][3] + sign * m[0][axis], m[1][3] + sign * m[1][axis], m[2][3] + sign * m[2][axis]}; - frustumPlanes[i].d = m[3][3] + sign * m[3][axis]; - NormalizePlane(frustumPlanes[i]); - } -} - -bool IsMeshInFrustum(Direct3DRMMeshImpl* mesh, const D3DRMMATRIX4D& worldMatrix) +bool IsMeshInFrustum(Direct3DRMMeshImpl* mesh, const D3DRMMATRIX4D& worldViewMatrix, const Plane* frustumPlanes) { D3DRMBOX box; mesh->GetBox(&box); @@ -197,14 +183,15 @@ bool IsMeshInFrustum(Direct3DRMMeshImpl* mesh, const D3DRMMATRIX4D& worldMatrix) }; for (D3DVECTOR& corner : boxCorners) { - corner = TransformPoint(corner, worldMatrix); + corner = TransformPoint(corner, worldViewMatrix); } for (int i = 0; i < 6; ++i) { + const Plane& plane = frustumPlanes[i]; int out = 0; for (int j = 0; j < 8; ++j) { - float dist = frustumPlanes[i].normal.x * boxCorners[j].x + frustumPlanes[i].normal.y * boxCorners[j].y + - frustumPlanes[i].normal.z * boxCorners[j].z + frustumPlanes[i].d; + const D3DVECTOR& corner = boxCorners[j]; + float dist = plane.normal.x * corner.x + plane.normal.y * corner.y + plane.normal.z * corner.z + plane.d; if (dist < 0.0f) { ++out; } @@ -264,7 +251,9 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3D Direct3DRMMeshImpl* mesh = nullptr; visual->QueryInterface(IID_IDirect3DRMMesh, (void**) &mesh); if (mesh) { - if (IsMeshInFrustum(mesh, worldMatrix)) { + D3DRMMATRIX4D modelViewMatrix; + MultiplyMatrix(modelViewMatrix, worldMatrix, m_viewMatrix); + if (IsMeshInFrustum(mesh, modelViewMatrix, m_frustumPlanes)) { DWORD groupCount = mesh->GetGroupCount(); for (DWORD gi = 0; gi < groupCount; ++gi) { const MeshGroup& meshGroup = mesh->GetGroup(gi); @@ -284,13 +273,13 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3D appearance, CalculateDepth(m_viewProjectionwMatrix, worldMatrix)} ); - memcpy(m_deferredDraws.back().worldMatrix, worldMatrix, sizeof(D3DRMMATRIX4D)); + memcpy(m_deferredDraws.back().modelViewMatrix, modelViewMatrix, sizeof(D3DRMMATRIX4D)); memcpy(m_deferredDraws.back().normalMatrix, worldMatrixInvert, sizeof(Matrix3x3)); } else { m_renderer->SubmitDraw( m_renderer->GetMeshId(mesh, &meshGroup), - worldMatrix, + modelViewMatrix, worldMatrixInvert, appearance ); @@ -319,12 +308,14 @@ HRESULT Direct3DRMViewportImpl::RenderScene() std::vector lights; CollectLightsFromFrame(m_rootFrame, identity, lights); m_renderer->PushLights(lights.data(), lights.size()); - HRESULT status = m_renderer->BeginFrame(m_viewMatrix); + HRESULT status = m_renderer->BeginFrame(); if (status != DD_OK) { return status; } - ExtractFrustumPlanes(m_viewProjectionwMatrix); + BuildViewFrustumPlanes(); + m_renderer->SetFrustumPlanes(m_frustumPlanes); + CollectMeshesFromFrame(m_rootFrame, identity); std::sort( @@ -334,7 +325,7 @@ HRESULT Direct3DRMViewportImpl::RenderScene() ); m_renderer->EnableTransparency(); for (const DeferredDrawCommand& cmd : m_deferredDraws) { - m_renderer->SubmitDraw(cmd.meshId, cmd.worldMatrix, cmd.normalMatrix, cmd.appearance); + m_renderer->SubmitDraw(cmd.meshId, cmd.modelViewMatrix, cmd.normalMatrix, cmd.appearance); } m_deferredDraws.clear(); diff --git a/miniwin/src/ddraw/ddsurface.cpp b/miniwin/src/ddraw/ddsurface.cpp index f218bd75..dc1518f1 100644 --- a/miniwin/src/ddraw/ddsurface.cpp +++ b/miniwin/src/ddraw/ddsurface.cpp @@ -173,9 +173,20 @@ HRESULT DirectDrawSurfaceImpl::Flip(LPDIRECTDRAWSURFACE lpDDSurfaceTargetOverrid return DDERR_GENERIC; } - SDL_Surface* copy = SDL_ConvertSurface(DDBackBuffer, HWBackBufferFormat); - SDL_UpdateTexture(HWBackBuffer, nullptr, copy->pixels, copy->pitch); - SDL_DestroySurface(copy); + SDL_Surface* blitSource; + if (HWBackBufferFormat != DDBackBuffer->format) { + blitSource = SDL_ConvertSurface(DDBackBuffer, HWBackBufferFormat); + if (!blitSource) { + return DDERR_GENERIC; + } + } + else { + blitSource = DDBackBuffer; + } + SDL_UpdateTexture(HWBackBuffer, nullptr, blitSource->pixels, blitSource->pitch); + if (HWBackBufferFormat != DDBackBuffer->format) { + SDL_DestroySurface(blitSource); + } SDL_RenderTexture(DDRenderer, HWBackBuffer, nullptr, nullptr); SDL_RenderPresent(DDRenderer); return DD_OK; diff --git a/miniwin/src/internal/d3drmmesh_impl.h b/miniwin/src/internal/d3drmmesh_impl.h index 3803b59e..b33a3934 100644 --- a/miniwin/src/internal/d3drmmesh_impl.h +++ b/miniwin/src/internal/d3drmmesh_impl.h @@ -13,7 +13,7 @@ struct MeshGroup { int vertexPerFace = 0; int version = 0; std::vector vertices; - std::vector indices; + std::vector indices; MeshGroup() = default; diff --git a/miniwin/src/internal/d3drmrenderer.h b/miniwin/src/internal/d3drmrenderer.h index ab6422f8..16ca4b8b 100644 --- a/miniwin/src/internal/d3drmrenderer.h +++ b/miniwin/src/internal/d3drmrenderer.h @@ -31,23 +31,29 @@ struct SceneLight { }; static_assert(sizeof(SceneLight) == 48); +struct Plane { + D3DVECTOR normal; + float d; +}; + extern SDL_Renderer* DDRenderer; class Direct3DRMRenderer : public IDirect3DDevice2 { public: virtual void PushLights(const SceneLight* vertices, size_t count) = 0; virtual void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) = 0; + virtual void SetFrustumPlanes(const Plane* frustumPlanes) = 0; virtual Uint32 GetTextureId(IDirect3DRMTexture* texture) = 0; virtual Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) = 0; virtual DWORD GetWidth() = 0; virtual DWORD GetHeight() = 0; virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0; virtual const char* GetName() = 0; - virtual HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) = 0; + virtual HRESULT BeginFrame() = 0; virtual void EnableTransparency() = 0; virtual void SubmitDraw( DWORD meshId, - const D3DRMMATRIX4D& worldMatrix, + const D3DRMMATRIX4D& modelViewMatrix, const Matrix3x3& normalMatrix, const Appearance& appearance ) = 0; diff --git a/miniwin/src/internal/d3drmrenderer_opengl1.h b/miniwin/src/internal/d3drmrenderer_opengl1.h index 580eb498..8ed3a9cc 100644 --- a/miniwin/src/internal/d3drmrenderer_opengl1.h +++ b/miniwin/src/internal/d3drmrenderer_opengl1.h @@ -25,7 +25,7 @@ struct GLMeshCacheEntry { std::vector positions; std::vector normals; std::vector texcoords; - std::vector indices; + std::vector indices; // VBO cache GLuint vboPositions; @@ -41,17 +41,18 @@ public: ~OpenGL1Renderer() override; void PushLights(const SceneLight* lightsArray, size_t count) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; + void SetFrustumPlanes(const Plane* frustumPlanes) override; Uint32 GetTextureId(IDirect3DRMTexture* texture) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; DWORD GetWidth() override; DWORD GetHeight() override; void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; const char* GetName() override; - HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override; + HRESULT BeginFrame() override; void EnableTransparency() override; void SubmitDraw( DWORD meshId, - const D3DRMMATRIX4D& worldMatrix, + const D3DRMMATRIX4D& modelViewMatrix, const Matrix3x3& normalMatrix, const Appearance& appearance ) override; @@ -62,7 +63,6 @@ private: void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh); std::vector m_textures; std::vector m_meshs; - D3DRMMATRIX4D m_viewMatrix; D3DRMMATRIX4D m_projection; SDL_Surface* m_renderedImage; int m_width, m_height; diff --git a/miniwin/src/internal/d3drmrenderer_sdl3gpu.h b/miniwin/src/internal/d3drmrenderer_sdl3gpu.h index 37ba4353..3a20000e 100644 --- a/miniwin/src/internal/d3drmrenderer_sdl3gpu.h +++ b/miniwin/src/internal/d3drmrenderer_sdl3gpu.h @@ -50,15 +50,16 @@ public: Uint32 GetTextureId(IDirect3DRMTexture* texture) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; + void SetFrustumPlanes(const Plane* frustumPlanes) override; DWORD GetWidth() override; DWORD GetHeight() override; void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; const char* GetName() override; - HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override; + HRESULT BeginFrame() override; void EnableTransparency() override; void SubmitDraw( DWORD meshId, - const D3DRMMATRIX4D& worldMatrix, + const D3DRMMATRIX4D& modelViewMatrix, const Matrix3x3& normalMatrix, const Appearance& appearance ) override; @@ -91,7 +92,6 @@ private: ViewportUniforms m_uniforms; FragmentShadingData m_fragmentShadingData; D3DDEVICEDESC m_desc; - D3DRMMATRIX4D m_viewMatrix; std::vector m_textures; std::vector m_meshs; SDL_GPUDevice* m_device; diff --git a/miniwin/src/internal/d3drmrenderer_software.h b/miniwin/src/internal/d3drmrenderer_software.h index 28347bc7..6df2b4a4 100644 --- a/miniwin/src/internal/d3drmrenderer_software.h +++ b/miniwin/src/internal/d3drmrenderer_software.h @@ -21,7 +21,7 @@ struct MeshCache { int version; bool flat; std::vector vertices; - std::vector indices; + std::vector indices; }; class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer { @@ -31,15 +31,16 @@ public: Uint32 GetTextureId(IDirect3DRMTexture* texture) override; Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; + void SetFrustumPlanes(const Plane* frustumPlanes) override; DWORD GetWidth() override; DWORD GetHeight() override; void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; const char* GetName() override; - HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override; + HRESULT BeginFrame() override; void EnableTransparency() override; void SubmitDraw( DWORD meshId, - const D3DRMMATRIX4D& worldMatrix, + const D3DRMMATRIX4D& modelViewMatrix, const Matrix3x3& normalMatrix, const Appearance& appearance ) override; @@ -54,7 +55,7 @@ private: const Appearance& appearance ); void DrawTriangleClipped(const D3DRMVERTEX (&v)[3], const Appearance& appearance); - void ProjectVertex(const D3DRMVERTEX& v, D3DRMVECTOR4D& p) const; + void ProjectVertex(const D3DVECTOR& v, D3DRMVECTOR4D& p) const; Uint32 BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g, Uint8 b, Uint8 a); SDL_Color ApplyLighting(const D3DVECTOR& position, const D3DVECTOR& normal, const Appearance& appearance); void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture); @@ -70,9 +71,11 @@ private: std::vector m_meshs; D3DVALUE m_front; D3DVALUE m_back; - D3DRMMATRIX4D m_viewMatrix; + Matrix3x3 m_normalMatrix; D3DRMMATRIX4D m_projection; std::vector m_zBuffer; + std::vector m_transformedVerts; + Plane m_frustumPlanes[6]; }; inline static void Direct3DRMSoftware_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) diff --git a/miniwin/src/internal/d3drmviewport_impl.h b/miniwin/src/internal/d3drmviewport_impl.h index 53e18717..c27af586 100644 --- a/miniwin/src/internal/d3drmviewport_impl.h +++ b/miniwin/src/internal/d3drmviewport_impl.h @@ -9,7 +9,7 @@ struct DeferredDrawCommand { DWORD meshId; - D3DRMMATRIX4D worldMatrix; + D3DRMMATRIX4D modelViewMatrix; Matrix3x3 normalMatrix; Appearance appearance; float depth; @@ -47,6 +47,7 @@ private: HRESULT RenderScene(); void CollectLightsFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix, std::vector& lights); void CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix); + void BuildViewFrustumPlanes(); void UpdateProjectionMatrix(); Direct3DRMRenderer* m_renderer; std::vector m_deferredDraws; @@ -62,6 +63,7 @@ private: D3DVALUE m_front = 1.f; D3DVALUE m_back = 10.f; D3DVALUE m_field = 0.5f; + Plane m_frustumPlanes[6]; }; struct Direct3DRMViewportArrayImpl diff --git a/miniwin/src/internal/meshutils.cpp b/miniwin/src/internal/meshutils.cpp index d56f1d54..818ecd87 100644 --- a/miniwin/src/internal/meshutils.cpp +++ b/miniwin/src/internal/meshutils.cpp @@ -43,7 +43,7 @@ void FlattenSurfaces( const size_t indexCount, bool hasTexture, std::vector& dedupedVertices, - std::vector& newIndices + std::vector& newIndices ) { std::unordered_map uniqueVertexMap; diff --git a/miniwin/src/internal/meshutils.h b/miniwin/src/internal/meshutils.h index 2ffdd17e..fb12a145 100644 --- a/miniwin/src/internal/meshutils.h +++ b/miniwin/src/internal/meshutils.h @@ -11,5 +11,5 @@ void FlattenSurfaces( const size_t indexCount, bool hasTexture, std::vector& dedupedVertices, - std::vector& newIndices + std::vector& newIndices );