[iortcw] 03/152: All: Rend2: Merge DDS support / r_cubemapsize / exportCubemaps command
Simon McVittie
smcv at debian.org
Fri Sep 8 10:39:33 UTC 2017
This is an automated email from the git hooks/post-receive script.
smcv pushed a commit to annotated tag 1.5a
in repository iortcw.
commit 721dead5f5ff2930b3241b3e6fe9a334a0fd3a73
Author: MAN-AT-ARMS <M4N4T4RMS at gmail.com>
Date: Sun Dec 27 08:48:09 2015 -0500
All: Rend2: Merge DDS support / r_cubemapsize / exportCubemaps command
---
MP/Makefile | 1 +
MP/code/rend2/tr_backend.c | 61 ++++++
MP/code/rend2/tr_bsp.c | 2 +-
MP/code/rend2/tr_image.c | 162 +++++++++++---
MP/code/rend2/tr_image_dds.c | 498 +++++++++++++++++++++++++++++++++++++++++++
MP/code/rend2/tr_init.c | 31 +++
MP/code/rend2/tr_local.h | 10 +-
SP/Makefile | 1 +
SP/code/rend2/tr_backend.c | 61 ++++++
SP/code/rend2/tr_bsp.c | 2 +-
SP/code/rend2/tr_image.c | 165 +++++++++++---
SP/code/rend2/tr_image_dds.c | 498 +++++++++++++++++++++++++++++++++++++++++++
SP/code/rend2/tr_init.c | 31 +++
SP/code/rend2/tr_local.h | 10 +-
14 files changed, 1461 insertions(+), 72 deletions(-)
diff --git a/MP/Makefile b/MP/Makefile
index 01b2ff6..9aa73ed 100644
--- a/MP/Makefile
+++ b/MP/Makefile
@@ -1747,6 +1747,7 @@ Q3R2OBJ = \
$(B)/rend2/tr_image_pcx.o \
$(B)/rend2/tr_image_png.o \
$(B)/rend2/tr_image_tga.o \
+ $(B)/rend2/tr_image_dds.o \
$(B)/rend2/tr_init.o \
$(B)/rend2/tr_light.o \
$(B)/rend2/tr_main.o \
diff --git a/MP/code/rend2/tr_backend.c b/MP/code/rend2/tr_backend.c
index 708a657..34550ae 100644
--- a/MP/code/rend2/tr_backend.c
+++ b/MP/code/rend2/tr_backend.c
@@ -2004,6 +2004,64 @@ const void *RB_PostProcess(const void *data)
return (const void *)(cmd + 1);
}
+// FIXME: put this function declaration elsewhere
+void R_SaveDDS(const char *filename, byte *pic, int width, int height, int depth);
+
+/*
+=============
+RB_ExportCubemaps
+
+=============
+*/
+const void *RB_ExportCubemaps(const void *data)
+{
+ const exportCubemapsCommand_t *cmd = data;
+
+ // finish any 2D drawing if needed
+ if (tess.numIndexes)
+ RB_EndSurface();
+
+ if (!glRefConfig.framebufferObject || !tr.world || tr.numCubemaps == 0)
+ {
+ // do nothing
+ ri.Printf(PRINT_ALL, "Nothing to export!\n");
+ return (const void *)(cmd + 1);
+ }
+
+ if (cmd)
+ {
+ FBO_t *oldFbo = glState.currentFBO;
+ int sideSize = r_cubemapSize->integer * r_cubemapSize->integer * 4;
+ byte *cubemapPixels = ri.Z_Malloc(sideSize * 6);
+ int i, j;
+
+ FBO_Bind(tr.renderCubeFbo);
+
+ for (i = 0; i < tr.numCubemaps; i++)
+ {
+ char filename[MAX_QPATH];
+ cubemap_t *cubemap = &tr.cubemaps[i];
+ unsigned char *p = cubemapPixels;
+
+ for (j = 0; j < 6; j++)
+ {
+ qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, cubemap->image->texnum, 0);
+ qglReadPixels(0, 0, r_cubemapSize->integer, r_cubemapSize->integer, GL_RGBA, GL_UNSIGNED_BYTE, p);
+ p += sideSize;
+ }
+
+ Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", tr.world->baseName, i);
+ R_SaveDDS(filename, cubemapPixels, r_cubemapSize->integer, r_cubemapSize->integer, 6);
+ ri.Printf(PRINT_ALL, "Saved cubemap %d as %s\n", i, filename);
+ }
+
+ FBO_Bind(oldFbo);
+
+ ri.Free(cubemapPixels);
+ }
+
+ return (const void *)(cmd + 1);
+}
/*
====================
@@ -2058,6 +2116,9 @@ void RB_ExecuteRenderCommands( const void *data ) {
case RC_POSTPROCESS:
data = RB_PostProcess(data);
break;
+ case RC_EXPORT_CUBEMAPS:
+ data = RB_ExportCubemaps(data);
+ break;
case RC_END_OF_LIST:
default:
// finish any 2D drawing if needed
diff --git a/MP/code/rend2/tr_bsp.c b/MP/code/rend2/tr_bsp.c
index 27f4242..be2170e 100644
--- a/MP/code/rend2/tr_bsp.c
+++ b/MP/code/rend2/tr_bsp.c
@@ -3425,7 +3425,7 @@ void R_RenderAllCubemaps(void)
for (i = 0; i < tr.numCubemaps; i++)
{
- tr.cubemaps[i].image = R_CreateImage(va("*cubeMap%d", i), NULL, CUBE_MAP_SIZE, CUBE_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, GL_RGBA8);
+ 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);
}
ri.Printf(PRINT_ALL, "Total cubemaps: %d\n", tr.numCubemaps );
diff --git a/MP/code/rend2/tr_image.c b/MP/code/rend2/tr_image.c
index 6b2d124..0b01a25 100644
--- a/MP/code/rend2/tr_image.c
+++ b/MP/code/rend2/tr_image.c
@@ -1777,13 +1777,16 @@ static qboolean RawImage_HasAlpha(const byte *scan, int numPixels)
return qfalse;
}
-static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean lightMap, imgType_t type, imgFlags_t flags)
+static GLenum RawImage_GetFormat(const byte *data, int numPixels, GLenum picFormat, qboolean lightMap, imgType_t type, imgFlags_t flags)
{
int samples = 3;
GLenum internalFormat = GL_RGB;
qboolean forceNoCompression = (flags & IMGFLAG_NO_COMPRESSION);
qboolean normalmap = (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT);
+ if (picFormat != GL_RGBA8)
+ return picFormat;
+
if(normalmap)
{
if ((type == IMGTYPE_NORMALHEIGHT) && RawImage_HasAlpha(data, numPixels))
@@ -2021,11 +2024,80 @@ static void RawImage_UploadToRgtc2Texture(byte *data, int width, int height, int
ri.Hunk_FreeTempMemory(compressedData);
}
-static void RawImage_UploadTexture( byte *data, int x, int y, int width, int height, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture )
+static void RawImage_UploadTexture( 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;
qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2);
+ if (data && picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT)
+ {
+ int bytesPer4x4Block = 0;
+ int miplevel = 0;
+
+ switch (picFormat)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RED_RGTC1:
+ case GL_COMPRESSED_SIGNED_RED_RGTC1:
+ bytesPer4x4Block = 8;
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_RG_RGTC2:
+ case GL_COMPRESSED_SIGNED_RG_RGTC2:
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB:
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB:
+ case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB:
+ bytesPer4x4Block = 16;
+ break;
+ default:
+ ri.Printf(PRINT_ALL, "Unsupported texture format %08x\n", picFormat);
+ return;
+ break;
+ }
+
+ if (flags & IMGFLAG_PICMIP)
+ {
+ 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))
+ numMips = 1;
+
+ for (miplevel = 0; miplevel < numMips; miplevel++)
+ {
+ int size = ((width + 3) / 4) * ((height + 3) / 4) * bytesPer4x4Block;
+
+ if (subtexture)
+ qglCompressedTexSubImage2DARB(GL_TEXTURE_2D, miplevel, x, y, width, height, internalFormat, size, data);
+ else
+ qglCompressedTexImage2DARB(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:
@@ -2057,29 +2129,20 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei
if (flags & IMGFLAG_MIPMAP)
{
- int miplevel;
+ int miplevel = 0;
- miplevel = 0;
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 >>= 1;
- height >>= 1;
- if (width < 1)
- width = 1;
- if (height < 1)
- height = 1;
+ width = MAX(1, width >> 1);
+ height = MAX(1, height >> 1);
miplevel++;
if ( data && r_colorMipLevels->integer )
@@ -2108,7 +2171,7 @@ Upload32
===============
*/
-static void Upload32(byte *data, int x, int y, int width, int height, image_t *image)
+static void Upload32(byte *data, int x, int y, int width, int height, GLenum picFormat, int numMips, image_t *image)
{
byte *resampledBuffer = NULL;
int i, c;
@@ -2138,11 +2201,16 @@ static void Upload32(byte *data, int x, int y, int width, int height, image_t *i
if (!data)
{
RawImage_ScaleToPower2(NULL, &width, &height, type, flags, NULL);
- RawImage_UploadTexture(NULL, 0, 0, width, height, internalFormat, type, flags, qfalse);
+ RawImage_UploadTexture(NULL, 0, 0, width, height, GL_RGBA8, 0, internalFormat, type, flags, qfalse);
goto done;
}
else if (!subtexture)
{
+ if (picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT)
+ {
+ RawImage_UploadTexture(data, 0, 0, width, height, picFormat, numMips, internalFormat, type, flags, qfalse);
+ goto done;
+ }
notScaled = RawImage_ScaleToPower2(&data, &width, &height, type, flags, &resampledBuffer);
}
@@ -2180,12 +2248,12 @@ static void Upload32(byte *data, int x, int y, int width, int height, image_t *i
if (subtexture)
{
// FIXME: Incorrect if original texture was not a power of 2 texture or picmipped
- RawImage_UploadTexture(data, x, y, width, height, internalFormat, type, flags, qtrue);
+ RawImage_UploadTexture(data, x, y, width, height, GL_RGBA8, 0, internalFormat, type, flags, qtrue);
GL_CheckErrors();
return;
}
- RawImage_UploadTexture(data, 0, 0, width, height, internalFormat, type, flags, qfalse);
+ RawImage_UploadTexture(data, 0, 0, width, height, GL_RGBA8, 0, internalFormat, type, flags, qfalse);
done:
@@ -2234,12 +2302,12 @@ done:
/*
================
-R_CreateImage
+R_CreateImage2
This is the only way any image_t are created
================
*/
-image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat ) {
+image_t *R_CreateImage2( const char *name, byte *pic, int width, int height, GLenum picFormat, int numMips, imgType_t type, imgFlags_t flags, int internalFormat ) {
image_t *image;
qboolean isLightmap = qfalse;
long hash;
@@ -2277,7 +2345,7 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgT
if (image->flags & IMGFLAG_CUBEMAP)
internalFormat = GL_RGBA8;
else
- internalFormat = RawImage_GetFormat(pic, width * height, isLightmap, image->type, image->flags);
+ internalFormat = RawImage_GetFormat(pic, width * height, picFormat, isLightmap, image->type, image->flags);
}
image->internalFormat = internalFormat;
@@ -2327,7 +2395,7 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgT
}
else
{
- Upload32( pic, 0, 0, image->width, image->height, image );
+ Upload32( pic, 0, 0, image->width, image->height, picFormat, numMips, image );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode );
@@ -2345,6 +2413,18 @@ image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgT
return image;
}
+/*
+================
+R_CreateImage
+
+Wrapper for R_CreateImage2(), for the old parameters.
+================
+*/
+image_t *R_CreateImage(const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat)
+{
+ return R_CreateImage2(name, pic, width, height, GL_RGBA8, 0, type, flags, internalFormat);
+}
+
void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int height )
{
if (qglActiveTextureARB) {
@@ -2353,13 +2433,16 @@ void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int h
GL_Bind(image);
- Upload32(pic, x, y, width, height, image);
+ Upload32(pic, x, y, width, height, GL_RGBA8, 0, image);
GL_SelectTexture(0);
}
//===================================================================
+// Prototype for dds loader function which isn't common to both renderers
+void R_LoadDDS(const char *filename, byte **pic, int *width, int *height, GLenum *picFormat, int *numMips);
+
typedef struct
{
char *ext;
@@ -2389,7 +2472,7 @@ Loads any of the supported image types into a cannonical
32 bit format.
=================
*/
-void R_LoadImage( const char *name, byte **pic, int *width, int *height )
+void R_LoadImage( const char *name, byte **pic, int *width, int *height, GLenum *picFormat, int *numMips )
{
qboolean orgNameFailed = qfalse;
int orgLoader = -1;
@@ -2401,11 +2484,28 @@ void R_LoadImage( const char *name, byte **pic, int *width, int *height )
*pic = NULL;
*width = 0;
*height = 0;
+ *picFormat = GL_RGBA8;
+ *numMips = 0;
Q_strncpyz( localName, name, MAX_QPATH );
ext = COM_GetExtension( localName );
+ // If compressed textures are enabled, try loading a DDS first, it'll load fastest
+ if (r_ext_compressed_textures->integer)
+ {
+ char ddsName[MAX_QPATH];
+
+ COM_StripExtension(name, ddsName, MAX_QPATH);
+ Q_strcat(ddsName, MAX_QPATH, ".dds");
+
+ R_LoadDDS(ddsName, pic, width, height, picFormat, numMips);
+
+ // If loaded, we're done.
+ if (*pic)
+ return;
+ }
+
if( *ext )
{
// Look for the correct loader and use it
@@ -2476,6 +2576,8 @@ image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags )
image_t *image;
int width, height;
byte *pic;
+ GLenum picFormat;
+ int picNumMips;
long hash;
if ( !name ) {
@@ -2502,12 +2604,12 @@ image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags )
//
// load the pic from disk
//
- R_LoadImage( name, &pic, &width, &height );
+ R_LoadImage( name, &pic, &width, &height, &picFormat, &picNumMips );
if ( pic == NULL ) {
return NULL;
}
- if (r_normalMapping->integer && !(type == IMGTYPE_NORMAL) && (flags & IMGFLAG_PICMIP) && (flags & IMGFLAG_MIPMAP) && (flags & IMGFLAG_GENNORMALMAP))
+ if (r_normalMapping->integer && (picFormat == GL_RGBA8) && !(type == IMGTYPE_NORMAL) && (flags & IMGFLAG_PICMIP) && (flags & IMGFLAG_MIPMAP) && (flags & IMGFLAG_GENNORMALMAP))
{
char normalName[MAX_QPATH];
image_t *normalImage;
@@ -2610,7 +2712,7 @@ image_t *R_FindImageFile( const char *name, imgType_t type, imgFlags_t flags )
}
}
- image = R_CreateImage( ( char * ) name, pic, width, height, type, flags, 0 );
+ image = R_CreateImage2( ( char * ) name, pic, width, height, picFormat, picNumMips, type, flags, 0 );
ri.Free( pic );
return image;
}
@@ -2912,7 +3014,7 @@ void R_CreateBuiltinImages( void ) {
if (r_cubeMapping->integer)
{
- tr.renderCubeImage = R_CreateImage("*renderCube", NULL, CUBE_MAP_SIZE, CUBE_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, rgbFormat);
+ tr.renderCubeImage = R_CreateImage("*renderCube", NULL, r_cubemapSize->integer, r_cubemapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, rgbFormat);
}
}
}
@@ -3881,6 +3983,8 @@ void R_CropAndNumberImagesInDirectory( char *dir, char *ext, int maxWidth, in
#endif
byte *pic, *temppic;
int width, height, newWidth, newHeight;
+ GLenum picFormat;
+ int picNumMips;
char *pch;
int b,c,d,lastNumber;
int lastBox[2] = {0,0};
@@ -3904,7 +4008,7 @@ void R_CropAndNumberImagesInDirectory( char *dir, char *ext, int maxWidth, in
Com_sprintf( filename, sizeof( filename ), "%s/%s", dir, fileList[j] );
ri.Printf( PRINT_ALL, "...cropping '%s'.. ", filename );
- R_LoadImage( filename, &pic, &width, &height );
+ R_LoadImage( filename, &pic, &width, &height, &picFormat, &picNumMips );
if ( !pic ) {
ri.Printf( PRINT_ALL, "error reading file, ignoring.\n" );
continue;
diff --git a/MP/code/rend2/tr_image_dds.c b/MP/code/rend2/tr_image_dds.c
new file mode 100644
index 0000000..26318be
--- /dev/null
+++ b/MP/code/rend2/tr_image_dds.c
@@ -0,0 +1,498 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+ 2015 James Canete
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Quake III Arena source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+#include "tr_local.h"
+
+typedef unsigned int ui32_t;
+
+typedef struct ddsHeader_s
+{
+ ui32_t headerSize;
+ ui32_t flags;
+ ui32_t height;
+ ui32_t width;
+ ui32_t pitchOrFirstMipSize;
+ ui32_t volumeDepth;
+ ui32_t numMips;
+ ui32_t reserved1[11];
+ ui32_t always_0x00000020;
+ ui32_t pixelFormatFlags;
+ ui32_t fourCC;
+ ui32_t rgbBitCount;
+ ui32_t rBitMask;
+ ui32_t gBitMask;
+ ui32_t bBitMask;
+ ui32_t aBitMask;
+ ui32_t caps;
+ ui32_t caps2;
+ ui32_t caps3;
+ ui32_t caps4;
+ ui32_t reserved2;
+}
+ddsHeader_t;
+
+// flags:
+#define _DDSFLAGS_REQUIRED 0x001007
+#define _DDSFLAGS_PITCH 0x8
+#define _DDSFLAGS_MIPMAPCOUNT 0x20000
+#define _DDSFLAGS_FIRSTMIPSIZE 0x80000
+#define _DDSFLAGS_VOLUMEDEPTH 0x800000
+
+// pixelFormatFlags:
+#define DDSPF_ALPHAPIXELS 0x1
+#define DDSPF_ALPHA 0x2
+#define DDSPF_FOURCC 0x4
+#define DDSPF_RGB 0x40
+#define DDSPF_YUV 0x200
+#define DDSPF_LUMINANCE 0x20000
+
+// caps:
+#define DDSCAPS_COMPLEX 0x8
+#define DDSCAPS_MIPMAP 0x400000
+#define DDSCAPS_REQUIRED 0x1000
+
+// caps2:
+#define DDSCAPS2_CUBEMAP 0xFE00
+#define DDSCAPS2_VOLUME 0x200000
+
+typedef struct ddsHeaderDxt10_s
+{
+ ui32_t dxgiFormat;
+ ui32_t dimensions;
+ ui32_t miscFlags;
+ ui32_t arraySize;
+ ui32_t miscFlags2;
+}
+ddsHeaderDxt10_t;
+
+// dxgiFormat
+// from http://msdn.microsoft.com/en-us/library/windows/desktop/bb173059%28v=vs.85%29.aspx
+typedef enum DXGI_FORMAT {
+ DXGI_FORMAT_UNKNOWN = 0,
+ DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
+ DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
+ DXGI_FORMAT_R32G32B32A32_UINT = 3,
+ DXGI_FORMAT_R32G32B32A32_SINT = 4,
+ DXGI_FORMAT_R32G32B32_TYPELESS = 5,
+ DXGI_FORMAT_R32G32B32_FLOAT = 6,
+ DXGI_FORMAT_R32G32B32_UINT = 7,
+ DXGI_FORMAT_R32G32B32_SINT = 8,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
+ DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
+ DXGI_FORMAT_R16G16B16A16_UNORM = 11,
+ DXGI_FORMAT_R16G16B16A16_UINT = 12,
+ DXGI_FORMAT_R16G16B16A16_SNORM = 13,
+ DXGI_FORMAT_R16G16B16A16_SINT = 14,
+ DXGI_FORMAT_R32G32_TYPELESS = 15,
+ DXGI_FORMAT_R32G32_FLOAT = 16,
+ DXGI_FORMAT_R32G32_UINT = 17,
+ DXGI_FORMAT_R32G32_SINT = 18,
+ DXGI_FORMAT_R32G8X24_TYPELESS = 19,
+ DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
+ DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
+ DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
+ DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
+ DXGI_FORMAT_R10G10B10A2_UNORM = 24,
+ DXGI_FORMAT_R10G10B10A2_UINT = 25,
+ DXGI_FORMAT_R11G11B10_FLOAT = 26,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
+ DXGI_FORMAT_R8G8B8A8_UNORM = 28,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
+ DXGI_FORMAT_R8G8B8A8_UINT = 30,
+ DXGI_FORMAT_R8G8B8A8_SNORM = 31,
+ DXGI_FORMAT_R8G8B8A8_SINT = 32,
+ DXGI_FORMAT_R16G16_TYPELESS = 33,
+ DXGI_FORMAT_R16G16_FLOAT = 34,
+ DXGI_FORMAT_R16G16_UNORM = 35,
+ DXGI_FORMAT_R16G16_UINT = 36,
+ DXGI_FORMAT_R16G16_SNORM = 37,
+ DXGI_FORMAT_R16G16_SINT = 38,
+ DXGI_FORMAT_R32_TYPELESS = 39,
+ DXGI_FORMAT_D32_FLOAT = 40,
+ DXGI_FORMAT_R32_FLOAT = 41,
+ DXGI_FORMAT_R32_UINT = 42,
+ DXGI_FORMAT_R32_SINT = 43,
+ DXGI_FORMAT_R24G8_TYPELESS = 44,
+ DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
+ DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
+ DXGI_FORMAT_R8G8_TYPELESS = 48,
+ DXGI_FORMAT_R8G8_UNORM = 49,
+ DXGI_FORMAT_R8G8_UINT = 50,
+ DXGI_FORMAT_R8G8_SNORM = 51,
+ DXGI_FORMAT_R8G8_SINT = 52,
+ DXGI_FORMAT_R16_TYPELESS = 53,
+ DXGI_FORMAT_R16_FLOAT = 54,
+ DXGI_FORMAT_D16_UNORM = 55,
+ DXGI_FORMAT_R16_UNORM = 56,
+ DXGI_FORMAT_R16_UINT = 57,
+ DXGI_FORMAT_R16_SNORM = 58,
+ DXGI_FORMAT_R16_SINT = 59,
+ DXGI_FORMAT_R8_TYPELESS = 60,
+ DXGI_FORMAT_R8_UNORM = 61,
+ DXGI_FORMAT_R8_UINT = 62,
+ DXGI_FORMAT_R8_SNORM = 63,
+ DXGI_FORMAT_R8_SINT = 64,
+ DXGI_FORMAT_A8_UNORM = 65,
+ DXGI_FORMAT_R1_UNORM = 66,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
+ DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
+ DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
+ DXGI_FORMAT_BC1_TYPELESS = 70,
+ DXGI_FORMAT_BC1_UNORM = 71,
+ DXGI_FORMAT_BC1_UNORM_SRGB = 72,
+ DXGI_FORMAT_BC2_TYPELESS = 73,
+ DXGI_FORMAT_BC2_UNORM = 74,
+ DXGI_FORMAT_BC2_UNORM_SRGB = 75,
+ DXGI_FORMAT_BC3_TYPELESS = 76,
+ DXGI_FORMAT_BC3_UNORM = 77,
+ DXGI_FORMAT_BC3_UNORM_SRGB = 78,
+ DXGI_FORMAT_BC4_TYPELESS = 79,
+ DXGI_FORMAT_BC4_UNORM = 80,
+ DXGI_FORMAT_BC4_SNORM = 81,
+ DXGI_FORMAT_BC5_TYPELESS = 82,
+ DXGI_FORMAT_BC5_UNORM = 83,
+ DXGI_FORMAT_BC5_SNORM = 84,
+ DXGI_FORMAT_B5G6R5_UNORM = 85,
+ DXGI_FORMAT_B5G5R5A1_UNORM = 86,
+ DXGI_FORMAT_B8G8R8A8_UNORM = 87,
+ DXGI_FORMAT_B8G8R8X8_UNORM = 88,
+ DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
+ DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
+ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
+ DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
+ DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
+ DXGI_FORMAT_BC6H_TYPELESS = 94,
+ DXGI_FORMAT_BC6H_UF16 = 95,
+ DXGI_FORMAT_BC6H_SF16 = 96,
+ DXGI_FORMAT_BC7_TYPELESS = 97,
+ DXGI_FORMAT_BC7_UNORM = 98,
+ DXGI_FORMAT_BC7_UNORM_SRGB = 99,
+ DXGI_FORMAT_AYUV = 100,
+ DXGI_FORMAT_Y410 = 101,
+ DXGI_FORMAT_Y416 = 102,
+ DXGI_FORMAT_NV12 = 103,
+ DXGI_FORMAT_P010 = 104,
+ DXGI_FORMAT_P016 = 105,
+ DXGI_FORMAT_420_OPAQUE = 106,
+ DXGI_FORMAT_YUY2 = 107,
+ DXGI_FORMAT_Y210 = 108,
+ DXGI_FORMAT_Y216 = 109,
+ DXGI_FORMAT_NV11 = 110,
+ DXGI_FORMAT_AI44 = 111,
+ DXGI_FORMAT_IA44 = 112,
+ DXGI_FORMAT_P8 = 113,
+ DXGI_FORMAT_A8P8 = 114,
+ DXGI_FORMAT_B4G4R4A4_UNORM = 115,
+ DXGI_FORMAT_FORCE_UINT = 0xffffffffUL
+} DXGI_FORMAT;
+
+#define EncodeFourCC(x) ((((ui32_t)((x)[0])) ) | \
+ (((ui32_t)((x)[1])) << 8 ) | \
+ (((ui32_t)((x)[2])) << 16) | \
+ (((ui32_t)((x)[3])) << 24) )
+
+
+void R_LoadDDS ( const char *filename, byte **pic, int *width, int *height, GLenum *picFormat, int *numMips )
+{
+ union {
+ byte *b;
+ void *v;
+ } buffer;
+ int len;
+ ddsHeader_t *ddsHeader = NULL;
+ ddsHeaderDxt10_t *ddsHeaderDxt10 = NULL;
+ byte *data;
+
+ if (!picFormat)
+ {
+ ri.Printf(PRINT_ERROR, "R_LoadDDS() called without picFormat parameter!");
+ return;
+ }
+
+ if (width)
+ *width = 0;
+ if (height)
+ *height = 0;
+ if (picFormat)
+ *picFormat = GL_RGBA8;
+ if (numMips)
+ *numMips = 1;
+
+ *pic = NULL;
+
+ //
+ // load the file
+ //
+ len = ri.FS_ReadFile( ( char * ) filename, &buffer.v);
+ if (!buffer.b || len < 0) {
+ return;
+ }
+
+ //
+ // reject files that are too small to hold even a header
+ //
+ if (len < 4 + sizeof(*ddsHeader))
+ {
+ ri.Printf(PRINT_ALL, "File %s is too small to be a DDS file.\n", filename);
+ ri.FS_FreeFile(buffer.v);
+ return;
+ }
+
+ //
+ // reject files that don't start with "DDS "
+ //
+ if (*((ui32_t *)(buffer.b)) != EncodeFourCC("DDS "))
+ {
+ ri.Printf(PRINT_ALL, "File %s is not a DDS file.\n", filename);
+ ri.FS_FreeFile(buffer.v);
+ return;
+ }
+
+ //
+ // parse header and dx10 header if available
+ //
+ ddsHeader = (ddsHeader_t *)(buffer.b + 4);
+ if ((ddsHeader->pixelFormatFlags & DDSPF_FOURCC) && ddsHeader->fourCC == EncodeFourCC("DX10"))
+ {
+ if (len < 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10))
+ {
+ ri.Printf(PRINT_ALL, "File %s indicates a DX10 header it is too small to contain.\n", filename);
+ ri.FS_FreeFile(buffer.v);
+ return;
+ }
+
+ ddsHeaderDxt10 = (ddsHeaderDxt10_t *)(buffer.b + 4 + sizeof(ddsHeader_t));
+ data = buffer.b + 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10);
+ len -= 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10);
+ }
+ else
+ {
+ data = buffer.b + 4 + sizeof(*ddsHeader);
+ len -= 4 + sizeof(*ddsHeader);
+ }
+
+ if (width)
+ *width = ddsHeader->width;
+ if (height)
+ *height = ddsHeader->height;
+
+ if (numMips)
+ {
+ if (ddsHeader->flags & _DDSFLAGS_MIPMAPCOUNT)
+ *numMips = ddsHeader->numMips;
+ else
+ *numMips = 1;
+ }
+
+ // FIXME: handle cube map
+ //if ((ddsHeader->caps2 & DDSCAPS2_CUBEMAP) == DDSCAPS2_CUBEMAP)
+
+ //
+ // Convert DXGI format/FourCC into OpenGL format
+ //
+ if (ddsHeaderDxt10)
+ {
+ switch (ddsHeaderDxt10->dxgiFormat)
+ {
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ // FIXME: check for GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
+ *picFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ break;
+
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ // FIXME: check for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
+ *picFormat = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
+ break;
+
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ break;
+
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ *picFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+ break;
+
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ break;
+
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ *picFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+ break;
+
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ *picFormat = GL_COMPRESSED_RED_RGTC1;
+ break;
+
+ case DXGI_FORMAT_BC4_SNORM:
+ *picFormat = GL_COMPRESSED_SIGNED_RED_RGTC1;
+ break;
+
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ *picFormat = GL_COMPRESSED_RG_RGTC2;
+ break;
+
+ case DXGI_FORMAT_BC5_SNORM:
+ *picFormat = GL_COMPRESSED_SIGNED_RG_RGTC2;
+ break;
+
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ *picFormat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB;
+ break;
+
+ case DXGI_FORMAT_BC6H_SF16:
+ *picFormat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB;
+ break;
+
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ *picFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
+ break;
+
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ *picFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB;
+ break;
+
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ *picFormat = GL_SRGB8_ALPHA8_EXT;
+ break;
+
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ *picFormat = GL_RGBA8;
+ break;
+
+ default:
+ ri.Printf(PRINT_ALL, "DDS File %s has unsupported DXGI format %d.", filename, ddsHeaderDxt10->dxgiFormat);
+ ri.FS_FreeFile(buffer.v);
+ return;
+ break;
+ }
+ }
+ else
+ {
+ if (ddsHeader->pixelFormatFlags & DDSPF_FOURCC)
+ {
+ if (ddsHeader->fourCC == EncodeFourCC("DXT1"))
+ *picFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ else if (ddsHeader->fourCC == EncodeFourCC("DXT2"))
+ *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ else if (ddsHeader->fourCC == EncodeFourCC("DXT3"))
+ *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ else if (ddsHeader->fourCC == EncodeFourCC("DXT4"))
+ *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ else if (ddsHeader->fourCC == EncodeFourCC("DXT5"))
+ *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ else if (ddsHeader->fourCC == EncodeFourCC("ATI1"))
+ *picFormat = GL_COMPRESSED_RED_RGTC1;
+ else if (ddsHeader->fourCC == EncodeFourCC("BC4U"))
+ *picFormat = GL_COMPRESSED_RED_RGTC1;
+ else if (ddsHeader->fourCC == EncodeFourCC("BC4S"))
+ *picFormat = GL_COMPRESSED_SIGNED_RED_RGTC1;
+ else if (ddsHeader->fourCC == EncodeFourCC("ATI2"))
+ *picFormat = GL_COMPRESSED_RG_RGTC2;
+ else if (ddsHeader->fourCC == EncodeFourCC("BC5U"))
+ *picFormat = GL_COMPRESSED_RG_RGTC2;
+ else if (ddsHeader->fourCC == EncodeFourCC("BC5S"))
+ *picFormat = GL_COMPRESSED_SIGNED_RG_RGTC2;
+ else
+ {
+ ri.Printf(PRINT_ALL, "DDS File %s has unsupported FourCC.", filename);
+ ri.FS_FreeFile(buffer.v);
+ return;
+ }
+ }
+ else if (ddsHeader->pixelFormatFlags == (DDSPF_RGB | DDSPF_ALPHAPIXELS)
+ && ddsHeader->rgbBitCount == 32
+ && ddsHeader->rBitMask == 0x000000ff
+ && ddsHeader->gBitMask == 0x0000ff00
+ && ddsHeader->bBitMask == 0x00ff0000
+ && ddsHeader->aBitMask == 0xff000000)
+ {
+ *picFormat = GL_RGBA8;
+ }
+ else
+ {
+ ri.Printf(PRINT_ALL, "DDS File %s has unsupported RGBA format.", filename);
+ ri.FS_FreeFile(buffer.v);
+ return;
+ }
+ }
+
+ *pic = ri.Z_Malloc(len);
+ Com_Memcpy(*pic, data, len);
+
+ ri.FS_FreeFile(buffer.v);
+}
+
+void R_SaveDDS(const char *filename, byte *pic, int width, int height, int depth)
+{
+ byte *data;
+ ddsHeader_t *ddsHeader;
+ int picSize, size;
+
+ if (!depth)
+ depth = 1;
+
+ picSize = width * height * depth * 4;
+ size = 4 + sizeof(*ddsHeader) + picSize;
+ data = ri.Z_Malloc(size);
+
+ data[0] = 'D';
+ data[1] = 'D';
+ data[2] = 'S';
+ data[3] = ' ';
+
+ ddsHeader = (ddsHeader_t *)(data + 4);
+ memset(ddsHeader, 0, sizeof(ddsHeader_t));
+
+ ddsHeader->headerSize = 0x7c;
+ ddsHeader->flags = _DDSFLAGS_REQUIRED;
+ ddsHeader->height = height;
+ ddsHeader->width = width;
+ ddsHeader->always_0x00000020 = 0x00000020;
+ ddsHeader->caps = DDSCAPS_COMPLEX | DDSCAPS_REQUIRED;
+
+ if (depth == 6)
+ ddsHeader->caps2 = DDSCAPS2_CUBEMAP;
+
+ ddsHeader->pixelFormatFlags = DDSPF_RGB | DDSPF_ALPHAPIXELS;
+ ddsHeader->rgbBitCount = 32;
+ ddsHeader->rBitMask = 0x000000ff;
+ ddsHeader->gBitMask = 0x0000ff00;
+ ddsHeader->bBitMask = 0x00ff0000;
+ ddsHeader->aBitMask = 0xff000000;
+
+ Com_Memcpy(data + 4 + sizeof(*ddsHeader), pic, picSize);
+
+ ri.FS_WriteFile(filename, data, size);
+
+ ri.Free(data);
+}
diff --git a/MP/code/rend2/tr_init.c b/MP/code/rend2/tr_init.c
index 0bae878..56a1adb 100644
--- a/MP/code/rend2/tr_init.c
+++ b/MP/code/rend2/tr_init.c
@@ -161,6 +161,7 @@ cvar_t *r_specularMapping;
cvar_t *r_deluxeMapping;
cvar_t *r_parallaxMapping;
cvar_t *r_cubeMapping;
+cvar_t *r_cubemapSize;
cvar_t *r_specularIsMetallic;
cvar_t *r_glossIsRoughness;
cvar_t *r_baseNormalX;
@@ -903,6 +904,33 @@ void R_ScreenShotJPEG_f (void) {
}
}
+/*
+==================
+R_ExportCubemaps
+==================
+*/
+void R_ExportCubemaps(void)
+{
+ exportCubemapsCommand_t *cmd;
+
+ cmd = R_GetCommandBuffer(sizeof(*cmd));
+ if (!cmd) {
+ return;
+ }
+ cmd->commandId = RC_EXPORT_CUBEMAPS;
+}
+
+
+/*
+==================
+R_ExportCubemaps_f
+==================
+*/
+void R_ExportCubemaps_f(void)
+{
+ R_ExportCubemaps();
+}
+
//============================================================================
/*
@@ -1327,6 +1355,7 @@ void R_Register( void ) {
r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
+ r_cubemapSize = ri.Cvar_Get( "r_cubemapSize", "128", CVAR_ARCHIVE | CVAR_LATCH );
r_specularIsMetallic = ri.Cvar_Get( "r_specularIsMetallic", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_glossIsRoughness = ri.Cvar_Get("r_glossIsRoughness", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_baseNormalX = ri.Cvar_Get( "r_baseNormalX", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
@@ -1487,6 +1516,7 @@ void R_Register( void ) {
ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
ri.Cmd_AddCommand( "minimize", GLimp_Minimize );
ri.Cmd_AddCommand( "gfxmeminfo", GfxMemInfo_f );
+ ri.Cmd_AddCommand( "exportCubemaps", R_ExportCubemaps_f );
ri.Cmd_AddCommand( "taginfo", R_TagInfo_f );
// Ridah
@@ -1640,6 +1670,7 @@ void RE_Shutdown( qboolean destroyWindow ) {
ri.Cmd_RemoveCommand( "modelist" );
ri.Cmd_RemoveCommand( "shaderstate" );
ri.Cmd_RemoveCommand( "gfxmeminfo" );
+ ri.Cmd_RemoveCommand( "exportCubemaps" );
ri.Cmd_RemoveCommand( "taginfo" );
// Ridah
diff --git a/MP/code/rend2/tr_local.h b/MP/code/rend2/tr_local.h
index 7411e11..da99449 100644
--- a/MP/code/rend2/tr_local.h
+++ b/MP/code/rend2/tr_local.h
@@ -61,8 +61,6 @@ typedef unsigned int glIndex_t;
#define MAX_CALC_PSHADOWS 64
#define MAX_DRAWN_PSHADOWS 32 // do not increase past 32, because bit flags are used on surfaces
#define PSHADOW_MAP_SIZE 512
-#define CUBE_MAP_MIPS 7
-#define CUBE_MAP_SIZE (1 << CUBE_MAP_MIPS)
#define USE_VERT_TANGENT_SPACE
#define USE_OVERBRIGHT
@@ -1992,6 +1990,7 @@ extern cvar_t *r_specularMapping;
extern cvar_t *r_deluxeMapping;
extern cvar_t *r_parallaxMapping;
extern cvar_t *r_cubeMapping;
+extern cvar_t *r_cubemapSize;
extern cvar_t *r_specularIsMetallic;
extern cvar_t *r_glossIsRoughness;
extern cvar_t *r_baseNormalX;
@@ -2689,6 +2688,10 @@ typedef struct {
viewParms_t viewParms;
} postProcessCommand_t;
+typedef struct {
+ int commandId;
+} exportCubemapsCommand_t;
+
typedef enum {
RC_END_OF_LIST,
RC_SET_COLOR,
@@ -2703,7 +2706,8 @@ typedef enum {
RC_COLORMASK,
RC_CLEARDEPTH,
RC_CAPSHADOWMAP,
- RC_POSTPROCESS
+ RC_POSTPROCESS,
+ RC_EXPORT_CUBEMAPS
} renderCommand_t;
diff --git a/SP/Makefile b/SP/Makefile
index 94205e6..13284eb 100644
--- a/SP/Makefile
+++ b/SP/Makefile
@@ -1723,6 +1723,7 @@ Q3R2OBJ = \
$(B)/rend2/tr_image_pcx.o \
$(B)/rend2/tr_image_png.o \
$(B)/rend2/tr_image_tga.o \
+ $(B)/rend2/tr_image_dds.o \
$(B)/rend2/tr_init.o \
$(B)/rend2/tr_light.o \
$(B)/rend2/tr_main.o \
diff --git a/SP/code/rend2/tr_backend.c b/SP/code/rend2/tr_backend.c
index 146f35d..3f02686 100644
--- a/SP/code/rend2/tr_backend.c
+++ b/SP/code/rend2/tr_backend.c
@@ -2257,6 +2257,64 @@ const void *RB_PostProcess(const void *data)
return (const void *)(cmd + 1);
}
+// FIXME: put this function declaration elsewhere
+void R_SaveDDS(const char *filename, byte *pic, int width, int height, int depth);
+
+/*
+=============
+RB_ExportCubemaps
+
+=============
+*/
+const void *RB_ExportCubemaps(const void *data)
+{
+ const exportCubemapsCommand_t *cmd = data;
+
+ // finish any 2D drawing if needed
+ if (tess.numIndexes)
+ RB_EndSurface();
+
+ if (!glRefConfig.framebufferObject || !tr.world || tr.numCubemaps == 0)
+ {
+ // do nothing
+ ri.Printf(PRINT_ALL, "Nothing to export!\n");
+ return (const void *)(cmd + 1);
+ }
+
+ if (cmd)
+ {
+ FBO_t *oldFbo = glState.currentFBO;
+ int sideSize = r_cubemapSize->integer * r_cubemapSize->integer * 4;
+ byte *cubemapPixels = ri.Z_Malloc(sideSize * 6);
+ int i, j;
+
+ FBO_Bind(tr.renderCubeFbo);
+
+ for (i = 0; i < tr.numCubemaps; i++)
+ {
+ char filename[MAX_QPATH];
+ cubemap_t *cubemap = &tr.cubemaps[i];
+ unsigned char *p = cubemapPixels;
+
+ for (j = 0; j < 6; j++)
+ {
+ qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + j, cubemap->image->texnum, 0);
+ qglReadPixels(0, 0, r_cubemapSize->integer, r_cubemapSize->integer, GL_RGBA, GL_UNSIGNED_BYTE, p);
+ p += sideSize;
+ }
+
+ Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", tr.world->baseName, i);
+ R_SaveDDS(filename, cubemapPixels, r_cubemapSize->integer, r_cubemapSize->integer, 6);
+ ri.Printf(PRINT_ALL, "Saved cubemap %d as %s\n", i, filename);
+ }
+
+ FBO_Bind(oldFbo);
+
+ ri.Free(cubemapPixels);
+ }
+
+ return (const void *)(cmd + 1);
+}
/*
====================
@@ -2308,6 +2366,9 @@ void RB_ExecuteRenderCommands( const void *data ) {
case RC_POSTPROCESS:
data = RB_PostProcess(data);
break;
+ case RC_EXPORT_CUBEMAPS:
+ data = RB_ExportCubemaps(data);
+ break;
case RC_END_OF_LIST:
default:
// finish any 2D drawing if needed
diff --git a/SP/code/rend2/tr_bsp.c b/SP/code/rend2/tr_bsp.c
index 8fc2987..8bd2c00 100644
--- a/SP/code/rend2/tr_bsp.c
+++ b/SP/code/rend2/tr_bsp.c
@@ -3412,7 +3412,7 @@ void R_RenderAllCubemaps(void)
for (i = 0; i < tr.numCubemaps; i++)
{
- tr.cubemaps[i].image = R_CreateImage(va("*cubeMap%d", i), NULL, CUBE_MAP_SIZE, CUBE_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, GL_RGBA8);
+ 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);
}
ri.Printf(PRINT_ALL, "Total cubemaps: %d\n", tr.numCubemaps );
diff --git a/SP/code/rend2/tr_image.c b/SP/code/rend2/tr_image.c
index f5d6c98..aa228d3 100644
--- a/SP/code/rend2/tr_image.c
+++ b/SP/code/rend2/tr_image.c
@@ -1771,13 +1771,16 @@ static qboolean RawImage_HasAlpha(const byte *scan, int numPixels)
return qfalse;
}
-static GLenum RawImage_GetFormat(const byte *data, int numPixels, qboolean lightMap, imgType_t type, imgFlags_t flags)
+static GLenum RawImage_GetFormat(const byte *data, int numPixels, GLenum picFormat, qboolean lightMap, imgType_t type, imgFlags_t flags)
{
int samples = 3;
GLenum internalFormat = GL_RGB;
qboolean forceNoCompression = (flags & IMGFLAG_NO_COMPRESSION);
qboolean normalmap = (type == IMGTYPE_NORMAL || type == IMGTYPE_NORMALHEIGHT);
+ if (picFormat != GL_RGBA8)
+ return picFormat;
+
if(normalmap)
{
if ((type == IMGTYPE_NORMALHEIGHT) && RawImage_HasAlpha(data, numPixels))
@@ -2015,11 +2018,80 @@ static void RawImage_UploadToRgtc2Texture(byte *data, int width, int height, int
ri.Hunk_FreeTempMemory(compressedData);
}
-static void RawImage_UploadTexture( byte *data, int x, int y, int width, int height, GLenum internalFormat, imgType_t type, imgFlags_t flags, qboolean subtexture )
+static void RawImage_UploadTexture( 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;
qboolean rgtc = (internalFormat == GL_COMPRESSED_RG_RGTC2);
+ if (data && picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT)
+ {
+ int bytesPer4x4Block = 0;
+ int miplevel = 0;
+
+ switch (picFormat)
+ {
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+ case GL_COMPRESSED_RED_RGTC1:
+ case GL_COMPRESSED_SIGNED_RED_RGTC1:
+ bytesPer4x4Block = 8;
+ break;
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_RG_RGTC2:
+ case GL_COMPRESSED_SIGNED_RG_RGTC2:
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB:
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB:
+ case GL_COMPRESSED_RGBA_BPTC_UNORM_ARB:
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB:
+ bytesPer4x4Block = 16;
+ break;
+ default:
+ ri.Printf(PRINT_ALL, "Unsupported texture format %08x\n", picFormat);
+ return;
+ break;
+ }
+
+ if (flags & IMGFLAG_PICMIP)
+ {
+ 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))
+ numMips = 1;
+
+ for (miplevel = 0; miplevel < numMips; miplevel++)
+ {
+ int size = ((width + 3) / 4) * ((height + 3) / 4) * bytesPer4x4Block;
+
+ if (subtexture)
+ qglCompressedTexSubImage2DARB(GL_TEXTURE_2D, miplevel, x, y, width, height, internalFormat, size, data);
+ else
+ qglCompressedTexImage2DARB(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:
@@ -2051,29 +2123,20 @@ static void RawImage_UploadTexture( byte *data, int x, int y, int width, int hei
if (flags & IMGFLAG_MIPMAP)
{
- int miplevel;
+ int miplevel = 0;
- miplevel = 0;
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 >>= 1;
- height >>= 1;
- if (width < 1)
- width = 1;
- if (height < 1)
- height = 1;
+ width = MAX(1, width >> 1);
+ height = MAX(1, height >> 1);
miplevel++;
if ( data && r_colorMipLevels->integer )
@@ -2102,7 +2165,7 @@ Upload32
===============
*/
-static void Upload32(byte *data, int x, int y, int width, int height, image_t *image)
+static void Upload32(byte *data, int x, int y, int width, int height, GLenum picFormat, int numMips, image_t *image)
{
byte *resampledBuffer = NULL;
int i, c;
@@ -2132,11 +2195,16 @@ static void Upload32(byte *data, int x, int y, int width, int height, image_t *i
if (!data)
{
RawImage_ScaleToPower2(NULL, &width, &height, type, flags, NULL);
- RawImage_UploadTexture(NULL, 0, 0, width, height, internalFormat, type, flags, qfalse);
+ RawImage_UploadTexture(NULL, 0, 0, width, height, GL_RGBA8, 0, internalFormat, type, flags, qfalse);
goto done;
}
else if (!subtexture)
{
+ if (picFormat != GL_RGBA8 && picFormat != GL_SRGB8_ALPHA8_EXT)
+ {
+ RawImage_UploadTexture(data, 0, 0, width, height, picFormat, numMips, internalFormat, type, flags, qfalse);
+ goto done;
+ }
notScaled = RawImage_ScaleToPower2(&data, &width, &height, type, flags, &resampledBuffer);
}
@@ -2174,12 +2242,12 @@ static void Upload32(byte *data, int x, int y, int width, int height, image_t *i
if (subtexture)
{
// FIXME: Incorrect if original texture was not a power of 2 texture or picmipped
- RawImage_UploadTexture(data, x, y, width, height, internalFormat, type, flags, qtrue);
+ RawImage_UploadTexture(data, x, y, width, height, GL_RGBA8, 0, internalFormat, type, flags, qtrue);
GL_CheckErrors();
return;
}
- RawImage_UploadTexture(data, 0, 0, width, height, internalFormat, type, flags, qfalse);
+ RawImage_UploadTexture(data, 0, 0, width, height, GL_RGBA8, 0, internalFormat, type, flags, qfalse);
done:
@@ -2231,13 +2299,12 @@ done:
/*
================
-R_CreateImage
+R_CreateImageExt2
This is the only way any image_t are created
================
*/
-image_t *R_CreateImageExt( const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat, qboolean characterMip )
-{
+image_t *R_CreateImageExt2( const char *name, byte *pic, int width, int height, GLenum picFormat, int numMips, imgType_t type, imgFlags_t flags, int internalFormat, qboolean characterMip ) {
image_t *image;
qboolean isLightmap = qfalse;
int glWrapClampMode;
@@ -2275,7 +2342,7 @@ image_t *R_CreateImageExt( const char *name, byte *pic, int width, int height, i
if (image->flags & IMGFLAG_CUBEMAP)
internalFormat = GL_RGBA8;
else
- internalFormat = RawImage_GetFormat(pic, width * height, isLightmap, image->type, image->flags);
+ internalFormat = RawImage_GetFormat(pic, width * height, picFormat, isLightmap, image->type, image->flags);
}
image->internalFormat = internalFormat;
@@ -2325,7 +2392,7 @@ image_t *R_CreateImageExt( const char *name, byte *pic, int width, int height, i
}
else
{
- Upload32( pic, 0, 0, image->width, image->height, image );
+ Upload32( pic, 0, 0, image->width, image->height, picFormat, numMips, image );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampMode );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampMode );
@@ -2343,9 +2410,15 @@ image_t *R_CreateImageExt( const char *name, byte *pic, int width, int height, i
return image;
}
-image_t *R_CreateImage( const char *name, byte *pic, int width, int height,
- imgType_t type, imgFlags_t flags, int internalFormat ) {
- return R_CreateImageExt( name, pic, width, height, type, flags, internalFormat, qfalse );
+/*
+================
+R_CreateImage
+
+Wrapper for R_CreateImageExt2(), for the old parameters.
+================
+*/
+image_t *R_CreateImage( const char *name, byte *pic, int width, int height, imgType_t type, imgFlags_t flags, int internalFormat ) {
+ return R_CreateImageExt2(name, pic, width, height, GL_RGBA8, 0, type, flags, internalFormat, qfalse);
}
//----(SA) end
@@ -2358,13 +2431,16 @@ void R_UpdateSubImage( image_t *image, byte *pic, int x, int y, int width, int h
GL_Bind(image);
- Upload32(pic, x, y, width, height, image);
+ Upload32(pic, x, y, width, height, GL_RGBA8, 0, image);
GL_SelectTexture(0);
}
//===================================================================
+// Prototype for dds loader function which isn't common to both renderers
+void R_LoadDDS(const char *filename, byte **pic, int *width, int *height, GLenum *picFormat, int *numMips);
+
typedef struct
{
char *ext;
@@ -2394,7 +2470,7 @@ Loads any of the supported image types into a cannonical
32 bit format.
=================
*/
-void R_LoadImage( const char *name, byte **pic, int *width, int *height )
+void R_LoadImage( const char *name, byte **pic, int *width, int *height, GLenum *picFormat, int *numMips )
{
qboolean orgNameFailed = qfalse;
int orgLoader = -1;
@@ -2406,11 +2482,28 @@ void R_LoadImage( const char *name, byte **pic, int *width, int *height )
*pic = NULL;
*width = 0;
*height = 0;
+ *picFormat = GL_RGBA8;
+ *numMips = 0;
Q_strncpyz( localName, name, MAX_QPATH );
ext = COM_GetExtension( localName );
+ // If compressed textures are enabled, try loading a DDS first, it'll load fastest
+ if (r_ext_compressed_textures->integer)
+ {
+ char ddsName[MAX_QPATH];
+
+ COM_StripExtension(name, ddsName, MAX_QPATH);
+ Q_strcat(ddsName, MAX_QPATH, ".dds");
+
+ R_LoadDDS(ddsName, pic, width, height, picFormat, numMips);
+
+ // If loaded, we're done.
+ if (*pic)
+ return;
+ }
+
if( *ext )
{
// Look for the correct loader and use it
@@ -2478,12 +2571,12 @@ Finds or loads the given image.
Returns NULL if it fails, not a default image.
==============
*/
-
-
image_t *R_FindImageFileExt( const char *name, imgType_t type, imgFlags_t flags, qboolean characterMIP ) {
image_t *image;
int width, height;
byte *pic;
+ GLenum picFormat;
+ int picNumMips;
long hash;
if ( !name ) {
@@ -2513,12 +2606,12 @@ image_t *R_FindImageFileExt( const char *name, imgType_t type, imgFlags_t flags,
//
// load the pic from disk
//
- R_LoadImage( name, &pic, &width, &height );
+ R_LoadImage( name, &pic, &width, &height, &picFormat, &picNumMips );
if ( pic == NULL ) {
return NULL;
}
- if (r_normalMapping->integer && !(type == IMGTYPE_NORMAL) && (flags & IMGFLAG_PICMIP) && (flags & IMGFLAG_MIPMAP) && (flags & IMGFLAG_GENNORMALMAP))
+ if (r_normalMapping->integer && (picFormat == GL_RGBA8) && !(type == IMGTYPE_NORMAL) && (flags & IMGFLAG_PICMIP) && (flags & IMGFLAG_MIPMAP) && (flags & IMGFLAG_GENNORMALMAP))
{
char normalName[MAX_QPATH];
image_t *normalImage;
@@ -2621,7 +2714,7 @@ image_t *R_FindImageFileExt( const char *name, imgType_t type, imgFlags_t flags,
}
}
- image = R_CreateImageExt( ( char * ) name, pic, width, height, type, flags, 0, characterMIP );
+ image = R_CreateImageExt2( ( char * ) name, pic, width, height, picFormat, picNumMips, type, flags, 0, characterMIP );
ri.Free( pic );
return image;
}
@@ -2929,7 +3022,7 @@ void R_CreateBuiltinImages( void ) {
if (r_cubeMapping->integer)
{
- tr.renderCubeImage = R_CreateImage("*renderCube", NULL, CUBE_MAP_SIZE, CUBE_MAP_SIZE, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, rgbFormat);
+ tr.renderCubeImage = R_CreateImage("*renderCube", NULL, r_cubemapSize->integer, r_cubemapSize->integer, IMGTYPE_COLORALPHA, IMGFLAG_NO_COMPRESSION | IMGFLAG_CLAMPTOEDGE | IMGFLAG_MIPMAP | IMGFLAG_CUBEMAP, rgbFormat);
}
}
}
@@ -3898,6 +3991,8 @@ void R_CropAndNumberImagesInDirectory( char *dir, char *ext, int maxWidth, in
#endif
byte *pic, *temppic;
int width, height, newWidth, newHeight;
+ GLenum picFormat;
+ int picNumMips;
char *pch;
int b,c,d,lastNumber;
int lastBox[2] = {0,0};
@@ -3921,7 +4016,7 @@ void R_CropAndNumberImagesInDirectory( char *dir, char *ext, int maxWidth, in
Com_sprintf( filename, sizeof( filename ), "%s/%s", dir, fileList[j] );
ri.Printf( PRINT_ALL, "...cropping '%s'.. ", filename );
- R_LoadImage( filename, &pic, &width, &height );
+ R_LoadImage( filename, &pic, &width, &height, &picFormat, &picNumMips );
if ( !pic ) {
ri.Printf( PRINT_ALL, "error reading file, ignoring.\n" );
continue;
diff --git a/SP/code/rend2/tr_image_dds.c b/SP/code/rend2/tr_image_dds.c
new file mode 100644
index 0000000..26318be
--- /dev/null
+++ b/SP/code/rend2/tr_image_dds.c
@@ -0,0 +1,498 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+ 2015 James Canete
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake III Arena source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Quake III Arena source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+#include "tr_local.h"
+
+typedef unsigned int ui32_t;
+
+typedef struct ddsHeader_s
+{
+ ui32_t headerSize;
+ ui32_t flags;
+ ui32_t height;
+ ui32_t width;
+ ui32_t pitchOrFirstMipSize;
+ ui32_t volumeDepth;
+ ui32_t numMips;
+ ui32_t reserved1[11];
+ ui32_t always_0x00000020;
+ ui32_t pixelFormatFlags;
+ ui32_t fourCC;
+ ui32_t rgbBitCount;
+ ui32_t rBitMask;
+ ui32_t gBitMask;
+ ui32_t bBitMask;
+ ui32_t aBitMask;
+ ui32_t caps;
+ ui32_t caps2;
+ ui32_t caps3;
+ ui32_t caps4;
+ ui32_t reserved2;
+}
+ddsHeader_t;
+
+// flags:
+#define _DDSFLAGS_REQUIRED 0x001007
+#define _DDSFLAGS_PITCH 0x8
+#define _DDSFLAGS_MIPMAPCOUNT 0x20000
+#define _DDSFLAGS_FIRSTMIPSIZE 0x80000
+#define _DDSFLAGS_VOLUMEDEPTH 0x800000
+
+// pixelFormatFlags:
+#define DDSPF_ALPHAPIXELS 0x1
+#define DDSPF_ALPHA 0x2
+#define DDSPF_FOURCC 0x4
+#define DDSPF_RGB 0x40
+#define DDSPF_YUV 0x200
+#define DDSPF_LUMINANCE 0x20000
+
+// caps:
+#define DDSCAPS_COMPLEX 0x8
+#define DDSCAPS_MIPMAP 0x400000
+#define DDSCAPS_REQUIRED 0x1000
+
+// caps2:
+#define DDSCAPS2_CUBEMAP 0xFE00
+#define DDSCAPS2_VOLUME 0x200000
+
+typedef struct ddsHeaderDxt10_s
+{
+ ui32_t dxgiFormat;
+ ui32_t dimensions;
+ ui32_t miscFlags;
+ ui32_t arraySize;
+ ui32_t miscFlags2;
+}
+ddsHeaderDxt10_t;
+
+// dxgiFormat
+// from http://msdn.microsoft.com/en-us/library/windows/desktop/bb173059%28v=vs.85%29.aspx
+typedef enum DXGI_FORMAT {
+ DXGI_FORMAT_UNKNOWN = 0,
+ DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
+ DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
+ DXGI_FORMAT_R32G32B32A32_UINT = 3,
+ DXGI_FORMAT_R32G32B32A32_SINT = 4,
+ DXGI_FORMAT_R32G32B32_TYPELESS = 5,
+ DXGI_FORMAT_R32G32B32_FLOAT = 6,
+ DXGI_FORMAT_R32G32B32_UINT = 7,
+ DXGI_FORMAT_R32G32B32_SINT = 8,
+ DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
+ DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
+ DXGI_FORMAT_R16G16B16A16_UNORM = 11,
+ DXGI_FORMAT_R16G16B16A16_UINT = 12,
+ DXGI_FORMAT_R16G16B16A16_SNORM = 13,
+ DXGI_FORMAT_R16G16B16A16_SINT = 14,
+ DXGI_FORMAT_R32G32_TYPELESS = 15,
+ DXGI_FORMAT_R32G32_FLOAT = 16,
+ DXGI_FORMAT_R32G32_UINT = 17,
+ DXGI_FORMAT_R32G32_SINT = 18,
+ DXGI_FORMAT_R32G8X24_TYPELESS = 19,
+ DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
+ DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
+ DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
+ DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
+ DXGI_FORMAT_R10G10B10A2_UNORM = 24,
+ DXGI_FORMAT_R10G10B10A2_UINT = 25,
+ DXGI_FORMAT_R11G11B10_FLOAT = 26,
+ DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
+ DXGI_FORMAT_R8G8B8A8_UNORM = 28,
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
+ DXGI_FORMAT_R8G8B8A8_UINT = 30,
+ DXGI_FORMAT_R8G8B8A8_SNORM = 31,
+ DXGI_FORMAT_R8G8B8A8_SINT = 32,
+ DXGI_FORMAT_R16G16_TYPELESS = 33,
+ DXGI_FORMAT_R16G16_FLOAT = 34,
+ DXGI_FORMAT_R16G16_UNORM = 35,
+ DXGI_FORMAT_R16G16_UINT = 36,
+ DXGI_FORMAT_R16G16_SNORM = 37,
+ DXGI_FORMAT_R16G16_SINT = 38,
+ DXGI_FORMAT_R32_TYPELESS = 39,
+ DXGI_FORMAT_D32_FLOAT = 40,
+ DXGI_FORMAT_R32_FLOAT = 41,
+ DXGI_FORMAT_R32_UINT = 42,
+ DXGI_FORMAT_R32_SINT = 43,
+ DXGI_FORMAT_R24G8_TYPELESS = 44,
+ DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
+ DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
+ DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
+ DXGI_FORMAT_R8G8_TYPELESS = 48,
+ DXGI_FORMAT_R8G8_UNORM = 49,
+ DXGI_FORMAT_R8G8_UINT = 50,
+ DXGI_FORMAT_R8G8_SNORM = 51,
+ DXGI_FORMAT_R8G8_SINT = 52,
+ DXGI_FORMAT_R16_TYPELESS = 53,
+ DXGI_FORMAT_R16_FLOAT = 54,
+ DXGI_FORMAT_D16_UNORM = 55,
+ DXGI_FORMAT_R16_UNORM = 56,
+ DXGI_FORMAT_R16_UINT = 57,
+ DXGI_FORMAT_R16_SNORM = 58,
+ DXGI_FORMAT_R16_SINT = 59,
+ DXGI_FORMAT_R8_TYPELESS = 60,
+ DXGI_FORMAT_R8_UNORM = 61,
+ DXGI_FORMAT_R8_UINT = 62,
+ DXGI_FORMAT_R8_SNORM = 63,
+ DXGI_FORMAT_R8_SINT = 64,
+ DXGI_FORMAT_A8_UNORM = 65,
+ DXGI_FORMAT_R1_UNORM = 66,
+ DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
+ DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
+ DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
+ DXGI_FORMAT_BC1_TYPELESS = 70,
+ DXGI_FORMAT_BC1_UNORM = 71,
+ DXGI_FORMAT_BC1_UNORM_SRGB = 72,
+ DXGI_FORMAT_BC2_TYPELESS = 73,
+ DXGI_FORMAT_BC2_UNORM = 74,
+ DXGI_FORMAT_BC2_UNORM_SRGB = 75,
+ DXGI_FORMAT_BC3_TYPELESS = 76,
+ DXGI_FORMAT_BC3_UNORM = 77,
+ DXGI_FORMAT_BC3_UNORM_SRGB = 78,
+ DXGI_FORMAT_BC4_TYPELESS = 79,
+ DXGI_FORMAT_BC4_UNORM = 80,
+ DXGI_FORMAT_BC4_SNORM = 81,
+ DXGI_FORMAT_BC5_TYPELESS = 82,
+ DXGI_FORMAT_BC5_UNORM = 83,
+ DXGI_FORMAT_BC5_SNORM = 84,
+ DXGI_FORMAT_B5G6R5_UNORM = 85,
+ DXGI_FORMAT_B5G5R5A1_UNORM = 86,
+ DXGI_FORMAT_B8G8R8A8_UNORM = 87,
+ DXGI_FORMAT_B8G8R8X8_UNORM = 88,
+ DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
+ DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
+ DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
+ DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
+ DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
+ DXGI_FORMAT_BC6H_TYPELESS = 94,
+ DXGI_FORMAT_BC6H_UF16 = 95,
+ DXGI_FORMAT_BC6H_SF16 = 96,
+ DXGI_FORMAT_BC7_TYPELESS = 97,
+ DXGI_FORMAT_BC7_UNORM = 98,
+ DXGI_FORMAT_BC7_UNORM_SRGB = 99,
+ DXGI_FORMAT_AYUV = 100,
+ DXGI_FORMAT_Y410 = 101,
+ DXGI_FORMAT_Y416 = 102,
+ DXGI_FORMAT_NV12 = 103,
+ DXGI_FORMAT_P010 = 104,
+ DXGI_FORMAT_P016 = 105,
+ DXGI_FORMAT_420_OPAQUE = 106,
+ DXGI_FORMAT_YUY2 = 107,
+ DXGI_FORMAT_Y210 = 108,
+ DXGI_FORMAT_Y216 = 109,
+ DXGI_FORMAT_NV11 = 110,
+ DXGI_FORMAT_AI44 = 111,
+ DXGI_FORMAT_IA44 = 112,
+ DXGI_FORMAT_P8 = 113,
+ DXGI_FORMAT_A8P8 = 114,
+ DXGI_FORMAT_B4G4R4A4_UNORM = 115,
+ DXGI_FORMAT_FORCE_UINT = 0xffffffffUL
+} DXGI_FORMAT;
+
+#define EncodeFourCC(x) ((((ui32_t)((x)[0])) ) | \
+ (((ui32_t)((x)[1])) << 8 ) | \
+ (((ui32_t)((x)[2])) << 16) | \
+ (((ui32_t)((x)[3])) << 24) )
+
+
+void R_LoadDDS ( const char *filename, byte **pic, int *width, int *height, GLenum *picFormat, int *numMips )
+{
+ union {
+ byte *b;
+ void *v;
+ } buffer;
+ int len;
+ ddsHeader_t *ddsHeader = NULL;
+ ddsHeaderDxt10_t *ddsHeaderDxt10 = NULL;
+ byte *data;
+
+ if (!picFormat)
+ {
+ ri.Printf(PRINT_ERROR, "R_LoadDDS() called without picFormat parameter!");
+ return;
+ }
+
+ if (width)
+ *width = 0;
+ if (height)
+ *height = 0;
+ if (picFormat)
+ *picFormat = GL_RGBA8;
+ if (numMips)
+ *numMips = 1;
+
+ *pic = NULL;
+
+ //
+ // load the file
+ //
+ len = ri.FS_ReadFile( ( char * ) filename, &buffer.v);
+ if (!buffer.b || len < 0) {
+ return;
+ }
+
+ //
+ // reject files that are too small to hold even a header
+ //
+ if (len < 4 + sizeof(*ddsHeader))
+ {
+ ri.Printf(PRINT_ALL, "File %s is too small to be a DDS file.\n", filename);
+ ri.FS_FreeFile(buffer.v);
+ return;
+ }
+
+ //
+ // reject files that don't start with "DDS "
+ //
+ if (*((ui32_t *)(buffer.b)) != EncodeFourCC("DDS "))
+ {
+ ri.Printf(PRINT_ALL, "File %s is not a DDS file.\n", filename);
+ ri.FS_FreeFile(buffer.v);
+ return;
+ }
+
+ //
+ // parse header and dx10 header if available
+ //
+ ddsHeader = (ddsHeader_t *)(buffer.b + 4);
+ if ((ddsHeader->pixelFormatFlags & DDSPF_FOURCC) && ddsHeader->fourCC == EncodeFourCC("DX10"))
+ {
+ if (len < 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10))
+ {
+ ri.Printf(PRINT_ALL, "File %s indicates a DX10 header it is too small to contain.\n", filename);
+ ri.FS_FreeFile(buffer.v);
+ return;
+ }
+
+ ddsHeaderDxt10 = (ddsHeaderDxt10_t *)(buffer.b + 4 + sizeof(ddsHeader_t));
+ data = buffer.b + 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10);
+ len -= 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10);
+ }
+ else
+ {
+ data = buffer.b + 4 + sizeof(*ddsHeader);
+ len -= 4 + sizeof(*ddsHeader);
+ }
+
+ if (width)
+ *width = ddsHeader->width;
+ if (height)
+ *height = ddsHeader->height;
+
+ if (numMips)
+ {
+ if (ddsHeader->flags & _DDSFLAGS_MIPMAPCOUNT)
+ *numMips = ddsHeader->numMips;
+ else
+ *numMips = 1;
+ }
+
+ // FIXME: handle cube map
+ //if ((ddsHeader->caps2 & DDSCAPS2_CUBEMAP) == DDSCAPS2_CUBEMAP)
+
+ //
+ // Convert DXGI format/FourCC into OpenGL format
+ //
+ if (ddsHeaderDxt10)
+ {
+ switch (ddsHeaderDxt10->dxgiFormat)
+ {
+ case DXGI_FORMAT_BC1_TYPELESS:
+ case DXGI_FORMAT_BC1_UNORM:
+ // FIXME: check for GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
+ *picFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ break;
+
+ case DXGI_FORMAT_BC1_UNORM_SRGB:
+ // FIXME: check for GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
+ *picFormat = GL_COMPRESSED_SRGB_S3TC_DXT1_EXT;
+ break;
+
+ case DXGI_FORMAT_BC2_TYPELESS:
+ case DXGI_FORMAT_BC2_UNORM:
+ *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ break;
+
+ case DXGI_FORMAT_BC2_UNORM_SRGB:
+ *picFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT;
+ break;
+
+ case DXGI_FORMAT_BC3_TYPELESS:
+ case DXGI_FORMAT_BC3_UNORM:
+ *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ break;
+
+ case DXGI_FORMAT_BC3_UNORM_SRGB:
+ *picFormat = GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT;
+ break;
+
+ case DXGI_FORMAT_BC4_TYPELESS:
+ case DXGI_FORMAT_BC4_UNORM:
+ *picFormat = GL_COMPRESSED_RED_RGTC1;
+ break;
+
+ case DXGI_FORMAT_BC4_SNORM:
+ *picFormat = GL_COMPRESSED_SIGNED_RED_RGTC1;
+ break;
+
+ case DXGI_FORMAT_BC5_TYPELESS:
+ case DXGI_FORMAT_BC5_UNORM:
+ *picFormat = GL_COMPRESSED_RG_RGTC2;
+ break;
+
+ case DXGI_FORMAT_BC5_SNORM:
+ *picFormat = GL_COMPRESSED_SIGNED_RG_RGTC2;
+ break;
+
+ case DXGI_FORMAT_BC6H_TYPELESS:
+ case DXGI_FORMAT_BC6H_UF16:
+ *picFormat = GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB;
+ break;
+
+ case DXGI_FORMAT_BC6H_SF16:
+ *picFormat = GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB;
+ break;
+
+ case DXGI_FORMAT_BC7_TYPELESS:
+ case DXGI_FORMAT_BC7_UNORM:
+ *picFormat = GL_COMPRESSED_RGBA_BPTC_UNORM_ARB;
+ break;
+
+ case DXGI_FORMAT_BC7_UNORM_SRGB:
+ *picFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB;
+ break;
+
+ case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
+ *picFormat = GL_SRGB8_ALPHA8_EXT;
+ break;
+
+ case DXGI_FORMAT_R8G8B8A8_UNORM:
+ case DXGI_FORMAT_R8G8B8A8_SNORM:
+ *picFormat = GL_RGBA8;
+ break;
+
+ default:
+ ri.Printf(PRINT_ALL, "DDS File %s has unsupported DXGI format %d.", filename, ddsHeaderDxt10->dxgiFormat);
+ ri.FS_FreeFile(buffer.v);
+ return;
+ break;
+ }
+ }
+ else
+ {
+ if (ddsHeader->pixelFormatFlags & DDSPF_FOURCC)
+ {
+ if (ddsHeader->fourCC == EncodeFourCC("DXT1"))
+ *picFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
+ else if (ddsHeader->fourCC == EncodeFourCC("DXT2"))
+ *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ else if (ddsHeader->fourCC == EncodeFourCC("DXT3"))
+ *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+ else if (ddsHeader->fourCC == EncodeFourCC("DXT4"))
+ *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ else if (ddsHeader->fourCC == EncodeFourCC("DXT5"))
+ *picFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+ else if (ddsHeader->fourCC == EncodeFourCC("ATI1"))
+ *picFormat = GL_COMPRESSED_RED_RGTC1;
+ else if (ddsHeader->fourCC == EncodeFourCC("BC4U"))
+ *picFormat = GL_COMPRESSED_RED_RGTC1;
+ else if (ddsHeader->fourCC == EncodeFourCC("BC4S"))
+ *picFormat = GL_COMPRESSED_SIGNED_RED_RGTC1;
+ else if (ddsHeader->fourCC == EncodeFourCC("ATI2"))
+ *picFormat = GL_COMPRESSED_RG_RGTC2;
+ else if (ddsHeader->fourCC == EncodeFourCC("BC5U"))
+ *picFormat = GL_COMPRESSED_RG_RGTC2;
+ else if (ddsHeader->fourCC == EncodeFourCC("BC5S"))
+ *picFormat = GL_COMPRESSED_SIGNED_RG_RGTC2;
+ else
+ {
+ ri.Printf(PRINT_ALL, "DDS File %s has unsupported FourCC.", filename);
+ ri.FS_FreeFile(buffer.v);
+ return;
+ }
+ }
+ else if (ddsHeader->pixelFormatFlags == (DDSPF_RGB | DDSPF_ALPHAPIXELS)
+ && ddsHeader->rgbBitCount == 32
+ && ddsHeader->rBitMask == 0x000000ff
+ && ddsHeader->gBitMask == 0x0000ff00
+ && ddsHeader->bBitMask == 0x00ff0000
+ && ddsHeader->aBitMask == 0xff000000)
+ {
+ *picFormat = GL_RGBA8;
+ }
+ else
+ {
+ ri.Printf(PRINT_ALL, "DDS File %s has unsupported RGBA format.", filename);
+ ri.FS_FreeFile(buffer.v);
+ return;
+ }
+ }
+
+ *pic = ri.Z_Malloc(len);
+ Com_Memcpy(*pic, data, len);
+
+ ri.FS_FreeFile(buffer.v);
+}
+
+void R_SaveDDS(const char *filename, byte *pic, int width, int height, int depth)
+{
+ byte *data;
+ ddsHeader_t *ddsHeader;
+ int picSize, size;
+
+ if (!depth)
+ depth = 1;
+
+ picSize = width * height * depth * 4;
+ size = 4 + sizeof(*ddsHeader) + picSize;
+ data = ri.Z_Malloc(size);
+
+ data[0] = 'D';
+ data[1] = 'D';
+ data[2] = 'S';
+ data[3] = ' ';
+
+ ddsHeader = (ddsHeader_t *)(data + 4);
+ memset(ddsHeader, 0, sizeof(ddsHeader_t));
+
+ ddsHeader->headerSize = 0x7c;
+ ddsHeader->flags = _DDSFLAGS_REQUIRED;
+ ddsHeader->height = height;
+ ddsHeader->width = width;
+ ddsHeader->always_0x00000020 = 0x00000020;
+ ddsHeader->caps = DDSCAPS_COMPLEX | DDSCAPS_REQUIRED;
+
+ if (depth == 6)
+ ddsHeader->caps2 = DDSCAPS2_CUBEMAP;
+
+ ddsHeader->pixelFormatFlags = DDSPF_RGB | DDSPF_ALPHAPIXELS;
+ ddsHeader->rgbBitCount = 32;
+ ddsHeader->rBitMask = 0x000000ff;
+ ddsHeader->gBitMask = 0x0000ff00;
+ ddsHeader->bBitMask = 0x00ff0000;
+ ddsHeader->aBitMask = 0xff000000;
+
+ Com_Memcpy(data + 4 + sizeof(*ddsHeader), pic, picSize);
+
+ ri.FS_WriteFile(filename, data, size);
+
+ ri.Free(data);
+}
diff --git a/SP/code/rend2/tr_init.c b/SP/code/rend2/tr_init.c
index 6f41ae5..da616a4 100644
--- a/SP/code/rend2/tr_init.c
+++ b/SP/code/rend2/tr_init.c
@@ -166,6 +166,7 @@ cvar_t *r_specularMapping;
cvar_t *r_deluxeMapping;
cvar_t *r_parallaxMapping;
cvar_t *r_cubeMapping;
+cvar_t *r_cubemapSize;
cvar_t *r_specularIsMetallic;
cvar_t *r_glossIsRoughness;
cvar_t *r_baseNormalX;
@@ -909,6 +910,33 @@ void R_ScreenShotJPEG_f (void) {
}
}
+/*
+==================
+R_ExportCubemaps
+==================
+*/
+void R_ExportCubemaps(void)
+{
+ exportCubemapsCommand_t *cmd;
+
+ cmd = R_GetCommandBuffer(sizeof(*cmd));
+ if (!cmd) {
+ return;
+ }
+ cmd->commandId = RC_EXPORT_CUBEMAPS;
+}
+
+
+/*
+==================
+R_ExportCubemaps_f
+==================
+*/
+void R_ExportCubemaps_f(void)
+{
+ R_ExportCubemaps();
+}
+
//============================================================================
/*
@@ -1350,6 +1378,7 @@ void R_Register( void ) {
r_deluxeMapping = ri.Cvar_Get( "r_deluxeMapping", "1", CVAR_ARCHIVE | CVAR_LATCH );
r_parallaxMapping = ri.Cvar_Get( "r_parallaxMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_cubeMapping = ri.Cvar_Get( "r_cubeMapping", "0", CVAR_ARCHIVE | CVAR_LATCH );
+ r_cubemapSize = ri.Cvar_Get( "r_cubemapSize", "128", CVAR_ARCHIVE | CVAR_LATCH );
r_specularIsMetallic = ri.Cvar_Get( "r_specularIsMetallic", "0", CVAR_ARCHIVE | CVAR_LATCH );
r_glossIsRoughness = ri.Cvar_Get("r_glossIsRoughness", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_baseNormalX = ri.Cvar_Get( "r_baseNormalX", "1.0", CVAR_ARCHIVE | CVAR_LATCH );
@@ -1512,6 +1541,7 @@ void R_Register( void ) {
ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
ri.Cmd_AddCommand( "minimize", GLimp_Minimize );
ri.Cmd_AddCommand( "gfxmeminfo", GfxMemInfo_f );
+ ri.Cmd_AddCommand( "exportCubemaps", R_ExportCubemaps_f );
ri.Cmd_AddCommand( "taginfo", R_TagInfo_f );
// Ridah
@@ -1664,6 +1694,7 @@ void RE_Shutdown( qboolean destroyWindow ) {
ri.Cmd_RemoveCommand( "modelist" );
ri.Cmd_RemoveCommand( "shaderstate" );
ri.Cmd_RemoveCommand( "gfxmeminfo" );
+ ri.Cmd_RemoveCommand( "exportCubemaps" );
ri.Cmd_RemoveCommand( "taginfo" );
// Ridah
diff --git a/SP/code/rend2/tr_local.h b/SP/code/rend2/tr_local.h
index 469257f..72977eb 100644
--- a/SP/code/rend2/tr_local.h
+++ b/SP/code/rend2/tr_local.h
@@ -61,8 +61,6 @@ typedef unsigned int glIndex_t;
#define MAX_CALC_PSHADOWS 64
#define MAX_DRAWN_PSHADOWS 32 // do not increase past 32, because bit flags are used on surfaces
#define PSHADOW_MAP_SIZE 512
-#define CUBE_MAP_MIPS 7
-#define CUBE_MAP_SIZE (1 << CUBE_MAP_MIPS)
#define USE_VERT_TANGENT_SPACE
#define USE_OVERBRIGHT
@@ -2012,6 +2010,7 @@ extern cvar_t *r_specularMapping;
extern cvar_t *r_deluxeMapping;
extern cvar_t *r_parallaxMapping;
extern cvar_t *r_cubeMapping;
+extern cvar_t *r_cubemapSize;
extern cvar_t *r_specularIsMetallic;
extern cvar_t *r_glossIsRoughness;
extern cvar_t *r_baseNormalX;
@@ -2722,6 +2721,10 @@ typedef struct {
viewParms_t viewParms;
} postProcessCommand_t;
+typedef struct {
+ int commandId;
+} exportCubemapsCommand_t;
+
typedef enum {
RC_END_OF_LIST,
RC_SET_COLOR,
@@ -2735,7 +2738,8 @@ typedef enum {
RC_COLORMASK,
RC_CLEARDEPTH,
RC_CAPSHADOWMAP,
- RC_POSTPROCESS
+ RC_POSTPROCESS,
+ RC_EXPORT_CUBEMAPS
} renderCommand_t;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/iortcw.git
More information about the Pkg-games-commits
mailing list