OpenGL2: Load existing per-map cubemaps.

This commit is contained in:
SmileTheory 2016-01-28 16:39:42 -08:00
parent 558da25277
commit 2b2f1aeaa1
3 changed files with 208 additions and 175 deletions

View file

@ -3068,17 +3068,34 @@ void R_AssignCubemapsToWorldSurfaces(void)
} }
void R_RenderAllCubemaps(void) void R_LoadCubemaps(void)
{
int i;
imgFlags_t flags = IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_NOLIGHTSCALE | IMGFLAG_CUBEMAP;
for (i = 0; i < tr.numCubemaps; i++)
{
char filename[MAX_QPATH];
cubemap_t *cubemap = &tr.cubemaps[i];
Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", tr.world->baseName, i);
cubemap->image = R_FindImageFile(filename, IMGTYPE_COLORALPHA, flags);
}
}
void R_RenderMissingCubemaps(void)
{ {
int i, j; int i, j;
imgFlags_t flags = IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_NOLIGHTSCALE | IMGFLAG_CUBEMAP;
for (i = 0; i < tr.numCubemaps; i++) for (i = 0; i < tr.numCubemaps; i++)
{ {
tr.cubemaps[i].image = R_CreateImage(va("*cubeMap%d", i), NULL, r_cubemapSize->integer, r_cubemapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, GL_RGBA8); if (!tr.cubemaps[i].image)
}
for (i = 0; i < tr.numCubemaps; i++)
{ {
tr.cubemaps[i].image = R_CreateImage(va("*cubeMap%d", i), NULL, r_cubemapSize->integer, r_cubemapSize->integer, IMGTYPE_COLORALPHA, flags, GL_RGBA8);
for (j = 0; j < 6; j++) for (j = 0; j < 6; j++)
{ {
RE_ClearScene(); RE_ClearScene();
@ -3087,6 +3104,7 @@ void R_RenderAllCubemaps(void)
R_InitNextFrame(); R_InitNextFrame();
} }
} }
}
} }
@ -3425,10 +3443,11 @@ void RE_LoadWorldMap( const char *name ) {
// make sure the VAO glState entry is safe // make sure the VAO glState entry is safe
R_BindNullVao(); R_BindNullVao();
// Render all cubemaps // Render or load all cubemaps
if (r_cubeMapping->integer && tr.numCubemaps) if (r_cubeMapping->integer && tr.numCubemaps)
{ {
R_RenderAllCubemaps(); R_LoadCubemaps();
R_RenderMissingCubemaps();
} }
ri.FS_FreeFile( buffer.v ); ri.FS_FreeFile( buffer.v );

View file

@ -68,6 +68,9 @@ int GL_BindMultiTexture(GLenum texunit, GLenum target, GLuint texture)
if (glDsaState.textures[tmu] == texture) if (glDsaState.textures[tmu] == texture)
return 0; return 0;
if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)
target = GL_TEXTURE_CUBE_MAP;
qglBindMultiTexture(texunit, target, texture); qglBindMultiTexture(texunit, target, texture);
glDsaState.textures[tmu] = texture; glDsaState.textures[tmu] = texture;
return 1; return 1;

View file

