This commit is contained in:
Anders Jenbo 2025-06-06 02:32:04 +02:00
parent 5be9b09b40
commit 9ef35c3dc5
2 changed files with 73 additions and 29 deletions

View File

@ -6,12 +6,13 @@
#include <GL/glew.h>
#include <cstring>
#include <vector>
Direct3DRMRenderer* OpenGL15Renderer::Create(DWORD width, DWORD height)
{
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 5);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);
SDL_Window* window = DDWindow;
bool testWindow = false;
@ -37,55 +38,82 @@ Direct3DRMRenderer* OpenGL15Renderer::Create(DWORD width, DWORD height)
return nullptr;
}
if (!GLEW_EXT_framebuffer_object) {
SDL_Log("FBOs are not supported (missing GL_EXT_framebuffer_object)");
return nullptr;
}
if (!GLEW_EXT_framebuffer_multisample || !GLEW_EXT_framebuffer_blit) {
SDL_Log("MSAA not supported (missing GL_EXT_framebuffer_multisample or GL_EXT_framebuffer_blit)");
return nullptr;
}
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_MULTISAMPLE);
// Setup FBO
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
// Create color texture
// Create color texture for resolved FBO
GLuint colorTex;
glGenTextures(1, &colorTex);
glBindTexture(GL_TEXTURE_2D, colorTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
// Create depth renderbuffer
GLuint depthRb;
glGenRenderbuffers(1, &depthRb);
glBindRenderbuffer(GL_RENDERBUFFER, depthRb);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRb);
// Create multisample renderbuffers
GLuint msaaColorRb, msaaDepthRb;
glGenRenderbuffers(1, &msaaColorRb);
glBindRenderbuffer(GL_RENDERBUFFER, msaaColorRb);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_RGBA8, width, height);
glGenRenderbuffers(1, &msaaDepthRb);
glBindRenderbuffer(GL_RENDERBUFFER, msaaDepthRb);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, 8, GL_DEPTH_COMPONENT24, width, height);
// Create FBO for resolved (non-MSAA) rendering target
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTex, 0);
// No depth buffer needed here for resolve FBO
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr;
}
// Create MSAA FBO for actual rendering
GLuint msaaFBO;
glGenFramebuffers(1, &msaaFBO);
glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, msaaColorRb);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, msaaDepthRb);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
if (testWindow) {
SDL_DestroyWindow(window);
}
return nullptr;
}
// Unbind FBO
glBindFramebuffer(GL_FRAMEBUFFER, 0);
if (testWindow) {
SDL_DestroyWindow(window);
}
return new OpenGL15Renderer(width, height, context, fbo, colorTex, depthRb);
return new OpenGL15Renderer(width, height, context, fbo, msaaFBO);
}
OpenGL15Renderer::OpenGL15Renderer(
int width,
int height,
SDL_GLContext context,
GLuint fbo,
GLuint colorTex,
GLuint depthRb
)
: m_width(width), m_height(height), m_context(context), m_fbo(fbo), m_colorTex(colorTex), m_depthRb(depthRb)
OpenGL15Renderer::OpenGL15Renderer(int width, int height, SDL_GLContext context, GLuint fbo, GLuint msaaFBO)
: m_width(width), m_height(height), m_context(context), m_fbo(fbo), m_msaaFBO(msaaFBO)
{
m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_ABGR8888);
}
@ -95,6 +123,14 @@ OpenGL15Renderer::~OpenGL15Renderer()
if (m_renderedImage) {
SDL_DestroySurface(m_renderedImage);
}
if (m_fbo) {
glDeleteFramebuffers(1, &m_fbo);
}
if (m_msaaFBO) {
glDeleteFramebuffers(1, &m_msaaFBO);
}
// You may also want to delete textures and renderbuffers similarly if you keep references to them.
}
void OpenGL15Renderer::PushLights(const SceneLight* lightsArray, size_t count)
@ -227,7 +263,7 @@ HRESULT OpenGL15Renderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
memcpy(m_viewMatrix, viewMatrix, sizeof(D3DRMMATRIX4D));
SDL_GL_MakeCurrent(DDWindow, m_context);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_msaaFBO);
glViewport(0, 0, m_width, m_height);
glEnable(GL_BLEND);
@ -365,10 +401,19 @@ void OpenGL15Renderer::SubmitDraw(
HRESULT OpenGL15Renderer::FinalizeFrame()
{
// Resolve multisampled FBO into resolved FBO (texture)
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_msaaFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
glBlitFramebuffer(0, 0, m_width, m_height, 0, 0, m_width, m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
// Read pixels from resolved FBO (texture)
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glReadPixels(0, 0, m_width, m_height, GL_RGBA, GL_UNSIGNED_BYTE, m_renderedImage->pixels);
// Unbind framebuffer to avoid side effects
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Composite onto SDL backbuffer
// Copy the pixels to SDL backbuffer surface
SDL_BlitSurface(m_renderedImage, nullptr, DDBackBuffer, nullptr);
return DD_OK;

View File

@ -19,7 +19,7 @@ struct GLTextureCacheEntry {
class OpenGL15Renderer : public Direct3DRMRenderer {
public:
static Direct3DRMRenderer* Create(DWORD width, DWORD height);
OpenGL15Renderer(int width, int height, SDL_GLContext context, GLuint fbo, GLuint colorTex, GLuint depthRb);
OpenGL15Renderer(int width, int height, SDL_GLContext context, GLuint fbo, GLuint msaaFBO);
~OpenGL15Renderer() override;
void PushLights(const SceneLight* lightsArray, size_t count) override;
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
@ -48,8 +48,7 @@ class OpenGL15Renderer : public Direct3DRMRenderer {
std::vector<SceneLight> m_lights;
SDL_GLContext m_context;
GLuint m_fbo = 0;
GLuint m_colorTex = 0;
GLuint m_depthRb = 0;
GLuint m_msaaFBO = 0;
};
inline static void OpenGL15Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)