Originally to do mipmapping, I just used the base texture and then let the h/w automatically generate the mipmap chain. I wasn't sure the real3d api even exposed to the programmer the ability to directly set the mipmap data. Anyway, as pointed out by HarryTuttle scud actually uses darker mipmaps for an effect on the water. This patch uses the uses the actual mipmap data from the real3d memory. Only tested scud, so hopefully I didn't cause any cataclysmic errors :)

This commit is contained in:
Ian Curtis 2017-03-24 13:38:20 +00:00
parent df3805e741
commit 17f878421b
2 changed files with 59 additions and 34 deletions

View file

@ -65,18 +65,12 @@ void Texture::SetWrapMode(bool mirrorU, bool mirrorV)
} }
} }
UINT32 Texture::UploadTexture(const UINT16* src, UINT8* scratch, int format, bool mirrorU, bool mirrorV, int x, int y, int width, int height) void Texture::UploadTextureMip(int level, const UINT16* src, UINT8* scratch, int format, int x, int y, int width, int height)
{ {
int xi, yi, i; int xi, yi, i;
GLubyte texel; GLubyte texel;
GLubyte c, a; GLubyte c, a;
if (!src || !scratch) {
return 0; // sanity checking
}
DeleteTexture(); // free any existing texture
i = 0; i = 0;
switch (format) switch (format)
@ -280,38 +274,36 @@ UINT32 Texture::UploadTexture(const UINT16* src, UINT8* scratch, int format, boo
break; break;
} }
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scratch);
GLfloat maxAnistrophy;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnistrophy);
if (maxAnistrophy > 8) {
maxAnistrophy = 8.0f; //anymore than 8 can get expensive for little gain
} }
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // rgba is always 4 byte aligned UINT32 Texture::UploadTexture(const UINT16* src, UINT8* scratch, int format, bool mirrorU, bool mirrorV, int x, int y, int width, int height)
glGenTextures(1, &m_textureID); {
glBindTexture(GL_TEXTURE_2D, m_textureID); const int mipXBase[] = { 0, 1024, 1536, 1792, 1920, 1984, 2016, 2032, 2040, 2044, 2046, 2047 };
const int mipYBase[] = { 0, 512, 768, 896, 960, 992, 1008, 1016, 1020, 1022, 1023 };
const int mipDivisor[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 };
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mirrorU ? GL_MIRRORED_REPEAT : GL_REPEAT); //todo this in shaders? if (!src || !scratch) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mirrorV ? GL_MIRRORED_REPEAT : GL_REPEAT); return 0; // sanity checking
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); }
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnistrophy);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scratch);
// assuming successful we can copy details DeleteTexture(); // free any existing texture
CreateTextureObject(format, mirrorU, mirrorV, x, y, width, height);
m_x = x; int page = y / 1024;
m_y = y;
m_width = width;
m_height = height;
m_format = format;
m_mirrorU = mirrorU;
m_mirrorV = mirrorV;
printf("create format %i x: %i y: %i width: %i height: %i\n", format, x, y, width, height); y -= (page * 1024); // remove page from tex y
for (int i = 0; i < 6; i++) {
int xPos = mipXBase[i] + (x / mipDivisor[i]);
int yPos = mipYBase[i] + (y / mipDivisor[i]);
UploadTextureMip(i, src, scratch, format, xPos, yPos + (page * 1024), width, height);
width /= 2;
height /= 2;
}
return m_textureID; return m_textureID;
} }
@ -349,4 +341,35 @@ bool Texture::CheckMapPos(int ax1, int ax2, int ay1, int ay2)
return false; return false;
} }
void Texture::CreateTextureObject(int format, bool mirrorU, bool mirrorV, int x, int y, int width, int height)
{
GLfloat maxAnistrophy;
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnistrophy);
if (maxAnistrophy > 8) {
maxAnistrophy = 8.0f; //anymore than 8 can get expensive for little gain
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // rgba is always 4 byte aligned
glGenTextures(1, &m_textureID);
glBindTexture(GL_TEXTURE_2D, m_textureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mirrorU ? GL_MIRRORED_REPEAT : GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mirrorV ? GL_MIRRORED_REPEAT : GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAnistrophy);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 5); // 0-5 (real3d only uses 6 possible mipmap levels)
m_x = x;
m_y = y;
m_width = width;
m_height = height;
m_format = format;
m_mirrorU = mirrorU;
m_mirrorV = mirrorV;
printf("create format %i x: %i y: %i width: %i height: %i\n", format, x, y, width, height);
}
} // New3D } // New3D

View file

@ -26,6 +26,8 @@ public:
private: private:
void CreateTextureObject(int format, bool mirrorU, bool mirrorV, int x, int y, int width, int height);
void UploadTextureMip(int level, const UINT16* src, UINT8* scratch, int format, int x, int y, int width, int height);
void Reset(); void Reset();
int m_x; int m_x;