calculate the LOD on CPU side and restrict mipmap levels for huge

textures to remove bad looking mipmap generations at high zoom levels
This commit is contained in:
Jupeyy 2017-10-09 18:58:44 +02:00
parent 43fa2fd1a7
commit 26bd800d63
7 changed files with 58 additions and 29 deletions

View file

@ -5,7 +5,7 @@ layout (location = 1) in vec2 inVertexTexCoord;
layout (location = 2) in ivec2 inVertexTexRightOrBottom; layout (location = 2) in ivec2 inVertexTexRightOrBottom;
uniform mat4x2 Pos; uniform mat4x2 Pos;
uniform float ZoomFactor; uniform float LOD;
uniform vec2 Dir; uniform vec2 Dir;
@ -18,8 +18,8 @@ void main()
VertPos.y += Dir.y * (gl_InstanceID+1); VertPos.y += Dir.y * (gl_InstanceID+1);
gl_Position = vec4(Pos * VertPos, 0.0, 1.0); gl_Position = vec4(Pos * VertPos, 0.0, 1.0);
float F1 = -(0.75/1024.0) * ZoomFactor; float F1 = -(0.5/(1024.0 * pow(0.5, (LOD+1.0))));
float F2 = (1.75/1024.0) * ZoomFactor; float F2 = (0.5/(1024.0 * pow(0.5, (LOD+1.0))));
float tx = (inVertexTexCoord.x/(16.0)) - (inVertexTexRightOrBottom.x == 0 ? 0.0 : (1.0/1024.0)); float tx = (inVertexTexCoord.x/(16.0)) - (inVertexTexRightOrBottom.x == 0 ? 0.0 : (1.0/1024.0));
float ty = (inVertexTexCoord.y/(16.0)) - (inVertexTexRightOrBottom.y == 0 ? 0.0 : (1.0/1024.0)); float ty = (inVertexTexCoord.y/(16.0)) - (inVertexTexRightOrBottom.y == 0 ? 0.0 : (1.0/1024.0));
texCoord = vec2(tx + (inVertexTexRightOrBottom.x == 0 ? F2 : F1), ty + (inVertexTexRightOrBottom.y == 0 ? F2 : F1)); texCoord = vec2(tx + (inVertexTexRightOrBottom.x == 0 ? F2 : F1), ty + (inVertexTexRightOrBottom.y == 0 ? F2 : F1));

View file

@ -5,7 +5,7 @@ layout (location = 1) in vec2 inVertexTexCoord;
layout (location = 2) in ivec2 inVertexTexRightOrBottom; layout (location = 2) in ivec2 inVertexTexRightOrBottom;
uniform mat4x2 Pos; uniform mat4x2 Pos;
uniform float ZoomFactor; uniform float LOD;
uniform vec2 Offset; uniform vec2 Offset;
uniform vec2 Dir; uniform vec2 Dir;
@ -22,8 +22,8 @@ void main()
VertPos.y += Offset.y + Dir.y * YCount; VertPos.y += Offset.y + Dir.y * YCount;
gl_Position = vec4(Pos * VertPos, 0.0, 1.0); gl_Position = vec4(Pos * VertPos, 0.0, 1.0);
float F1 = -(0.75/1024.0) * ZoomFactor; float F1 = -(0.5/(1024.0 * pow(0.5, (LOD+1.0))));
float F2 = (1.75/1024.0) * ZoomFactor; float F2 = (0.5/(1024.0 * pow(0.5, (LOD+1.0))));
float tx = (inVertexTexCoord.x/(16.0)) - (inVertexTexRightOrBottom.x == 0 ? 0.0 : (1.0/1024.0)); float tx = (inVertexTexCoord.x/(16.0)) - (inVertexTexRightOrBottom.x == 0 ? 0.0 : (1.0/1024.0));
float ty = (inVertexTexCoord.y/(16.0)) - (inVertexTexRightOrBottom.y == 0 ? 0.0 : (1.0/1024.0)); float ty = (inVertexTexCoord.y/(16.0)) - (inVertexTexRightOrBottom.y == 0 ? 0.0 : (1.0/1024.0));
texCoord = vec2(tx + (inVertexTexRightOrBottom.x == 0 ? F2 : F1), ty + (inVertexTexRightOrBottom.y == 0 ? F2 : F1)); texCoord = vec2(tx + (inVertexTexRightOrBottom.x == 0 ? F2 : F1), ty + (inVertexTexRightOrBottom.y == 0 ? F2 : F1));

