mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-07 03:13:49 +00:00
Mip-mapping!
This commit is contained in:
parent
a8021084f2
commit
e4fa0b5717
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
static GLuint g_vertex_shader_object;
|
static GLuint g_vertex_shader_object;
|
||||||
static GLuint g_calc_light_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_noise_shader_object;
|
||||||
static GLuint g_calc_depth_shader_object;
|
static GLuint g_calc_depth_shader_object;
|
||||||
static GLuint g_test_alpha_shader_object;
|
static GLuint g_test_alpha_shader_object;
|
||||||
|
@ -179,10 +179,10 @@ void InitShaderCombiner()
|
||||||
glCompileShader(g_calc_light_shader_object);
|
glCompileShader(g_calc_light_shader_object);
|
||||||
assert(check_shader_compile_status(g_calc_light_shader_object));
|
assert(check_shader_compile_status(g_calc_light_shader_object));
|
||||||
|
|
||||||
g_calc_lod_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
|
g_calc_mipmap_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
glShaderSource(g_calc_lod_shader_object, 1, &fragment_shader_calc_lod, NULL);
|
glShaderSource(g_calc_mipmap_shader_object, 1, &fragment_shader_mipmap, NULL);
|
||||||
glCompileShader(g_calc_lod_shader_object);
|
glCompileShader(g_calc_mipmap_shader_object);
|
||||||
assert(check_shader_compile_status(g_calc_lod_shader_object));
|
assert(check_shader_compile_status(g_calc_mipmap_shader_object));
|
||||||
|
|
||||||
g_calc_noise_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
|
g_calc_noise_shader_object = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
glShaderSource(g_calc_noise_shader_object, 1, &noise_fragment_shader, NULL);
|
glShaderSource(g_calc_noise_shader_object, 1, &noise_fragment_shader, NULL);
|
||||||
|
@ -215,8 +215,8 @@ void DestroyShaderCombiner() {
|
||||||
#ifndef GLES2
|
#ifndef GLES2
|
||||||
glDeleteShader(g_calc_light_shader_object);
|
glDeleteShader(g_calc_light_shader_object);
|
||||||
g_calc_light_shader_object = 0;
|
g_calc_light_shader_object = 0;
|
||||||
glDeleteShader(g_calc_lod_shader_object);
|
glDeleteShader(g_calc_mipmap_shader_object);
|
||||||
g_calc_lod_shader_object = 0;
|
g_calc_mipmap_shader_object = 0;
|
||||||
glDeleteShader(g_calc_noise_shader_object);
|
glDeleteShader(g_calc_noise_shader_object);
|
||||||
g_calc_noise_shader_object = 0;
|
g_calc_noise_shader_object = 0;
|
||||||
glDeleteShader(g_test_alpha_shader_object);
|
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_common_functions);
|
||||||
strFragmentShader.append(fragment_shader_header_main);
|
strFragmentShader.append(fragment_shader_header_main);
|
||||||
const bool bUseLod = (m_nInputs & (1<<LOD_FRACTION)) > 0;
|
const bool bUseLod = (m_nInputs & (1<<LOD_FRACTION)) > 0;
|
||||||
if (bUseLod)
|
if (bUseLod) {
|
||||||
#ifdef GLES2
|
#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
|
#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
|
#endif
|
||||||
if ((m_nInputs & ((1<<TEXEL0)|(1<<TEXEL1)|(1<<TEXEL0_ALPHA)|(1<<TEXEL1_ALPHA))) > 0) {
|
} else {
|
||||||
|
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_readtex0color);
|
||||||
strFragmentShader.append(fragment_shader_readtex1color);
|
strFragmentShader.append(fragment_shader_readtex1color);
|
||||||
} else {
|
} else {
|
||||||
assert(strstr(strCombiner, "readtex") == 0);
|
assert(strstr(strCombiner, "readtex") == 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (config.enableHWLighting)
|
if (config.enableHWLighting)
|
||||||
#ifdef GLES2
|
#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
|
#else
|
||||||
strFragmentShader.append(" float intensity = calc_light(int(vNumLights), vShadeColor.rgb, input_color); \n");
|
strFragmentShader.append(" float intensity = calc_light(int(vNumLights), vShadeColor.rgb, input_color); \n");
|
||||||
#endif
|
#endif
|
||||||
|
@ -421,7 +432,7 @@ ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCo
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_TOONIFY
|
#ifdef USE_TOONIFY
|
||||||
strBuffer.append(" toonify(intensity); \n");
|
strFragmentShader.append(" toonify(intensity); \n");
|
||||||
#endif
|
#endif
|
||||||
strFragmentShader.append(" if (uEnableFog != 0) \n");
|
strFragmentShader.append(" if (uEnableFog != 0) \n");
|
||||||
strFragmentShader.append(" gl_FragColor = vec4(mix(gl_FragColor.rgb, uFogColor.rgb, vFogFragCoord), gl_FragColor.a); \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
|
#endif
|
||||||
|
|
||||||
#ifdef GLES2
|
#ifdef GLES2
|
||||||
strBuffer.append(alpha_test_fragment_shader);
|
strFragmentShader.append(alpha_test_fragment_shader);
|
||||||
strBuffer.append(noise_fragment_shader);
|
strFragmentShader.append(noise_fragment_shader);
|
||||||
if (bUseLod)
|
if (bUseLod)
|
||||||
strBuffer.append(fragment_shader_calc_lod);
|
strFragmentShader.append(fragment_shader_mipmap);
|
||||||
if (config.enableHWLighting)
|
if (config.enableHWLighting)
|
||||||
strBuffer.append(fragment_shader_calc_light);
|
strFragmentShader.append(fragment_shader_calc_light);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
@ -456,7 +467,7 @@ ShaderCombiner::ShaderCombiner(Combiner & _color, Combiner & _alpha, const gDPCo
|
||||||
if (config.enableHWLighting)
|
if (config.enableHWLighting)
|
||||||
glAttachShader(m_program, g_calc_light_shader_object);
|
glAttachShader(m_program, g_calc_light_shader_object);
|
||||||
if (bUseLod)
|
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);
|
glAttachShader(m_program, g_test_alpha_shader_object);
|
||||||
if (video().getRender().isImageTexturesSupported())
|
if (video().getRender().isImageTexturesSupported())
|
||||||
glAttachShader(m_program, g_calc_depth_shader_object);
|
glAttachShader(m_program, g_calc_depth_shader_object);
|
||||||
|
|
206
Shaders.h
206
Shaders.h
|
@ -162,14 +162,14 @@ static const char* fragment_shader_header_common_functions =
|
||||||
" \n"
|
" \n"
|
||||||
"lowp float snoise(in mediump vec2 v); \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_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 depth_compare(); \n"
|
||||||
"lowp bool alpha_test(in lowp float alphaValue); \n"
|
"lowp bool alpha_test(in lowp float alphaValue); \n"
|
||||||
#else
|
#else
|
||||||
" \n"
|
" \n"
|
||||||
"float snoise(in vec2 v); \n"
|
"float snoise(in vec2 v); \n"
|
||||||
"float calc_light(in int nLights, in vec3 input_color, out vec3 output_color);\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 depth_compare(); \n"
|
||||||
"bool alpha_test(in float alphaValue); \n"
|
"bool alpha_test(in float alphaValue); \n"
|
||||||
#endif
|
#endif
|
||||||
|
@ -224,70 +224,6 @@ static const char* fragment_shader_calc_light =
|
||||||
#endif
|
#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 =
|
static const char* alpha_test_fragment_shader =
|
||||||
#ifdef GLES2
|
#ifdef GLES2
|
||||||
"uniform lowp int uEnableAlphaTest; \n"
|
"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"
|
" 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 =
|
static const char* fragment_shader_end =
|
||||||
"} \n"
|
"} \n"
|
||||||
#endif
|
#endif
|
||||||
|
|
132
Textures.cpp
132
Textures.cpp
|
@ -389,7 +389,7 @@ void TextureCache::_loadBackground( CachedTexture *pTexture )
|
||||||
free(pDest);
|
free(pDest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::_load(CachedTexture *pTexture)
|
void TextureCache::_load(u32 _tile , CachedTexture *_pTexture)
|
||||||
{
|
{
|
||||||
u32 *pDest;
|
u32 *pDest;
|
||||||
|
|
||||||
|
@ -400,13 +400,15 @@ void TextureCache::_load(CachedTexture *pTexture)
|
||||||
GetTexelFunc GetTexel;
|
GetTexelFunc GetTexel;
|
||||||
GLuint glInternalFormat;
|
GLuint glInternalFormat;
|
||||||
GLenum glType;
|
GLenum glType;
|
||||||
|
u32 sizeShift;
|
||||||
|
|
||||||
if (((imageFormat[pTexture->size][pTexture->format].autoFormat == GL_RGBA) ||
|
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->format == G_IM_FMT_CI) && (gDP.otherMode.textureLUT == G_TT_IA16)) || (m_bitDepth == 2)) && (m_bitDepth != 0))
|
||||||
{
|
{
|
||||||
pTexture->textureBytes = (pTexture->realWidth * pTexture->realHeight) << 2;
|
sizeShift = 2;
|
||||||
if ((pTexture->format == G_IM_FMT_CI) && (gDP.otherMode.textureLUT == G_TT_IA16)) {
|
_pTexture->textureBytes = (_pTexture->realWidth * _pTexture->realHeight) << sizeShift;
|
||||||
if (pTexture->size == G_IM_SIZ_4b)
|
if ((_pTexture->format == G_IM_FMT_CI) && (gDP.otherMode.textureLUT == G_TT_IA16)) {
|
||||||
|
if (_pTexture->size == G_IM_SIZ_4b)
|
||||||
GetTexel = GetCI4IA_RGBA8888;
|
GetTexel = GetCI4IA_RGBA8888;
|
||||||
else
|
else
|
||||||
GetTexel = GetCI8IA_RGBA8888;
|
GetTexel = GetCI8IA_RGBA8888;
|
||||||
|
@ -414,14 +416,15 @@ void TextureCache::_load(CachedTexture *pTexture)
|
||||||
glInternalFormat = GL_RGBA;
|
glInternalFormat = GL_RGBA;
|
||||||
glType = GL_UNSIGNED_BYTE;
|
glType = GL_UNSIGNED_BYTE;
|
||||||
} else {
|
} else {
|
||||||
GetTexel = imageFormat[pTexture->size][pTexture->format].Get32;
|
GetTexel = imageFormat[_pTexture->size][_pTexture->format].Get32;
|
||||||
glInternalFormat = imageFormat[pTexture->size][pTexture->format].glInternalFormat32;
|
glInternalFormat = imageFormat[_pTexture->size][_pTexture->format].glInternalFormat32;
|
||||||
glType = imageFormat[pTexture->size][pTexture->format].glType32;
|
glType = imageFormat[_pTexture->size][_pTexture->format].glType32;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pTexture->textureBytes = (pTexture->realWidth * pTexture->realHeight) << 1;
|
sizeShift = 1;
|
||||||
if ((pTexture->format == G_IM_FMT_CI) && (gDP.otherMode.textureLUT == G_TT_IA16)) {
|
_pTexture->textureBytes = (_pTexture->realWidth * _pTexture->realHeight) << sizeShift;
|
||||||
if (pTexture->size == G_IM_SIZ_4b)
|
if ((_pTexture->format == G_IM_FMT_CI) && (gDP.otherMode.textureLUT == G_TT_IA16)) {
|
||||||
|
if (_pTexture->size == G_IM_SIZ_4b)
|
||||||
GetTexel = GetCI4IA_RGBA4444;
|
GetTexel = GetCI4IA_RGBA4444;
|
||||||
else
|
else
|
||||||
GetTexel = GetCI8IA_RGBA4444;
|
GetTexel = GetCI8IA_RGBA4444;
|
||||||
|
@ -429,67 +432,101 @@ void TextureCache::_load(CachedTexture *pTexture)
|
||||||
glInternalFormat = GL_RGBA4;
|
glInternalFormat = GL_RGBA4;
|
||||||
glType = GL_UNSIGNED_SHORT_4_4_4_4;
|
glType = GL_UNSIGNED_SHORT_4_4_4_4;
|
||||||
} else {
|
} else {
|
||||||
GetTexel = imageFormat[pTexture->size][pTexture->format].Get16;
|
GetTexel = imageFormat[_pTexture->size][_pTexture->format].Get16;
|
||||||
glInternalFormat = imageFormat[pTexture->size][pTexture->format].glInternalFormat16;
|
glInternalFormat = imageFormat[_pTexture->size][_pTexture->format].glInternalFormat16;
|
||||||
glType = imageFormat[pTexture->size][pTexture->format].glType16;
|
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;
|
line <<= 1;
|
||||||
|
|
||||||
if (pTexture->maskS) {
|
while (true) {
|
||||||
clampSClamp = pTexture->clampS ? pTexture->clampWidth - 1 : (pTexture->mirrorS ? (pTexture->width << 1) - 1 : pTexture->width - 1);
|
if (tmptex.maskS > 0) {
|
||||||
maskSMask = (1 << pTexture->maskS) - 1;
|
clampSClamp = tmptex.clampS ? tmptex.clampWidth - 1 : (tmptex.mirrorS ? (tmptex.width << 1) - 1 : tmptex.width - 1);
|
||||||
mirrorSBit = pTexture->mirrorS ? 1 << pTexture->maskS : 0;
|
maskSMask = (1 << tmptex.maskS) - 1;
|
||||||
|
mirrorSBit = tmptex.mirrorS ? 1 << tmptex.maskS : 0;
|
||||||
} else {
|
} else {
|
||||||
clampSClamp = min( pTexture->clampWidth, pTexture->width ) - 1;
|
clampSClamp = min(tmptex.clampWidth, tmptex.width) - 1;
|
||||||
maskSMask = 0xFFFF;
|
maskSMask = 0xFFFF;
|
||||||
mirrorSBit = 0x0000;
|
mirrorSBit = 0x0000;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pTexture->maskT) {
|
if (tmptex.maskT > 0) {
|
||||||
clampTClamp = pTexture->clampT ? pTexture->clampHeight - 1 : (pTexture->mirrorT ? (pTexture->height << 1) - 1: pTexture->height - 1);
|
clampTClamp = tmptex.clampT ? tmptex.clampHeight - 1 : (tmptex.mirrorT ? (tmptex.height << 1) - 1: tmptex.height - 1);
|
||||||
maskTMask = (1 << pTexture->maskT) - 1;
|
maskTMask = (1 << tmptex.maskT) - 1;
|
||||||
mirrorTBit = pTexture->mirrorT ? 1 << pTexture->maskT : 0;
|
mirrorTBit = tmptex.mirrorT ? 1 << tmptex.maskT : 0;
|
||||||
} else {
|
} else {
|
||||||
clampTClamp = min( pTexture->clampHeight, pTexture->height ) - 1;
|
clampTClamp = min( tmptex.clampHeight, tmptex.height ) - 1;
|
||||||
maskTMask = 0xFFFF;
|
maskTMask = 0xFFFF;
|
||||||
mirrorTBit = 0x0000;
|
mirrorTBit = 0x0000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hack for Zelda warp texture
|
// Hack for Zelda warp texture
|
||||||
if (((pTexture->tMem << 3) + (pTexture->width * pTexture->height << pTexture->size >> 1)) > 4096)
|
if (((tmptex.tMem << 3) + (tmptex.width * tmptex.height << tmptex.size >> 1)) > 4096)
|
||||||
pTexture->tMem = 0;
|
tmptex.tMem = 0;
|
||||||
|
|
||||||
j = 0;
|
j = 0;
|
||||||
for (y = 0; y < pTexture->realHeight; y++) {
|
for (y = 0; y < tmptex.realHeight; y++) {
|
||||||
ty = min(y, clampTClamp) & maskTMask;
|
ty = min(y, clampTClamp) & maskTMask;
|
||||||
|
|
||||||
if (y & mirrorTBit)
|
if (y & mirrorTBit)
|
||||||
ty ^= maskTMask;
|
ty ^= maskTMask;
|
||||||
|
|
||||||
pSrc = &TMEM[pTexture->tMem] + line * ty;
|
pSrc = &TMEM[tmptex.tMem] + line * ty;
|
||||||
|
|
||||||
i = (ty & 1) << 1;
|
i = (ty & 1) << 1;
|
||||||
for (x = 0; x < pTexture->realWidth; x++) {
|
for (x = 0; x < tmptex.realWidth; x++) {
|
||||||
tx = min(x, clampSClamp) & maskSMask;
|
tx = min(x, clampSClamp) & maskSMask;
|
||||||
|
|
||||||
if (x & mirrorSBit)
|
if (x & mirrorSBit)
|
||||||
tx ^= maskSMask;
|
tx ^= maskSMask;
|
||||||
|
|
||||||
if (glInternalFormat == GL_RGBA)
|
if (glInternalFormat == GL_RGBA)
|
||||||
((u32*)pDest)[j++] = GetTexel( pSrc, tx, i, pTexture->palette );
|
((u32*)pDest)[j++] = GetTexel( pSrc, tx, i, tmptex.palette );
|
||||||
else
|
else
|
||||||
((u16*)pDest)[j++] = GetTexel( pSrc, tx, i, pTexture->palette );
|
((u16*)pDest)[j++] = GetTexel( pSrc, tx, i, tmptex.palette );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glTexImage2D( GL_TEXTURE_2D, 0, glInternalFormat, pTexture->realWidth, pTexture->realHeight, 0, GL_RGBA, glType, pDest );
|
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);
|
free(pDest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,18 +587,23 @@ void TextureCache::activateTexture(u32 _t, CachedTexture *_pTexture)
|
||||||
// Bind the cached texture
|
// Bind the cached texture
|
||||||
glBindTexture( GL_TEXTURE_2D, _pTexture->glName );
|
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
|
// 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))
|
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 );
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
|
} 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
|
// 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_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 );
|
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)
|
else if (gSP.textureTile[_t]->shiftt > 0)
|
||||||
pCurrent->shiftScaleT /= (f32)(1 << gSP.textureTile[_t]->shiftt);
|
pCurrent->shiftScaleT /= (f32)(1 << gSP.textureTile[_t]->shiftt);
|
||||||
|
|
||||||
_load( pCurrent );
|
_load( _t, pCurrent );
|
||||||
activateTexture( _t, pCurrent );
|
activateTexture( _t, pCurrent );
|
||||||
|
|
||||||
m_cachedBytes += pCurrent->textureBytes;
|
m_cachedBytes += pCurrent->textureBytes;
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
struct CachedTexture
|
struct CachedTexture
|
||||||
{
|
{
|
||||||
CachedTexture(GLuint _glName) : glName(_glName) {}
|
CachedTexture(GLuint _glName) : glName(_glName), max_level(0) {}
|
||||||
|
|
||||||
GLuint glName;
|
GLuint glName;
|
||||||
u32 crc;
|
u32 crc;
|
||||||
|
@ -39,6 +39,7 @@ struct CachedTexture
|
||||||
|
|
||||||
u32 lastDList;
|
u32 lastDList;
|
||||||
u32 address;
|
u32 address;
|
||||||
|
u32 max_level;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ private:
|
||||||
|
|
||||||
void _checkCacheSize();
|
void _checkCacheSize();
|
||||||
CachedTexture * _addTexture(u32 _crc32);
|
CachedTexture * _addTexture(u32 _crc32);
|
||||||
void _load(CachedTexture *pTexture);
|
void _load(u32 _tile, CachedTexture *_pTexture);
|
||||||
void _loadBackground(CachedTexture *pTexture);
|
void _loadBackground(CachedTexture *pTexture);
|
||||||
void _updateBackground();
|
void _updateBackground();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user