diff --git a/miniwin/src/d3drm/backends/opengles2/renderer.cpp b/miniwin/src/d3drm/backends/opengles2/renderer.cpp index e1c86a62..2b46190b 100644 --- a/miniwin/src/d3drm/backends/opengles2/renderer.cpp +++ b/miniwin/src/d3drm/backends/opengles2/renderer.cpp @@ -15,8 +15,17 @@ static GLuint CompileShader(GLenum type, const char* source) GLint success; glGetShaderiv(shader, GL_COMPILE_STATUS, &success); if (!success) { + GLint logLength = 0; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); + if (logLength > 0) { + std::vector log(logLength); + glGetShaderInfoLog(shader, logLength, nullptr, log.data()); + SDL_Log("Shader compile error: %s", log.data()); + } + else { + SDL_Log("CompileShader (%s)", SDL_GetError()); + } glDeleteShader(shader); - SDL_Log("CompileShader (%s)", SDL_GetError()); return 0; } return shader; @@ -28,7 +37,7 @@ struct SceneLightGLES2 { float direction[4]; }; -Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) +Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height, float anisotropic) { // We have to reset the attributes here after having enumerated the // OpenGL ES 2.0 renderer, or else SDL gets very confused by SDL_GL_DEPTH_SIZE @@ -134,7 +143,7 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) // Specular if (u_shininess > 0.0 && u_lights[i].direction.w == 1.0) { - vec3 viewVec = normalize(-v_viewPos); // Assuming camera at origin + vec3 viewVec = normalize(-v_viewPos); vec3 H = normalize(lightVec + viewVec); float dotNH = max(dot(v_normal, H), 0.0); float spec = pow(dotNH, u_shininess); @@ -168,7 +177,7 @@ Direct3DRMRenderer* OpenGLES2Renderer::Create(DWORD width, DWORD height) glDeleteShader(vs); glDeleteShader(fs); - return new OpenGLES2Renderer(width, height, context, shaderProgram); + return new OpenGLES2Renderer(width, height, anisotropic, context, shaderProgram); } GLES2MeshCacheEntry GLES2UploadMesh(const MeshGroup& meshGroup, bool forceUV = false) @@ -237,7 +246,7 @@ GLES2MeshCacheEntry GLES2UploadMesh(const MeshGroup& meshGroup, bool forceUV = f return cache; } -bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI) +bool OpenGLES2Renderer::UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI) { SDL_Surface* surf = source; if (source->format != SDL_PIXELFORMAT_RGBA32) { @@ -262,11 +271,8 @@ bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - if (strstr((const char*) glGetString(GL_EXTENSIONS), "GL_EXT_texture_filter_anisotropic")) { - GLfloat maxAniso = 0.0f; - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso); - GLfloat desiredAniso = fminf(8.0f, maxAniso); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, desiredAniso); + if (m_anisotropic > 1.0f) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, m_anisotropic); } glGenerateMipmap(GL_TEXTURE_2D); } @@ -278,12 +284,34 @@ bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI) return true; } -OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram) - : m_context(context), m_shaderProgram(shaderProgram) +OpenGLES2Renderer::OpenGLES2Renderer( + DWORD width, + DWORD height, + float anisotropic, + SDL_GLContext context, + GLuint shaderProgram +) + : m_context(context), m_shaderProgram(shaderProgram), m_anisotropic(anisotropic) { glGenFramebuffers(1, &m_fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); + bool anisoAvailable = SDL_GL_ExtensionSupported("GL_EXT_texture_filter_anisotropic"); + GLfloat maxAniso = 0.0f; + if (anisoAvailable) { + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso); + } + if (m_anisotropic > maxAniso) { + m_anisotropic = maxAniso; + } + SDL_Log( + "Anisotropic is %s. Requested: %f, active: %f, max aniso: %f", + m_anisotropic > 1.0f ? "on" : "off", + anisotropic, + m_anisotropic, + maxAniso + ); + m_virtualWidth = width; m_virtualHeight = height; ViewportTransform viewportTransform = {1.0f, 0.0f, 0.0f}; @@ -310,14 +338,6 @@ OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext co } SDL_DestroySurface(dummySurface); - m_uiMesh.vertices = { - {{0.0f, 0.0f, 0.0f}, {0, 0, -1}, {0.0f, 0.0f}}, - {{1.0f, 0.0f, 0.0f}, {0, 0, -1}, {1.0f, 0.0f}}, - {{1.0f, 1.0f, 0.0f}, {0, 0, -1}, {1.0f, 1.0f}}, - {{0.0f, 1.0f, 0.0f}, {0, 0, -1}, {0.0f, 1.0f}} - }; - m_uiMesh.indices = {0, 1, 2, 0, 2, 3}; - m_uiMeshCache = GLES2UploadMesh(m_uiMesh, true); m_posLoc = glGetAttribLocation(m_shaderProgram, "a_position"); m_normLoc = glGetAttribLocation(m_shaderProgram, "a_normal"); m_texLoc = glGetAttribLocation(m_shaderProgram, "a_texCoord"); @@ -336,13 +356,26 @@ OpenGLES2Renderer::OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext co m_normalMatrixLoc = glGetUniformLocation(m_shaderProgram, "u_normalMatrix"); m_projectionMatrixLoc = glGetUniformLocation(m_shaderProgram, "u_projectionMatrix"); + m_uiMesh.vertices = { + {{0.0f, 0.0f, 0.0f}, {0, 0, -1}, {0.0f, 0.0f}}, + {{1.0f, 0.0f, 0.0f}, {0, 0, -1}, {1.0f, 0.0f}}, + {{1.0f, 1.0f, 0.0f}, {0, 0, -1}, {1.0f, 1.0f}}, + {{0.0f, 1.0f, 0.0f}, {0, 0, -1}, {0.0f, 1.0f}} + }; + m_uiMesh.indices = {0, 1, 2, 0, 2, 3}; + m_uiMeshCache = GLES2UploadMesh(m_uiMesh, true); + glUseProgram(m_shaderProgram); } OpenGLES2Renderer::~OpenGLES2Renderer() { SDL_DestroySurface(m_renderedImage); + glDeleteTextures(1, &m_dummyTexture); glDeleteProgram(m_shaderProgram); + glDeleteTextures(1, &m_colorTarget); + glDeleteRenderbuffers(1, &m_depthTarget); + glDeleteFramebuffers(1, &m_fbo); SDL_GL_DestroyContext(m_context); } @@ -610,6 +643,15 @@ void OpenGLES2Renderer::Resize(int width, int height, const ViewportTransform& v } m_renderedImage = SDL_CreateSurface(m_width, m_height, SDL_PIXELFORMAT_RGBA32); + if (m_colorTarget) { + glDeleteTextures(1, &m_colorTarget); + m_colorTarget = 0; + } + if (m_depthTarget) { + glDeleteRenderbuffers(1, &m_depthTarget); + m_depthTarget = 0; + } + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); // Create color texture @@ -636,6 +678,12 @@ void OpenGLES2Renderer::Resize(int width, int height, const ViewportTransform& v glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); } glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthTarget); + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) { + SDL_Log("FBO incomplete: 0x%X", status); + } + + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glViewport(0, 0, m_width, m_height); } diff --git a/miniwin/src/d3drm/d3drmrenderer.cpp b/miniwin/src/d3drm/d3drmrenderer.cpp index 56a4b1b0..f1e1fb8b 100644 --- a/miniwin/src/d3drm/d3drmrenderer.cpp +++ b/miniwin/src/d3drm/d3drmrenderer.cpp @@ -49,7 +49,7 @@ Direct3DRMRenderer* CreateDirect3DRMRenderer( #endif #ifdef USE_OPENGLES2 if (SDL_memcmp(guid, &OpenGLES2_GUID, sizeof(GUID)) == 0) { - return OpenGLES2Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight); + return OpenGLES2Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight, d3d->GetAnisotropic()); } #endif #ifdef USE_OPENGL1 @@ -79,7 +79,7 @@ void Direct3DRMRenderer_EnumDevices(const IDirect3DMiniwin* d3d, LPD3DENUMDEVICE OpenGLES3Renderer_EnumDevice(d3d, cb, ctx); #endif #ifdef USE_OPENGLES2 - OpenGLES2Renderer_EnumDevice(cb, ctx); + OpenGLES2Renderer_EnumDevice(d3d, cb, ctx); #endif #ifdef USE_OPENGL1 OpenGL1Renderer_EnumDevice(d3d, cb, ctx); diff --git a/miniwin/src/internal/d3drmrenderer_opengles2.h b/miniwin/src/internal/d3drmrenderer_opengles2.h index a0e97691..6a95d73f 100644 --- a/miniwin/src/internal/d3drmrenderer_opengles2.h +++ b/miniwin/src/internal/d3drmrenderer_opengles2.h @@ -32,8 +32,8 @@ struct GLES2MeshCacheEntry { class OpenGLES2Renderer : public Direct3DRMRenderer { public: - static Direct3DRMRenderer* Create(DWORD width, DWORD height); - OpenGLES2Renderer(DWORD width, DWORD height, SDL_GLContext context, GLuint shaderProgram); + static Direct3DRMRenderer* Create(DWORD width, DWORD height, float anisotropic); + OpenGLES2Renderer(DWORD width, DWORD height, float anisotropic, SDL_GLContext context, GLuint shaderProgram); ~OpenGLES2Renderer() override; void PushLights(const SceneLight* lightsArray, size_t count) override; @@ -62,6 +62,7 @@ class OpenGLES2Renderer : public Direct3DRMRenderer { private: void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture); void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh); + bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI); MeshGroup m_uiMesh; GLES2MeshCacheEntry m_uiMeshCache; @@ -72,6 +73,7 @@ class OpenGLES2Renderer : public Direct3DRMRenderer { bool m_dirty = false; std::vector m_lights; SDL_GLContext m_context; + float m_anisotropic; GLuint m_fbo; GLuint m_colorTarget; GLuint m_depthTarget; @@ -92,9 +94,9 @@ class OpenGLES2Renderer : public Direct3DRMRenderer { ViewportTransform m_viewportTransform; }; -inline static void OpenGLES2Renderer_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx) +inline static void OpenGLES2Renderer_EnumDevice(const IDirect3DMiniwin* d3d, LPD3DENUMDEVICESCALLBACK cb, void* ctx) { - Direct3DRMRenderer* device = OpenGLES2Renderer::Create(640, 480); + Direct3DRMRenderer* device = OpenGLES2Renderer::Create(640, 480, d3d->GetAnisotropic()); if (!device) { return; }