1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-04 10:03:36 +00:00

Add support for LOD with GLES2

This commit is contained in:
Francisco Zurita 2016-11-06 23:34:11 -05:00 committed by Sergey Lipskiy
parent d061ca044d
commit a48e1e37ca
4 changed files with 111 additions and 17 deletions

View File

@ -191,23 +191,29 @@ ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCo
if (bUseHWLight)
strFragmentShader.append(fragment_shader_calc_light);
if (bUseLod)
strFragmentShader.append(fragment_shader_fake_mipmap);
else if (usesTexture()) {
if (bUseLod) {
if (config.generalEmulation.enableLOD != 0)
strFragmentShader.append(fragment_shader_mipmap);
else
strFragmentShader.append(fragment_shader_fake_mipmap);
} else if (usesTexture()) {
if (config.texture.bilinearMode == BILINEAR_3POINT)
strFragmentShader.append(fragment_shader_readtex_3point);
else
strFragmentShader.append(fragment_shader_readtex);
}
if (config.generalEmulation.enableNoise != 0)
if (config.generalEmulation.enableNoise != 0) {
strFragmentShader.append(fragment_shader_noise);
}
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
const GLchar * strShaderData = strFragmentShader.data();
glShaderSource(fragmentShader, 1, &strShaderData, NULL);
glCompileShader(fragmentShader);
if (!checkShaderCompileStatus(fragmentShader))
LOG(LOG_ERROR, "Error in fragment shader:\n%s\n", strFragmentShader.data());
logErrorShader(GL_FRAGMENT_SHADER, strFragmentShader);
m_program = glCreateProgram();
_locate_attributes();
@ -251,6 +257,7 @@ void ShaderCombiner::_locateUniforms() {
LocateUniform(uFbMonochrome);
LocateUniform(uFbFixedAlpha);
LocateUniform(uMaxTile)
LocateUniform(uTextureDetail);
LocateUniform(uTexturePersp);
LocateUniform(uTextureFilterMode);
LocateUniform(uForceBlendCycle1);
@ -388,9 +395,20 @@ void ShaderCombiner::updateDitherMode(bool _bForce)
void ShaderCombiner::updateLOD(bool _bForce)
{
if (usesLOD()) {
m_uniforms.uMinLod.set(gDP.primColor.m, _bForce);
m_uniforms.uMaxTile.set(gSP.texture.level, _bForce);
if (!usesLOD())
return;
m_uniforms.uMinLod.set(gDP.primColor.m, _bForce);
m_uniforms.uMaxTile.set(gSP.texture.level, _bForce);
if (config.generalEmulation.enableLOD != 0) {
const int uCalcLOD = (gDP.otherMode.textureLOD == G_TL_LOD) ? 1 : 0;
m_uniforms.uEnableLod.set(uCalcLOD, _bForce);
if (config.frameBufferEmulation.nativeResFactor == 0)
m_uniforms.uScreenScale.set(video().getScaleX(), video().getScaleY(), _bForce);
else
m_uniforms.uScreenScale.set(float(config.frameBufferEmulation.nativeResFactor), float(config.frameBufferEmulation.nativeResFactor), _bForce);
m_uniforms.uTextureDetail.set(gDP.otherMode.textureDetail, _bForce);
}
}

View File

@ -1,4 +1,6 @@
#define SHADER_VERSION "#version 100 \n"
#define SHADER_VERSION "#version 100 \n" \
"#extension GL_EXT_shader_texture_lod : enable \n" \
"#extension GL_OES_standard_derivatives : enable \n"
static const char* vertex_shader =
SHADER_VERSION
@ -281,6 +283,75 @@ static const char* fragment_shader_end =
"} \n"
;
static const char* fragment_shader_mipmap =
"uniform lowp int uEnableLod; \n"
"uniform mediump float uMinLod; \n"
"uniform lowp int uMaxTile; \n"
"uniform lowp int uTextureDetail; \n"
" \n"
"mediump float mipmap(out lowp vec4 readtex0, out lowp vec4 readtex1) { \n"
" readtex0 = texture2D(uTex0, vTexCoord0); \n"
" readtex1 = texture2DLodEXT(uTex1, vTexCoord1, 0.0); \n"
" \n"
" mediump float fMaxTile = float(uMaxTile); \n"
#if 1
" mediump vec2 dx = abs(dFdx(vLodTexCoord)); \n"
" dx *= uScreenScale; \n"
" mediump float lod = max(dx.x, dx.y); \n"
#else
" mediump vec2 dx = dFdx(vLodTexCoord); \n"
" dx *= uScreenScale; \n"
" mediump vec2 dy = dFdy(vLodTexCoord); \n"
" dy *= uScreenScale; \n"
" mediump float lod = max(length(dx), length(dy)); \n"
#endif
" bool magnify = lod < 1.0; \n"
" mediump float lod_tile = magnify ? 0.0 : floor(log2(floor(lod))); \n"
" bool distant = lod > 128.0 || lod_tile >= fMaxTile; \n"
" mediump float lod_frac = fract(lod/pow(2.0, lod_tile)); \n"
" if (magnify) lod_frac = max(lod_frac, uMinLod); \n"
" if (uTextureDetail == 0) { \n"
" if (distant) lod_frac = 1.0; \n"
" else if (magnify) lod_frac = 0.0; \n"
" } \n"
" if (magnify && (uTextureDetail == 1 || uTextureDetail == 3)) \n"
" lod_frac = 1.0 - lod_frac; \n"
" if (uMaxTile == 0) { \n"
" if (uEnableLod != 0 && (uTextureDetail == 2 || uTextureDetail == 3)) \n"
" readtex1 = readtex0; \n"
" return lod_frac; \n"
" } \n"
" if (uEnableLod == 0) return lod_frac; \n"
" \n"
" lod_tile = min(lod_tile, fMaxTile); \n"
" lowp float lod_tile_m1 = max(0.0, lod_tile - 1.0); \n"
" lowp vec4 lodT = texture2DLodEXT(uTex1, vTexCoord1, lod_tile); \n"
" lowp vec4 lodT_m1 = texture2DLodEXT(uTex1, vTexCoord1, lod_tile_m1); \n"
" lowp vec4 lodT_p1 = texture2DLodEXT(uTex1, vTexCoord1, lod_tile + 1.0); \n"
" if (lod_tile < 1.0) { \n"
" if (magnify) { \n"
// !sharpen && !detail
" if (uTextureDetail == 0) readtex1 = readtex0; \n"
" } else { \n"
// detail
" if (uTextureDetail == 2 || uTextureDetail == 3) { \n"
" readtex0 = lodT; \n"
" readtex1 = lodT_p1; \n"
" } \n"
" } \n"
" } else { \n"
" if (uTextureDetail == 2 || uTextureDetail == 3) { \n"
" readtex0 = lodT; \n"
" readtex1 = lodT_p1; \n"
" } else { \n"
" readtex0 = lodT_m1; \n"
" readtex1 = lodT; \n"
" } \n"
" } \n"
" return lod_frac; \n"
"} \n"
;
static const char* fragment_shader_fake_mipmap =
"uniform lowp int uMaxTile; \n"
"uniform mediump float uMinLod; \n"

View File

@ -2102,6 +2102,13 @@ void OGLRender::_initExtensions()
} else
config.texture.maxAnisotropyF = 0.0f;
LOG(LOG_VERBOSE, "Max Anisotropy: %f\n", config.texture.maxAnisotropyF);
#ifdef GLES2
if(!OGLVideo::isExtensionSupported("GL_EXT_shader_texture_lod") ||
!OGLVideo::isExtensionSupported("GL_OES_standard_derivatives")) {
config.generalEmulation.enableLOD = 0;
}
#endif
}
void OGLRender::_initStates()

View File

@ -1066,13 +1066,11 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
pDest = (u32*)malloc(_pTexture->textureBytes);
assert(pDest != nullptr);
GLint mipLevel = 0, maxLevel = 0;
#ifndef GLES2
if (config.generalEmulation.enableLOD != 0 && gSP.texture.level > 1)
maxLevel = _tile == 0 ? 0 : gSP.texture.level - 1;
#endif
GLint mipLevel = 0;
_pTexture->max_level = 0;
_pTexture->max_level = maxLevel;
if (config.generalEmulation.enableLOD != 0 && gSP.texture.level > 1)
_pTexture->max_level = static_cast<u8>(_tile == 0 ? 0 : gSP.texture.level - 1);
CachedTexture tmptex(0);
memcpy(&tmptex, _pTexture, sizeof(CachedTexture));
@ -1099,7 +1097,7 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
bool bLoaded = false;
if ((config.textureFilter.txEnhancementMode | config.textureFilter.txFilterMode) != 0 &&
maxLevel == 0 &&
_pTexture->max_level == 0 &&
(config.textureFilter.txFilterIgnoreBG == 0 || (RSP.cmd != G_TEXRECT && RSP.cmd != G_TEXRECTFLIP)) &&
TFH.isInited())
{
@ -1135,7 +1133,7 @@ void TextureCache::_load(u32 _tile, CachedTexture *_pTexture)
tmptex.realHeight, 0, GL_RGBA, glType, pDest);
#endif
}
if (mipLevel == maxLevel)
if (mipLevel == _pTexture->max_level)
break;
++mipLevel;
const u32 tileMipLevel = gSP.texture.tile + mipLevel + 1;