Upload models to GPU before rendering (#272)

This commit is contained in:
Anders Jenbo 2025-06-10 06:34:49 +02:00 committed by GitHub
parent 9ebeda5c0e
commit c8b8035de8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 578 additions and 436 deletions

View File

@ -192,6 +192,91 @@ Uint32 OpenGL15Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
return (Uint32) (m_textures.size() - 1); return (Uint32) (m_textures.size() - 1);
} }
GLMeshCacheEntry GLUploadMesh(const MeshGroup& meshGroup)
{
GLMeshCacheEntry cache{&meshGroup, meshGroup.version};
cache.flat = meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT;
std::vector<D3DRMVERTEX> vertices;
if (cache.flat) {
FlattenSurfaces(
meshGroup.vertices.data(),
meshGroup.vertices.size(),
meshGroup.indices.data(),
meshGroup.indices.size(),
meshGroup.texture != nullptr,
vertices,
cache.indices
);
}
else {
vertices.assign(meshGroup.vertices.begin(), meshGroup.vertices.end());
cache.indices.assign(meshGroup.indices.begin(), meshGroup.indices.end());
}
cache.texcoords.resize(vertices.size());
std::transform(vertices.begin(), vertices.end(), cache.texcoords.begin(), [](const D3DRMVERTEX& v) {
return v.texCoord;
});
cache.positions.resize(vertices.size());
std::transform(vertices.begin(), vertices.end(), cache.positions.begin(), [](const D3DRMVERTEX& v) {
return v.position;
});
cache.normals.resize(vertices.size());
std::transform(vertices.begin(), vertices.end(), cache.normals.begin(), [](const D3DRMVERTEX& v) {
return v.normal;
});
return cache;
}
struct GLMeshDestroyContext {
OpenGL15Renderer* renderer;
Uint32 id;
};
void OpenGL15Renderer::AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh)
{
auto* ctx = new GLMeshDestroyContext{this, id};
mesh->AddDestroyCallback(
[](IDirect3DRMObject*, void* arg) {
auto* ctx = static_cast<GLMeshDestroyContext*>(arg);
ctx->renderer->m_meshs[ctx->id].meshGroup = nullptr;
delete ctx;
},
ctx
);
}
Uint32 OpenGL15Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup)
{
for (Uint32 i = 0; i < m_meshs.size(); ++i) {
auto& cache = m_meshs[i];
if (cache.meshGroup == meshGroup) {
if (cache.version != meshGroup->version) {
cache = std::move(GLUploadMesh(*meshGroup));
}
return i;
}
}
auto newCache = GLUploadMesh(*meshGroup);
for (Uint32 i = 0; i < m_meshs.size(); ++i) {
auto& cache = m_meshs[i];
if (!cache.meshGroup) {
cache = std::move(newCache);
AddMeshDestroyCallback(i, mesh);
return i;
}
}
m_meshs.push_back(std::move(newCache));
AddMeshDestroyCallback((Uint32) (m_meshs.size() - 1), mesh);
return (Uint32) (m_meshs.size() - 1);
}
DWORD OpenGL15Renderer::GetWidth() DWORD OpenGL15Renderer::GetWidth()
{ {
return m_width; return m_width;
@ -306,10 +391,7 @@ HRESULT OpenGL15Renderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
} }
void OpenGL15Renderer::SubmitDraw( void OpenGL15Renderer::SubmitDraw(
const D3DRMVERTEX* vertices, DWORD meshId,
const size_t vertexCount,
const DWORD* indices,
const size_t indexCount,
const D3DRMMATRIX4D& worldMatrix, const D3DRMMATRIX4D& worldMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
@ -323,47 +405,9 @@ void OpenGL15Renderer::SubmitDraw(
glLoadMatrixf(&mvMatrix[0][0]); glLoadMatrixf(&mvMatrix[0][0]);
glEnable(GL_NORMALIZE); glEnable(GL_NORMALIZE);
std::vector<D3DRMVERTEX> newVertices;
std::vector<DWORD> newIndices;
if (appearance.flat) {
glShadeModel(GL_FLAT);
// FIXME move this to a one time mesh upload stage
FlattenSurfaces(
vertices,
vertexCount,
indices,
indexCount,
appearance.textureId != NO_TEXTURE_ID,
newVertices,
newIndices
);
}
else {
glShadeModel(GL_SMOOTH);
newVertices.assign(vertices, vertices + vertexCount);
newIndices.assign(indices, indices + indexCount);
}
// Bind texture if present
std::vector<TexCoord> texcoords;
if (appearance.textureId != NO_TEXTURE_ID) {
auto& tex = m_textures[appearance.textureId];
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex.glTextureId);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
texcoords.resize(newVertices.size());
std::transform(newVertices.begin(), newVertices.end(), texcoords.begin(), [](const D3DRMVERTEX& v) {
return v.texCoord;
});
}
else {
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a); glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a);
float shininess = appearance.shininess; float shininess = appearance.shininess * m_shininessFactor;
glMaterialf(GL_FRONT, GL_SHININESS, shininess); glMaterialf(GL_FRONT, GL_SHININESS, shininess);
if (shininess != 0.0f) { if (shininess != 0.0f) {
GLfloat whiteSpec[] = {shininess, shininess, shininess, shininess}; GLfloat whiteSpec[] = {shininess, shininess, shininess, shininess};
@ -374,29 +418,36 @@ void OpenGL15Renderer::SubmitDraw(
glMaterialfv(GL_FRONT, GL_SPECULAR, noSpec); glMaterialfv(GL_FRONT, GL_SPECULAR, noSpec);
} }
std::vector<D3DVECTOR> positions; auto& mesh = m_meshs[meshId];
positions.resize(newVertices.size());
std::transform(newVertices.begin(), newVertices.end(), positions.begin(), [](const D3DRMVERTEX& v) {
return v.position;
});
std::vector<D3DVECTOR> normals;
normals.resize(newVertices.size());
std::transform(newVertices.begin(), newVertices.end(), normals.begin(), [](const D3DRMVERTEX& v) {
return v.normal;
});
glEnableClientState(GL_VERTEX_ARRAY); if (mesh.flat) {
glVertexPointer(3, GL_FLOAT, 0, positions.data()); glShadeModel(GL_FLAT);
}
glEnableClientState(GL_NORMAL_ARRAY); else {
glNormalPointer(GL_FLOAT, 0, normals.data()); glShadeModel(GL_SMOOTH);
if (appearance.textureId != NO_TEXTURE_ID) {
glTexCoordPointer(2, GL_FLOAT, 0, texcoords.data());
} }
// Bind texture if present
if (appearance.textureId != NO_TEXTURE_ID) {
auto& tex = m_textures[appearance.textureId];
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex.glTextureId);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords.data());
}
else {
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, mesh.positions.data());
glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, mesh.normals.data());
// Draw triangles // Draw triangles
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(newIndices.size()), GL_UNSIGNED_INT, newIndices.data()); glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mesh.indices.size()), GL_UNSIGNED_INT, mesh.indices.data());
glPopMatrix(); glPopMatrix();
} }

View File

