1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-02 09:03:37 +00:00

Mip-mapping!

This commit is contained in:
Sergey Lipskiy 2014-10-09 16:01:04 +07:00
parent a8021084f2
commit e4fa0b5717
4 changed files with 291 additions and 163 deletions

View File

@ -15,7 +15,7 @@
static GLuint g_vertex_shader_object;
static GLuint g_calc_light_shader_object;
static GLuint g_calc_lod_shader_object;
static GLuint g_calc_mipmap_shader_object;
static GLuint g_calc_noise_shader_object;
static GLuint g_calc_depth_shader_object;
static GLuint g_test_alpha_shader_object;
@ -179,10 +179,10 @@ void InitShaderCombiner()
glCompileShader(g_calc_light_shader_object);
assert(check_shader_compile_status(g_calc_light_shader_object));
g_calc_lod_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(g_calc_lod_shader_object, 1, &fragment_shader_calc_lod, NULL);
glCompileShader(g_calc_lod_shader_object);
assert(check_shader_compile_status(g_calc_lod_shader_object));
g_calc_mipmap_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(g_calc_mipmap_shader_object, 1, &fragment_shader_mipmap, NULL);
glCompileShader(g_calc_mipmap_shader_object);
assert(check_shader_compile_status(g_calc_mipmap_shader_object));
g_calc_noise_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(g_calc_noise_shader_object, 1, &noise_fragment_shader, NULL);
@ -215,8 +215,8 @@ void DestroyShaderCombiner() {
#ifndef GLES2
glDeleteShader(g_calc_light_shader_object);
g_calc_light_shader_object = 0;
glDeleteShader(g_calc_lod_shader_object);
g_calc_lod_shader_object = 0;
glDeleteShader(g_calc_mipmap_shader_object);
g_calc_mipmap_shader_object = 0;
glDeleteShader(g_calc_noise_shader_object);
g_calc_noise_shader_object = 0;
glDeleteShader(g_test_alpha_shader_object);
@ -385,21 +385,32 @@ ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCo
strFragmentShader.append(fragment_shader_header_common_functions);
strFragmentShader.append(fragment_shader_header_main);
const bool bUseLod = (m_nInputs & (1<<LOD_FRACTION)) > 0;
if (bUseLod)
if (bUseLod) {
#ifdef GLES2
strBuffer.append(" lowp float lod_frac = calc_lod(uPrimLod, vLodTexCoord); \n");
strFragmentShader.append(" lowp vec4 readtex0, readtex1; \n");
strFragmentShader.append(" lowp float lod_frac = mipmap(readtex0, readtex1); \n");
#else
strFragmentShader.append(" float lod_frac = calc_lod(uPrimLod, vLodTexCoord); \n");
strFragmentShader.append(" vec4 readtex0, readtex1; \n");
strFragmentShader.append(" float lod_frac = mipmap(readtex0, readtex1); \n");
#endif
if ((m_nInputs & ((1<<TEXEL0)|(1<<TEXEL1)|(1<<TEXEL0_ALPHA)|(1<<TEXEL1_ALPHA))) > 0) {
strFragmentShader.append(fragment_shader_readtex0color);
strFragmentShader.append(fragment_shader_readtex1color);
} else {
assert(strstr(strCombiner, "readtex") == 0);
if (_alpha.numStages == 1 && _color.numStages == 1) {
if ((m_nInputs & ((1 << TEXEL0) | (1 << TEXEL0_ALPHA))) > 0)
strFragmentShader.append(fragment_shader_readtex0color);
if ((m_nInputs & ((1 << TEXEL1) | (1 << TEXEL1_ALPHA))) > 0)
strFragmentShader.append(fragment_shader_readtex1color);
} else {
if ((m_nInputs & ((1 << TEXEL0) | (1 << TEXEL1) | (1 << TEXEL0_ALPHA) | (1 << TEXEL1_ALPHA))) > 0) {
strFragmentShader.append(fragment_shader_readtex0color);
strFragmentShader.append(fragment_shader_readtex1color);
} else {
assert(strstr(strCombiner, "readtex") == 0);
}
}
}
if (config.enableHWLighting)
#ifdef GLES2
strBuffer.append(" lowp float intensity = calc_light(int(vNumLights), vShadeColor.rgb, input_color); \n");
strFragmentShader.append(" lowp float intensity = calc_light(int(vNumLights), vShadeColor.rgb, input_color); \n");
#else
strFragmentShader.append(" float intensity = calc_light(int(vNumLights), vShadeColor.rgb, input_color); \n");
#endif
@ -421,7 +432,7 @@ ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCo
}
#ifdef USE_TOONIFY
strBuffer.append(" toonify(intensity); \n");
strFragmentShader.append(" toonify(intensity); \n");
#endif
strFragmentShader.append(" if (uEnableFog != 0) \n");
strFragmentShader.append(" gl_FragColor = vec4(mix(gl_FragColor.rgb, uFogColor.rgb, vFogFragCoord), gl_FragColor.a); \n");
@ -433,12 +444,12 @@ ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCo
#endif
#ifdef GLES2
strBuffer.append(alpha_test_fragment_shader);
strBuffer.append(noise_fragment_shader);
strFragmentShader.append(alpha_test_fragment_shader);
strFragmentShader.append(noise_fragment_shader);
if (bUseLod)
strBuffer.append(fragment_shader_calc_lod);
strFragmentShader.append(fragment_shader_mipmap);
if (config.enableHWLighting)
strBuffer.append(fragment_shader_calc_light);
strFragmentShader.append(fragment_shader_calc_light);
#endif
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
@ -456,7 +467,7 @@ ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCo
if (config.enableHWLighting)
glAttachShader(m_program, g_calc_light_shader_object);
if (bUseLod)
glAttachShader(m_program, g_calc_lod_shader_object);
glAttachShader(m_program, g_calc_mipmap_shader_object);
glAttachShader(m_program, g_test_alpha_shader_object);
if (video().getRender().isImageTexturesSupported())
glAttachShader(m_program, g_calc_depth_shader_object);

206
Shaders.h
View File

@ -162,14 +162,14 @@ static const char* fragment_shader_header_common_functions =
" \n"
"lowp float snoise(in mediump vec2 v); \n"
"lowp float calc_light(in lowp int nLights, in lowp vec3 input_color, out lowp vec3 output_color);\n"
"lowp float calc_lod(in lowp float primLod, in mediump vec2 texCoord); \n"
"lowp float mipmap(out lowp vec4 readtex0, out lowp vec4 readtex1); \n"
"lowp bool depth_compare(); \n"
"lowp bool alpha_test(in lowp float alphaValue); \n"
#else
" \n"
"float snoise(in vec2 v); \n"
"float calc_light(in int nLights, in vec3 input_color, out vec3 output_color);\n"
"float calc_lod(in float primLod, in vec2 texCoord); \n"
"float mipmap(out vec4 readtex0, out vec4 readtex1); \n"
"bool depth_compare(); \n"
"bool alpha_test(in float alphaValue); \n"
#endif
@ -224,70 +224,6 @@ static const char* fragment_shader_calc_light =
#endif
;
static const char* fragment_shader_calc_lod =
#ifdef GLES2
"uniform lowp int uEnableLod; \n"
"uniform lowp float uLodXScale; \n"
"uniform lowp float uLodYScale; \n"
"uniform lowp float uMinLod; \n"
"uniform lowp int uMaxTile; \n"
"uniform lowp int uTextureDetail; \n"
" \n"
"lowp float calc_lod(in lowp float primLod, in mediump vec2 texCoord) { \n"
//" if (uEnableLod == 0) \n"
" return primLod; \n"
/*
" mediump vec2 dx = dFdx(texCoord); \n"
" dx.x *= uLodXScale; \n"
" dx.y *= uLodYScale; \n"
" mediump vec2 dy = dFdy(texCoord); \n"
" dy.x *= uLodXScale; \n"
" dy.y *= uLodYScale; \n"
" mediump float lod = max(length(dx), length(dy)); \n"
" lowp float lod_frac; \n"
" if (lod < 1.0) { \n"
" lod_frac = max(lod, uMinLod); \n"
" if (uTextureDetail == 1) \n"
" lod_frac = 1.0 - lod_frac; \n"
" } else { \n"
" lowp float tile = min(float(uMaxTile), floor(log2(floor(lod)))); \n"
" lod_frac = max(uMinLod, fract(lod/pow(2.0, tile)));\n"
" } \n"
" return lod_frac; \n"
*/
"} \n"
#else
"uniform int uEnableLod; \n"
"uniform float uLodXScale; \n"
"uniform float uLodYScale; \n"
"uniform float uMinLod; \n"
"uniform int uMaxTile; \n"
"uniform int uTextureDetail; \n"
" \n"
"float calc_lod(in float primLod, in vec2 texCoord) { \n"
" if (uEnableLod == 0) \n"
" return primLod; \n"
" vec2 dx = dFdx(texCoord); \n"
" dx.x *= uLodXScale; \n"
" dx.y *= uLodYScale; \n"
" vec2 dy = dFdy(texCoord); \n"
" dy.x *= uLodXScale; \n"
" dy.y *= uLodYScale; \n"
" float lod = max(length(dx), length(dy)); \n"
" float lod_frac; \n"
" if (lod < 1.0) { \n"
" lod_frac = max(lod, uMinLod); \n"
" if (uTextureDetail == 1) \n"
" lod_frac = 1.0 - lod_frac; \n"
" } else { \n"
" float tile = min(float(uMaxTile), floor(log2(floor(lod)))); \n"
" lod_frac = max(uMinLod, fract(lod/pow(2.0, tile)));\n"
" } \n"
" return lod_frac; \n"
"} \n"
#endif
;
static const char* alpha_test_fragment_shader =
#ifdef GLES2
"uniform lowp int uEnableAlphaTest; \n"
@ -393,6 +329,144 @@ static const char* fragment_shader_readtex1color =
" if (uFbFixedAlpha == 2 || uFbFixedAlpha == 3) readtex1.a = 0.825; \n"
;
static const char* fragment_shader_mipmap =
#ifdef GLES2
"uniform lowp int uEnableLod; \n"
"uniform lowp float uLodXScale; \n"
"uniform lowp float uLodYScale; \n"
"uniform lowp float uMinLod; \n"
"uniform lowp int uMaxTile; \n"
"uniform lowp int uTextureDetail; \n"
" \n"
"lowp float mipmap(out lowp vec4 readtex0, out lowp vec4 readtex1) { \n"
" if (uEnableLod == 0) { \n"
" readtex0 = texture2D(uTex0, vTexCoord0); \n"
" readtex1 = texture2D(uTex1, vTexCoord1); \n"
" return uPrimLod; \n"
" } \n"
" mediump vec2 dx = dFdx(vLodTexCoord); \n"
" dx.x *= uLodXScale; \n"
" dx.y *= uLodYScale; \n"
" mediump vec2 dy = dFdy(vLodTexCoord); \n"
" dy.x *= uLodXScale; \n"
" dy.y *= uLodYScale; \n"
" mediump float lod = max(length(dx), length(dy)); \n"
" lowp float lod_tile, lod_frac; \n"
" lowp bool magnifying; \n"
" if (lod < 1.0) { \n"
" magnifying = true; \n"
" lod_tile = 0.0; \n"
" lod_frac = lod; \n"
" if (uTextureDetail != 0) \n"
" lod_frac = max(lod, uMinLod); \n"
" if (uTextureDetail == 1) \n"
" lod_frac = 1.0 - lod_frac; \n"
" } else { \n"
" magnifying = false; \n"
" lod_tile = min(float(uMaxTile), floor(log2(floor(lod)))); \n"
" lod_frac = fract(lod/pow(2.0, lod_tile)); \n"
" } \n"
" if (lod_tile < 1.0) { \n"
" if (magnifying) { \n"
" readtex0 = texture2D(uTex0, vTexCoord0); \n"
// !sharpen && !detail
" if (uTextureDetail == 0) readtex1 = readtex0; \n"
" else readtex1 = texture2D(uTex1, vTexCoord1); \n"
" } else { \n"
// detail
" if (uTextureDetail == 2) { \n"
" readtex0 = texture2DLod(uTex1, vTexCoord1, 0.0);\n"
" readtex1 = texture2DLod(uTex1, vTexCoord1, 1.0);\n"
" } else { \n"
" readtex0 = texture2D(uTex0, vTexCoord0); \n"
" readtex1 = texture2D(uTex1, vTexCoord1); \n"
" } \n"
" } \n"
" } else { \n"
" if (uTextureDetail == 2) { \n"
" readtex0 = texture2DLod(uTex1, vTexCoord1, lod_tile); \n"
" readtex1 = texture2DLod(uTex1, vTexCoord1, lod_tile + 1.0); \n"
" } else { \n"
" readtex0 = texture2DLod(uTex1, vTexCoord1, lod_tile - 1.0); \n"
" readtex1 = texture2DLod(uTex1, vTexCoord1, lod_tile); \n"
" } \n"
" } \n"
" return lod_frac; \n"
"} \n"
"} \n"
#else
"varying vec2 vTexCoord0; \n"
"varying vec2 vTexCoord1; \n"
"varying vec2 vLodTexCoord; \n"
"uniform sampler2D uTex0; \n"
"uniform sampler2D uTex1; \n"
"uniform float uPrimLod; \n"
"uniform int uEnableLod; \n"
"uniform float uLodXScale; \n"
"uniform float uLodYScale; \n"
"uniform float uMinLod; \n"
"uniform int uMaxTile; \n"
"uniform int uTextureDetail; \n"
" \n"
"float mipmap(out vec4 readtex0, out vec4 readtex1) { \n"
" if (uEnableLod == 0) { \n"
" readtex0 = texture2D(uTex0, vTexCoord0); \n"
" readtex1 = texture2D(uTex1, vTexCoord1); \n"
" return uPrimLod; \n"
" } \n"
" vec2 dx = dFdx(vLodTexCoord); \n"
" dx.x *= uLodXScale; \n"
" dx.y *= uLodYScale; \n"
" vec2 dy = dFdy(vLodTexCoord); \n"
" dy.x *= uLodXScale; \n"
" dy.y *= uLodYScale; \n"
" float lod = max(length(dx), length(dy)); \n"
//" float lod = max(length(dx), length(dy)) * max(uLodXScale, uLodYScale);\n"
" float lod_tile, lod_frac; \n"
" bool magnifying; \n"
" if (lod < 1.0) { \n"
" magnifying = true; \n"
" lod_tile = 0.0; \n"
" lod_frac = lod; \n"
" if (uTextureDetail != 0) \n"
" lod_frac = max(lod, uMinLod); \n"
" if (uTextureDetail == 1) \n"
" lod_frac = 1.0 - lod_frac; \n"
" } else { \n"
" magnifying = false; \n"
" lod_tile = min(float(uMaxTile), floor(log2(floor(lod)))); \n"
" lod_frac = fract(lod/pow(2.0, lod_tile)); \n"
" } \n"
" if (lod_tile < 1.0) { \n"
" if (magnifying) { \n"
" readtex0 = texture2D(uTex0, vTexCoord0); \n"
// !sharpen && !detail
" if (uTextureDetail == 0) readtex1 = readtex0; \n"
" else readtex1 = texture2D(uTex1, vTexCoord1); \n"
" } else { \n"
// detail
" if (uTextureDetail == 2) { \n"
" readtex0 = texture2DLod(uTex1, vTexCoord1, 0.0);\n"
" readtex1 = texture2DLod(uTex1, vTexCoord1, 1.0);\n"
" } else { \n"
" readtex0 = texture2D(uTex0, vTexCoord0); \n"
" readtex1 = texture2D(uTex1, vTexCoord1); \n"
" } \n"
" } \n"
" } else { \n"
" if (uTextureDetail == 2) { \n"
" readtex0 = texture2DLod(uTex1, vTexCoord1, lod_tile); \n"
" readtex1 = texture2DLod(uTex1, vTexCoord1, lod_tile + 1.0); \n"
" } else { \n"
" readtex0 = texture2DLod(uTex1, vTexCoord1, lod_tile - 1.0); \n"
" readtex1 = texture2DLod(uTex1, vTexCoord1, lod_tile); \n"
" } \n"
" } \n"
" return lod_frac; \n"
"} \n"
#endif
;
static const char* fragment_shader_end =
"} \n"
#endif

View File

@ -389,7 +389,7 @@ void TextureCache::_loadBackground( CachedTexture *pTexture )
free(pDest);
}
void TextureCache::_load(CachedTexture *pTexture)
void TextureCache::_load(u32 _tile , CachedTexture *_pTexture)
{
u32 *pDest;
@ -400,13 +400,15 @@ void TextureCache::_load(CachedTexture *pTexture)
GetTexelFunc GetTexel;
GLuint glInternalFormat;
GLenum glType;
u32 sizeShift;
if (((imageFormat[pTexture->size][pTexture->format].autoFormat == GL_RGBA) ||
((pTexture->format == G_IM_FMT_CI) && (gDP.otherMode.textureLUT == G_TT_IA16)) || (m_bitDepth == 2)) && (m_bitDepth != 0))
if (((imageFormat[_pTexture->size][_pTexture->format].autoFormat == GL_RGBA) ||
((_pTexture->format == G_IM_FMT_CI) && (gDP.otherMode.textureLUT == G_TT_IA16)) || (m_bitDepth == 2)) && (m_bitDepth != 0))
{
pTexture->textureBytes = (pTexture->realWidth * pTexture->realHeight) << 2;
if ((pTexture->format == G_IM_FMT_CI) && (gDP.otherMode.textureLUT == G_TT_IA16)) {
if (pTexture->size == G_IM_SIZ_4b)
sizeShift = 2;
_pTexture->textureBytes = (_pTexture->realWidth * _pTexture->realHeight) << sizeShift;
if ((_pTexture->format == G_IM_FMT_CI) && (gDP.otherMode.textureLUT == G_TT_IA16)) {
if (_pTexture->size == G_IM_SIZ_4b)
GetTexel = GetCI4IA_RGBA8888;
else
GetTexel = GetCI8IA_RGBA8888;
@ -414,14 +416,15 @@ void TextureCache::_load(CachedTexture *pTexture)
glInternalFormat = GL_RGBA;
glType = GL_UNSIGNED_BYTE;
} else {
GetTexel = imageFormat[pTexture->size][pTexture->format].Get32;
glInternalFormat = imageFormat[pTexture->size][pTexture->format].glInternalFormat32;
glType = imageFormat[pTexture->size][pTexture->format].glType32;
GetTexel = imageFormat[_pTexture->size][_pTexture->format].Get32;
glInternalFormat = imageFormat[_pTexture->size][_pTexture->format].glInternalFormat32;
glType = imageFormat[_pTexture->size][_pTexture->format].glType32;
}
} else {
pTexture->textureBytes = (pTexture->realWidth * pTexture->realHeight) << 1;
if ((pTexture->format == G_IM_FMT_CI) && (gDP.otherMode.textureLUT == G_TT_IA16)) {
if (pTexture->size == G_IM_SIZ_4b)
sizeShift = 1;
_pTexture->textureBytes = (_pTexture->realWidth * _pTexture->realHeight) << sizeShift;
if ((_pTexture->format == G_IM_FMT_CI) && (gDP.otherMode.textureLUT == G_TT_IA16)) {
if (_pTexture->size == G_IM_SIZ_4b)
GetTexel = GetCI4IA_RGBA4444;
else
GetTexel = GetCI8IA_RGBA4444;
@ -429,67 +432,101 @@ void TextureCache::_load(CachedTexture *pTexture)
glInternalFormat = GL_RGBA4;
glType = GL_UNSIGNED_SHORT_4_4_4_4;
} else {
GetTexel = imageFormat[pTexture->size][pTexture->format].Get16;
glInternalFormat = imageFormat[pTexture->size][pTexture->format].glInternalFormat16;
glType = imageFormat[pTexture->size][pTexture->format].glType16;
GetTexel = imageFormat[_pTexture->size][_pTexture->format].Get16;
glInternalFormat = imageFormat[_pTexture->size][_pTexture->format].glInternalFormat16;
glType = imageFormat[_pTexture->size][_pTexture->format].glType16;
}
}
pDest = (u32*)malloc( pTexture->textureBytes );
pDest = (u32*)malloc( _pTexture->textureBytes );
line = pTexture->line;
GLint mipLevel = 0, maxLevel = 0;
if (gSP.texture.level > 1)
maxLevel = _tile == 0 ? 0 : gSP.texture.level - 1;
if (pTexture->size == G_IM_SIZ_32b)
_pTexture->max_level = maxLevel;
CachedTexture tmptex(0);
memcpy(&tmptex, _pTexture, sizeof(CachedTexture));
line = tmptex.line;
if (tmptex.size == G_IM_SIZ_32b)
line <<= 1;
if (pTexture->maskS) {
clampSClamp = pTexture->clampS ? pTexture->clampWidth - 1 : (pTexture->mirrorS ? (pTexture->width << 1) - 1 : pTexture->width - 1);
maskSMask = (1 << pTexture->maskS) - 1;
mirrorSBit = pTexture->mirrorS ? 1 << pTexture->maskS : 0;
} else {
clampSClamp = min( pTexture->clampWidth, pTexture->width ) - 1;
maskSMask = 0xFFFF;
mirrorSBit = 0x0000;
}
if (pTexture->maskT) {
clampTClamp = pTexture->clampT ? pTexture->clampHeight - 1 : (pTexture->mirrorT ? (pTexture->height << 1) - 1: pTexture->height - 1);
maskTMask = (1 << pTexture->maskT) - 1;
mirrorTBit = pTexture->mirrorT ? 1 << pTexture->maskT : 0;
} else {
clampTClamp = min( pTexture->clampHeight, pTexture->height ) - 1;
maskTMask = 0xFFFF;
mirrorTBit = 0x0000;
}
// Hack for Zelda warp texture
if (((pTexture->tMem << 3) + (pTexture->width * pTexture->height << pTexture->size >> 1)) > 4096)
pTexture->tMem = 0;
j = 0;
for (y = 0; y < pTexture->realHeight; y++) {
ty = min(y, clampTClamp) & maskTMask;
if (y & mirrorTBit)
ty ^= maskTMask;
pSrc = &TMEM[pTexture->tMem] + line * ty;
i = (ty & 1) << 1;
for (x = 0; x < pTexture->realWidth; x++) {
tx = min(x, clampSClamp) & maskSMask;
if (x & mirrorSBit)
tx ^= maskSMask;
if (glInternalFormat == GL_RGBA)
((u32*)pDest)[j++] = GetTexel( pSrc, tx, i, pTexture->palette );
else
((u16*)pDest)[j++] = GetTexel( pSrc, tx, i, pTexture->palette );
while (true) {
if (tmptex.maskS > 0) {
clampSClamp = tmptex.clampS ? tmptex.clampWidth - 1 : (tmptex.mirrorS ? (tmptex.width << 1) - 1 : tmptex.width - 1);
maskSMask = (1 << tmptex.maskS) - 1;
mirrorSBit = tmptex.mirrorS ? 1 << tmptex.maskS : 0;
} else {
clampSClamp = min(tmptex.clampWidth, tmptex.width) - 1;
maskSMask = 0xFFFF;
mirrorSBit = 0x0000;
}
}
glTexImage2D( GL_TEXTURE_2D, 0, glInternalFormat, pTexture->realWidth, pTexture->realHeight, 0, GL_RGBA, glType, pDest );
if (tmptex.maskT > 0) {
clampTClamp = tmptex.clampT ? tmptex.clampHeight - 1 : (tmptex.mirrorT ? (tmptex.height << 1) - 1: tmptex.height - 1);
maskTMask = (1 << tmptex.maskT) - 1;
mirrorTBit = tmptex.mirrorT ? 1 << tmptex.maskT : 0;
} else {
clampTClamp = min( tmptex.clampHeight, tmptex.height ) - 1;
maskTMask = 0xFFFF;
mirrorTBit = 0x0000;
}
// Hack for Zelda warp texture
if (((tmptex.tMem << 3) + (tmptex.width * tmptex.height << tmptex.size >> 1)) > 4096)
tmptex.tMem = 0;
j = 0;
for (y = 0; y < tmptex.realHeight; y++) {
ty = min(y, clampTClamp) & maskTMask;
if (y & mirrorTBit)
ty ^= maskTMask;
pSrc = &TMEM[tmptex.tMem] + line * ty;
i = (ty & 1) << 1;
for (x = 0; x < tmptex.realWidth; x++) {
tx = min(x, clampSClamp) & maskSMask;
if (x & mirrorSBit)
tx ^= maskSMask;
if (glInternalFormat == GL_RGBA)
((u32*)pDest)[j++] = GetTexel( pSrc, tx, i, tmptex.palette );
else
((u16*)pDest)[j++] = GetTexel( pSrc, tx, i, tmptex.palette );
}
}
glTexImage2D(GL_TEXTURE_2D, mipLevel, glInternalFormat, tmptex.realWidth, tmptex.realHeight, 0, GL_RGBA, glType, pDest);
if (mipLevel == maxLevel)
break;
++mipLevel;
if (line > 1)
line >>= 1;
if (tmptex.maskS > 0)
--tmptex.maskS;
if (tmptex.clampWidth > 1)
tmptex.clampWidth >>= 1;
if (tmptex.width > 1)
tmptex.width >>= 1;
if (tmptex.realWidth > 1)
tmptex.realWidth >>= 1;
if (tmptex.maskT > 0)
--tmptex.maskT;
if (tmptex.clampHeight > 1)
tmptex.clampHeight >>= 1;
if (tmptex.height > 1)
tmptex.height >>= 1;
if (tmptex.realHeight > 1)
tmptex.realHeight >>= 1;
tmptex.tMem = gDP.tiles[gSP.texture.tile + mipLevel + 1].tmem;
tmptex.palette = gDP.tiles[gSP.texture.tile + mipLevel + 1].palette;
_pTexture->textureBytes += (tmptex.realWidth * tmptex.realHeight) << sizeShift;
};
free(pDest);
}
@ -550,18 +587,23 @@ void TextureCache::activateTexture(u32 _t, CachedTexture *_pTexture)
// Bind the cached texture
glBindTexture( GL_TEXTURE_2D, _pTexture->glName );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, _pTexture->max_level);
// Set filter mode. Almost always bilinear, but check anyways
if ((gDP.otherMode.textureFilter == G_TF_BILERP) || (gDP.otherMode.textureFilter == G_TF_AVERAGE) || (config.texture.forceBilinear))
{
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
}
else
{
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
if ((gDP.otherMode.textureFilter == G_TF_BILERP) || (gDP.otherMode.textureFilter == G_TF_AVERAGE) || (config.texture.forceBilinear)) {
if (_pTexture->max_level > 0)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
} else {
if (_pTexture->max_level > 0)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
// Set clamping modes
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, _pTexture->clampS ? GL_CLAMP_TO_EDGE : GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, _pTexture->clampT ? GL_CLAMP_TO_EDGE : GL_REPEAT );
@ -920,7 +962,7 @@ void TextureCache::update(u32 _t)
else if (gSP.textureTile[_t]->shiftt > 0)
pCurrent->shiftScaleT /= (f32)(1 << gSP.textureTile[_t]->shiftt);
_load( pCurrent );
_load( _t, pCurrent );
activateTexture( _t, pCurrent );
m_cachedBytes += pCurrent->textureBytes;

View File

@ -14,7 +14,7 @@
struct CachedTexture
{
CachedTexture(GLuint _glName) : glName(_glName) {}
CachedTexture(GLuint _glName) : glName(_glName), max_level(0) {}
GLuint glName;
u32 crc;
@ -39,6 +39,7 @@ struct CachedTexture
u32 lastDList;
u32 address;
u32 max_level;
};
@ -71,7 +72,7 @@ private:
void _checkCacheSize();
CachedTexture * _addTexture(u32 _crc32);
void _load(CachedTexture *pTexture);
void _load(u32 _tile, CachedTexture *_pTexture);
void _loadBackground(CachedTexture *pTexture);
void _updateBackground();