From 60a5ace16309ccd3d174a3ec14a1062540934066 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 21 Jan 2021 22:02:49 +0100 Subject: [PATCH] anisotropy plugin --- src/d3d/d3d8.cpp | 20 ++++++++---- src/d3d/d3ddevice.cpp | 23 ++++++++++--- src/gl/gl3device.cpp | 11 +++++-- src/gl/gl3raster.cpp | 7 ++-- src/gl/rwgl3.h | 2 ++ src/hanim.cpp | 3 +- src/rwbase.h | 1 + src/rwobjects.h | 7 ++++ src/texture.cpp | 76 +++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 133 insertions(+), 17 deletions(-) diff --git a/src/d3d/d3d8.cpp b/src/d3d/d3d8.cpp index de7ae29..78bef2d 100644 --- a/src/d3d/d3d8.cpp +++ b/src/d3d/d3d8.cpp @@ -471,6 +471,19 @@ readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format Raster *ras = nil; for(int i = 0; i < numLevels; i++){ + uint32 size = stream->readU32(); + + // don't read levels that don't exist + if(ras && i >= ras->getNumLevels()){ + stream->seek(size); + continue; + } + + // one allocation is enough, first level is largest + if(data == nil) + data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_IMAGE); + stream->read8(data, size); + if(ras){ ras->lock(i, Raster::LOCKWRITE|Raster::LOCKNOFETCH); img->width = ras->width; @@ -478,13 +491,6 @@ readAsImage(Stream *stream, int32 width, int32 height, int32 depth, int32 format img->stride = img->width*img->bpp; } - uint32 size = stream->readU32(); - // one allocation is enough, first level is largest - if(data == nil) - data = rwNewT(uint8, size, MEMDUR_FUNCTION | ID_IMAGE); - stream->read8(data, size); - - if(format & (Raster::PAL4 | Raster::PAL8)){ uint8 *idx = data; uint8 *pixels = img->pixels; diff --git a/src/d3d/d3ddevice.cpp b/src/d3d/d3ddevice.cpp index 8ff8e7a..e75ecf9 100644 --- a/src/d3d/d3ddevice.cpp +++ b/src/d3d/d3ddevice.cpp @@ -63,6 +63,7 @@ struct RwRasterStateCache { Texture::Addressing addressingU; Texture::Addressing addressingV; Texture::FilterMode filter; + int32 maxAniso; }; #define MAXNUMSTAGES 8 @@ -342,7 +343,10 @@ restoreD3d9Device(void) setSamplerState(i, D3DSAMP_ADDRESSU, addressConvMap[rwStateCache.texstage[i].addressingU]); setSamplerState(i, D3DSAMP_ADDRESSV, addressConvMap[rwStateCache.texstage[i].addressingV]); setSamplerState(i, D3DSAMP_MAGFILTER, filterConvMap[rwStateCache.texstage[i].filter]); - setSamplerState(i, D3DSAMP_MINFILTER, filterConvMap[rwStateCache.texstage[i].filter]); + if(rwStateCache.texstage[i].maxAniso == 1) + setSamplerState(i, D3DSAMP_MINFILTER, filterConvMap[rwStateCache.texstage[i].filter]); + else + setSamplerState(i, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC); setSamplerState(i, D3DSAMP_MIPFILTER, filterConvMap_MIP[rwStateCache.texstage[i].filter]); } for(s = 0; s < MAXNUMSTATES; s++) @@ -474,14 +478,25 @@ setRasterStage(uint32 stage, Raster *raster) } static void -setFilterMode(uint32 stage, int32 filter) +setFilterMode(uint32 stage, int32 filter, int32 maxAniso = 1) { if(rwStateCache.texstage[stage].filter != (Texture::FilterMode)filter){ rwStateCache.texstage[stage].filter = (Texture::FilterMode)filter; setSamplerState(stage, D3DSAMP_MAGFILTER, filterConvMap[filter]); - setSamplerState(stage, D3DSAMP_MINFILTER, filterConvMap[filter]); + if(maxAniso == 1) + setSamplerState(stage, D3DSAMP_MINFILTER, filterConvMap[filter]); + else + setSamplerState(stage, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC); setSamplerState(stage, D3DSAMP_MIPFILTER, filterConvMap_MIP[filter]); } + if(rwStateCache.texstage[stage].maxAniso != maxAniso){ + rwStateCache.texstage[stage].maxAniso = maxAniso; + if(maxAniso == 1) + setSamplerState(stage, D3DSAMP_MINFILTER, filterConvMap[filter]); + else + setSamplerState(stage, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC); + setSamplerState(stage, D3DSAMP_MAXANISOTROPY, maxAniso); + } } static void @@ -510,7 +525,7 @@ setTexture(uint32 stage, Texture *tex) return; } if(tex->raster){ - setFilterMode(stage, tex->getFilter()); + setFilterMode(stage, tex->getFilter(), tex->getMaxAnisotropy()); setAddressU(stage, tex->getAddressU()); setAddressV(stage, tex->getAddressV()); } diff --git a/src/gl/gl3device.cpp b/src/gl/gl3device.cpp index 90a3f35..53e31c4 100644 --- a/src/gl/gl3device.cpp +++ b/src/gl/gl3device.cpp @@ -527,7 +527,7 @@ static GLint addressConvMap[] = { }; static void -setFilterMode(uint32 stage, int32 filter) +setFilterMode(uint32 stage, int32 filter, int32 maxAniso = 1) { if(rwStateCache.texstage[stage].filter != (Texture::FilterMode)filter){ rwStateCache.texstage[stage].filter = (Texture::FilterMode)filter; @@ -545,6 +545,11 @@ setFilterMode(uint32 stage, int32 filter) } natras->filterMode = filter; } + if(natras->maxAnisotropy != maxAniso){ + setActiveTexture(stage); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)maxAniso); + natras->maxAnisotropy = maxAniso; + } } } } @@ -675,7 +680,7 @@ setTexture(int32 stage, Texture *tex) return; } setRasterStageOnly(stage, tex->raster); - setFilterMode(stage, tex->getFilter()); + setFilterMode(stage, tex->getFilter(), tex->getMaxAnisotropy()); setAddressU(stage, tex->getAddressU()); setAddressV(stage, tex->getAddressV()); } @@ -1787,6 +1792,8 @@ initOpenGL(void) // printf("%d %s\n", i, ext); } + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gl3Caps.maxAnisotropy); + if(gl3Caps.gles){ if(gl3Caps.glversion >= 30) shaderDecl = shaderDecl310es; diff --git a/src/gl/gl3raster.cpp b/src/gl/gl3raster.cpp index 2d84a53..db21a63 100644 --- a/src/gl/gl3raster.cpp +++ b/src/gl/gl3raster.cpp @@ -132,9 +132,7 @@ rasterCreateTexture(Raster *raster) natras->filterMode = 0; natras->addressU = 0; natras->addressV = 0; - -// TEST -// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 16.0f); + natras->maxAnisotropy = 1; bindTexture(prev); return raster; @@ -196,6 +194,7 @@ rasterCreateCameraTexture(Raster *raster) natras->filterMode = 0; natras->addressU = 0; natras->addressV = 0; + natras->maxAnisotropy = 1; bindTexture(prev); @@ -259,6 +258,7 @@ rasterCreateZbuffer(Raster *raster) natras->filterMode = 0; natras->addressU = 0; natras->addressV = 0; + natras->maxAnisotropy = 1; bindTexture(prev); } @@ -329,6 +329,7 @@ allocateDXT(Raster *raster, int32 dxt, int32 numLevels, bool32 hasAlpha) natras->filterMode = 0; natras->addressU = 0; natras->addressV = 0; + natras->maxAnisotropy = 1; bindTexture(prev); diff --git a/src/gl/rwgl3.h b/src/gl/rwgl3.h index b14b28c..93c1718 100644 --- a/src/gl/rwgl3.h +++ b/src/gl/rwgl3.h @@ -239,6 +239,7 @@ struct Gl3Raster uint8 filterMode; uint8 addressU; uint8 addressV; + int32 maxAnisotropy; uint32 fbo; // used for camera texture only! Raster *fboMate; // color or zbuffer raster mate of this one @@ -251,6 +252,7 @@ struct Gl3Caps int glversion; bool dxtSupported; bool astcSupported; // not used yet + float maxAnisotropy; }; extern Gl3Caps gl3Caps; // GLES can't read back textures very nicely. diff --git a/src/hanim.cpp b/src/hanim.cpp index 966c4be..6bc7c5e 100644 --- a/src/hanim.cpp +++ b/src/hanim.cpp @@ -408,6 +408,7 @@ registerHAnimPlugin(void) Frame::registerPluginStream(ID_HANIM, readHAnim, writeHAnim, - getSizeHAnim);} + getSizeHAnim); +} } diff --git a/src/rwbase.h b/src/rwbase.h index a65e4f1..d34ac27 100644 --- a/src/rwbase.h +++ b/src/rwbase.h @@ -592,6 +592,7 @@ enum PluginID ID_HANIM = MAKEPLUGINID(VEND_CRITERIONTK, 0x1E), ID_USERDATA = MAKEPLUGINID(VEND_CRITERIONTK, 0x1F), ID_MATFX = MAKEPLUGINID(VEND_CRITERIONTK, 0x20), + ID_ANISOT = MAKEPLUGINID(VEND_CRITERIONTK, 0x27), ID_PDS = MAKEPLUGINID(VEND_CRITERIONTK, 0x31), ID_ADC = MAKEPLUGINID(VEND_CRITERIONTK, 0x34), ID_UVANIMATION = MAKEPLUGINID(VEND_CRITERIONTK, 0x35), diff --git a/src/rwobjects.h b/src/rwobjects.h index 71e0518..2a85586 100644 --- a/src/rwobjects.h +++ b/src/rwobjects.h @@ -404,11 +404,18 @@ struct Texture static bool32 getMipmapping(void); static bool32 getAutoMipmapping(void); + void setMaxAnisotropy(int32 maxaniso); // only if plugin is attached + int32 getMaxAnisotropy(void); + #ifndef RWPUBLIC static void registerModule(void); #endif }; +extern int32 anisotOffset; +#define GETANISOTROPYEXT(texture) PLUGINOFFSET(int32, texture, rw::anisotOffset) +void registerAnisotropyPlugin(void); +int32 getMaxSupportedMaxAnisotropy(void); struct SurfaceProperties { diff --git a/src/texture.cpp b/src/texture.cpp index fcd9597..958ae08 100644 --- a/src/texture.cpp +++ b/src/texture.cpp @@ -3,6 +3,7 @@ #include #include +#define WITH_D3D #include "rwbase.h" #include "rwerror.h" #include "rwplg.h" @@ -14,6 +15,7 @@ #include "d3d/rwxbox.h" #include "d3d/rwd3d8.h" #include "d3d/rwd3d9.h" +#include "d3d/rwd3dimpl.h" #include "gl/rwgl3.h" #define PLUGIN_ID 0 @@ -517,4 +519,78 @@ Texture::streamGetSizeNative(void) return 0; } + + +int32 anisotOffset; + +static void* +createAnisot(void *object, int32 offset, int32) +{ + *GETANISOTROPYEXT(object) = 1; + return object; +} + +static void* +copyAnisot(void *dst, void *src, int32 offset, int32) +{ + *GETANISOTROPYEXT(dst) = *GETANISOTROPYEXT(src); + return dst; +} + +static Stream* +readAnisot(Stream *stream, int32, void *object, int32 offset, int32) +{ + *GETANISOTROPYEXT(object) = stream->readI32(); + return stream; +} + +static Stream* +writeAnisot(Stream *stream, int32, void *object, int32 offset, int32) +{ + stream->writeI32(*GETANISOTROPYEXT(object)); + return stream; +} + +static int32 +getSizeAnisot(void *object, int32 offset, int32) +{ + if(*GETANISOTROPYEXT(object) == 1) + return 0; + return sizeof(int32); +} + +void +registerAnisotropyPlugin(void) +{ + anisotOffset = Texture::registerPlugin(sizeof(int32), ID_ANISOT, createAnisot, nil, copyAnisot); + Texture::registerPluginStream(ID_ANISOT, readAnisot, writeAnisot, getSizeAnisot); +} + +void +Texture::setMaxAnisotropy(int32 maxaniso) +{ + if(anisotOffset > 0) + *GETANISOTROPYEXT(this) = maxaniso; +} + +int32 +Texture::getMaxAnisotropy(void) +{ + if(anisotOffset > 0) + return *GETANISOTROPYEXT(this); + return 1; +} + +int32 +getMaxSupportedMaxAnisotropy(void) +{ +#ifdef RW_D3D9 + return d3d::d3d9Globals.caps.MaxAnisotropy; +#endif +#ifdef RW_GL3 + return (int32)gl3::gl3Caps.maxAnisotropy; +#endif + return 1; +} + }