@ -91,76 +91,6 @@ struct ScopedShader {
void release() { ptr = nullptr; } void release() { ptr = nullptr; }
}; };
SDL_GPUTexture* CreateTextureFromSurface(
SDL_GPUDevice* device,
SDL_GPUTransferBuffer* transferBuffer,
SDL_Surface* surface
)
{
ScopedSurface surf{SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ABGR8888)};
if (!surf.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ConvertSurface (%s)", SDL_GetError());
return nullptr;
}
const Uint32 dataSize = surf.ptr->pitch * surf.ptr->h;
SDL_GPUTextureCreateInfo textureInfo = {};
textureInfo.type = SDL_GPU_TEXTURETYPE_2D;
textureInfo.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
textureInfo.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
textureInfo.width = surf.ptr->w;
textureInfo.height = surf.ptr->h;
textureInfo.layer_count_or_depth = 1;
textureInfo.num_levels = 1;
ScopedTexture texture{device, SDL_CreateGPUTexture(device, &textureInfo)};
if (!texture.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTexture (%s)", SDL_GetError());
return nullptr;
}
void* transferData = SDL_MapGPUTransferBuffer(device, transferBuffer, false);
if (!transferData) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_MapGPUTransferBuffer (%s)", SDL_GetError());
return nullptr;
}
memcpy(transferData, surf.ptr->pixels, dataSize);
SDL_UnmapGPUTransferBuffer(device, transferBuffer);
SDL_GPUTextureTransferInfo transferRegionInfo = {};
transferRegionInfo.transfer_buffer = transferBuffer;
SDL_GPUTextureRegion textureRegion = {};
textureRegion.texture = texture.ptr;
textureRegion.w = surf.ptr->w;
textureRegion.h = surf.ptr->h;
textureRegion.d = 1;
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(device);
if (!cmdbuf) {
SDL_LogError(
LOG_CATEGORY_MINIWIN,
"SDL_AcquireGPUCommandBuffer in CreateTextureFromSurface failed (%s)",
SDL_GetError()
);
return nullptr;
}
SDL_GPUCopyPass* pass = SDL_BeginGPUCopyPass(cmdbuf);
SDL_UploadToGPUTexture(pass, &transferRegionInfo, &textureRegion, false);
SDL_EndGPUCopyPass(pass);
if (!SDL_SubmitGPUCommandBuffer(cmdbuf)) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_SubmitGPUCommandBuffer (%s)", SDL_GetError());
return nullptr;
}
auto texptr = texture.ptr;
// Release texture ownership so caller can manage it safely
texture.release();
return texptr;
}
static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device, bool depthWrite) static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device, bool depthWrite)
{ {
const SDL_GPUShaderCreateInfo* vertexCreateInfo = const SDL_GPUShaderCreateInfo* vertexCreateInfo =
@ -325,24 +255,6 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
return nullptr; return nullptr;
} }
SDL_Surface* dummySurface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ABGR8888);
if (!dummySurface) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create surface: %s", SDL_GetError());
return nullptr;
}
if (!SDL_LockSurface(dummySurface)) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to lock surface: %s", SDL_GetError());
SDL_DestroySurface(dummySurface);
return nullptr;
}
((Uint32*) dummySurface->pixels)[0] = 0xFFFFFFFF;
ScopedTexture dummyTexture{device.ptr, CreateTextureFromSurface(device.ptr, uploadBuffer.ptr, dummySurface)};
SDL_DestroySurface(dummySurface);
if (!dummyTexture.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create texture from surface");
return nullptr;
}
SDL_GPUSamplerCreateInfo samplerInfo = {}; SDL_GPUSamplerCreateInfo samplerInfo = {};
samplerInfo.min_filter = SDL_GPU_FILTER_LINEAR; samplerInfo.min_filter = SDL_GPU_FILTER_LINEAR;
samplerInfo.mag_filter = SDL_GPU_FILTER_LINEAR; samplerInfo.mag_filter = SDL_GPU_FILTER_LINEAR;
@ -364,7 +276,6 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
transparentPipeline.ptr, transparentPipeline.ptr,
transferTexture.ptr, transferTexture.ptr,
depthTexture.ptr, depthTexture.ptr,
dummyTexture.ptr,
sampler.ptr, sampler.ptr,
uploadBuffer.ptr, uploadBuffer.ptr,
downloadBuffer.ptr downloadBuffer.ptr
@ -376,7 +287,6 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
transparentPipeline.release(); transparentPipeline.release();
transferTexture.release(); transferTexture.release();
depthTexture.release(); depthTexture.release();
dummyTexture.release();
sampler.release(); sampler.release();
uploadBuffer.release(); uploadBuffer.release();
downloadBuffer.release(); downloadBuffer.release();
@ -392,15 +302,29 @@ Direct3DRMSDL3GPURenderer::Direct3DRMSDL3GPURenderer(
SDL_GPUGraphicsPipeline* transparentPipeline, SDL_GPUGraphicsPipeline* transparentPipeline,
SDL_GPUTexture* transferTexture, SDL_GPUTexture* transferTexture,
SDL_GPUTexture* depthTexture, SDL_GPUTexture* depthTexture,
SDL_GPUTexture* dummyTexture,
SDL_GPUSampler* sampler, SDL_GPUSampler* sampler,
SDL_GPUTransferBuffer* uploadBuffer, SDL_GPUTransferBuffer* uploadBuffer,
SDL_GPUTransferBuffer* downloadBuffer SDL_GPUTransferBuffer* downloadBuffer
) )
: m_width(width), m_height(height), m_device(device), m_opaquePipeline(opaquePipeline), : m_width(width), m_height(height), m_device(device), m_opaquePipeline(opaquePipeline),
m_transparentPipeline(transparentPipeline), m_transferTexture(transferTexture), m_depthTexture(depthTexture), m_transparentPipeline(transparentPipeline), m_transferTexture(transferTexture), m_depthTexture(depthTexture),
m_dummyTexture(dummyTexture), m_sampler(sampler), m_uploadBuffer(uploadBuffer), m_downloadBuffer(downloadBuffer) m_sampler(sampler), m_uploadBuffer(uploadBuffer), m_downloadBuffer(downloadBuffer)
{ {
SDL_Surface* dummySurface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ABGR8888);
if (!dummySurface) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create surface: %s", SDL_GetError());
return;
}
if (!SDL_LockSurface(dummySurface)) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to lock surface: %s", SDL_GetError());
SDL_DestroySurface(dummySurface);
return;
}
((Uint32*) dummySurface->pixels)[0] = 0xFFFFFFFF;
SDL_UnlockSurface(dummySurface);
m_dummyTexture = CreateTextureFromSurface(dummySurface);
SDL_DestroySurface(dummySurface);
} }
Direct3DRMSDL3GPURenderer::~Direct3DRMSDL3GPURenderer() Direct3DRMSDL3GPURenderer::~Direct3DRMSDL3GPURenderer()
@ -412,10 +336,12 @@ Direct3DRMSDL3GPURenderer::~Direct3DRMSDL3GPURenderer()
SDL_ReleaseGPUSampler(m_device, m_sampler); SDL_ReleaseGPUSampler(m_device, m_sampler);
SDL_ReleaseGPUTexture(m_device, m_dummyTexture); SDL_ReleaseGPUTexture(m_device, m_dummyTexture);
SDL_ReleaseGPUTexture(m_device, m_depthTexture); SDL_ReleaseGPUTexture(m_device, m_depthTexture);
SDL_ReleaseGPUBuffer(m_device, m_vertexBuffer);
SDL_ReleaseGPUTexture(m_device, m_transferTexture); SDL_ReleaseGPUTexture(m_device, m_transferTexture);
SDL_ReleaseGPUGraphicsPipeline(m_device, m_opaquePipeline); SDL_ReleaseGPUGraphicsPipeline(m_device, m_opaquePipeline);
SDL_ReleaseGPUGraphicsPipeline(m_device, m_transparentPipeline); SDL_ReleaseGPUGraphicsPipeline(m_device, m_transparentPipeline);
if (m_uploadFence) {
SDL_ReleaseGPUFence(m_device, m_uploadFence);
}
SDL_DestroyGPUDevice(m_device); SDL_DestroyGPUDevice(m_device);
} }
@ -436,6 +362,19 @@ void Direct3DRMSDL3GPURenderer::SetProjection(const D3DRMMATRIX4D& projection, D
memcpy(&m_uniforms.projection, projection, sizeof(D3DRMMATRIX4D)); memcpy(&m_uniforms.projection, projection, sizeof(D3DRMMATRIX4D));
} }
void Direct3DRMSDL3GPURenderer::WaitForPendingUpload()
{
if (!m_uploadFence) {
return;
}
bool success = SDL_WaitForGPUFences(m_device, true, &m_uploadFence, 1);
SDL_ReleaseGPUFence(m_device, m_uploadFence);
m_uploadFence = nullptr;
if (!success) {
return;
}
}
struct SDLTextureDestroyContext { struct SDLTextureDestroyContext {
Direct3DRMSDL3GPURenderer* renderer; Direct3DRMSDL3GPURenderer* renderer;
Uint32 id; Uint32 id;
@ -459,6 +398,69 @@ void Direct3DRMSDL3GPURenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRM
); );
} }
SDL_GPUTexture* Direct3DRMSDL3GPURenderer::CreateTextureFromSurface(SDL_Surface* surface)
{
ScopedSurface surf{SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ABGR8888)};
if (!surf.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ConvertSurface (%s)", SDL_GetError());
return nullptr;
}
const Uint32 dataSize = surf.ptr->pitch * surf.ptr->h;
SDL_GPUTextureCreateInfo textureInfo = {};
textureInfo.type = SDL_GPU_TEXTURETYPE_2D;
textureInfo.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
textureInfo.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
textureInfo.width = surf.ptr->w;
textureInfo.height = surf.ptr->h;
textureInfo.layer_count_or_depth = 1;
textureInfo.num_levels = 1;
ScopedTexture texture{m_device, SDL_CreateGPUTexture(m_device, &textureInfo)};
if (!texture.ptr) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTexture (%s)", SDL_GetError());
return nullptr;
}
SDL_GPUTransferBuffer* transferBuffer = GetUploadBuffer(dataSize);
void* transferData = SDL_MapGPUTransferBuffer(m_device, transferBuffer, false);
if (!transferData) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_MapGPUTransferBuffer (%s)", SDL_GetError());
return nullptr;
}
memcpy(transferData, surf.ptr->pixels, dataSize);
SDL_UnmapGPUTransferBuffer(m_device, transferBuffer);
SDL_GPUTextureTransferInfo transferRegionInfo = {};
transferRegionInfo.transfer_buffer = transferBuffer;
SDL_GPUTextureRegion textureRegion = {};
textureRegion.texture = texture.ptr;
textureRegion.w = surf.ptr->w;
textureRegion.h = surf.ptr->h;
textureRegion.d = 1;
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
if (!cmdbuf) {
SDL_LogError(
LOG_CATEGORY_MINIWIN,
"SDL_AcquireGPUCommandBuffer in CreateTextureFromSurface failed (%s)",
SDL_GetError()
);
return nullptr;
}
SDL_GPUCopyPass* pass = SDL_BeginGPUCopyPass(cmdbuf);
SDL_UploadToGPUTexture(pass, &transferRegionInfo, &textureRegion, false);
SDL_EndGPUCopyPass(pass);
m_uploadFence = SDL_SubmitGPUCommandBufferAndAcquireFence(cmdbuf);
auto texptr = texture.ptr;
// Release texture ownership so caller can manage it safely
texture.release();
return texptr;
}
Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture) Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture)
{ {
auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture); auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
@ -470,7 +472,7 @@ Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture)
if (tex.texture == texture) { if (tex.texture == texture) {
if (tex.version != texture->m_version) { if (tex.version != texture->m_version) {
SDL_ReleaseGPUTexture(m_device, tex.gpuTexture); SDL_ReleaseGPUTexture(m_device, tex.gpuTexture);
tex.gpuTexture = CreateTextureFromSurface(m_device, GetUploadBuffer(surf->w * surf->h * 4), surf); tex.gpuTexture = CreateTextureFromSurface(surf);
if (!tex.gpuTexture) { if (!tex.gpuTexture) {
return NO_TEXTURE_ID; return NO_TEXTURE_ID;
} }
@ -480,7 +482,7 @@ Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture)
} }
} }
SDL_GPUTexture* newTex = CreateTextureFromSurface(m_device, GetUploadBuffer(surf->w * surf->h * 4), surf); SDL_GPUTexture* newTex = CreateTextureFromSurface(surf);
if (!newTex) { if (!newTex) {
return NO_TEXTURE_ID; return NO_TEXTURE_ID;
} }
@ -499,6 +501,123 @@ Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture)
return (Uint32) (m_textures.size() - 1); return (Uint32) (m_textures.size() - 1);
} }
SDL3MeshCache Direct3DRMSDL3GPURenderer::UploadMesh(const MeshGroup& meshGroup)
{
std::vector<D3DRMVERTEX> flatVertices;
if (meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT) {
std::vector<D3DRMVERTEX> newVertices;
std::vector<DWORD> newIndices;
FlattenSurfaces(
meshGroup.vertices.data(),
meshGroup.vertices.size(),
meshGroup.indices.data(),
meshGroup.indices.size(),
meshGroup.texture != nullptr,
newVertices,
newIndices
);
for (DWORD& index : newIndices) {
flatVertices.push_back(newVertices[index]);
}
}
else {
// TODO handle indexed verticies on GPU
for (int i = 0; i < meshGroup.indices.size(); ++i) {
flatVertices.push_back(meshGroup.vertices[meshGroup.indices[i]]);
}
}
SDL_GPUBufferCreateInfo bufferCreateInfo = {};
bufferCreateInfo.usage = SDL_GPU_BUFFERUSAGE_VERTEX;
bufferCreateInfo.size = sizeof(D3DRMVERTEX) * flatVertices.size();
SDL_GPUBuffer* vertexBuffer = SDL_CreateGPUBuffer(m_device, &bufferCreateInfo);
if (!vertexBuffer) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUBuffer failed (%s)", SDL_GetError());
}
SDL_GPUTransferBuffer* uploadBuffer = GetUploadBuffer(sizeof(D3DRMVERTEX) * flatVertices.size());
if (!uploadBuffer) {
return {};
}
D3DRMVERTEX* transferData = (D3DRMVERTEX*) SDL_MapGPUTransferBuffer(m_device, uploadBuffer, false);
if (!transferData) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_MapGPUTransferBuffer returned NULL buffer (%s)", SDL_GetError());
return {};
}
memcpy(transferData, flatVertices.data(), sizeof(D3DRMVERTEX) * flatVertices.size());
SDL_UnmapGPUTransferBuffer(m_device, uploadBuffer);
SDL_GPUTransferBufferLocation transferLocation = {};
transferLocation.transfer_buffer = uploadBuffer;
SDL_GPUBufferRegion bufferRegion = {};
bufferRegion.buffer = vertexBuffer;
bufferRegion.size = static_cast<Uint32>(sizeof(D3DRMVERTEX) * flatVertices.size());
// Upload the transfer data to the vertex buffer
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
if (!cmdbuf) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer in SubmitDraw failed (%s)", SDL_GetError());
return {};
}
SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdbuf);
SDL_UploadToGPUBuffer(copyPass, &transferLocation, &bufferRegion, false);
SDL_EndGPUCopyPass(copyPass);
m_uploadFence = SDL_SubmitGPUCommandBufferAndAcquireFence(cmdbuf);
return {&meshGroup, meshGroup.version, vertexBuffer, flatVertices.size()};
}
struct SDLMeshDestroyContext {
Direct3DRMSDL3GPURenderer* renderer;
Uint32 id;
};
void Direct3DRMSDL3GPURenderer::AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh)
{
auto* ctx = new SDLMeshDestroyContext{this, id};
mesh->AddDestroyCallback(
[](IDirect3DRMObject*, void* arg) {
auto* ctx = static_cast<SDLMeshDestroyContext*>(arg);
auto& cache = ctx->renderer->m_meshs[ctx->id];
SDL_ReleaseGPUBuffer(ctx->renderer->m_device, cache.vertexBuffer);
cache.meshGroup = nullptr;
delete ctx;
},
ctx
);
}
Uint32 Direct3DRMSDL3GPURenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup)
{
for (Uint32 i = 0; i < m_meshs.size(); ++i) {
auto& cache = m_meshs[i];
if (cache.meshGroup == meshGroup) {
if (cache.version != meshGroup->version) {
SDL_ReleaseGPUBuffer(m_device, cache.vertexBuffer);
cache = std::move(UploadMesh(*meshGroup));
}
return i;
}
}
auto newCache = UploadMesh(*meshGroup);
for (Uint32 i = 0; i < m_meshs.size(); ++i) {
auto& cache = m_meshs[i];
if (!cache.meshGroup) {
cache = std::move(newCache);
AddMeshDestroyCallback(i, mesh);
return i;
}
}
m_meshs.push_back(std::move(newCache));
AddMeshDestroyCallback((Uint32) (m_meshs.size() - 1), mesh);
return (Uint32) (m_meshs.size() - 1);
}
DWORD Direct3DRMSDL3GPURenderer::GetWidth() DWORD Direct3DRMSDL3GPURenderer::GetWidth()
{ {
return m_width; return m_width;
@ -527,42 +646,6 @@ const char* Direct3DRMSDL3GPURenderer::GetName()
return "SDL3 GPU HAL"; return "SDL3 GPU HAL";
} }
HRESULT Direct3DRMSDL3GPURenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
{
if (!DDBackBuffer) {
return DDERR_GENERIC;
}
memcpy(&m_viewMatrix, viewMatrix, sizeof(D3DRMMATRIX4D));
// Clear color and depth targets
SDL_GPUColorTargetInfo colorTargetInfo = {};
colorTargetInfo.texture = m_transferTexture;
colorTargetInfo.clear_color = {0, 0, 0, 0};
colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
SDL_GPUDepthStencilTargetInfo depthStencilTargetInfo = {};
depthStencilTargetInfo.texture = m_depthTexture;
depthStencilTargetInfo.clear_depth = 0.0f;
depthStencilTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
if (!cmdbuf) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer in BeginFrame failed (%s)", SDL_GetError());
return DDERR_GENERIC;
}
SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, &depthStencilTargetInfo);
SDL_EndGPURenderPass(renderPass);
if (!SDL_SubmitGPUCommandBuffer(cmdbuf)) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_SubmitGPUCommandBuffer failed (%s)", SDL_GetError());
return DDERR_GENERIC;
}
return DD_OK;
}
void PackNormalMatrix(const Matrix3x3& normalMatrix3x3, D3DRMMATRIX4D& packedNormalMatrix4x4) void PackNormalMatrix(const Matrix3x3& normalMatrix3x3, D3DRMMATRIX4D& packedNormalMatrix4x4)
{ {
for (int row = 0; row < 3; ++row) { for (int row = 0; row < 3; ++row) {
@ -578,6 +661,7 @@ void PackNormalMatrix(const Matrix3x3& normalMatrix3x3, D3DRMMATRIX4D& packedNor
SDL_GPUTransferBuffer* Direct3DRMSDL3GPURenderer::GetUploadBuffer(size_t size) SDL_GPUTransferBuffer* Direct3DRMSDL3GPURenderer::GetUploadBuffer(size_t size)
{ {
WaitForPendingUpload();
if (m_uploadBufferSize < size) { if (m_uploadBufferSize < size) {
SDL_ReleaseGPUTransferBuffer(m_device, m_uploadBuffer); SDL_ReleaseGPUTransferBuffer(m_device, m_uploadBuffer);
@ -599,140 +683,75 @@ SDL_GPUTransferBuffer* Direct3DRMSDL3GPURenderer::GetUploadBuffer(size_t size)
return m_uploadBuffer; return m_uploadBuffer;
} }
HRESULT Direct3DRMSDL3GPURenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
{
if (!DDBackBuffer) {
return DDERR_GENERIC;
}
memcpy(&m_viewMatrix, viewMatrix, sizeof(D3DRMMATRIX4D));
// Clear color and depth targets
SDL_GPUColorTargetInfo colorTargetInfo = {};
colorTargetInfo.texture = m_transferTexture;
colorTargetInfo.clear_color = {0, 0, 0, 0};
colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
SDL_GPUDepthStencilTargetInfo depthStencilTargetInfo = {};
depthStencilTargetInfo.texture = m_depthTexture;
depthStencilTargetInfo.clear_depth = 0.0f;
depthStencilTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
depthStencilTargetInfo.store_op = SDL_GPU_STOREOP_STORE;
m_cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
if (!m_cmdbuf) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer in BeginFrame failed (%s)", SDL_GetError());
return DDERR_GENERIC;
}
m_renderPass = SDL_BeginGPURenderPass(m_cmdbuf, &colorTargetInfo, 1, &depthStencilTargetInfo);
SDL_BindGPUGraphicsPipeline(m_renderPass, m_opaquePipeline);
return DD_OK;
}
void Direct3DRMSDL3GPURenderer::SubmitDraw( void Direct3DRMSDL3GPURenderer::SubmitDraw(
const D3DRMVERTEX* vertices, DWORD meshId,
const size_t vertexCount,
const DWORD* indices,
const size_t indexCount,
const D3DRMMATRIX4D& worldMatrix, const D3DRMMATRIX4D& worldMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
) )
{ {
// TODO only switch piplinen after all opaque's have been rendered
SDL_BindGPUGraphicsPipeline(m_renderPass, appearance.color.a == 255 ? m_opaquePipeline : m_transparentPipeline);
D3DRMMATRIX4D worldViewMatrix; D3DRMMATRIX4D worldViewMatrix;
MultiplyMatrix(worldViewMatrix, worldMatrix, m_viewMatrix); MultiplyMatrix(worldViewMatrix, worldMatrix, m_viewMatrix);
memcpy(&m_uniforms.worldViewMatrix, worldViewMatrix, sizeof(D3DRMMATRIX4D)); memcpy(&m_uniforms.worldViewMatrix, worldViewMatrix, sizeof(D3DRMMATRIX4D));
PackNormalMatrix(normalMatrix, m_uniforms.normalMatrix); PackNormalMatrix(normalMatrix, m_uniforms.normalMatrix);
m_fragmentShadingData.color = appearance.color; m_fragmentShadingData.color = appearance.color;
m_fragmentShadingData.shininess = appearance.shininess; m_fragmentShadingData.shininess = appearance.shininess * m_shininessFactor;
bool useTexture = appearance.textureId != NO_TEXTURE_ID;
m_fragmentShadingData.useTexture = appearance.textureId != NO_TEXTURE_ID;
std::vector<D3DRMVERTEX> flatVertices; auto& mesh = m_meshs[meshId];
if (appearance.flat) {
std::vector<D3DRMVERTEX> newVertices;
std::vector<DWORD> newIndices;
// FIXME move this to a one time mesh upload stage
FlattenSurfaces(
vertices,
vertexCount,
indices,
indexCount,
appearance.textureId != NO_TEXTURE_ID,
newVertices,
newIndices
);
for (DWORD& index : newIndices) {
flatVertices.push_back(newVertices[index]);
}
}
else {
// TODO handle indexed verticies on GPU
for (int i = 0; i < indexCount; ++i) {
flatVertices.push_back(vertices[indices[i]]);
}
}
if (flatVertices.size() > m_vertexBufferCount) {
if (m_vertexBuffer) {
SDL_ReleaseGPUBuffer(m_device, m_vertexBuffer);
}
SDL_GPUBufferCreateInfo bufferCreateInfo = {};
bufferCreateInfo.usage = SDL_GPU_BUFFERUSAGE_VERTEX;
bufferCreateInfo.size = static_cast<Uint32>(sizeof(D3DRMVERTEX) * flatVertices.size());
m_vertexBuffer = SDL_CreateGPUBuffer(m_device, &bufferCreateInfo);
if (!m_vertexBuffer) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUBuffer failed (%s)", SDL_GetError());
}
m_vertexBufferCount = flatVertices.size();
}
m_vertexCount = flatVertices.size();
SDL_GPUTransferBuffer* uploadBuffer = GetUploadBuffer(sizeof(D3DRMVERTEX) * m_vertexCount);
if (!uploadBuffer) {
return;
}
D3DRMVERTEX* transferData = (D3DRMVERTEX*) SDL_MapGPUTransferBuffer(m_device, uploadBuffer, false);
if (!transferData) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_MapGPUTransferBuffer returned NULL buffer (%s)", SDL_GetError());
return;
}
memcpy(transferData, flatVertices.data(), m_vertexCount * sizeof(D3DRMVERTEX));
SDL_UnmapGPUTransferBuffer(m_device, uploadBuffer);
// Upload the transfer data to the vertex buffer
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
if (!cmdbuf) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer in SubmitDraw failed (%s)", SDL_GetError());
return;
}
SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdbuf);
SDL_GPUTransferBufferLocation transferLocation = {};
transferLocation.transfer_buffer = uploadBuffer;
SDL_GPUBufferRegion bufferRegion = {};
bufferRegion.buffer = m_vertexBuffer;
bufferRegion.size = static_cast<Uint32>(sizeof(D3DRMVERTEX) * m_vertexCount);
SDL_UploadToGPUBuffer(copyPass, &transferLocation, &bufferRegion, false);
SDL_EndGPUCopyPass(copyPass);
// Render the graphics // Render the graphics
SDL_GPUColorTargetInfo colorTargetInfo = {}; SDL_GPUTexture* texture = useTexture ? m_textures[appearance.textureId].gpuTexture : m_dummyTexture;
colorTargetInfo.texture = m_transferTexture; SDL_GPUTextureSamplerBinding samplerBinding = {texture, m_sampler};
colorTargetInfo.load_op = SDL_GPU_LOADOP_LOAD; SDL_BindGPUFragmentSamplers(m_renderPass, 0, &samplerBinding, 1);
SDL_PushGPUVertexUniformData(m_cmdbuf, 0, &m_uniforms, sizeof(m_uniforms));
SDL_GPUDepthStencilTargetInfo depthStencilTargetInfo = {}; SDL_PushGPUFragmentUniformData(m_cmdbuf, 0, &m_fragmentShadingData, sizeof(m_fragmentShadingData));
depthStencilTargetInfo.texture = m_depthTexture; SDL_GPUBufferBinding vertexBufferBinding = {mesh.vertexBuffer};
depthStencilTargetInfo.load_op = SDL_GPU_LOADOP_LOAD; SDL_BindGPUVertexBuffers(m_renderPass, 0, &vertexBufferBinding, 1);
depthStencilTargetInfo.store_op = SDL_GPU_STOREOP_STORE; SDL_DrawGPUPrimitives(m_renderPass, mesh.vertexCount, 1, 0, 0);
SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, &depthStencilTargetInfo);
SDL_BindGPUGraphicsPipeline(renderPass, appearance.color.a == 255 ? m_opaquePipeline : m_transparentPipeline);
m_fragmentShadingData.useTexture = appearance.textureId != NO_TEXTURE_ID;
SDL_GPUTextureSamplerBinding samplerBinding = {};
samplerBinding.texture =
m_fragmentShadingData.useTexture ? m_textures[appearance.textureId].gpuTexture : m_dummyTexture;
samplerBinding.sampler = m_sampler;
SDL_BindGPUFragmentSamplers(renderPass, 0, &samplerBinding, 1);
SDL_PushGPUVertexUniformData(cmdbuf, 0, &m_uniforms, sizeof(m_uniforms));
SDL_PushGPUFragmentUniformData(cmdbuf, 0, &m_fragmentShadingData, sizeof(m_fragmentShadingData));
if (m_vertexCount) {
SDL_GPUBufferBinding vertexBufferBinding = {};
vertexBufferBinding.buffer = m_vertexBuffer;
vertexBufferBinding.offset = 0;
SDL_BindGPUVertexBuffers(renderPass, 0, &vertexBufferBinding, 1);
SDL_DrawGPUPrimitives(renderPass, m_vertexCount, 1, 0, 0);
}
SDL_EndGPURenderPass(renderPass);
SDL_GPUFence* fence = SDL_SubmitGPUCommandBufferAndAcquireFence(cmdbuf);
if (!fence || !SDL_WaitForGPUFences(m_device, true, &fence, 1)) {
if (fence) {
SDL_ReleaseGPUFence(m_device, fence);
}
return;
}
SDL_ReleaseGPUFence(m_device, fence);
} }
HRESULT Direct3DRMSDL3GPURenderer::FinalizeFrame() HRESULT Direct3DRMSDL3GPURenderer::FinalizeFrame()
{ {
SDL_EndGPURenderPass(m_renderPass);
m_renderPass = nullptr;
// Download rendered image // Download rendered image
SDL_GPUTextureRegion region = {}; SDL_GPUTextureRegion region = {};
region.texture = m_transferTexture; region.texture = m_transferTexture;
@ -742,23 +761,23 @@ HRESULT Direct3DRMSDL3GPURenderer::FinalizeFrame()
SDL_GPUTextureTransferInfo transferInfo = {}; SDL_GPUTextureTransferInfo transferInfo = {};
transferInfo.transfer_buffer = m_downloadBuffer; transferInfo.transfer_buffer = m_downloadBuffer;
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device); SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(m_cmdbuf);
if (!cmdbuf) {
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer in FinalizeFrame failed (%s)", SDL_GetError());
return DDERR_GENERIC;
}
SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdbuf);
SDL_DownloadFromGPUTexture(copyPass, &region, &transferInfo); SDL_DownloadFromGPUTexture(copyPass, &region, &transferInfo);
SDL_EndGPUCopyPass(copyPass); SDL_EndGPUCopyPass(copyPass);
SDL_GPUFence* fence = SDL_SubmitGPUCommandBufferAndAcquireFence(cmdbuf);
if (!fence || !SDL_WaitForGPUFences(m_device, true, &fence, 1)) { WaitForPendingUpload();
if (fence) {
SDL_ReleaseGPUFence(m_device, fence); // Render the frame
} SDL_GPUFence* fence = SDL_SubmitGPUCommandBufferAndAcquireFence(m_cmdbuf);
m_cmdbuf = nullptr;
if (!fence) {
return DDERR_GENERIC; return DDERR_GENERIC;
} }
bool success = SDL_WaitForGPUFences(m_device, true, &fence, 1);
SDL_ReleaseGPUFence(m_device, fence); SDL_ReleaseGPUFence(m_device, fence);
if (!success) {
return DDERR_GENERIC;
}
void* downloadedData = SDL_MapGPUTransferBuffer(m_device, m_downloadBuffer, false); void* downloadedData = SDL_MapGPUTransferBuffer(m_device, m_downloadBuffer, false);
if (!downloadedData) { if (!downloadedData) {
return DDERR_GENERIC; return DDERR_GENERIC;

View File

@ -185,7 +185,7 @@ SDL_Color Direct3DRMSoftwareRenderer::ApplyLighting(
if (appearance.shininess != 0.0f) { if (appearance.shininess != 0.0f) {
// Using dotNL ignores view angle, but this matches DirectX 5 behavior. // Using dotNL ignores view angle, but this matches DirectX 5 behavior.
float spec = std::pow(dotNL, appearance.shininess); float spec = std::pow(dotNL, appearance.shininess * m_shininessFactor);
specular.r += spec * lightColor.r; specular.r += spec * lightColor.r;
specular.g += spec * lightColor.g; specular.g += spec * lightColor.g;
specular.b += spec * lightColor.b; specular.b += spec * lightColor.b;
@ -439,6 +439,78 @@ Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture)
return static_cast<Uint32>(m_textures.size() - 1); return static_cast<Uint32>(m_textures.size() - 1);
} }
MeshCache UploadMesh(const MeshGroup& meshGroup)
{
MeshCache cache{&meshGroup, meshGroup.version};
cache.flat = meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT;
std::vector<D3DRMVERTEX> vertices;
if (cache.flat) {
FlattenSurfaces(
meshGroup.vertices.data(),
meshGroup.vertices.size(),
meshGroup.indices.data(),
meshGroup.indices.size(),
meshGroup.texture != nullptr,
cache.vertices,
cache.indices
);
}
else {
cache.vertices.assign(meshGroup.vertices.begin(), meshGroup.vertices.end());
cache.indices.assign(meshGroup.indices.begin(), meshGroup.indices.end());
}
return cache;
}
struct MeshDestroyContext {
Direct3DRMSoftwareRenderer* renderer;
Uint32 id;
};
void Direct3DRMSoftwareRenderer::AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh)
{
auto* ctx = new MeshDestroyContext{this, id};
mesh->AddDestroyCallback(
[](IDirect3DRMObject*, void* arg) {
auto* ctx = static_cast<MeshDestroyContext*>(arg);
ctx->renderer->m_meshs[ctx->id].meshGroup = nullptr;
delete ctx;
},
ctx
);
}
Uint32 Direct3DRMSoftwareRenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup)
{
for (Uint32 i = 0; i < m_meshs.size(); ++i) {
auto& cache = m_meshs[i];
if (cache.meshGroup == meshGroup) {
if (cache.version != meshGroup->version) {
cache = std::move(UploadMesh(*meshGroup));
}
return i;
}
}
auto newCache = UploadMesh(*meshGroup);
for (Uint32 i = 0; i < m_meshs.size(); ++i) {
auto& cache = m_meshs[i];
if (!cache.meshGroup) {
cache = std::move(newCache);
AddMeshDestroyCallback(i, mesh);
return i;
}
}
m_meshs.push_back(std::move(newCache));
AddMeshDestroyCallback((Uint32) (m_meshs.size() - 1), mesh);
return (Uint32) (m_meshs.size() - 1);
}
DWORD Direct3DRMSoftwareRenderer::GetWidth() DWORD Direct3DRMSoftwareRenderer::GetWidth()
{ {
return m_width; return m_width;
@ -483,10 +555,7 @@ HRESULT Direct3DRMSoftwareRenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
} }
void Direct3DRMSoftwareRenderer::SubmitDraw( void Direct3DRMSoftwareRenderer::SubmitDraw(
const D3DRMVERTEX* vertices, DWORD meshId,
const size_t vertexCount,
const DWORD* indices,
const size_t indexCount,
const D3DRMMATRIX4D& worldMatrix, const D3DRMMATRIX4D& worldMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
@ -495,29 +564,12 @@ void Direct3DRMSoftwareRenderer::SubmitDraw(
D3DRMMATRIX4D mvMatrix; D3DRMMATRIX4D mvMatrix;
MultiplyMatrix(mvMatrix, worldMatrix, m_viewMatrix); MultiplyMatrix(mvMatrix, worldMatrix, m_viewMatrix);
std::vector<D3DRMVERTEX> newVertices; auto& mesh = m_meshs[meshId];
std::vector<DWORD> newIndices;
if (appearance.flat) {
// FIXME move this to a one time mesh upload stage
FlattenSurfaces(
vertices,
vertexCount,
indices,
indexCount,
appearance.textureId != NO_TEXTURE_ID,
newVertices,
newIndices
);
}
else {
newVertices.assign(vertices, vertices + vertexCount);
newIndices.assign(indices, indices + indexCount);
}
// Pre-transform all vertex positions and normals // Pre-transform all vertex positions and normals
std::vector<D3DRMVERTEX> transformedVerts(newVertices.size()); std::vector<D3DRMVERTEX> transformedVerts(mesh.vertices.size());
for (size_t i = 0; i < newVertices.size(); ++i) { for (size_t i = 0; i < mesh.vertices.size(); ++i) {
const D3DRMVERTEX& src = newVertices[i]; const D3DRMVERTEX& src = mesh.vertices[i];
D3DRMVERTEX& dst = transformedVerts[i]; D3DRMVERTEX& dst = transformedVerts[i];
dst.position = TransformPoint(src.position, mvMatrix); dst.position = TransformPoint(src.position, mvMatrix);
// TODO defer normal transformation til lighting to allow culling first // TODO defer normal transformation til lighting to allow culling first
@ -526,9 +578,11 @@ void Direct3DRMSoftwareRenderer::SubmitDraw(
} }
// Assemble triangles using index buffer // Assemble triangles using index buffer
for (size_t i = 0; i + 2 < newIndices.size(); i += 3) { for (size_t i = 0; i + 2 < mesh.indices.size(); i += 3) {
DrawTriangleClipped( DrawTriangleClipped(
{transformedVerts[newIndices[i]], transformedVerts[newIndices[i + 1]], transformedVerts[newIndices[i + 2]]}, {transformedVerts[mesh.indices[i]],
transformedVerts[mesh.indices[i + 1]],
transformedVerts[mesh.indices[i + 2]]},
appearance appearance
); );
} }

View File

@ -117,7 +117,12 @@ HRESULT Direct3DRMMeshImpl::SetGroupColor(DWORD groupIndex, D3DCOLOR color)
return DDERR_INVALIDPARAMS; return DDERR_INVALIDPARAMS;
} }
m_groups[groupIndex].color = color; m_groups[groupIndex].color = {
static_cast<Uint8>((color >> 16) & 0xFF),
static_cast<Uint8>((color >> 8) & 0xFF),
static_cast<Uint8>((color >> 0) & 0xFF),
static_cast<Uint8>((color >> 24) & 0xFF)
};
return DD_OK; return DD_OK;
} }
@ -127,10 +132,9 @@ HRESULT Direct3DRMMeshImpl::SetGroupColorRGB(DWORD groupIndex, float r, float g,
return DDERR_INVALIDPARAMS; return DDERR_INVALIDPARAMS;
} }
D3DCOLOR color = (0xFF << 24) | (static_cast<BYTE>(r * 255.0f) << 16) | (static_cast<BYTE>(g * 255.0f) << 8) | m_groups[groupIndex]
(static_cast<BYTE>(b * 255.0f)); .color = {static_cast<Uint8>(r * 255.0f), static_cast<Uint8>(g * 255.0f), static_cast<Uint8>(b * 255.0f), 255};
m_groups[groupIndex].color = color;
return DD_OK; return DD_OK;
} }
@ -139,7 +143,9 @@ D3DCOLOR Direct3DRMMeshImpl::GetGroupColor(D3DRMGROUPINDEX index)
if (index < 0 || index >= static_cast<int>(m_groups.size())) { if (index < 0 || index >= static_cast<int>(m_groups.size())) {
return 0xFFFFFFFF; return 0xFFFFFFFF;
} }
return m_groups[index].color;
const SDL_Color& color = m_groups[index].color;
return (color.a << 24) | (color.r << 16) | (color.g << 8) | color.b;
} }
HRESULT Direct3DRMMeshImpl::SetGroupMaterial(DWORD groupIndex, IDirect3DRMMaterial* material) HRESULT Direct3DRMMeshImpl::SetGroupMaterial(DWORD groupIndex, IDirect3DRMMaterial* material)
@ -171,6 +177,7 @@ HRESULT Direct3DRMMeshImpl::SetGroupTexture(DWORD groupIndex, IDirect3DRMTexture
texture->AddRef(); texture->AddRef();
group.texture = texture; group.texture = texture;
group.version++;
return DD_OK; return DD_OK;
} }
@ -229,7 +236,10 @@ HRESULT Direct3DRMMeshImpl::SetGroupQuality(DWORD groupIndex, D3DRMRENDERQUALITY
break; break;
} }
m_groups[groupIndex].quality = quality; auto& group = m_groups[groupIndex];
group.quality = quality;
group.version++;
return DD_OK; return DD_OK;
} }
@ -248,7 +258,8 @@ HRESULT Direct3DRMMeshImpl::SetVertices(DWORD groupIndex, int offset, int count,
return DDERR_INVALIDPARAMS; return DDERR_INVALIDPARAMS;
} }
auto& vertList = m_groups[groupIndex].vertices; auto& group = m_groups[groupIndex];
auto& vertList = group.vertices;
if (offset + count > static_cast<int>(vertList.size())) { if (offset + count > static_cast<int>(vertList.size())) {
vertList.resize(offset + count); vertList.resize(offset + count);
@ -258,6 +269,8 @@ HRESULT Direct3DRMMeshImpl::SetVertices(DWORD groupIndex, int offset, int count,
UpdateBox(); UpdateBox();
group.version++;
return DD_OK; return DD_OK;
} }

View File

@ -180,13 +180,31 @@ void ExtractFrustumPlanes(const D3DRMMATRIX4D& m)
} }
} }
bool IsBoxInFrustum(const D3DVECTOR corners[8], const Plane planes[6]) bool IsMeshInFrustum(Direct3DRMMeshImpl* mesh, const D3DRMMATRIX4D& worldMatrix)
{ {
D3DRMBOX box;
mesh->GetBox(&box);
D3DVECTOR boxCorners[8] = {
{box.min.x, box.min.y, box.min.z},
{box.min.x, box.min.y, box.max.z},
{box.min.x, box.max.y, box.min.z},
{box.min.x, box.max.y, box.max.z},
{box.max.x, box.min.y, box.min.z},
{box.max.x, box.min.y, box.max.z},
{box.max.x, box.max.y, box.min.z},
{box.max.x, box.max.y, box.max.z},
};
for (D3DVECTOR& corner : boxCorners) {
corner = TransformPoint(corner, worldMatrix);
}
for (int i = 0; i < 6; ++i) { for (int i = 0; i < 6; ++i) {
int out = 0; int out = 0;
for (int j = 0; j < 8; ++j) { for (int j = 0; j < 8; ++j) {
float dist = planes[i].normal.x * corners[j].x + planes[i].normal.y * corners[j].y + float dist = frustumPlanes[i].normal.x * boxCorners[j].x + frustumPlanes[i].normal.y * boxCorners[j].y +
planes[i].normal.z * corners[j].z + planes[i].d; frustumPlanes[i].normal.z * boxCorners[j].z + frustumPlanes[i].d;
if (dist < 0.0f) { if (dist < 0.0f) {
++out; ++out;
} }
@ -210,8 +228,6 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3D
Matrix3x3 worldMatrixInvert; Matrix3x3 worldMatrixInvert;
D3DRMMatrixInvertForNormal(worldMatrixInvert, worldMatrix); D3DRMMatrixInvertForNormal(worldMatrixInvert, worldMatrix);
const float shininessFactor = m_renderer->GetShininessFactor();
IDirect3DRMVisualArray* visuals = nullptr; IDirect3DRMVisualArray* visuals = nullptr;
frame->GetVisuals(&visuals); frame->GetVisuals(&visuals);
DWORD n = visuals->GetSize(); DWORD n = visuals->GetSize();
@ -230,63 +246,24 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3D
Direct3DRMMeshImpl* mesh = nullptr; Direct3DRMMeshImpl* mesh = nullptr;
visual->QueryInterface(IID_IDirect3DRMMesh, (void**) &mesh); visual->QueryInterface(IID_IDirect3DRMMesh, (void**) &mesh);
if (!mesh) { if (mesh) {
visual->Release(); if (IsMeshInFrustum(mesh, worldMatrix)) {
continue; DWORD groupCount = mesh->GetGroupCount();
} for (DWORD gi = 0; gi < groupCount; ++gi) {
const MeshGroup& meshGroup = mesh->GetGroup(gi);
D3DRMBOX box; m_renderer->SubmitDraw(
mesh->GetBox(&box); m_renderer->GetMeshId(mesh, &meshGroup),
D3DVECTOR boxCorners[8] = { worldMatrix,
{box.min.x, box.min.y, box.min.z}, worldMatrixInvert,
{box.min.x, box.min.y, box.max.z}, {meshGroup.color,
{box.min.x, box.max.y, box.min.z}, meshGroup.material ? meshGroup.material->GetPower() : 0.0f,
{box.min.x, box.max.y, box.max.z}, meshGroup.texture ? m_renderer->GetTextureId(meshGroup.texture) : NO_TEXTURE_ID,
{box.max.x, box.min.y, box.min.z}, meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT}
{box.max.x, box.min.y, box.max.z}, );
{box.max.x, box.max.y, box.min.z}, }
{box.max.x, box.max.y, box.max.z}, }
};
for (D3DVECTOR& boxCorner : boxCorners) {
boxCorner = TransformPoint(boxCorner, worldMatrix);
}
if (!IsBoxInFrustum(boxCorners, frustumPlanes)) {
mesh->Release(); mesh->Release();
visual->Release();
continue;
} }
DWORD groupCount = mesh->GetGroupCount();
for (DWORD gi = 0; gi < groupCount; ++gi) {
const MeshGroup& meshGroup = mesh->GetGroup(gi);
Uint32 textureId = NO_TEXTURE_ID;
if (meshGroup.texture) {
textureId = m_renderer->GetTextureId(meshGroup.texture);
}
float shininess = 0.0f;
if (meshGroup.material) {
shininess = meshGroup.material->GetPower() * shininessFactor;
}
m_renderer->SubmitDraw(
meshGroup.vertices.data(),
meshGroup.vertices.size(),
meshGroup.indices.data(),
meshGroup.indices.size(),
worldMatrix,
worldMatrixInvert,
{{static_cast<Uint8>((meshGroup.color >> 16) & 0xFF),
static_cast<Uint8>((meshGroup.color >> 8) & 0xFF),
static_cast<Uint8>((meshGroup.color >> 0) & 0xFF),
static_cast<Uint8>((meshGroup.color >> 24) & 0xFF)},
shininess,
textureId,
meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT}
);
}
mesh->Release();
visual->Release(); visual->Release();
} }
visuals->Release(); visuals->Release();

View File

@ -6,11 +6,12 @@
#include <vector> #include <vector>
struct MeshGroup { struct MeshGroup {
D3DCOLOR color = 0xFFFFFFFF; SDL_Color color = {0xFF, 0xFF, 0xFF, 0xFF};
IDirect3DRMTexture* texture = nullptr; IDirect3DRMTexture* texture = nullptr;
IDirect3DRMMaterial* material = nullptr; IDirect3DRMMaterial* material = nullptr;
D3DRMRENDERQUALITY quality = D3DRMRENDER_GOURAUD; D3DRMRENDERQUALITY quality = D3DRMRENDER_GOURAUD;
int vertexPerFace = 0; int vertexPerFace = 0;
int version = 0;
std::vector<D3DRMVERTEX> vertices; std::vector<D3DRMVERTEX> vertices;
std::vector<unsigned int> indices; std::vector<unsigned int> indices;

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "d3drmmesh_impl.h"
#include "mathutils.h" #include "mathutils.h"
#include "miniwin/d3drm.h" #include "miniwin/d3drm.h"
#include "miniwin/miniwindevice.h" #include "miniwin/miniwindevice.h"
@ -35,16 +36,14 @@ class Direct3DRMRenderer : public IDirect3DDevice2 {
virtual void PushLights(const SceneLight* vertices, size_t count) = 0; virtual void PushLights(const SceneLight* vertices, size_t count) = 0;
virtual void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) = 0; virtual void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) = 0;
virtual Uint32 GetTextureId(IDirect3DRMTexture* texture) = 0; virtual Uint32 GetTextureId(IDirect3DRMTexture* texture) = 0;
virtual Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) = 0;
virtual DWORD GetWidth() = 0; virtual DWORD GetWidth() = 0;
virtual DWORD GetHeight() = 0; virtual DWORD GetHeight() = 0;
virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0; virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0;
virtual const char* GetName() = 0; virtual const char* GetName() = 0;
virtual HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) = 0; virtual HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) = 0;
virtual void SubmitDraw( virtual void SubmitDraw(
const D3DRMVERTEX* vertices, DWORD meshId,
const size_t vertexCount,
const DWORD* indices,
const size_t indexCount,
const D3DRMMATRIX4D& worldMatrix, const D3DRMMATRIX4D& worldMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance

View File

@ -16,6 +16,16 @@ struct GLTextureCacheEntry {
GLuint glTextureId; GLuint glTextureId;
}; };
struct GLMeshCacheEntry {
const MeshGroup* meshGroup;
int version;
bool flat;
std::vector<D3DVECTOR> positions;
std::vector<D3DVECTOR> normals;
std::vector<TexCoord> texcoords;
std::vector<DWORD> indices;
};
class OpenGL15Renderer : public Direct3DRMRenderer { class OpenGL15Renderer : public Direct3DRMRenderer {
public: public:
static Direct3DRMRenderer* Create(DWORD width, DWORD height); static Direct3DRMRenderer* Create(DWORD width, DWORD height);
@ -24,16 +34,14 @@ class OpenGL15Renderer : public Direct3DRMRenderer {
void PushLights(const SceneLight* lightsArray, size_t count) override; void PushLights(const SceneLight* lightsArray, size_t count) override;
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
Uint32 GetTextureId(IDirect3DRMTexture* texture) override; Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
DWORD GetWidth() override; DWORD GetWidth() override;
DWORD GetHeight() override; DWORD GetHeight() override;
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override; void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
const char* GetName() override; const char* GetName() override;
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override; HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
void SubmitDraw( void SubmitDraw(
const D3DRMVERTEX* vertices, DWORD meshId,
const size_t vertexCount,
const DWORD* indices,
const size_t indexCount,
const D3DRMMATRIX4D& worldMatrix, const D3DRMMATRIX4D& worldMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
@ -42,7 +50,9 @@ class OpenGL15Renderer : public Direct3DRMRenderer {
private: private:
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture); void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
std::vector<GLTextureCacheEntry> m_textures; std::vector<GLTextureCacheEntry> m_textures;
std::vector<GLMeshCacheEntry> m_meshs;
D3DRMMATRIX4D m_viewMatrix; D3DRMMATRIX4D m_viewMatrix;
D3DRMMATRIX4D m_projection; D3DRMMATRIX4D m_projection;
SDL_Surface* m_renderedImage; SDL_Surface* m_renderedImage;

View File

@ -34,12 +34,20 @@ struct SDL3TextureCache {
SDL_GPUTexture* gpuTexture; SDL_GPUTexture* gpuTexture;
}; };
struct SDL3MeshCache {
const MeshGroup* meshGroup;
int version;
SDL_GPUBuffer* vertexBuffer;
size_t vertexCount;
};
class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer { class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
public: public:
static Direct3DRMRenderer* Create(DWORD width, DWORD height); static Direct3DRMRenderer* Create(DWORD width, DWORD height);
~Direct3DRMSDL3GPURenderer() override; ~Direct3DRMSDL3GPURenderer() override;
void PushLights(const SceneLight* vertices, size_t count) override; void PushLights(const SceneLight* vertices, size_t count) override;
Uint32 GetTextureId(IDirect3DRMTexture* texture) override; Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
DWORD GetWidth() override; DWORD GetWidth() override;
DWORD GetHeight() override; DWORD GetHeight() override;
@ -47,10 +55,7 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
const char* GetName() override; const char* GetName() override;
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override; HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
void SubmitDraw( void SubmitDraw(
const D3DRMVERTEX* vertices, DWORD meshId,
const size_t vertexCount,
const DWORD* indices,
const size_t indexCount,
const D3DRMMATRIX4D& worldMatrix, const D3DRMMATRIX4D& worldMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
@ -66,25 +71,27 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
SDL_GPUGraphicsPipeline* transparentPipeline, SDL_GPUGraphicsPipeline* transparentPipeline,
SDL_GPUTexture* transferTexture, SDL_GPUTexture* transferTexture,
SDL_GPUTexture* depthTexture, SDL_GPUTexture* depthTexture,
SDL_GPUTexture* dummyTexture,
SDL_GPUSampler* sampler, SDL_GPUSampler* sampler,
SDL_GPUTransferBuffer* uploadBuffer, SDL_GPUTransferBuffer* uploadBuffer,
SDL_GPUTransferBuffer* downloadBuffer SDL_GPUTransferBuffer* downloadBuffer
); );
void WaitForPendingUpload();
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture); void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
SDL_GPUTransferBuffer* GetUploadBuffer(size_t size); SDL_GPUTransferBuffer* GetUploadBuffer(size_t size);
SDL_GPUTexture* CreateTextureFromSurface(SDL_Surface* surface);
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
SDL3MeshCache UploadMesh(const MeshGroup& meshGroup);
DWORD m_width; DWORD m_width;
DWORD m_height; DWORD m_height;
D3DVALUE m_front; D3DVALUE m_front;
D3DVALUE m_back; D3DVALUE m_back;
int m_vertexCount;
int m_vertexBufferCount = 0;
ViewportUniforms m_uniforms; ViewportUniforms m_uniforms;
FragmentShadingData m_fragmentShadingData; FragmentShadingData m_fragmentShadingData;
D3DDEVICEDESC m_desc; D3DDEVICEDESC m_desc;
D3DRMMATRIX4D m_viewMatrix; D3DRMMATRIX4D m_viewMatrix;
std::vector<SDL3TextureCache> m_textures; std::vector<SDL3TextureCache> m_textures;
std::vector<SDL3MeshCache> m_meshs;
SDL_GPUDevice* m_device; SDL_GPUDevice* m_device;
SDL_GPUGraphicsPipeline* m_opaquePipeline; SDL_GPUGraphicsPipeline* m_opaquePipeline;
SDL_GPUGraphicsPipeline* m_transparentPipeline; SDL_GPUGraphicsPipeline* m_transparentPipeline;
@ -96,6 +103,9 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
SDL_GPUTransferBuffer* m_downloadBuffer; SDL_GPUTransferBuffer* m_downloadBuffer;
SDL_GPUBuffer* m_vertexBuffer = nullptr; SDL_GPUBuffer* m_vertexBuffer = nullptr;
SDL_GPUSampler* m_sampler; SDL_GPUSampler* m_sampler;
SDL_GPUCommandBuffer* m_cmdbuf = nullptr;
SDL_GPURenderPass* m_renderPass = nullptr;
SDL_GPUFence* m_uploadFence = nullptr;
}; };
inline static void Direct3DRMSDL3GPU_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) inline static void Direct3DRMSDL3GPU_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)

View File

@ -16,11 +16,20 @@ struct TextureCache {
SDL_Surface* cached; SDL_Surface* cached;
}; };
struct MeshCache {
const MeshGroup* meshGroup;
int version;
bool flat;
std::vector<D3DRMVERTEX> vertices;
std::vector<DWORD> indices;
};
class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer { class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
public: public:
Direct3DRMSoftwareRenderer(DWORD width, DWORD height); Direct3DRMSoftwareRenderer(DWORD width, DWORD height);
void PushLights(const SceneLight* vertices, size_t count) override; void PushLights(const SceneLight* vertices, size_t count) override;
Uint32 GetTextureId(IDirect3DRMTexture* texture) override; Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override; void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
DWORD GetWidth() override; DWORD GetWidth() override;
DWORD GetHeight() override; DWORD GetHeight() override;
@ -28,10 +37,7 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
const char* GetName() override; const char* GetName() override;
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override; HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
void SubmitDraw( void SubmitDraw(
const D3DRMVERTEX* vertices, DWORD meshId,
const size_t vertexCount,
const DWORD* indices,
const size_t indexCount,
const D3DRMMATRIX4D& worldMatrix, const D3DRMMATRIX4D& worldMatrix,
const Matrix3x3& normalMatrix, const Matrix3x3& normalMatrix,
const Appearance& appearance const Appearance& appearance
@ -51,6 +57,7 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
void BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g, Uint8 b, Uint8 a); void BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
SDL_Color ApplyLighting(const D3DVECTOR& position, const D3DVECTOR& normal, const Appearance& appearance); SDL_Color ApplyLighting(const D3DVECTOR& position, const D3DVECTOR& normal, const Appearance& appearance);
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture); void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
DWORD m_width; DWORD m_width;
DWORD m_height; DWORD m_height;
@ -59,6 +66,7 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
int m_bytesPerPixel; int m_bytesPerPixel;
std::vector<SceneLight> m_lights; std::vector<SceneLight> m_lights;
std::vector<TextureCache> m_textures; std::vector<TextureCache> m_textures;
std::vector<MeshCache> m_meshs;
D3DVALUE m_front; D3DVALUE m_front;
D3DVALUE m_back; D3DVALUE m_back;
D3DRMMATRIX4D m_viewMatrix; D3DRMMATRIX4D m_viewMatrix;