Clean up rendering (#301)

This commit is contained in:
Anders Jenbo 2025-06-16 04:28:32 +02:00 committed by GitHub
parent e6a005fd33
commit 2828452b35
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 184 additions and 144 deletions

View File

@ -145,10 +145,10 @@ struct D3DRMVERTEX {
D3DVECTOR position;
D3DVECTOR normal;
union {
TexCoord texCoord;
struct {
D3DVALUE tu, tv;
};
TexCoord texCoord;
};
};

View File

@ -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<uint16_t>(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<GLsizei>(mesh.indices.size()), GL_UNSIGNED_INT, nullptr);
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(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<GLsizei>(mesh.indices.size()), GL_UNSIGNED_INT, mesh.indices.data());
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mesh.indices.size()), GL_UNSIGNED_SHORT, mesh.indices.data());
}
glPopMatrix();

View File

@ -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<Uint16> finalIndices;
if (meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT) {
std::vector<DWORD> newIndices;
std::vector<uint16_t> 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;

View File

@ -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<D3DRMVERTEX> 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<D3DRMVERTEX> 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
);
}

View File

@ -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<SceneLight> 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();

View File

@ -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;

View File

@ -13,7 +13,7 @@ struct MeshGroup {
int vertexPerFace = 0;
int version = 0;
std::vector<D3DRMVERTEX> vertices;
std::vector<unsigned int> indices;
std::vector<DWORD> indices;
MeshGroup() = default;

View File

@ -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;

View File

@ -25,7 +25,7 @@ struct GLMeshCacheEntry {
std::vector<D3DVECTOR> positions;
std::vector<D3DVECTOR> normals;
std::vector<TexCoord> texcoords;
std::vector<DWORD> indices;
std::vector<uint16_t> 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<GLTextureCacheEntry> m_textures;
std::vector<GLMeshCacheEntry> m_meshs;
D3DRMMATRIX4D m_viewMatrix;
D3DRMMATRIX4D m_projection;
SDL_Surface* m_renderedImage;
int m_width, m_height;

View File

@ -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<SDL3TextureCache> m_textures;
std::vector<SDL3MeshCache> m_meshs;
SDL_GPUDevice* m_device;

View File

@ -21,7 +21,7 @@ struct MeshCache {
int version;
bool flat;
std::vector<D3DRMVERTEX> vertices;
std::vector<DWORD> indices;
std::vector<uint16_t> 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<MeshCache> m_meshs;
D3DVALUE m_front;
D3DVALUE m_back;
D3DRMMATRIX4D m_viewMatrix;
Matrix3x3 m_normalMatrix;
D3DRMMATRIX4D m_projection;
std::vector<float> m_zBuffer;
std::vector<D3DRMVERTEX> m_transformedVerts;
Plane m_frustumPlanes[6];
};
inline static void Direct3DRMSoftware_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)

View File

@ -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<SceneLight>& lights);
void CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix);
void BuildViewFrustumPlanes();
void UpdateProjectionMatrix();
Direct3DRMRenderer* m_renderer;
std::vector<DeferredDrawCommand> 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

View File

@ -43,7 +43,7 @@ void FlattenSurfaces(
const size_t indexCount,
bool hasTexture,
std::vector<D3DRMVERTEX>& dedupedVertices,
std::vector<DWORD>& newIndices
std::vector<uint16_t>& newIndices
)
{
std::unordered_map<D3DRMVERTEX, DWORD> uniqueVertexMap;

View File

@ -11,5 +11,5 @@ void FlattenSurfaces(
const size_t indexCount,
bool hasTexture,
std::vector<D3DRMVERTEX>& dedupedVertices,
std::vector<DWORD>& newIndices
std::vector<uint16_t>& newIndices
);