@ -1863,16 +1863,10 @@ static void RawImage_UploadToRgtc2Texture(GLuint texture, byte *data, int width,
ri.Hunk_FreeTempMemory(compressedData); ri.Hunk_FreeTempMemory(compressedData);
} }
static int CalculateMipSize(int width, int height, GLenum picFormat)
static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int width, int height, GLenum picFormat, int numMips, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture )
{ {
int dataFormat, dataType; int numBlocks = ((width + 3) / 4) * ((height + 3) / 4);
qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2); int numPixels = width * height;
if (data && picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT)
{
int bytesPer4x4Block = 0;
int miplevel = 0;
switch (picFormat) switch (picFormat)
{ {
@ -1882,8 +1876,8 @@ static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
case GL_COMPRESSED_RED_RGTC1: case GL_COMPRESSED_RED_RGTC1:
case GL_COMPRESSED_SIGNED_RED_RGTC1: case GL_COMPRESSED_SIGNED_RED_RGTC1:
bytesPer4x4Block = 8; return numBlocks * 8;
break;
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
@ -1894,51 +1888,32 @@ static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int
case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB: case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB:
case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB: case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB: case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB:
bytesPer4x4Block = 16; return numBlocks * 16;
break;
case GL_RGBA8:
case GL_SRGB8_ALPHA8_EXT:
return numPixels * 4;
default: default:
ri.Printf(PRINT_ALL, "Unsupported texture format %08x\n", picFormat); ri.Printf(PRINT_ALL, "Unsupported texture format %08x\n", picFormat);
return; return 0;
break;
} }
if (flags & IMGFLAG_PICMIP) return 0;
{ }
for (miplevel = r_picmip->integer; miplevel > 0 && numMips > 1; miplevel--, numMips--)
{
int size = ((width + 3) / 4) * ((height + 3) / 4) * bytesPer4x4Block;
x >>= 1;
y >>= 1;
width = MAX(1, width >> 1);
height = MAX(1, height >> 1);
data += size;
}
}
if (!(flags & IMGFLAG_MIPMAP)) static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int width, int height, GLenum target, GLenum picFormat, int numMips, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture )
numMips = 1; {
int dataFormat, dataType;
qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2);
qboolean compressed = (!(picFormat == GL_RGBA8) || (picFormat == GL_SRGB8_ALPHA8_EXT));
qboolean mipmap = !!(flags & IMGFLAG_MIPMAP);
qboolean picmip = !!(flags & IMGFLAG_PICMIP);
int size, miplevel;
qboolean lastMip = qfalse;
for (miplevel = 0; miplevel < numMips; miplevel++) switch (internalFormat)
{
int size = ((width + 3) / 4) * ((height + 3) / 4) * bytesPer4x4Block;
if (subtexture)
qglCompressedTextureSubImage2D(texture, GL_TEXTURE_2D, miplevel, x, y, width, height, internalFormat, size, data);
else
qglCompressedTextureImage2D(texture, GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, size, data);
x >>= 1;
y >>= 1;
width = MAX(1, width >> 1);
height = MAX(1, height >> 1);
data += size;
}
return;
}
switch(internalFormat)
{ {
case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT:
case GL_DEPTH_COMPONENT16_ARB: case GL_DEPTH_COMPONENT16_ARB:
@ -1957,52 +1932,83 @@ static void RawImage_UploadTexture(GLuint texture, byte *data, int x, int y, int
break; break;
} }
if ( subtexture ) if (!data)
qglTextureSubImage2D(texture, GL_TEXTURE_2D, 0, x, y, width, height, dataFormat, dataType, data );
else
{ {
if (rgtc) miplevel = 0;
RawImage_UploadToRgtc2Texture(texture, data, width, height, 0); do
else
qglTextureImage2D(texture, GL_TEXTURE_2D, 0, internalFormat, width, height, 0, dataFormat, dataType, data);
}
if (flags & IMGFLAG_MIPMAP)
{ {
int miplevel = 0; lastMip = (width == 1 && height == 1) || !mipmap;
qglTextureImage2D(texture, target, miplevel, internalFormat, width, height, 0, dataFormat, dataType, NULL);
while (width > 1 || height > 1)
{
if (data)
{
if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT)
R_MipMapNormalHeight( data, data, width, height, glRefConfig.swizzleNormalmap );
else
R_MipMapsRGB( data, width, height );
}
width = MAX(1, width >> 1); width = MAX(1, width >> 1);
height = MAX(1, height >> 1); height = MAX(1, height >> 1);
miplevel++; miplevel++;
}
while (!lastMip);
if ( data && r_colorMipLevels->integer ) return;
R_BlendOverTexture( (byte *)data, width * height, mipBlendColors[miplevel] ); }
if ( subtexture ) if (compressed && picmip)
{ {
for (miplevel = r_picmip->integer; miplevel > 0 && numMips > 1; miplevel--, numMips--)
{
size = CalculateMipSize(width, height, picFormat);
x >>= 1; x >>= 1;
y >>= 1; y >>= 1;
qglTextureSubImage2D(texture, GL_TEXTURE_2D, miplevel, x, y, width, height, dataFormat, dataType, data ); width = MAX(1, width >> 1);
height = MAX(1, height >> 1);
data += size;
}
}
miplevel = 0;
do
{
lastMip = (width == 1 && height == 1) || !mipmap;
size = CalculateMipSize(width, height, picFormat);
if (compressed)
{
if (subtexture)
qglCompressedTextureSubImage2D(texture, target, miplevel, x, y, width, height, picFormat, size, data);
else
qglCompressedTextureImage2D(texture, target, miplevel, picFormat, width, height, 0, size, data);
} }
else else
{ {
if (miplevel != 0 && r_colorMipLevels->integer)
R_BlendOverTexture((byte *)data, width * height, mipBlendColors[miplevel]);
if (rgtc) if (rgtc)
RawImage_UploadToRgtc2Texture(texture, data, width, height, miplevel); RawImage_UploadToRgtc2Texture(texture, data, width, height, miplevel);
else if (subtexture)
qglTextureSubImage2D(texture, target, miplevel, x, y, width, height, dataFormat, dataType, data);
else else
qglTextureImage2D(texture, GL_TEXTURE_2D, miplevel, internalFormat, width, height, 0, dataFormat, dataType, data); qglTextureImage2D(texture, target, miplevel, internalFormat, width, height, 0, dataFormat, dataType, data);
if (!lastMip && numMips < 2)
{
if (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT)
R_MipMapNormalHeight(data, data, width, height, glRefConfig.swizzleNormalmap);
else
R_MipMapsRGB(data, width, height);
} }
} }
x >>= 1;
y >>= 1;
width = MAX(1, width >> 1);
height = MAX(1, height >> 1);
miplevel++;
if (numMips > 1)
{
data += size;
numMips--;
} }
}
while (!lastMip);
} }
@ -2023,19 +2029,35 @@ static void Upload32(byte *data, int x, int y, int width, int height, GLenum pic
GLenum internalFormat = image->internalFormat; GLenum internalFormat = image->internalFormat;
qboolean subtexture = (x != 0) || (y != 0) || (width != image->width) || (height != image->height); qboolean subtexture = (x != 0) || (y != 0) || (width != image->width) || (height != image->height);
qboolean notScaled = qtrue; qboolean notScaled = qtrue;
qboolean mipmap = !!(flags & IMGFLAG_MIPMAP); qboolean compressed = (picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT);
qboolean mipmap = !!(flags & IMGFLAG_MIPMAP) && (!compressed || numMips > 1);
qboolean cubemap = !!(flags & IMGFLAG_CUBEMAP);
GLenum uploadTarget = cubemap ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : GL_TEXTURE_2D;
GLenum textureTarget = cubemap ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
int depth = cubemap ? 6 : 1;
if (!data) if (!data)
{ {
RawImage_ScaleToPower2(NULL, &width, &height, type, flags, NULL); RawImage_ScaleToPower2(NULL, &width, &height, type, flags, NULL);
RawImage_UploadTexture(image->texnum, NULL, 0, 0, width, height, GL_RGBA8, 0, internalFormat, type, flags, qfalse); for (i = 0; i < depth; i++)
RawImage_UploadTexture(image->texnum, NULL, 0, 0, width, height, uploadTarget + i, GL_RGBA8, 0, internalFormat, type, flags, qfalse);
goto done; goto done;
} }
else if (!subtexture) else if (!subtexture)
{ {
if (picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT) if (compressed || cubemap)
{ {
RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, picFormat, numMips, internalFormat, type, flags, qfalse); for (i = 0; i < depth; i++)
{
int w2 = width, h2 = height;
RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, uploadTarget + i, picFormat, numMips, internalFormat, type, flags, qfalse);
for (c = numMips; c; c--)
{
data += CalculateMipSize(w2, h2, picFormat);
w2 = MAX(1, w2 >> 1);
h2 = MAX(1, h2 >> 1);
}
}
goto done; goto done;
} }
notScaled = RawImage_ScaleToPower2(&data, &width, &height, type, flags, &resampledBuffer); notScaled = RawImage_ScaleToPower2(&data, &width, &height, type, flags, &resampledBuffer);
@ -2075,12 +2097,12 @@ static void Upload32(byte *data, int x, int y, int width, int height, GLenum pic
if (subtexture) if (subtexture)
{ {
// FIXME: Incorrect if original texture was not a power of 2 texture or picmipped // FIXME: Incorrect if original texture was not a power of 2 texture or picmipped
RawImage_UploadTexture(image->texnum, data, x, y, width, height, GL_RGBA8, 0, internalFormat, type, flags, qtrue); RawImage_UploadTexture(image->texnum, data, x, y, width, height, uploadTarget, GL_RGBA8, 0, internalFormat, type, flags, qtrue);
GL_CheckErrors(); GL_CheckErrors();
return; return;
} }
RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, GL_RGBA8, 0, internalFormat, type, flags, qfalse); RawImage_UploadTexture(image->texnum, data, 0, 0, width, height, uploadTarget, GL_RGBA8, 0, internalFormat, type, flags, qfalse);
done: done:
@ -2089,20 +2111,20 @@ done:
if (mipmap) if (mipmap)
{ {
if ( textureFilterAnisotropic ) if (textureFilterAnisotropic && !cubemap)
qglTextureParameteri( image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, qglTextureParameteri(image->texnum, textureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT,
(GLint)Com_Clamp( 1, maxAnisotropy, r_ext_max_anisotropy->integer ) ); (GLint)Com_Clamp(1, maxAnisotropy, r_ext_max_anisotropy->integer));
qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); qglTextureParameterf(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, gl_filter_min);
qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); qglTextureParameterf(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, gl_filter_max);
} }
else else
{ {
if ( textureFilterAnisotropic ) if (textureFilterAnisotropic && !cubemap)
qglTextureParameteri(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1); qglTextureParameteri(image->texnum, textureTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTextureParameterf(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); qglTextureParameterf(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
} }
// Fix for sampling depth buffer on old nVidia cards // Fix for sampling depth buffer on old nVidia cards
@ -2113,9 +2135,9 @@ done:
case GL_DEPTH_COMPONENT16_ARB: case GL_DEPTH_COMPONENT16_ARB:
case GL_DEPTH_COMPONENT24_ARB: case GL_DEPTH_COMPONENT24_ARB:
case GL_DEPTH_COMPONENT32_ARB: case GL_DEPTH_COMPONENT32_ARB:
qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); qglTextureParameterf(image->texnum, textureTarget, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE);
qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); qglTextureParameterf(image->texnum, textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); qglTextureParameterf(image->texnum, textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
break; break;
default: default:
break; break;
@ -2169,49 +2191,20 @@ image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, GLe
glWrapClampMode = GL_REPEAT; glWrapClampMode = GL_REPEAT;
if (!internalFormat) if (!internalFormat)
{
if (image->flags & IMGFLAG_CUBEMAP)
internalFormat = GL_RGBA8;
else
internalFormat = RawImage_GetFormat(pic, width * height, picFormat, isLightmap, image->type, image->flags); internalFormat = RawImage_GetFormat(pic, width * height, picFormat, isLightmap, image->type, image->flags);
}
image->internalFormat = internalFormat; image->internalFormat = internalFormat;
Upload32(pic, 0, 0, image->width, image->height, picFormat, numMips, image);
if (image->flags & IMGFLAG_CUBEMAP) if (image->flags & IMGFLAG_CUBEMAP)
{ {
qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); qglTextureParameterf(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, glWrapClampMode);
qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); qglTextureParameterf(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, glWrapClampMode);
qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, glWrapClampMode);
qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (image->flags & IMGFLAG_MIPMAP)
{
qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
} }
else else
{ {
qglTextureParameteri(image->texnum, GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
qglTextureImage2D(image->texnum, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pic);
if (image->flags & IMGFLAG_MIPMAP)
qglGenerateTextureMipmap(image->texnum, GL_TEXTURE_CUBE_MAP);
image->uploadWidth = width;
image->uploadHeight = height;
}
else
{
Upload32( pic, 0, 0, image->width, image->height, picFormat, numMips, image );
qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode); qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode);
qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode); qglTextureParameterf(image->texnum, GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode);
} }
@ -2383,6 +2376,7 @@ image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags )
GLenum picFormat; GLenum picFormat;
int picNumMips; int picNumMips;
long hash; long hash;
imgFlags_t checkFlagsTrue, checkFlagsFalse;
if (!name) { if (!name) {
return NULL; return NULL;
@ -2413,7 +2407,10 @@ image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags )
return NULL; return NULL;
} }
if (r_normalMapping->integer && (picFormat == GL_RGBA8) && !(type == IMGTYPE_NORMAL) && (flags & IMGFLAG_PICMIP) && (flags & IMGFLAG_MIPMAP) && (flags & IMGFLAG_GENNORMALMAP)) checkFlagsTrue = IMGFLAG_PICMIP | IMGFLAG_MIPMAP | IMGFLAG_GENNORMALMAP;
checkFlagsFalse = IMGFLAG_CUBEMAP;
if (r_normalMapping->integer && (picFormat == GL_RGBA8) && (type == IMGTYPE_COLORALPHA) &&
((flags & checkFlagsTrue) == checkFlagsTrue) && !(flags & checkFlagsFalse))
{ {
char normalName[MAX_QPATH]; char normalName[MAX_QPATH];
image_t *normalImage; image_t *normalImage;
@ -2516,6 +2513,20 @@ image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags )
} }
} }
// force mipmaps off if image is compressed but doesn't have enough mips
if ((flags & IMGFLAG_MIPMAP) && picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT)
{
int wh = MAX(width, height);
int neededMips = 0;
while (wh)
{
neededMips++;
wh >>= 1;
}
if (neededMips > picNumMips)
flags &= ~IMGFLAG_MIPMAP;
}
image = R_CreateImage2( ( char * ) name, pic, width, height, picFormat, picNumMips, type, flags, 0 ); image = R_CreateImage2( ( char * ) name, pic, width, height, picFormat, picNumMips, type, flags, 0 );
ri.Free( pic ); ri.Free( pic );
return image; return image;