mirror of
https://github.com/isledecomp/isle-portable.git
synced 2025-09-22 11:31:57 -04:00
Clean up rendering (#301)
This commit is contained in:
parent
e6a005fd33
commit
2828452b35
@ -145,10 +145,10 @@ struct D3DRMVERTEX {
|
||||
D3DVECTOR position;
|
||||
D3DVECTOR normal;
|
||||
union {
|
||||
TexCoord texCoord;
|
||||
struct {
|
||||
D3DVALUE tu, tv;
|
||||
};
|
||||
TexCoord texCoord;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user