View file

@ -5,16 +5,16 @@ layout (location = 1) in vec2 inVertexTexCoord;
layout (location = 2) in ivec2 inVertexTexRightOrBottom; layout (location = 2) in ivec2 inVertexTexRightOrBottom;
uniform mat4x2 Pos; uniform mat4x2 Pos;
uniform float ZoomFactor; uniform float LOD;
noperspective out vec2 texCoord; noperspective out vec2 texCoord;
void main() void main()
{ {
gl_Position = vec4(Pos * vec4(inVertex, 0.0, 1.0), 0.0, 1.0); gl_Position = vec4(Pos * vec4(inVertex, 0.0, 1.0), 0.0, 1.0);
float F1 = -(0.75/1024.0) * ZoomFactor; float F1 = -(0.5/(1024.0 * pow(0.5, (LOD+1.0))));
float F2 = (1.75/1024.0) * ZoomFactor; float F2 = (0.5/(1024.0 * pow(0.5, (LOD+1.0))));
float tx = (inVertexTexCoord.x/(16.0)) - (inVertexTexRightOrBottom.x == 0 ? 0.0 : (1.0/1024.0)); float tx = (inVertexTexCoord.x/(16.0));
float ty = (inVertexTexCoord.y/(16.0)) - (inVertexTexRightOrBottom.y == 0 ? 0.0 : (1.0/1024.0)); float ty = (inVertexTexCoord.y/(16.0));
texCoord = vec2(tx + (inVertexTexRightOrBottom.x == 0 ? F2 : F1), ty + (inVertexTexRightOrBottom.y == 0 ? F2 : F1)); texCoord = vec2(tx + (inVertexTexRightOrBottom.x == 0 ? F2 : F1), ty + (inVertexTexRightOrBottom.y == 0 ? F2 : F1));
} }

View file

