mirror of
https://github.com/isledecomp/isle-portable.git
synced 2025-09-22 03:22:35 -04:00
Refactor renderers (#237)
This commit is contained in:
parent
8e55368615
commit
12d01ae311
@ -1,5 +1,6 @@
|
||||
#include "d3drmrenderer_opengl15.h"
|
||||
#include "ddraw_impl.h"
|
||||
#include "mathutils.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <cstring>
|
||||
@ -92,19 +93,14 @@ OpenGL15Renderer::~OpenGL15Renderer()
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGL15Renderer::PushVertices(const PositionColorVertex* verts, size_t count)
|
||||
{
|
||||
m_vertices.assign(verts, verts + count);
|
||||
}
|
||||
|
||||
void OpenGL15Renderer::PushLights(const SceneLight* lightsArray, size_t count)
|
||||
{
|
||||
m_lights.assign(lightsArray, lightsArray + count);
|
||||
}
|
||||
|
||||
void OpenGL15Renderer::SetProjection(D3DRMMATRIX4D perspective, D3DVALUE front, D3DVALUE back)
|
||||
void OpenGL15Renderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back)
|
||||
{
|
||||
memcpy(&m_projection, perspective, sizeof(D3DRMMATRIX4D));
|
||||
memcpy(&m_projection, projection, sizeof(D3DRMMATRIX4D));
|
||||
m_projection[1][1] *= -1.0f; // OpenGL is upside down
|
||||
}
|
||||
|
||||
@ -141,11 +137,14 @@ const char* OpenGL15Renderer::GetName()
|
||||
return "OpenGL 1.5 HAL";
|
||||
}
|
||||
|
||||
HRESULT OpenGL15Renderer::Render()
|
||||
HRESULT OpenGL15Renderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
|
||||
{
|
||||
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);
|
||||
@ -220,21 +219,41 @@ HRESULT OpenGL15Renderer::Render()
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
// Render geometry
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
void OpenGL15Renderer::SubmitDraw(
|
||||
const GeometryVertex* vertices,
|
||||
const size_t count,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
)
|
||||
{
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glPushMatrix();
|
||||
|
||||
D3DRMMATRIX4D mvMatrix;
|
||||
MultiplyMatrix(mvMatrix, worldMatrix, m_viewMatrix);
|
||||
glLoadMatrixf(&mvMatrix[0][0]);
|
||||
glEnable(GL_NORMALIZE);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
for (const auto& v : m_vertices) {
|
||||
glColor4ub(v.colors.r, v.colors.g, v.colors.b, v.colors.a);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
const GeometryVertex& v = vertices[i];
|
||||
glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a);
|
||||
glNormal3f(v.normals.x, v.normals.y, v.normals.z);
|
||||
glTexCoord2f(v.texCoord.u, v.texCoord.v);
|
||||
|
||||
// Set per-vertex specular material
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, v.shininess);
|
||||
if (v.shininess != 0.0f) {
|
||||
GLfloat whiteSpec[] = {v.shininess, v.shininess, v.shininess, v.shininess};
|
||||
float shininess = appearance.shininess;
|
||||
glMaterialf(GL_FRONT, GL_SHININESS, shininess);
|
||||
if (shininess != 0.0f) {
|
||||
GLfloat whiteSpec[] = {shininess, shininess, shininess, shininess};
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, whiteSpec);
|
||||
}
|
||||
else {
|
||||
GLfloat noSpec[] = {0.f, 0.f, 0.f, 1.f};
|
||||
GLfloat noSpec[] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
glMaterialfv(GL_FRONT, GL_SPECULAR, noSpec);
|
||||
}
|
||||
|
||||
@ -242,6 +261,11 @@ HRESULT OpenGL15Renderer::Render()
|
||||
}
|
||||
glEnd();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
HRESULT OpenGL15Renderer::FinalizeFrame()
|
||||
{
|
||||
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
|
@ -2,12 +2,13 @@
|
||||
#include "d3drmrenderer.h"
|
||||
#include "d3drmrenderer_sdl3gpu.h"
|
||||
#include "ddraw_impl.h"
|
||||
#include "mathutils.h"
|
||||
#include "miniwin.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <cstddef>
|
||||
|
||||
static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device)
|
||||
static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device, bool depthWrite)
|
||||
{
|
||||
const SDL_GPUShaderCreateInfo* vertexCreateInfo =
|
||||
GetVertexShaderCode(VertexShaderId::PositionColor, SDL_GetGPUShaderFormats(device));
|
||||
@ -31,40 +32,25 @@ static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device
|
||||
|
||||
SDL_GPUVertexBufferDescription vertexBufferDescs[1] = {};
|
||||
vertexBufferDescs[0].slot = 0;
|
||||
vertexBufferDescs[0].pitch = sizeof(PositionColorVertex);
|
||||
vertexBufferDescs[0].pitch = sizeof(GeometryVertex);
|
||||
vertexBufferDescs[0].input_rate = SDL_GPU_VERTEXINPUTRATE_VERTEX;
|
||||
vertexBufferDescs[0].instance_step_rate = 0;
|
||||
|
||||
SDL_GPUVertexAttribute vertexAttrs[6] = {};
|
||||
SDL_GPUVertexAttribute vertexAttrs[3] = {};
|
||||
vertexAttrs[0].location = 0;
|
||||
vertexAttrs[0].buffer_slot = 0;
|
||||
vertexAttrs[0].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3;
|
||||
vertexAttrs[0].offset = offsetof(PositionColorVertex, position);
|
||||
vertexAttrs[0].offset = offsetof(GeometryVertex, position);
|
||||
|
||||
vertexAttrs[1].location = 1;
|
||||
vertexAttrs[1].buffer_slot = 0;
|
||||
vertexAttrs[1].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3;
|
||||
vertexAttrs[1].offset = offsetof(PositionColorVertex, normals);
|
||||
vertexAttrs[1].offset = offsetof(GeometryVertex, normals);
|
||||
|
||||
vertexAttrs[2].location = 2;
|
||||
vertexAttrs[2].buffer_slot = 0;
|
||||
vertexAttrs[2].format = SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM;
|
||||
vertexAttrs[2].offset = offsetof(PositionColorVertex, colors);
|
||||
|
||||
vertexAttrs[3].location = 3;
|
||||
vertexAttrs[3].buffer_slot = 0;
|
||||
vertexAttrs[3].format = SDL_GPU_VERTEXELEMENTFORMAT_UINT;
|
||||
vertexAttrs[3].offset = offsetof(PositionColorVertex, texId);
|
||||
|
||||
vertexAttrs[4].location = 4;
|
||||
vertexAttrs[4].buffer_slot = 0;
|
||||
vertexAttrs[4].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2;
|
||||
vertexAttrs[4].offset = offsetof(PositionColorVertex, texCoord);
|
||||
|
||||
vertexAttrs[5].location = 5;
|
||||
vertexAttrs[5].buffer_slot = 0;
|
||||
vertexAttrs[5].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT;
|
||||
vertexAttrs[5].offset = offsetof(PositionColorVertex, shininess);
|
||||
vertexAttrs[2].format = SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2;
|
||||
vertexAttrs[2].offset = offsetof(GeometryVertex, texCoord);
|
||||
|
||||
SDL_GPUVertexInputState vertexInputState = {};
|
||||
vertexInputState.vertex_buffer_descriptions = vertexBufferDescs;
|
||||
@ -74,6 +60,19 @@ static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device
|
||||
|
||||
SDL_GPUColorTargetDescription colorTargets = {};
|
||||
colorTargets.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
||||
if (depthWrite) {
|
||||
colorTargets.blend_state.enable_blend = false;
|
||||
}
|
||||
else {
|
||||
colorTargets.blend_state.enable_blend = true;
|
||||
colorTargets.blend_state.src_color_blendfactor = SDL_GPU_BLENDFACTOR_SRC_ALPHA;
|
||||
colorTargets.blend_state.dst_color_blendfactor = SDL_GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
colorTargets.blend_state.color_blend_op = SDL_GPU_BLENDOP_ADD;
|
||||
colorTargets.blend_state.src_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ONE;
|
||||
colorTargets.blend_state.dst_alpha_blendfactor = SDL_GPU_BLENDFACTOR_ZERO;
|
||||
colorTargets.blend_state.alpha_blend_op = SDL_GPU_BLENDOP_ADD;
|
||||
colorTargets.blend_state.enable_color_write_mask = false;
|
||||
}
|
||||
|
||||
SDL_GPURasterizerState rasterizerState = {};
|
||||
rasterizerState.fill_mode = SDL_GPU_FILLMODE_FILL;
|
||||
@ -92,7 +91,7 @@ static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device
|
||||
pipelineCreateInfo.target_info.has_depth_stencil_target = true;
|
||||
pipelineCreateInfo.target_info.depth_stencil_format = SDL_GPU_TEXTUREFORMAT_D16_UNORM;
|
||||
pipelineCreateInfo.depth_stencil_state.enable_depth_test = true;
|
||||
pipelineCreateInfo.depth_stencil_state.enable_depth_write = true;
|
||||
pipelineCreateInfo.depth_stencil_state.enable_depth_write = depthWrite;
|
||||
pipelineCreateInfo.depth_stencil_state.enable_stencil_test = false;
|
||||
pipelineCreateInfo.depth_stencil_state.compare_op = SDL_GPU_COMPAREOP_GREATER;
|
||||
pipelineCreateInfo.depth_stencil_state.write_mask = 0xff;
|
||||
@ -116,8 +115,13 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUDevice failed (%s)", SDL_GetError());
|
||||
return nullptr;
|
||||
}
|
||||
SDL_GPUGraphicsPipeline* pipeline = InitializeGraphicsPipeline(device);
|
||||
if (!pipeline) {
|
||||
SDL_GPUGraphicsPipeline* opaquePipeline = InitializeGraphicsPipeline(device, true);
|
||||
if (!opaquePipeline) {
|
||||
return nullptr;
|
||||
}
|
||||
SDL_GPUGraphicsPipeline* transparentPipeline = InitializeGraphicsPipeline(device, false);
|
||||
if (!transparentPipeline) {
|
||||
SDL_ReleaseGPUGraphicsPipeline(device, opaquePipeline);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -131,7 +135,8 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
|
||||
textureInfo.usage = SDL_GPU_TEXTUREUSAGE_COLOR_TARGET;
|
||||
SDL_GPUTexture* transferTexture = SDL_CreateGPUTexture(device, &textureInfo);
|
||||
if (!transferTexture) {
|
||||
SDL_ReleaseGPUGraphicsPipeline(device, pipeline);
|
||||
SDL_ReleaseGPUGraphicsPipeline(device, opaquePipeline);
|
||||
SDL_ReleaseGPUGraphicsPipeline(device, transparentPipeline);
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTexture for backbuffer failed (%s)", SDL_GetError());
|
||||
return nullptr;
|
||||
}
|
||||
@ -146,7 +151,8 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
|
||||
depthTextureInfo.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET;
|
||||
SDL_GPUTexture* depthTexture = SDL_CreateGPUTexture(device, &depthTextureInfo);
|
||||
if (!depthTexture) {
|
||||
SDL_ReleaseGPUGraphicsPipeline(device, pipeline);
|
||||
SDL_ReleaseGPUGraphicsPipeline(device, opaquePipeline);
|
||||
SDL_ReleaseGPUGraphicsPipeline(device, transparentPipeline);
|
||||
SDL_ReleaseGPUTexture(device, transferTexture);
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTexture for depth buffer (%s)", SDL_GetError());
|
||||
return nullptr;
|
||||
@ -158,7 +164,8 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
|
||||
downloadTransferInfo.size = static_cast<Uint32>(width * height * 4);
|
||||
SDL_GPUTransferBuffer* downloadTransferBuffer = SDL_CreateGPUTransferBuffer(device, &downloadTransferInfo);
|
||||
if (!downloadTransferBuffer) {
|
||||
SDL_ReleaseGPUGraphicsPipeline(device, pipeline);
|
||||
SDL_ReleaseGPUGraphicsPipeline(device, opaquePipeline);
|
||||
SDL_ReleaseGPUGraphicsPipeline(device, transparentPipeline);
|
||||
SDL_ReleaseGPUTexture(device, depthTexture);
|
||||
SDL_ReleaseGPUTexture(device, transferTexture);
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTransferBuffer failed (%s)", SDL_GetError());
|
||||
@ -169,7 +176,8 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
|
||||
width,
|
||||
height,
|
||||
device,
|
||||
pipeline,
|
||||
opaquePipeline,
|
||||
transparentPipeline,
|
||||
transferTexture,
|
||||
depthTexture,
|
||||
downloadTransferBuffer
|
||||
@ -180,13 +188,15 @@ Direct3DRMSDL3GPURenderer::Direct3DRMSDL3GPURenderer(
|
||||
DWORD width,
|
||||
DWORD height,
|
||||
SDL_GPUDevice* device,
|
||||
SDL_GPUGraphicsPipeline* pipeline,
|
||||
SDL_GPUGraphicsPipeline* opaquePipeline,
|
||||
SDL_GPUGraphicsPipeline* transparentPipeline,
|
||||
SDL_GPUTexture* transferTexture,
|
||||
SDL_GPUTexture* depthTexture,
|
||||
SDL_GPUTransferBuffer* downloadTransferBuffer
|
||||
)
|
||||
: m_width(width), m_height(height), m_device(device), m_pipeline(pipeline), m_transferTexture(transferTexture),
|
||||
m_depthTexture(depthTexture), m_downloadTransferBuffer(downloadTransferBuffer)
|
||||
: m_width(width), m_height(height), m_device(device), m_opaquePipeline(opaquePipeline),
|
||||
m_transparentPipeline(transparentPipeline), m_transferTexture(transferTexture), m_depthTexture(depthTexture),
|
||||
m_downloadTransferBuffer(downloadTransferBuffer)
|
||||
{
|
||||
}
|
||||
|
||||
@ -196,7 +206,8 @@ Direct3DRMSDL3GPURenderer::~Direct3DRMSDL3GPURenderer()
|
||||
SDL_ReleaseGPUTransferBuffer(m_device, m_downloadTransferBuffer);
|
||||
SDL_ReleaseGPUTexture(m_device, m_depthTexture);
|
||||
SDL_ReleaseGPUTexture(m_device, m_transferTexture);
|
||||
SDL_ReleaseGPUGraphicsPipeline(m_device, m_pipeline);
|
||||
SDL_ReleaseGPUGraphicsPipeline(m_device, m_opaquePipeline);
|
||||
SDL_ReleaseGPUGraphicsPipeline(m_device, m_transparentPipeline);
|
||||
SDL_DestroyGPUDevice(m_device);
|
||||
}
|
||||
|
||||
@ -206,79 +217,15 @@ void Direct3DRMSDL3GPURenderer::PushLights(const SceneLight* vertices, size_t co
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "Unsupported number of lights (%d)", static_cast<int>(count));
|
||||
count = 3;
|
||||
}
|
||||
memcpy(&m_lights.lights, vertices, sizeof(SceneLight) * count);
|
||||
m_lights.count = count;
|
||||
memcpy(&m_fragmentShadingData.lights, vertices, sizeof(SceneLight) * count);
|
||||
m_fragmentShadingData.lightCount = count;
|
||||
}
|
||||
|
||||
void Direct3DRMSDL3GPURenderer::PushVertices(const PositionColorVertex* vertices, size_t count)
|
||||
{
|
||||
if (count > 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(PositionColorVertex) * count);
|
||||
m_vertexBuffer = SDL_CreateGPUBuffer(m_device, &bufferCreateInfo);
|
||||
if (!m_vertexBuffer) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUBuffer returned NULL buffer (%s)", SDL_GetError());
|
||||
}
|
||||
m_vertexBufferCount = count;
|
||||
}
|
||||
|
||||
m_vertexCount = count;
|
||||
if (!count) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_GPUTransferBufferCreateInfo transferCreateInfo = {};
|
||||
transferCreateInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
|
||||
transferCreateInfo.size = static_cast<Uint32>(sizeof(PositionColorVertex) * m_vertexCount);
|
||||
SDL_GPUTransferBuffer* transferBuffer = SDL_CreateGPUTransferBuffer(m_device, &transferCreateInfo);
|
||||
if (!transferBuffer) {
|
||||
SDL_LogError(
|
||||
LOG_CATEGORY_MINIWIN,
|
||||
"SDL_CreateGPUTransferBuffer returned NULL transfer buffer (%s)",
|
||||
SDL_GetError()
|
||||
);
|
||||
}
|
||||
|
||||
PositionColorVertex* transferData =
|
||||
(PositionColorVertex*) SDL_MapGPUTransferBuffer(m_device, transferBuffer, false);
|
||||
if (!transferData) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_MapGPUTransferBuffer returned NULL buffer (%s)", SDL_GetError());
|
||||
}
|
||||
|
||||
memcpy(transferData, vertices, m_vertexCount * sizeof(PositionColorVertex));
|
||||
|
||||
SDL_UnmapGPUTransferBuffer(m_device, transferBuffer);
|
||||
|
||||
// Upload the transfer data to the vertex buffer
|
||||
SDL_GPUCommandBuffer* uploadCmdBuf = SDL_AcquireGPUCommandBuffer(m_device);
|
||||
SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(uploadCmdBuf);
|
||||
SDL_GPUTransferBufferLocation transferLocation = {};
|
||||
transferLocation.transfer_buffer = transferBuffer;
|
||||
transferLocation.offset = 0;
|
||||
|
||||
SDL_GPUBufferRegion bufferRegion = {};
|
||||
bufferRegion.buffer = m_vertexBuffer;
|
||||
bufferRegion.offset = 0;
|
||||
bufferRegion.size = static_cast<Uint32>(sizeof(PositionColorVertex) * m_vertexCount);
|
||||
|
||||
SDL_UploadToGPUBuffer(copyPass, &transferLocation, &bufferRegion, false);
|
||||
|
||||
SDL_EndGPUCopyPass(copyPass);
|
||||
if (!SDL_SubmitGPUCommandBuffer(uploadCmdBuf)) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_SubmitGPUCommandBuffer failes (%s)", SDL_GetError());
|
||||
}
|
||||
SDL_ReleaseGPUTransferBuffer(m_device, transferBuffer);
|
||||
}
|
||||
|
||||
void Direct3DRMSDL3GPURenderer::SetProjection(D3DRMMATRIX4D perspective, D3DVALUE front, D3DVALUE back)
|
||||
void Direct3DRMSDL3GPURenderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back)
|
||||
{
|
||||
m_front = front;
|
||||
m_back = back;
|
||||
memcpy(&m_uniforms.perspective, perspective, sizeof(D3DRMMATRIX4D));
|
||||
memcpy(&m_uniforms.projection, projection, sizeof(D3DRMMATRIX4D));
|
||||
}
|
||||
|
||||
Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* texture)
|
||||
@ -314,35 +261,133 @@ const char* Direct3DRMSDL3GPURenderer::GetName()
|
||||
return "SDL3 GPU HAL";
|
||||
}
|
||||
|
||||
HRESULT Direct3DRMSDL3GPURenderer::Render()
|
||||
HRESULT Direct3DRMSDL3GPURenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
|
||||
{
|
||||
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
|
||||
if (cmdbuf == NULL) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer failed (%s)", SDL_GetError());
|
||||
if (!DDBackBuffer) {
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
|
||||
// Render the graphics
|
||||
memcpy(&m_viewMatrix, viewMatrix, sizeof(D3DRMMATRIX4D));
|
||||
|
||||
// Clear color and depth targets
|
||||
SDL_GPUColorTargetInfo colorTargetInfo = {};
|
||||
colorTargetInfo.texture = m_transferTexture;
|
||||
// Make the render target transparent so we can combine it with the back buffer
|
||||
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.f;
|
||||
depthStencilTargetInfo.clear_stencil = 0;
|
||||
depthStencilTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
|
||||
depthStencilTargetInfo.store_op = SDL_GPU_STOREOP_STORE;
|
||||
depthStencilTargetInfo.stencil_load_op = SDL_GPU_LOADOP_CLEAR;
|
||||
depthStencilTargetInfo.stencil_store_op = SDL_GPU_STOREOP_STORE;
|
||||
|
||||
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
|
||||
if (!cmdbuf) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer failed (%s)", SDL_GetError());
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
|
||||
SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, &depthStencilTargetInfo);
|
||||
SDL_BindGPUGraphicsPipeline(renderPass, m_pipeline);
|
||||
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 Direct3DRMSDL3GPURenderer::SubmitDraw(
|
||||
const GeometryVertex* vertices,
|
||||
const size_t count,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
)
|
||||
{
|
||||
D3DRMMATRIX4D worldViewMatrix;
|
||||
MultiplyMatrix(worldViewMatrix, worldMatrix, m_viewMatrix);
|
||||
memcpy(&m_uniforms.worldViewMatrix, worldViewMatrix, sizeof(D3DRMMATRIX4D));
|
||||
m_fragmentShadingData.color = appearance.color;
|
||||
m_fragmentShadingData.shininess = appearance.shininess;
|
||||
|
||||
if (count > 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(GeometryVertex) * count);
|
||||
m_vertexBuffer = SDL_CreateGPUBuffer(m_device, &bufferCreateInfo);
|
||||
if (!m_vertexBuffer) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUBuffer returned NULL buffer (%s)", SDL_GetError());
|
||||
}
|
||||
m_vertexBufferCount = count;
|
||||
}
|
||||
|
||||
m_vertexCount = count;
|
||||
if (!count) {
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_GPUTransferBufferCreateInfo transferCreateInfo = {};
|
||||
transferCreateInfo.usage = SDL_GPU_TRANSFERBUFFERUSAGE_UPLOAD;
|
||||
transferCreateInfo.size = static_cast<Uint32>(sizeof(GeometryVertex) * m_vertexCount);
|
||||
SDL_GPUTransferBuffer* transferBuffer = SDL_CreateGPUTransferBuffer(m_device, &transferCreateInfo);
|
||||
if (!transferBuffer) {
|
||||
SDL_LogError(
|
||||
LOG_CATEGORY_MINIWIN,
|
||||
"SDL_CreateGPUTransferBuffer returned NULL transfer buffer (%s)",
|
||||
SDL_GetError()
|
||||
);
|
||||
}
|
||||
|
||||
GeometryVertex* transferData = (GeometryVertex*) SDL_MapGPUTransferBuffer(m_device, transferBuffer, false);
|
||||
if (!transferData) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_MapGPUTransferBuffer returned NULL buffer (%s)", SDL_GetError());
|
||||
}
|
||||
|
||||
memcpy(transferData, vertices, m_vertexCount * sizeof(GeometryVertex));
|
||||
|
||||
SDL_UnmapGPUTransferBuffer(m_device, transferBuffer);
|
||||
|
||||
// Upload the transfer data to the vertex buffer
|
||||
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
|
||||
if (!cmdbuf) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer failed (%s)", SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdbuf);
|
||||
SDL_GPUTransferBufferLocation transferLocation = {};
|
||||
transferLocation.transfer_buffer = transferBuffer;
|
||||
transferLocation.offset = 0;
|
||||
|
||||
SDL_GPUBufferRegion bufferRegion = {};
|
||||
bufferRegion.buffer = m_vertexBuffer;
|
||||
bufferRegion.offset = 0;
|
||||
bufferRegion.size = static_cast<Uint32>(sizeof(GeometryVertex) * m_vertexCount);
|
||||
|
||||
SDL_UploadToGPUBuffer(copyPass, &transferLocation, &bufferRegion, false);
|
||||
|
||||
SDL_EndGPUCopyPass(copyPass);
|
||||
SDL_ReleaseGPUTransferBuffer(m_device, transferBuffer);
|
||||
|
||||
// Render the graphics
|
||||
SDL_GPUColorTargetInfo colorTargetInfo = {};
|
||||
colorTargetInfo.texture = m_transferTexture;
|
||||
colorTargetInfo.load_op = SDL_GPU_LOADOP_LOAD;
|
||||
|
||||
SDL_GPUDepthStencilTargetInfo depthStencilTargetInfo = {};
|
||||
depthStencilTargetInfo.texture = m_depthTexture;
|
||||
depthStencilTargetInfo.load_op = SDL_GPU_LOADOP_LOAD;
|
||||
depthStencilTargetInfo.store_op = SDL_GPU_STOREOP_STORE;
|
||||
|
||||
SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, &depthStencilTargetInfo);
|
||||
SDL_BindGPUGraphicsPipeline(renderPass, appearance.color.a == 255 ? m_opaquePipeline : m_transparentPipeline);
|
||||
|
||||
SDL_PushGPUVertexUniformData(cmdbuf, 0, &m_uniforms, sizeof(m_uniforms));
|
||||
SDL_PushGPUFragmentUniformData(cmdbuf, 0, &m_lights, sizeof(m_lights));
|
||||
SDL_PushGPUFragmentUniformData(cmdbuf, 0, &m_fragmentShadingData, sizeof(m_fragmentShadingData));
|
||||
|
||||
if (m_vertexCount) {
|
||||
SDL_GPUBufferBinding vertexBufferBinding = {};
|
||||
@ -354,6 +399,19 @@ HRESULT Direct3DRMSDL3GPURenderer::Render()
|
||||
|
||||
SDL_EndGPURenderPass(renderPass);
|
||||
|
||||
if (!SDL_SubmitGPUCommandBuffer(cmdbuf)) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_SubmitGPUCommandBuffer failes (%s)", SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Direct3DRMSDL3GPURenderer::FinalizeFrame()
|
||||
{
|
||||
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
|
||||
if (cmdbuf == NULL) {
|
||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer failed (%s)", SDL_GetError());
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
|
||||
// Download rendered image
|
||||
SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdbuf);
|
||||
SDL_GPUTextureRegion region = {};
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -2,20 +2,14 @@ struct VS_Input
|
||||
{
|
||||
float3 Position : POSITION;
|
||||
float3 Normal : NORMAL0;
|
||||
float4 Color : COLOR0;
|
||||
uint TexId : TEXCOORD0;
|
||||
float2 TexCoord : TEXCOORD1;
|
||||
float Shininess : TEXCOORD2;
|
||||
};
|
||||
|
||||
struct FS_Input
|
||||
{
|
||||
float4 Position : SV_POSITION;
|
||||
float3 Normal : NORMAL0;
|
||||
float4 Color : COLOR0;
|
||||
uint TexId : TEXCOORD0;
|
||||
float2 TexCoord : TEXCOORD1;
|
||||
float Shininess : TEXCOORD2;
|
||||
float3 WorldPosition : TEXCOORD3;
|
||||
};
|
||||
|
||||
|
@ -2,19 +2,18 @@
|
||||
|
||||
cbuffer ViewportUniforms : register(b0, space1)
|
||||
{
|
||||
float4x4 perspective;
|
||||
float4x4 projection;
|
||||
float4x4 viewMatrix;
|
||||
}
|
||||
|
||||
FS_Input main(VS_Input input)
|
||||
{
|
||||
FS_Input output;
|
||||
output.TexCoord = input.TexCoord;
|
||||
output.Color = input.Color;
|
||||
float3 viewPos = mul(viewMatrix, float4(input.Position, 1.0)).xyz;
|
||||
output.WorldPosition = viewPos;
|
||||
output.Position = mul(projection, float4(viewPos, 1.0));
|
||||
output.Normal = input.Normal;
|
||||
output.Position = mul(perspective, float4(input.Position, 1.0));
|
||||
output.WorldPosition = input.Position;
|
||||
output.TexId = input.TexId;
|
||||
output.Shininess = input.Shininess;
|
||||
output.TexCoord = input.TexCoord;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
@ -1,9 +1,21 @@
|
||||
#include "Common.hlsl"
|
||||
|
||||
cbuffer LightBuffer : register(b0, space3)
|
||||
cbuffer FragmentShadingData : register(b0, space3)
|
||||
{
|
||||
SceneLight lights[3];
|
||||
int lightCount;
|
||||
float Shininess;
|
||||
uint ColorRaw;
|
||||
}
|
||||
|
||||
float4 unpackColor(uint packed)
|
||||
{
|
||||
float4 color;
|
||||
color.r = ((packed >> 0) & 0xFF) / 255.0f;
|
||||
color.g = ((packed >> 8) & 0xFF) / 255.0f;
|
||||
color.b = ((packed >> 16) & 0xFF) / 255.0f;
|
||||
color.a = ((packed >> 24) & 0xFF) / 255.0f;
|
||||
return color;
|
||||
}
|
||||
|
||||
FS_Output main(FS_Input input)
|
||||
@ -41,18 +53,17 @@ FS_Output main(FS_Input input)
|
||||
if (dotNL > 0.0f) {
|
||||
diffuse += dotNL * lightColor;
|
||||
|
||||
if (input.Shininess != 0.0f) {
|
||||
if (Shininess != 0.0f) {
|
||||
// Using dotNL ignores view angle, but this matches DirectX 5 behavior.
|
||||
float spec1 = pow(dotNL, input.Shininess);
|
||||
float spec1 = pow(dotNL, Shininess);
|
||||
specular += spec1 * lightColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float3 baseColor = input.Color.rgb;
|
||||
float3 finalColor = saturate(diffuse * baseColor + specular);
|
||||
|
||||
output.Color = float4(finalColor, input.Color.a);
|
||||
float4 Color = unpackColor(ColorRaw);
|
||||
float3 finalColor = saturate(diffuse * Color.rgb + specular);
|
||||
output.Color = float4(finalColor, Color.a);
|
||||
output.Depth = input.Position.w;
|
||||
return output;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "d3drmrenderer.h"
|
||||
#include "d3drmrenderer_software.h"
|
||||
#include "ddsurface_impl.h"
|
||||
#include "mathutils.h"
|
||||
#include "miniwin.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
@ -19,20 +20,11 @@ void Direct3DRMSoftwareRenderer::PushLights(const SceneLight* lights, size_t cou
|
||||
m_lights.assign(lights, lights + count);
|
||||
}
|
||||
|
||||
void Direct3DRMSoftwareRenderer::PushVertices(const PositionColorVertex* vertices, size_t count)
|
||||
{
|
||||
if (!count) {
|
||||
return;
|
||||
}
|
||||
m_vertexBuffer.resize(count);
|
||||
memcpy(m_vertexBuffer.data(), vertices, count * sizeof(PositionColorVertex));
|
||||
}
|
||||
|
||||
void Direct3DRMSoftwareRenderer::SetProjection(D3DRMMATRIX4D perspective, D3DVALUE front, D3DVALUE back)
|
||||
void Direct3DRMSoftwareRenderer::SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back)
|
||||
{
|
||||
m_front = front;
|
||||
m_back = back;
|
||||
memcpy(proj, perspective, sizeof(proj));
|
||||
memcpy(m_projection, projection, sizeof(D3DRMMATRIX4D));
|
||||
}
|
||||
|
||||
void Direct3DRMSoftwareRenderer::ClearZBuffer()
|
||||
@ -40,12 +32,16 @@ void Direct3DRMSoftwareRenderer::ClearZBuffer()
|
||||
std::fill(m_zBuffer.begin(), m_zBuffer.end(), std::numeric_limits<float>::infinity());
|
||||
}
|
||||
|
||||
void Direct3DRMSoftwareRenderer::ProjectVertex(const PositionColorVertex& v, D3DRMVECTOR4D& p) const
|
||||
void Direct3DRMSoftwareRenderer::ProjectVertex(const GeometryVertex& v, D3DRMVECTOR4D& p) const
|
||||
{
|
||||
float px = proj[0][0] * v.position.x + proj[1][0] * v.position.y + proj[2][0] * v.position.z + proj[3][0];
|
||||
float py = proj[0][1] * v.position.x + proj[1][1] * v.position.y + proj[2][1] * v.position.z + proj[3][1];
|
||||
float pz = proj[0][2] * v.position.x + proj[1][2] * v.position.y + proj[2][2] * v.position.z + proj[3][2];
|
||||
float pw = proj[0][3] * v.position.x + proj[1][3] * v.position.y + proj[2][3] * v.position.z + proj[3][3];
|
||||
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];
|
||||
|
||||
p.w = pw;
|
||||
|
||||
@ -62,7 +58,7 @@ void Direct3DRMSoftwareRenderer::ProjectVertex(const PositionColorVertex& v, D3D
|
||||
p.z = pz;
|
||||
}
|
||||
|
||||
PositionColorVertex SplitEdge(PositionColorVertex a, const PositionColorVertex& b, float plane)
|
||||
GeometryVertex SplitEdge(GeometryVertex a, const GeometryVertex& b, float plane)
|
||||
{
|
||||
float t = (plane - a.position.z) / (b.position.z - a.position.z);
|
||||
a.position.x = a.position.x + t * (b.position.x - a.position.x);
|
||||
@ -86,15 +82,11 @@ PositionColorVertex SplitEdge(PositionColorVertex a, const PositionColorVertex&
|
||||
return a;
|
||||
}
|
||||
|
||||
void Direct3DRMSoftwareRenderer::DrawTriangleClipped(
|
||||
const PositionColorVertex& v0,
|
||||
const PositionColorVertex& v1,
|
||||
const PositionColorVertex& v2
|
||||
)
|
||||
void Direct3DRMSoftwareRenderer::DrawTriangleClipped(const GeometryVertex (&v)[3], const Appearance& appearance)
|
||||
{
|
||||
bool in0 = v0.position.z >= m_front;
|
||||
bool in1 = v1.position.z >= m_front;
|
||||
bool in2 = v2.position.z >= m_front;
|
||||
bool in0 = v[0].position.z >= m_front;
|
||||
bool in1 = v[1].position.z >= m_front;
|
||||
bool in2 = v[2].position.z >= m_front;
|
||||
|
||||
int insideCount = in0 + in1 + in2;
|
||||
|
||||
@ -103,34 +95,34 @@ void Direct3DRMSoftwareRenderer::DrawTriangleClipped(
|
||||
}
|
||||
|
||||
if (insideCount == 3) {
|
||||
DrawTriangleProjected(v0, v1, v2);
|
||||
DrawTriangleProjected(v[0], v[1], v[2], appearance);
|
||||
}
|
||||
else if (insideCount == 2) {
|
||||
PositionColorVertex split;
|
||||
GeometryVertex split;
|
||||
if (!in0) {
|
||||
split = SplitEdge(v2, v0, m_front);
|
||||
DrawTriangleProjected(v1, v2, split);
|
||||
DrawTriangleProjected(v1, split, SplitEdge(v1, v0, m_front));
|
||||
split = SplitEdge(v[2], v[0], m_front);
|
||||
DrawTriangleProjected(v[1], v[2], split, appearance);
|
||||
DrawTriangleProjected(v[1], split, SplitEdge(v[1], v[0], m_front), appearance);
|
||||
}
|
||||
else if (!in1) {
|
||||
split = SplitEdge(v0, v1, m_front);
|
||||
DrawTriangleProjected(v2, v0, split);
|
||||
DrawTriangleProjected(v2, split, SplitEdge(v2, v1, m_front));
|
||||
split = SplitEdge(v[0], v[1], m_front);
|
||||
DrawTriangleProjected(v[2], v[0], split, appearance);
|
||||
DrawTriangleProjected(v[2], split, SplitEdge(v[2], v[1], m_front), appearance);
|
||||
}
|
||||
else {
|
||||
split = SplitEdge(v1, v2, m_front);
|
||||
DrawTriangleProjected(v0, v1, split);
|
||||
DrawTriangleProjected(v0, split, SplitEdge(v0, v2, m_front));
|
||||
split = SplitEdge(v[1], v[2], m_front);
|
||||
DrawTriangleProjected(v[0], v[1], split, appearance);
|
||||
DrawTriangleProjected(v[0], split, SplitEdge(v[0], v[2], m_front), appearance);
|
||||
}
|
||||
}
|
||||
else if (in0) {
|
||||
DrawTriangleProjected(v0, SplitEdge(v0, v1, m_front), SplitEdge(v0, v2, m_front));
|
||||
DrawTriangleProjected(v[0], SplitEdge(v[0], v[1], m_front), SplitEdge(v[0], v[2], m_front), appearance);
|
||||
}
|
||||
else if (in1) {
|
||||
DrawTriangleProjected(SplitEdge(v1, v0, m_front), v1, SplitEdge(v1, v2, m_front));
|
||||
DrawTriangleProjected(SplitEdge(v[1], v[0], m_front), v[1], SplitEdge(v[1], v[2], m_front), appearance);
|
||||
}
|
||||
else {
|
||||
DrawTriangleProjected(SplitEdge(v2, v0, m_front), SplitEdge(v2, v1, m_front), v2);
|
||||
DrawTriangleProjected(SplitEdge(v[2], v[0], m_front), SplitEdge(v[2], v[1], m_front), v[2], appearance);
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,7 +149,7 @@ void Direct3DRMSoftwareRenderer::BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g,
|
||||
memcpy(pixelAddr, &blended, m_bytesPerPixel);
|
||||
}
|
||||
|
||||
SDL_Color Direct3DRMSoftwareRenderer::ApplyLighting(const PositionColorVertex& vertex)
|
||||
SDL_Color Direct3DRMSoftwareRenderer::ApplyLighting(const GeometryVertex& vertex, const Appearance& appearance)
|
||||
{
|
||||
FColor specular = {0, 0, 0, 0};
|
||||
FColor diffuse = {0, 0, 0, 0};
|
||||
@ -167,7 +159,7 @@ SDL_Color Direct3DRMSoftwareRenderer::ApplyLighting(const PositionColorVertex& v
|
||||
D3DVECTOR normal = vertex.normals;
|
||||
float normLen = std::sqrt(normal.x * normal.x + normal.y * normal.y + normal.z * normal.z);
|
||||
if (normLen == 0.0f) {
|
||||
return vertex.colors;
|
||||
return appearance.color;
|
||||
}
|
||||
|
||||
normal.x /= normLen;
|
||||
@ -209,9 +201,9 @@ SDL_Color Direct3DRMSoftwareRenderer::ApplyLighting(const PositionColorVertex& v
|
||||
diffuse.g += dotNL * lightColor.g;
|
||||
diffuse.b += dotNL * lightColor.b;
|
||||
|
||||
if (vertex.shininess != 0.0f) {
|
||||
if (appearance.shininess != 0.0f) {
|
||||
// Using dotNL ignores view angle, but this matches DirectX 5 behavior.
|
||||
float spec = std::pow(dotNL, vertex.shininess);
|
||||
float spec = std::pow(dotNL, appearance.shininess);
|
||||
specular.r += spec * lightColor.r;
|
||||
specular.g += spec * lightColor.g;
|
||||
specular.b += spec * lightColor.b;
|
||||
@ -220,17 +212,18 @@ SDL_Color Direct3DRMSoftwareRenderer::ApplyLighting(const PositionColorVertex& v
|
||||
}
|
||||
|
||||
return SDL_Color{
|
||||
static_cast<Uint8>(std::min(255.0f, diffuse.r * vertex.colors.r + specular.r * 255.0f)),
|
||||
static_cast<Uint8>(std::min(255.0f, diffuse.g * vertex.colors.g + specular.g * 255.0f)),
|
||||
static_cast<Uint8>(std::min(255.0f, diffuse.b * vertex.colors.b + specular.b * 255.0f)),
|
||||
vertex.colors.a
|
||||
static_cast<Uint8>(std::min(255.0f, diffuse.r * appearance.color.r + specular.r * 255.0f)),
|
||||
static_cast<Uint8>(std::min(255.0f, diffuse.g * appearance.color.g + specular.g * 255.0f)),
|
||||
static_cast<Uint8>(std::min(255.0f, diffuse.b * appearance.color.b + specular.b * 255.0f)),
|
||||
appearance.color.a
|
||||
};
|
||||
}
|
||||
|
||||
void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
|
||||
const PositionColorVertex& v0,
|
||||
const PositionColorVertex& v1,
|
||||
const PositionColorVertex& v2
|
||||
const GeometryVertex& v0,
|
||||
const GeometryVertex& v1,
|
||||
const GeometryVertex& v2,
|
||||
const Appearance& appearance
|
||||
)
|
||||
{
|
||||
D3DRMVECTOR4D p0, p1, p2;
|
||||
@ -268,17 +261,17 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
|
||||
float invArea = 1.0f / area;
|
||||
|
||||
// Per-vertex lighting using vertex normals
|
||||
SDL_Color c0 = ApplyLighting(v0);
|
||||
SDL_Color c1 = ApplyLighting(v1);
|
||||
SDL_Color c2 = ApplyLighting(v2);
|
||||
SDL_Color c0 = ApplyLighting(v0, appearance);
|
||||
SDL_Color c1 = ApplyLighting(v1, appearance);
|
||||
SDL_Color c2 = ApplyLighting(v2, appearance);
|
||||
|
||||
Uint32 texId = v0.texId;
|
||||
Uint32 textureId = appearance.textureId;
|
||||
int texturePitch;
|
||||
Uint8* texels = nullptr;
|
||||
int texWidthScale;
|
||||
int texHeightScale;
|
||||
if (texId != NO_TEXTURE_ID) {
|
||||
SDL_Surface* texture = m_textures[texId].cached;
|
||||
if (textureId != NO_TEXTURE_ID) {
|
||||
SDL_Surface* texture = m_textures[textureId].cached;
|
||||
if (texture) {
|
||||
texturePitch = texture->pitch;
|
||||
texels = static_cast<Uint8*>(texture->pixels);
|
||||
@ -319,7 +312,7 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
|
||||
Uint8 b = static_cast<Uint8>(w0 * c0.b + w1 * c1.b + w2 * c2.b);
|
||||
Uint8* pixelAddr = pixels + y * pitch + x * m_bytesPerPixel;
|
||||
|
||||
if (v0.colors.a == 255) {
|
||||
if (appearance.color.a == 255) {
|
||||
zref = z;
|
||||
|
||||
if (texels) {
|
||||
@ -362,7 +355,7 @@ void Direct3DRMSoftwareRenderer::DrawTriangleProjected(
|
||||
}
|
||||
else {
|
||||
// Transparent alpha blending with vertex alpha
|
||||
BlendPixel(pixelAddr, r, g, b, v0.colors.a);
|
||||
BlendPixel(pixelAddr, r, g, b, appearance.color.a);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -461,21 +454,47 @@ const char* Direct3DRMSoftwareRenderer::GetName()
|
||||
return "Miniwin Emulation";
|
||||
}
|
||||
|
||||
HRESULT Direct3DRMSoftwareRenderer::Render()
|
||||
HRESULT Direct3DRMSoftwareRenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
|
||||
{
|
||||
if (!DDBackBuffer || m_vertexBuffer.size() % 3 != 0 || !SDL_LockSurface(DDBackBuffer)) {
|
||||
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;
|
||||
for (size_t i = 0; i + 2 < m_vertexBuffer.size(); i += 3) {
|
||||
DrawTriangleClipped(m_vertexBuffer[i], m_vertexBuffer[i + 1], m_vertexBuffer[i + 2]);
|
||||
}
|
||||
SDL_UnlockSurface(DDBackBuffer);
|
||||
|
||||
m_vertexBuffer.clear();
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
|
||||
void Direct3DRMSoftwareRenderer::SubmitDraw(
|
||||
const GeometryVertex* vertices,
|
||||
const size_t count,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
)
|
||||
{
|
||||
D3DRMMATRIX4D mvMatrix;
|
||||
MultiplyMatrix(mvMatrix, worldMatrix, m_viewMatrix);
|
||||
|
||||
for (size_t i = 0; i + 2 < count; i += 3) {
|
||||
GeometryVertex vrts[3];
|
||||
for (size_t j = 0; j < 3; ++j) {
|
||||
const GeometryVertex& src = vertices[i + j];
|
||||
vrts[j].position = TransformPoint(src.position, mvMatrix);
|
||||
vrts[j].normals = Normalize(TransformNormal(src.normals, normalMatrix));
|
||||
vrts[j].texCoord = src.texCoord;
|
||||
}
|
||||
DrawTriangleClipped(vrts, appearance);
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Direct3DRMSoftwareRenderer::FinalizeFrame()
|
||||
{
|
||||
SDL_UnlockSurface(DDBackBuffer);
|
||||
|
||||
return DD_OK;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "d3drmrenderer.h"
|
||||
#include "d3drmviewport_impl.h"
|
||||
#include "ddraw_impl.h"
|
||||
#include "mathutils.h"
|
||||
#include "miniwin.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
@ -12,8 +13,6 @@
|
||||
#include <functional>
|
||||
#include <math.h>
|
||||
|
||||
typedef D3DVALUE Matrix3x3[3][3];
|
||||
|
||||
Direct3DRMViewportImpl::Direct3DRMViewportImpl(DWORD width, DWORD height, Direct3DRMRenderer* rendere)
|
||||
: m_width(width), m_height(height), m_renderer(rendere)
|
||||
{
|
||||
@ -101,16 +100,6 @@ inline D3DVECTOR CrossProduct(const D3DVECTOR& a, const D3DVECTOR& b)
|
||||
return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x};
|
||||
}
|
||||
|
||||
inline D3DVECTOR Normalize(const D3DVECTOR& v)
|
||||
{
|
||||
float len = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||
if (len > 0.0f) {
|
||||
float invLen = 1.0f / len;
|
||||
return {v.x * invLen, v.y * invLen, v.z * invLen};
|
||||
}
|
||||
return {0, 0, 0};
|
||||
}
|
||||
|
||||
D3DVECTOR ComputeTriangleNormal(const D3DVECTOR& v0, const D3DVECTOR& v1, const D3DVECTOR& v2)
|
||||
{
|
||||
D3DVECTOR u = {v1.x - v0.x, v1.y - v0.y, v1.z - v0.z};
|
||||
@ -121,24 +110,6 @@ D3DVECTOR ComputeTriangleNormal(const D3DVECTOR& v0, const D3DVECTOR& v1, const
|
||||
return normal;
|
||||
}
|
||||
|
||||
inline D3DVECTOR TransformNormal(const D3DVECTOR& v, const Matrix3x3& m)
|
||||
{
|
||||
return {
|
||||
v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0],
|
||||
v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1],
|
||||
v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2]
|
||||
};
|
||||
}
|
||||
|
||||
inline D3DVECTOR TransformPoint(const D3DVECTOR& p, const D3DRMMATRIX4D& m)
|
||||
{
|
||||
return {
|
||||
p.x * m[0][0] + p.y * m[1][0] + p.z * m[2][0] + m[3][0],
|
||||
p.x * m[0][1] + p.y * m[1][1] + p.z * m[2][1] + m[3][1],
|
||||
p.x * m[0][2] + p.y * m[1][2] + p.z * m[2][2] + m[3][2]
|
||||
};
|
||||
}
|
||||
|
||||
void Direct3DRMViewportImpl::CollectLightsFromFrame(
|
||||
IDirect3DRMFrame* frame,
|
||||
D3DRMMATRIX4D parentToWorld,
|
||||
@ -241,11 +212,7 @@ bool IsBoxInFrustum(const D3DVECTOR corners[8], const Plane planes[6])
|
||||
return true;
|
||||
}
|
||||
|
||||
void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
||||
IDirect3DRMFrame* frame,
|
||||
D3DRMMATRIX4D parentMatrix,
|
||||
std::vector<PositionColorVertex>& verts
|
||||
)
|
||||
void Direct3DRMViewportImpl::CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix)
|
||||
{
|
||||
Direct3DRMFrameImpl* frameImpl = static_cast<Direct3DRMFrameImpl*>(frame);
|
||||
D3DRMMATRIX4D localMatrix;
|
||||
@ -267,7 +234,7 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
||||
IDirect3DRMFrame* childFrame = nullptr;
|
||||
visual->QueryInterface(IID_IDirect3DRMFrame, (void**) &childFrame);
|
||||
if (childFrame) {
|
||||
CollectMeshesFromFrame(childFrame, worldMatrix, verts);
|
||||
CollectMeshesFromFrame(childFrame, worldMatrix);
|
||||
childFrame->Release();
|
||||
visual->Release();
|
||||
continue;
|
||||
@ -306,6 +273,7 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
||||
DWORD vtxCount, faceCount, vpf, dataSize;
|
||||
mesh->GetGroup(gi, &vtxCount, &faceCount, &vpf, &dataSize, nullptr);
|
||||
|
||||
std::vector<GeometryVertex> verts(dataSize * vpf);
|
||||
std::vector<D3DRMVERTEX> d3dVerts(vtxCount);
|
||||
std::vector<DWORD> faces(dataSize);
|
||||
mesh->GetVertices(gi, 0, vtxCount, d3dVerts.data());
|
||||
@ -316,9 +284,9 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
||||
|
||||
IDirect3DRMTexture* texture = nullptr;
|
||||
mesh->GetGroupTexture(gi, &texture);
|
||||
Uint32 texId = NO_TEXTURE_ID;
|
||||
Uint32 textureId = NO_TEXTURE_ID;
|
||||
if (texture) {
|
||||
texId = m_renderer->GetTextureId(texture);
|
||||
textureId = m_renderer->GetTextureId(texture);
|
||||
texture->Release();
|
||||
}
|
||||
|
||||
@ -346,22 +314,21 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
||||
norm = dv.normal;
|
||||
}
|
||||
|
||||
D3DVECTOR worldPos = TransformPoint(pos, worldMatrix);
|
||||
D3DVECTOR viewNorm = TransformNormal(norm, worldMatrixInvert);
|
||||
|
||||
verts.push_back(
|
||||
{TransformPoint(worldPos, m_viewMatrix),
|
||||
Normalize(viewNorm),
|
||||
{static_cast<Uint8>((color >> 16) & 0xFF),
|
||||
static_cast<Uint8>((color >> 8) & 0xFF),
|
||||
static_cast<Uint8>((color >> 0) & 0xFF),
|
||||
static_cast<Uint8>((color >> 24) & 0xFF)},
|
||||
texId,
|
||||
{dv.tu, dv.tv},
|
||||
shininess}
|
||||
);
|
||||
verts.push_back({pos, norm, {dv.tu, dv.tv}});
|
||||
}
|
||||
}
|
||||
m_renderer->SubmitDraw(
|
||||
verts.data(),
|
||||
verts.size(),
|
||||
worldMatrix,
|
||||
worldMatrixInvert,
|
||||
{{static_cast<Uint8>((color >> 16) & 0xFF),
|
||||
static_cast<Uint8>((color >> 8) & 0xFF),
|
||||
static_cast<Uint8>((color >> 0) & 0xFF),
|
||||
static_cast<Uint8>((color >> 24) & 0xFF)},
|
||||
shininess,
|
||||
textureId}
|
||||
);
|
||||
}
|
||||
mesh->Release();
|
||||
visual->Release();
|
||||
@ -369,7 +336,7 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(
|
||||
visuals->Release();
|
||||
}
|
||||
|
||||
void Direct3DRMViewportImpl::CollectSceneData()
|
||||
HRESULT Direct3DRMViewportImpl::RenderScene()
|
||||
{
|
||||
m_backgroundColor = static_cast<Direct3DRMFrameImpl*>(m_rootFrame)->m_backgroundColor;
|
||||
|
||||
@ -384,11 +351,14 @@ void Direct3DRMViewportImpl::CollectSceneData()
|
||||
std::vector<SceneLight> lights;
|
||||
CollectLightsFromFrame(m_rootFrame, identity, lights);
|
||||
m_renderer->PushLights(lights.data(), lights.size());
|
||||
HRESULT status = m_renderer->BeginFrame(m_viewMatrix);
|
||||
if (status != DD_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
std::vector<PositionColorVertex> verts;
|
||||
ExtractFrustumPlanes(viewProj);
|
||||
CollectMeshesFromFrame(m_rootFrame, identity, verts);
|
||||
m_renderer->PushVertices(verts.data(), verts.size());
|
||||
CollectMeshesFromFrame(m_rootFrame, identity);
|
||||
return m_renderer->FinalizeFrame();
|
||||
}
|
||||
|
||||
HRESULT Direct3DRMViewportImpl::Render(IDirect3DRMFrame* rootFrame)
|
||||
@ -397,8 +367,7 @@ HRESULT Direct3DRMViewportImpl::Render(IDirect3DRMFrame* rootFrame)
|
||||
return DDERR_GENERIC;
|
||||
}
|
||||
m_rootFrame = rootFrame;
|
||||
CollectSceneData();
|
||||
return m_renderer->Render();
|
||||
return RenderScene();
|
||||
}
|
||||
|
||||
HRESULT Direct3DRMViewportImpl::ForceUpdate(int x, int y, int w, int h)
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "mathutils.h"
|
||||
#include "miniwin/d3drm.h"
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
@ -10,15 +11,18 @@ struct TexCoord {
|
||||
float u, v;
|
||||
};
|
||||
|
||||
struct PositionColorVertex {
|
||||
struct GeometryVertex {
|
||||
D3DVECTOR position;
|
||||
D3DVECTOR normals;
|
||||
SDL_Color colors;
|
||||
Uint32 texId;
|
||||
TexCoord texCoord;
|
||||
float shininess;
|
||||
};
|
||||
static_assert(sizeof(PositionColorVertex) == 44);
|
||||
static_assert(sizeof(GeometryVertex) == 32);
|
||||
|
||||
struct Appearance {
|
||||
SDL_Color color;
|
||||
float shininess;
|
||||
Uint32 textureId;
|
||||
};
|
||||
|
||||
struct FColor {
|
||||
float r, g, b, a;
|
||||
@ -35,13 +39,20 @@ static_assert(sizeof(SceneLight) == 48);
|
||||
|
||||
class Direct3DRMRenderer : public IDirect3DDevice2 {
|
||||
public:
|
||||
virtual void PushVertices(const PositionColorVertex* vertices, size_t count) = 0;
|
||||
virtual void PushLights(const SceneLight* vertices, size_t count) = 0;
|
||||
virtual void SetProjection(D3DRMMATRIX4D perspective, D3DVALUE front, D3DVALUE back) = 0;
|
||||
virtual void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) = 0;
|
||||
virtual Uint32 GetTextureId(IDirect3DRMTexture* texture) = 0;
|
||||
virtual DWORD GetWidth() = 0;
|
||||
virtual DWORD GetHeight() = 0;
|
||||
virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0;
|
||||
virtual const char* GetName() = 0;
|
||||
virtual HRESULT Render() = 0;
|
||||
virtual HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) = 0;
|
||||
virtual void SubmitDraw(
|
||||
const GeometryVertex* vertices,
|
||||
const size_t count,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
) = 0;
|
||||
virtual HRESULT FinalizeFrame() = 0;
|
||||
};
|
||||
|
@ -15,23 +15,30 @@ public:
|
||||
static Direct3DRMRenderer* Create(DWORD width, DWORD height);
|
||||
OpenGL15Renderer(int width, int height, SDL_GLContext context, GLuint fbo, GLuint colorTex, GLuint depthRb);
|
||||
~OpenGL15Renderer() override;
|
||||
void PushVertices(const PositionColorVertex* verts, size_t count) override;
|
||||
void PushLights(const SceneLight* lightsArray, size_t count) override;
|
||||
void SetProjection(D3DRMMATRIX4D perspective, D3DVALUE front, D3DVALUE back) override;
|
||||
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
|
||||
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
|
||||
DWORD GetWidth() override;
|
||||
DWORD GetHeight() override;
|
||||
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
|
||||
const char* GetName() override;
|
||||
HRESULT Render() override;
|
||||
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
||||
void SubmitDraw(
|
||||
const GeometryVertex* vertices,
|
||||
const size_t count,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
) override;
|
||||
HRESULT FinalizeFrame() override;
|
||||
|
||||
private:
|
||||
SDL_GLContext m_context;
|
||||
D3DRMMATRIX4D m_viewMatrix;
|
||||
D3DRMMATRIX4D m_projection;
|
||||
SDL_Surface* m_renderedImage;
|
||||
int m_width, m_height;
|
||||
std::vector<PositionColorVertex> m_vertices;
|
||||
std::vector<SceneLight> m_lights;
|
||||
SDL_GLContext m_context;
|
||||
GLuint m_fbo = 0;
|
||||
GLuint m_colorTex = 0;
|
||||
GLuint m_depthRb = 0;
|
||||
|
@ -8,34 +8,50 @@
|
||||
DEFINE_GUID(SDL3_GPU_GUID, 0x682656F3, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01);
|
||||
|
||||
typedef struct {
|
||||
D3DRMMATRIX4D perspective;
|
||||
D3DRMMATRIX4D projection;
|
||||
D3DRMMATRIX4D worldViewMatrix;
|
||||
} ViewportUniforms;
|
||||
static_assert(sizeof(ViewportUniforms) % 16 == 0);
|
||||
static_assert(sizeof(ViewportUniforms) == 128);
|
||||
|
||||
struct SceneLights {
|
||||
struct FragmentShadingData {
|
||||
SceneLight lights[3];
|
||||
int count;
|
||||
int lightCount;
|
||||
float shininess;
|
||||
SDL_Color color;
|
||||
int padding1[1];
|
||||
};
|
||||
static_assert(sizeof(FragmentShadingData) % 16 == 0);
|
||||
static_assert(sizeof(FragmentShadingData) == 160);
|
||||
|
||||
class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
|
||||
public:
|
||||
static Direct3DRMRenderer* Create(DWORD width, DWORD height);
|
||||
~Direct3DRMSDL3GPURenderer() override;
|
||||
void PushVertices(const PositionColorVertex* vertices, size_t count) override;
|
||||
void PushLights(const SceneLight* vertices, size_t count) override;
|
||||
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
|
||||
void SetProjection(D3DRMMATRIX4D perspective, D3DVALUE front, D3DVALUE back) override;
|
||||
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
|
||||
DWORD GetWidth() override;
|
||||
DWORD GetHeight() override;
|
||||
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
|
||||
const char* GetName() override;
|
||||
HRESULT Render() override;
|
||||
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
||||
void SubmitDraw(
|
||||
const GeometryVertex* vertices,
|
||||
const size_t count,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
) override;
|
||||
HRESULT FinalizeFrame() override;
|
||||
|
||||
private:
|
||||
Direct3DRMSDL3GPURenderer(
|
||||
DWORD width,
|
||||
DWORD height,
|
||||
SDL_GPUDevice* device,
|
||||
SDL_GPUGraphicsPipeline* pipeline,
|
||||
SDL_GPUGraphicsPipeline* opaquePipeline,
|
||||
SDL_GPUGraphicsPipeline* transparentPipeline,
|
||||
SDL_GPUTexture* transferTexture,
|
||||
SDL_GPUTexture* depthTexture,
|
||||
SDL_GPUTransferBuffer* downloadTransferBuffer
|
||||
@ -49,10 +65,12 @@ private:
|
||||
int m_vertexCount;
|
||||
int m_vertexBufferCount = 0;
|
||||
ViewportUniforms m_uniforms;
|
||||
SceneLights m_lights;
|
||||
FragmentShadingData m_fragmentShadingData;
|
||||
D3DDEVICEDESC m_desc;
|
||||
D3DRMMATRIX4D m_viewMatrix;
|
||||
SDL_GPUDevice* m_device;
|
||||
SDL_GPUGraphicsPipeline* m_pipeline;
|
||||
SDL_GPUGraphicsPipeline* m_opaquePipeline;
|
||||
SDL_GPUGraphicsPipeline* m_transparentPipeline;
|
||||
SDL_GPUTexture* m_transferTexture;
|
||||
SDL_GPUTexture* m_depthTexture;
|
||||
SDL_GPUTransferBuffer* m_downloadTransferBuffer;
|
||||
|
@ -19,27 +19,35 @@ struct TextureCache {
|
||||
class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
|
||||
public:
|
||||
Direct3DRMSoftwareRenderer(DWORD width, DWORD height);
|
||||
void PushVertices(const PositionColorVertex* vertices, size_t count) override;
|
||||
void PushLights(const SceneLight* vertices, size_t count) override;
|
||||
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
|
||||
void SetProjection(D3DRMMATRIX4D perspective, D3DVALUE front, D3DVALUE back) override;
|
||||
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
|
||||
DWORD GetWidth() override;
|
||||
DWORD GetHeight() override;
|
||||
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
|
||||
const char* GetName() override;
|
||||
HRESULT Render() override;
|
||||
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
||||
void SubmitDraw(
|
||||
const GeometryVertex* vertices,
|
||||
const size_t count,
|
||||
const D3DRMMATRIX4D& worldMatrix,
|
||||
const Matrix3x3& normalMatrix,
|
||||
const Appearance& appearance
|
||||
) override;
|
||||
HRESULT FinalizeFrame() override;
|
||||
|
||||
private:
|
||||
void ClearZBuffer();
|
||||
void DrawTriangleProjected(const PositionColorVertex&, const PositionColorVertex&, const PositionColorVertex&);
|
||||
void DrawTriangleClipped(
|
||||
const PositionColorVertex& v0,
|
||||
const PositionColorVertex& v1,
|
||||
const PositionColorVertex& v2
|
||||
void DrawTriangleProjected(
|
||||
const GeometryVertex& v0,
|
||||
const GeometryVertex& v1,
|
||||
const GeometryVertex& v2,
|
||||
const Appearance& appearance
|
||||
);
|
||||
void ProjectVertex(const PositionColorVertex& v, D3DRMVECTOR4D& p) const;
|
||||
void DrawTriangleClipped(const GeometryVertex (&v)[3], const Appearance& appearance);
|
||||
void ProjectVertex(const GeometryVertex& v, D3DRMVECTOR4D& p) const;
|
||||
void BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
||||
SDL_Color ApplyLighting(const PositionColorVertex& vertex);
|
||||
SDL_Color ApplyLighting(const GeometryVertex& vertex, const Appearance& appearance);
|
||||
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
||||
|
||||
DWORD m_width;
|
||||
@ -51,8 +59,8 @@ private:
|
||||
std::vector<TextureCache> m_textures;
|
||||
D3DVALUE m_front;
|
||||
D3DVALUE m_back;
|
||||
std::vector<PositionColorVertex> m_vertexBuffer;
|
||||
float proj[4][4] = {0};
|
||||
D3DRMMATRIX4D m_viewMatrix;
|
||||
D3DRMMATRIX4D m_projection;
|
||||
std::vector<float> m_zBuffer;
|
||||
};
|
||||
|
||||
|
@ -35,13 +35,9 @@ struct Direct3DRMViewportImpl : public Direct3DRMObjectBaseImpl<IDirect3DRMViewp
|
||||
void CloseDevice();
|
||||
|
||||
private:
|
||||
void CollectSceneData();
|
||||
HRESULT RenderScene();
|
||||
void CollectLightsFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix, std::vector<SceneLight>& lights);
|
||||
void CollectMeshesFromFrame(
|
||||
IDirect3DRMFrame* frame,
|
||||
D3DRMMATRIX4D parentMatrix,
|
||||
std::vector<PositionColorVertex>& verts
|
||||
);
|
||||
void CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3DRMMATRIX4D parentMatrix);
|
||||
void UpdateProjectionMatrix();
|
||||
Direct3DRMRenderer* m_renderer;
|
||||
D3DCOLOR m_backgroundColor = 0xFF000000;
|
||||
|
47
miniwin/src/internal/mathutils.h
Normal file
47
miniwin/src/internal/mathutils.h
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "miniwin/d3drm.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
typedef D3DVALUE Matrix3x3[3][3];
|
||||
|
||||
inline D3DVECTOR TransformNormal(const D3DVECTOR& v, const Matrix3x3& m)
|
||||
{
|
||||
return {
|
||||
v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0],
|
||||
v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1],
|
||||
v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2]
|
||||
};
|
||||
}
|
||||
|
||||
inline D3DVECTOR Normalize(const D3DVECTOR& v)
|
||||
{
|
||||
float len = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||
if (len > 0.0f) {
|
||||
float invLen = 1.0f / len;
|
||||
return {v.x * invLen, v.y * invLen, v.z * invLen};
|
||||
}
|
||||
return {0, 0, 0};
|
||||
}
|
||||
|
||||
inline D3DVECTOR TransformPoint(const D3DVECTOR& p, const D3DRMMATRIX4D& m)
|
||||
{
|
||||
return {
|
||||
p.x * m[0][0] + p.y * m[1][0] + p.z * m[2][0] + m[3][0],
|
||||
p.x * m[0][1] + p.y * m[1][1] + p.z * m[2][1] + m[3][1],
|
||||
p.x * m[0][2] + p.y * m[1][2] + p.z * m[2][2] + m[3][2]
|
||||
};
|
||||
}
|
||||
|
||||
inline void MultiplyMatrix(D3DRMMATRIX4D& out, const D3DRMMATRIX4D& a, const D3DRMMATRIX4D& b)
|
||||
{
|
||||
for (int row = 0; row < 4; ++row) {
|
||||
for (int col = 0; col < 4; ++col) {
|
||||
out[row][col] = 0.0;
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
out[row][col] += a[row][k] * b[k][col];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user