Make Anisotropic filtering configurable (#641)

This commit is contained in:
Christian Semmler 2025-07-23 13:18:05 -07:00 committed by GitHub
parent a9db8d321e
commit 1a2e03de47
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 69 additions and 27 deletions

View File

@ -183,6 +183,7 @@ IsleApp::IsleApp()
m_frameRate = 100.0f; m_frameRate = 100.0f;
m_exclusiveFullScreen = FALSE; m_exclusiveFullScreen = FALSE;
m_msaaSamples = 0; m_msaaSamples = 0;
m_anisotropic = 0.0f;
} }
// FUNCTION: ISLE 0x4011a0 // FUNCTION: ISLE 0x4011a0
@ -1190,7 +1191,8 @@ bool IsleApp::LoadConfig()
} }
m_frameRate = (1000.0f / iniparser_getdouble(dict, "isle:Frame Delta", m_frameDelta)); m_frameRate = (1000.0f / iniparser_getdouble(dict, "isle:Frame Delta", m_frameDelta));
m_frameDelta = static_cast<int>(std::round(iniparser_getdouble(dict, "isle:Frame Delta", m_frameDelta))); m_frameDelta = static_cast<int>(std::round(iniparser_getdouble(dict, "isle:Frame Delta", m_frameDelta)));
m_videoParam.SetMSAASamples(iniparser_getint(dict, "isle:MSAA", m_msaaSamples)); m_videoParam.SetMSAASamples((m_msaaSamples = iniparser_getint(dict, "isle:MSAA", m_msaaSamples)));
m_videoParam.SetAnisotropic((m_anisotropic = iniparser_getdouble(dict, "isle:Anisotropic", m_anisotropic)));
const char* deviceId = iniparser_getstring(dict, "isle:3D Device ID", NULL); const char* deviceId = iniparser_getstring(dict, "isle:3D Device ID", NULL);
if (deviceId != NULL) { if (deviceId != NULL) {

View File

@ -115,6 +115,7 @@ class IsleApp {
MxFloat m_frameRate; MxFloat m_frameRate;
MxBool m_exclusiveFullScreen; MxBool m_exclusiveFullScreen;
MxU32 m_msaaSamples; MxU32 m_msaaSamples;
MxFloat m_anisotropic;
}; };
extern IsleApp* g_isle; extern IsleApp* g_isle;

View File

@ -81,6 +81,7 @@ BOOL MxDirect3D::Create(
#endif #endif
if (videoParam) { if (videoParam) {
miniwind3d->RequestMSAA(videoParam->GetMSAASamples()); miniwind3d->RequestMSAA(videoParam->GetMSAASamples());
miniwind3d->RequestAnisotropic(videoParam->GetAnisotropic());
} }
} }

View File

@ -238,6 +238,7 @@ BOOL MxDeviceEnumerate::EnumDirectDrawCallback(LPGUID p_guid, LPSTR p_driverDesc
#endif #endif
if (videoParam) { if (videoParam) {
miniwind3d->RequestMSAA(videoParam->GetMSAASamples()); miniwind3d->RequestMSAA(videoParam->GetMSAASamples());
miniwind3d->RequestAnisotropic(videoParam->GetAnisotropic());
} }
} }

View File

@ -56,6 +56,9 @@ class MxVideoParam {
void SetMSAASamples(MxU32 p_msaaSamples) { m_msaaSamples = p_msaaSamples; } void SetMSAASamples(MxU32 p_msaaSamples) { m_msaaSamples = p_msaaSamples; }
MxU32 GetMSAASamples() { return m_msaaSamples; } MxU32 GetMSAASamples() { return m_msaaSamples; }
void SetAnisotropic(MxFloat p_anisotropic) { m_anisotropic = p_anisotropic; }
MxFloat GetAnisotropic() { return m_anisotropic; }
private: private:
MxRect32 m_rect; // 0x00 MxRect32 m_rect; // 0x00
MxPalette* m_palette; // 0x10 MxPalette* m_palette; // 0x10
@ -64,6 +67,7 @@ class MxVideoParam {
int m_unk0x1c; // 0x1c int m_unk0x1c; // 0x1c
char* m_deviceId; // 0x20 char* m_deviceId; // 0x20
MxU32 m_msaaSamples; MxU32 m_msaaSamples;
MxFloat m_anisotropic;
}; };
#endif // MXVIDEOPARAM_H #endif // MXVIDEOPARAM_H