@ -621,7 +621,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand
m_pTileProgram->m_LocIsTextured = -1; m_pTileProgram->m_LocIsTextured = -1;
m_pTileProgram->m_LocTextureSampler = -1; m_pTileProgram->m_LocTextureSampler = -1;
m_pTileProgram->m_LocColor = m_pTileProgram->GetUniformLoc("vertColor"); m_pTileProgram->m_LocColor = m_pTileProgram->GetUniformLoc("vertColor");
m_pTileProgram->m_LocZoomFactor = -1; m_pTileProgram->m_LocLOD = -1;
} }
{ {
CGLSL VertexShader; CGLSL VertexShader;
@ -640,7 +640,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand
m_pTileProgramTextured->m_LocIsTextured = -1; m_pTileProgramTextured->m_LocIsTextured = -1;
m_pTileProgramTextured->m_LocTextureSampler = m_pTileProgramTextured->GetUniformLoc("textureSampler"); m_pTileProgramTextured->m_LocTextureSampler = m_pTileProgramTextured->GetUniformLoc("textureSampler");
m_pTileProgramTextured->m_LocColor = m_pTileProgramTextured->GetUniformLoc("vertColor"); m_pTileProgramTextured->m_LocColor = m_pTileProgramTextured->GetUniformLoc("vertColor");
m_pTileProgramTextured->m_LocZoomFactor = m_pTileProgramTextured->GetUniformLoc("ZoomFactor"); m_pTileProgramTextured->m_LocLOD = m_pTileProgramTextured->GetUniformLoc("LOD");
} }
{ {
CGLSL VertexShader; CGLSL VertexShader;
@ -659,7 +659,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand
m_pBorderTileProgram->m_LocIsTextured = -1; m_pBorderTileProgram->m_LocIsTextured = -1;
m_pBorderTileProgram->m_LocTextureSampler = -1; m_pBorderTileProgram->m_LocTextureSampler = -1;
m_pBorderTileProgram->m_LocColor = m_pBorderTileProgram->GetUniformLoc("vertColor"); m_pBorderTileProgram->m_LocColor = m_pBorderTileProgram->GetUniformLoc("vertColor");
m_pBorderTileProgram->m_LocZoomFactor = -1; m_pBorderTileProgram->m_LocLOD = -1;
m_pBorderTileProgram->m_LocOffset = m_pBorderTileProgram->GetUniformLoc("Offset"); m_pBorderTileProgram->m_LocOffset = m_pBorderTileProgram->GetUniformLoc("Offset");
m_pBorderTileProgram->m_LocDir = m_pBorderTileProgram->GetUniformLoc("Dir"); m_pBorderTileProgram->m_LocDir = m_pBorderTileProgram->GetUniformLoc("Dir");
m_pBorderTileProgram->m_LocJumpIndex = m_pBorderTileProgram->GetUniformLoc("JumpIndex"); m_pBorderTileProgram->m_LocJumpIndex = m_pBorderTileProgram->GetUniformLoc("JumpIndex");
@ -681,7 +681,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand
m_pBorderTileProgramTextured->m_LocIsTextured = -1; m_pBorderTileProgramTextured->m_LocIsTextured = -1;
m_pBorderTileProgramTextured->m_LocTextureSampler = m_pBorderTileProgramTextured->GetUniformLoc("textureSampler"); m_pBorderTileProgramTextured->m_LocTextureSampler = m_pBorderTileProgramTextured->GetUniformLoc("textureSampler");
m_pBorderTileProgramTextured->m_LocColor = m_pBorderTileProgramTextured->GetUniformLoc("vertColor"); m_pBorderTileProgramTextured->m_LocColor = m_pBorderTileProgramTextured->GetUniformLoc("vertColor");
m_pBorderTileProgramTextured->m_LocZoomFactor = m_pBorderTileProgramTextured->GetUniformLoc("ZoomFactor"); m_pBorderTileProgramTextured->m_LocLOD = m_pBorderTileProgramTextured->GetUniformLoc("LOD");
m_pBorderTileProgramTextured->m_LocOffset = m_pBorderTileProgramTextured->GetUniformLoc("Offset"); m_pBorderTileProgramTextured->m_LocOffset = m_pBorderTileProgramTextured->GetUniformLoc("Offset");
m_pBorderTileProgramTextured->m_LocDir = m_pBorderTileProgramTextured->GetUniformLoc("Dir"); m_pBorderTileProgramTextured->m_LocDir = m_pBorderTileProgramTextured->GetUniformLoc("Dir");
m_pBorderTileProgramTextured->m_LocJumpIndex = m_pBorderTileProgramTextured->GetUniformLoc("JumpIndex"); m_pBorderTileProgramTextured->m_LocJumpIndex = m_pBorderTileProgramTextured->GetUniformLoc("JumpIndex");
@ -703,7 +703,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand
m_pBorderTileLineProgram->m_LocIsTextured = -1; m_pBorderTileLineProgram->m_LocIsTextured = -1;
m_pBorderTileLineProgram->m_LocTextureSampler = -1; m_pBorderTileLineProgram->m_LocTextureSampler = -1;
m_pBorderTileLineProgram->m_LocColor = m_pBorderTileLineProgram->GetUniformLoc("vertColor"); m_pBorderTileLineProgram->m_LocColor = m_pBorderTileLineProgram->GetUniformLoc("vertColor");
m_pBorderTileLineProgram->m_LocZoomFactor = -1; m_pBorderTileLineProgram->m_LocLOD = -1;
m_pBorderTileLineProgram->m_LocDir = m_pBorderTileLineProgram->GetUniformLoc("Dir"); m_pBorderTileLineProgram->m_LocDir = m_pBorderTileLineProgram->GetUniformLoc("Dir");
} }
{ {
@ -723,7 +723,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Init(const SCommand_Init *pCommand
m_pBorderTileLineProgramTextured->m_LocIsTextured = -1; m_pBorderTileLineProgramTextured->m_LocIsTextured = -1;
m_pBorderTileLineProgramTextured->m_LocTextureSampler = m_pBorderTileLineProgramTextured->GetUniformLoc("textureSampler"); m_pBorderTileLineProgramTextured->m_LocTextureSampler = m_pBorderTileLineProgramTextured->GetUniformLoc("textureSampler");
m_pBorderTileLineProgramTextured->m_LocColor = m_pBorderTileLineProgramTextured->GetUniformLoc("vertColor"); m_pBorderTileLineProgramTextured->m_LocColor = m_pBorderTileLineProgramTextured->GetUniformLoc("vertColor");
m_pBorderTileLineProgramTextured->m_LocZoomFactor = m_pBorderTileLineProgramTextured->GetUniformLoc("ZoomFactor"); m_pBorderTileLineProgramTextured->m_LocLOD = m_pBorderTileLineProgramTextured->GetUniformLoc("LOD");
m_pBorderTileLineProgramTextured->m_LocDir = m_pBorderTileLineProgramTextured->GetUniformLoc("Dir"); m_pBorderTileLineProgramTextured->m_LocDir = m_pBorderTileLineProgramTextured->GetUniformLoc("Dir");
} }
@ -926,7 +926,14 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_Texture_Create(const CCommandBuffe
{ {
glSamplerParameteri(m_aTextures[pCommand->m_Slot].m_Sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glSamplerParameteri(m_aTextures[pCommand->m_Slot].m_Sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(m_aTextures[pCommand->m_Slot].m_Sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); glSamplerParameteri(m_aTextures[pCommand->m_Slot].m_Sampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
gluBuild2DMipmaps(GL_TEXTURE_2D, StoreOglformat, Width, Height, Oglformat, GL_UNSIGNED_BYTE, pTexData); //prevent mipmap display bugs, when zooming out far
if(Width >= 1024 && Height >= 1024)
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5);
}
glTexImage2D(GL_TEXTURE_2D, 0, StoreOglformat, Width, Height, 0, Oglformat, GL_UNSIGNED_BYTE, pTexData);
glGenerateMipmap(GL_TEXTURE_2D);
} }
//this is the initial value for the wrap modes //this is the initial value for the wrap modes
@ -1166,7 +1173,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderBorderTile(const CCommandBuf
} }
else pProgram = m_pBorderTileProgram; else pProgram = m_pBorderTileProgram;
pProgram->UseProgram(); pProgram->UseProgram();
if(pProgram->m_LocZoomFactor != -1) pProgram->SetUniform(pProgram->m_LocZoomFactor, (float)(pCommand->m_ZoomScreenRatio < .5f ? .5f : pCommand->m_ZoomScreenRatio)); if(pProgram->m_LocLOD != -1) pProgram->SetUniform(pProgram->m_LocLOD, (float)(pCommand->m_LOD));
SetState(pCommand->m_State, pProgram); SetState(pCommand->m_State, pProgram);
pProgram->SetUniformVec4(pProgram->m_LocColor, 1, (float*)&pCommand->m_Color); pProgram->SetUniformVec4(pProgram->m_LocColor, 1, (float*)&pCommand->m_Color);
@ -1197,7 +1204,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderBorderTileLine(const CComman
} }
else pProgram = m_pBorderTileLineProgram; else pProgram = m_pBorderTileLineProgram;
pProgram->UseProgram(); pProgram->UseProgram();
if(pProgram->m_LocZoomFactor != -1) pProgram->SetUniform(pProgram->m_LocZoomFactor, (float)(pCommand->m_ZoomScreenRatio < .5f ? .5f : pCommand->m_ZoomScreenRatio)); if(pProgram->m_LocLOD != -1) pProgram->SetUniform(pProgram->m_LocLOD, (float)(pCommand->m_LOD));
SetState(pCommand->m_State, pProgram); SetState(pCommand->m_State, pProgram);
pProgram->SetUniformVec4(pProgram->m_LocColor, 1, (float*)&pCommand->m_Color); pProgram->SetUniformVec4(pProgram->m_LocColor, 1, (float*)&pCommand->m_Color);
@ -1231,7 +1238,7 @@ void CCommandProcessorFragment_OpenGL3_3::Cmd_RenderVertexArray(const CCommandBu
else pProgram = m_pTileProgram; else pProgram = m_pTileProgram;
pProgram->UseProgram(); pProgram->UseProgram();
if(pProgram->m_LocZoomFactor != -1) pProgram->SetUniform(pProgram->m_LocZoomFactor, (float)(pCommand->m_ZoomScreenRatio < .5f ? .5f : pCommand->m_ZoomScreenRatio)); if(pProgram->m_LocLOD != -1) pProgram->SetUniform(pProgram->m_LocLOD, (float)(pCommand->m_LOD));
SetState(pCommand->m_State, pProgram); SetState(pCommand->m_State, pProgram);
pProgram->SetUniformVec4(pProgram->m_LocColor, 1, (float*)&pCommand->m_Color); pProgram->SetUniformVec4(pProgram->m_LocColor, 1, (float*)&pCommand->m_Color);

View file

@ -18,7 +18,7 @@
#include <engine/keys.h> #include <engine/keys.h>
#include <engine/console.h> #include <engine/console.h>
#include <math.h> // cosf, sinf #include <math.h> // cosf, sinf, log2f
#include "graphics_threaded.h" #include "graphics_threaded.h"
@ -879,7 +879,15 @@ void CGraphics_Threaded::DrawVisualObject(int VisualObjectIDX, float* pColor, ch
Cmd.m_IndicesDrawNum = NumIndicesOffet; Cmd.m_IndicesDrawNum = NumIndicesOffet;
Cmd.m_VisualObjectIDX = m_VertexArrayIndices[VisualObjectIDX]; Cmd.m_VisualObjectIDX = m_VertexArrayIndices[VisualObjectIDX];
mem_copy(&Cmd.m_Color, pColor, sizeof(Cmd.m_Color)); mem_copy(&Cmd.m_Color, pColor, sizeof(Cmd.m_Color));
Cmd.m_ZoomScreenRatio = (m_State.m_ScreenBR.x - m_State.m_ScreenTL.x) / ScreenWidth(); float ScreenZoomRatio = (m_State.m_ScreenBR.x - m_State.m_ScreenTL.x) / ScreenWidth();
//the number of pixels we would skip in the fragment shader -- basically the LOD
float LODFactor = (64.f / (32.f * 1.f/ScreenZoomRatio));
//log2 gives us the amount of halving the texture for mipmapping
int LOD = (int)log2f(LODFactor);
//5 because log2(1024/(2^5)) is 5 -- 1024/(2^6) = 32 which would mean 2 pixels per tile index
if(LOD > 5) LOD = 5;
if(LOD < 0) LOD = 0;
Cmd.m_LOD = LOD;
void* Data = m_pCommandBuffer->AllocData((sizeof(char*) + sizeof(unsigned int))*NumIndicesOffet); void* Data = m_pCommandBuffer->AllocData((sizeof(char*) + sizeof(unsigned int))*NumIndicesOffet);
if(Data == 0x0) if(Data == 0x0)
@ -935,7 +943,14 @@ void CGraphics_Threaded::DrawBorderTile(int VisualObjectIDX, float* pColor, char
Cmd.m_DrawNum = DrawNum; Cmd.m_DrawNum = DrawNum;
Cmd.m_VisualObjectIDX = m_VertexArrayIndices[VisualObjectIDX]; Cmd.m_VisualObjectIDX = m_VertexArrayIndices[VisualObjectIDX];
mem_copy(&Cmd.m_Color, pColor, sizeof(Cmd.m_Color)); mem_copy(&Cmd.m_Color, pColor, sizeof(Cmd.m_Color));
Cmd.m_ZoomScreenRatio = (m_State.m_ScreenBR.x - m_State.m_ScreenTL.x) / ScreenWidth(); float ScreenZoomRatio = (m_State.m_ScreenBR.x - m_State.m_ScreenTL.x) / ScreenWidth();
//the number of pixels we would skip in the fragment shader -- basically the LOD
float LODFactor = (64.f / (32.f * 1.f/ScreenZoomRatio));
//log2 gives us the amount of halving the texture for mipmapping
int LOD = (int)log2f(LODFactor);
if(LOD > 5) LOD = 5;
if(LOD < 0) LOD = 0;
Cmd.m_LOD = LOD;
Cmd.m_pIndicesOffset = pOffset; Cmd.m_pIndicesOffset = pOffset;
Cmd.m_JumpIndex = JumpIndex; Cmd.m_JumpIndex = JumpIndex;
@ -969,7 +984,14 @@ void CGraphics_Threaded::DrawBorderTileLine(int VisualObjectIDX, float* pColor,
Cmd.m_DrawNum = RedrawNum; Cmd.m_DrawNum = RedrawNum;
Cmd.m_VisualObjectIDX = m_VertexArrayIndices[VisualObjectIDX]; Cmd.m_VisualObjectIDX = m_VertexArrayIndices[VisualObjectIDX];
mem_copy(&Cmd.m_Color, pColor, sizeof(Cmd.m_Color)); mem_copy(&Cmd.m_Color, pColor, sizeof(Cmd.m_Color));
Cmd.m_ZoomScreenRatio = (m_State.m_ScreenBR.x - m_State.m_ScreenTL.x) / ScreenWidth(); float ScreenZoomRatio = (m_State.m_ScreenBR.x - m_State.m_ScreenTL.x) / ScreenWidth();
//the number of pixels we would skip in the fragment shader -- basically the LOD
float LODFactor = (64.f / (32.f * 1.f/ScreenZoomRatio));
//log2 gives us the amount of halving the texture for mipmapping
int LOD = (int)log2f(LODFactor);
if(LOD > 5) LOD = 5;
if(LOD < 0) LOD = 0;
Cmd.m_LOD = LOD;
Cmd.m_pIndicesOffset = pOffset; Cmd.m_pIndicesOffset = pOffset;

View file

@ -252,7 +252,7 @@ public:
int m_IndicesDrawNum; int m_IndicesDrawNum;
int m_VisualObjectIDX; int m_VisualObjectIDX;
float m_ZoomScreenRatio; int m_LOD;
}; };
struct SCommand_RenderBorderTile : public SCommand struct SCommand_RenderBorderTile : public SCommand
@ -263,7 +263,7 @@ public:
char *m_pIndicesOffset; // you should use the command buffer data to allocate vertices for this command char *m_pIndicesOffset; // you should use the command buffer data to allocate vertices for this command
unsigned int m_DrawNum; unsigned int m_DrawNum;
int m_VisualObjectIDX; int m_VisualObjectIDX;
float m_ZoomScreenRatio; int m_LOD;
float m_Offset[2]; float m_Offset[2];
float m_Dir[2]; float m_Dir[2];
@ -279,7 +279,7 @@ public:
unsigned int m_IndexDrawNum; unsigned int m_IndexDrawNum;
unsigned int m_DrawNum; unsigned int m_DrawNum;
int m_VisualObjectIDX; int m_VisualObjectIDX;
float m_ZoomScreenRatio; int m_LOD;
float m_Dir[2]; float m_Dir[2];
}; };

View file

@ -58,7 +58,7 @@ public:
class CGLSLTileProgram : public CGLSLTWProgram { class CGLSLTileProgram : public CGLSLTWProgram {
public: public:
int m_LocColor; int m_LocColor;
int m_LocZoomFactor; int m_LocLOD;
}; };
class CGLSLBorderTileProgram : public CGLSLTileProgram { class CGLSLBorderTileProgram : public CGLSLTileProgram {