View File

@ -29,6 +29,7 @@ MxVideoParam::MxVideoParam(MxRect32& p_rect, MxPalette* p_palette, MxULong p_bac
m_unk0x1c = 0; m_unk0x1c = 0;
m_deviceId = NULL; m_deviceId = NULL;
m_msaaSamples = 0; m_msaaSamples = 0;
m_anisotropic = 0.0f;
} }
// FUNCTION: LEGO1 0x100becf0 // FUNCTION: LEGO1 0x100becf0
@ -43,6 +44,7 @@ MxVideoParam::MxVideoParam(MxVideoParam& p_videoParam)
m_deviceId = NULL; m_deviceId = NULL;
SetDeviceName(p_videoParam.m_deviceId); SetDeviceName(p_videoParam.m_deviceId);
m_msaaSamples = p_videoParam.m_msaaSamples; m_msaaSamples = p_videoParam.m_msaaSamples;
m_anisotropic = p_videoParam.m_anisotropic;
} }
// FUNCTION: LEGO1 0x100bed50 // FUNCTION: LEGO1 0x100bed50
@ -85,6 +87,7 @@ MxVideoParam& MxVideoParam::operator=(const MxVideoParam& p_videoParam)
m_unk0x1c = p_videoParam.m_unk0x1c; m_unk0x1c = p_videoParam.m_unk0x1c;
SetDeviceName(p_videoParam.m_deviceId); SetDeviceName(p_videoParam.m_deviceId);
m_msaaSamples = p_videoParam.m_msaaSamples; m_msaaSamples = p_videoParam.m_msaaSamples;
m_anisotropic = p_videoParam.m_anisotropic;
return *this; return *this;
} }

View File

@ -5,4 +5,6 @@ DEFINE_GUID(IID_IDirect3DMiniwin, 0xf8a97f2d, 0x9b3a, 0x4f1c, 0x9e, 0x8d, 0x6a,
struct IDirect3DMiniwin : virtual public IUnknown { struct IDirect3DMiniwin : virtual public IUnknown {
virtual HRESULT RequestMSAA(DWORD msaaSamples) = 0; virtual HRESULT RequestMSAA(DWORD msaaSamples) = 0;
virtual DWORD GetMSAASamples() const = 0; virtual DWORD GetMSAASamples() const = 0;
virtual HRESULT RequestAnisotropic(float anisotropic) = 0;
virtual float GetAnisotropic() const = 0;
}; };

View File

@ -37,7 +37,7 @@ struct SceneLightGLES3 {
float direction[4]; float direction[4];
}; };
Direct3DRMRenderer* OpenGLES3Renderer::Create(DWORD width, DWORD height, DWORD msaaSamples) Direct3DRMRenderer* OpenGLES3Renderer::Create(DWORD width, DWORD height, DWORD msaaSamples, float anisotropic)
{ {
// We have to reset the attributes here after having enumerated the // 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 // OpenGL ES 2.0 renderer, or else SDL gets very confused by SDL_GL_DEPTH_SIZE
@ -179,7 +179,7 @@ Direct3DRMRenderer* OpenGLES3Renderer::Create(DWORD width, DWORD height, DWORD m
glDeleteShader(vs); glDeleteShader(vs);
glDeleteShader(fs); glDeleteShader(fs);
return new OpenGLES3Renderer(width, height, msaaSamples, context, shaderProgram); return new OpenGLES3Renderer(width, height, msaaSamples, anisotropic, context, shaderProgram);
} }
GLES3MeshCacheEntry OpenGLES3Renderer::GLES3UploadMesh(const MeshGroup& meshGroup, bool forceUV) GLES3MeshCacheEntry OpenGLES3Renderer::GLES3UploadMesh(const MeshGroup& meshGroup, bool forceUV)
@ -259,7 +259,7 @@ GLES3MeshCacheEntry OpenGLES3Renderer::GLES3UploadMesh(const MeshGroup& meshGrou
return cache; return cache;
} }
bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI) bool OpenGLES3Renderer::UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI)
{ {
SDL_Surface* surf = source; SDL_Surface* surf = source;
if (source->format != SDL_PIXELFORMAT_RGBA32) { if (source->format != SDL_PIXELFORMAT_RGBA32) {
@ -284,11 +284,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_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (SDL_GL_ExtensionSupported("GL_EXT_texture_filter_anisotropic")) { if (m_anisotropic > 1.0f) {
GLfloat maxAniso = 0.0f; glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, m_anisotropic);
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso);
GLfloat desiredAniso = fminf(8.0f, maxAniso);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, desiredAniso);
} }
glGenerateMipmap(GL_TEXTURE_2D); glGenerateMipmap(GL_TEXTURE_2D);
} }
@ -304,10 +301,11 @@ OpenGLES3Renderer::OpenGLES3Renderer(
DWORD width, DWORD width,
DWORD height, DWORD height,
DWORD msaaSamples, DWORD msaaSamples,
float anisotropic,
SDL_GLContext context, SDL_GLContext context,
GLuint shaderProgram GLuint shaderProgram
) )
: m_context(context), m_shaderProgram(shaderProgram), m_msaa(msaaSamples) : m_context(context), m_shaderProgram(shaderProgram), m_msaa(msaaSamples), m_anisotropic(anisotropic)
{ {
glGenFramebuffers(1, &m_fbo); glGenFramebuffers(1, &m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
@ -329,6 +327,22 @@ OpenGLES3Renderer::OpenGLES3Renderer(
glGenFramebuffers(1, &m_resolveFBO); glGenFramebuffers(1, &m_resolveFBO);
} }
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_virtualWidth = width;
m_virtualHeight = height; m_virtualHeight = height;
ViewportTransform viewportTransform = {1.0f, 0.0f, 0.0f}; ViewportTransform viewportTransform = {1.0f, 0.0f, 0.0f};

View File

@ -36,7 +36,12 @@ Direct3DRMRenderer* CreateDirect3DRMRenderer(
#endif #endif
#ifdef USE_OPENGLES3 #ifdef USE_OPENGLES3
if (SDL_memcmp(guid, &OpenGLES3_GUID, sizeof(GUID)) == 0) { if (SDL_memcmp(guid, &OpenGLES3_GUID, sizeof(GUID)) == 0) {
return OpenGLES3Renderer::Create(DDSDesc.dwWidth, DDSDesc.dwHeight, d3d->GetMSAASamples()); return OpenGLES3Renderer::Create(
DDSDesc.dwWidth,
DDSDesc.dwHeight,
d3d->GetMSAASamples(),
d3d->GetAnisotropic()
);
} }
#endif #endif
#ifdef USE_OPENGL1 #ifdef USE_OPENGL1

View File

@ -331,17 +331,6 @@ HRESULT DirectDrawImpl::CreateDevice(
return DD_OK; return DD_OK;
} }
HRESULT DirectDrawImpl::RequestMSAA(DWORD msaaSamples)
{
m_msaaSamples = msaaSamples;
return DD_OK;
}
DWORD DirectDrawImpl::GetMSAASamples() const
{
return m_msaaSamples;
}
HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context) HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context)
{ {
const char* driverName = SDL_GetCurrentVideoDriver(); const char* driverName = SDL_GetCurrentVideoDriver();

View File

@ -33,8 +33,15 @@ struct GLES3MeshCacheEntry {
class OpenGLES3Renderer : public Direct3DRMRenderer { class OpenGLES3Renderer : public Direct3DRMRenderer {
public: public:
static Direct3DRMRenderer* Create(DWORD width, DWORD height, DWORD msaaSamples); static Direct3DRMRenderer* Create(DWORD width, DWORD height, DWORD msaaSamples, float anisotropic);
OpenGLES3Renderer(DWORD width, DWORD height, DWORD msaaSamples, SDL_GLContext context, GLuint shaderProgram); OpenGLES3Renderer(
DWORD width,
DWORD height,
DWORD msaaSamples,
float anisotropic,
SDL_GLContext context,
GLuint shaderProgram
);
~OpenGLES3Renderer() override; ~OpenGLES3Renderer() override;
void PushLights(const SceneLight* lightsArray, size_t count) override; void PushLights(const SceneLight* lightsArray, size_t count) override;
@ -64,6 +71,7 @@ class OpenGLES3Renderer : public Direct3DRMRenderer {
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture); void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh); void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
GLES3MeshCacheEntry GLES3UploadMesh(const MeshGroup& meshGroup, bool forceUV = false); GLES3MeshCacheEntry GLES3UploadMesh(const MeshGroup& meshGroup, bool forceUV = false);
bool UploadTexture(SDL_Surface* source, GLuint& outTexId, bool isUI);
MeshGroup m_uiMesh; MeshGroup m_uiMesh;
GLES3MeshCacheEntry m_uiMeshCache; GLES3MeshCacheEntry m_uiMeshCache;
@ -75,6 +83,7 @@ class OpenGLES3Renderer : public Direct3DRMRenderer {
std::vector<SceneLight> m_lights; std::vector<SceneLight> m_lights;
SDL_GLContext m_context; SDL_GLContext m_context;
uint32_t m_msaa; uint32_t m_msaa;
float m_anisotropic;
GLuint m_fbo; GLuint m_fbo;
GLuint m_resolveFBO; GLuint m_resolveFBO;
GLuint m_colorTarget; GLuint m_colorTarget;
@ -99,7 +108,7 @@ class OpenGLES3Renderer : public Direct3DRMRenderer {
inline static void OpenGLES3Renderer_EnumDevice(const IDirect3DMiniwin* d3d, LPD3DENUMDEVICESCALLBACK cb, void* ctx) inline static void OpenGLES3Renderer_EnumDevice(const IDirect3DMiniwin* d3d, LPD3DENUMDEVICESCALLBACK cb, void* ctx)
{ {
Direct3DRMRenderer* device = OpenGLES3Renderer::Create(640, 480, d3d->GetMSAASamples()); Direct3DRMRenderer* device = OpenGLES3Renderer::Create(640, 480, d3d->GetMSAASamples(), d3d->GetAnisotropic());
if (!device) { if (!device) {
return; return;
} }

View File

@ -47,14 +47,25 @@ struct DirectDrawImpl : public IDirectDraw2, public IDirect3D2, public IDirect3D
override; override;
HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx) override; HRESULT EnumDevices(LPD3DENUMDEVICESCALLBACK cb, void* ctx) override;
// IDirect3DMiniwin interface // IDirect3DMiniwin interface
HRESULT RequestMSAA(DWORD msaaSamples) override; HRESULT RequestMSAA(DWORD msaaSamples) override
DWORD GetMSAASamples() const override; {
m_msaaSamples = msaaSamples;
return DD_OK;
}
DWORD GetMSAASamples() const override { return m_msaaSamples; }
HRESULT RequestAnisotropic(float anisotropic) override
{
m_anisotropic = anisotropic;
return DD_OK;
}
float GetAnisotropic() const override { return m_anisotropic; }
private: private:
FrameBufferImpl* m_frameBuffer; FrameBufferImpl* m_frameBuffer;
int m_virtualWidth = 0; int m_virtualWidth = 0;
int m_virtualHeight = 0; int m_virtualHeight = 0;
DWORD m_msaaSamples = 0; DWORD m_msaaSamples = 0;
float m_anisotropic = 0.0f;
}; };
HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context); HRESULT DirectDrawEnumerate(LPDDENUMCALLBACKA cb, void* context);