diff --git a/code/renderergl2/tr_bsp.c b/code/renderergl2/tr_bsp.c index fad9d2f8..553c4140 100644 --- a/code/renderergl2/tr_bsp.c +++ b/code/renderergl2/tr_bsp.c @@ -3067,16 +3067,23 @@ void R_AssignCubemapsToWorldSurfaces(void) } } +// FIXME: put this function declaration elsewhere +void R_SaveDDS(const char *filename, byte *pic, int width, int height, int depth); void R_RenderAllCubemaps(void) { + byte *data = NULL; + int sideSize = CUBE_MAP_SIZE * CUBE_MAP_SIZE * 4; int i, j; 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); } - + + if (r_exportCubemaps->integer) + data = ri.Malloc(sideSize * 6); + for (i = 0; i < tr.numCubemaps; i++) { for (j = 0; j < 6; j++) @@ -3086,6 +3093,34 @@ void R_RenderAllCubemaps(void) R_IssuePendingRenderCommands(); R_InitNextFrame(); } + + if (r_exportCubemaps->integer) + { + char filename[MAX_QPATH]; + byte *p; + cubemap_t *cubemap = &tr.cubemaps[i]; + + // FIXME: do this in backEnd + FBO_Bind(tr.renderCubeFbo); + + p = data; + 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, CUBE_MAP_SIZE, CUBE_MAP_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, p); + p += sideSize; + } + FBO_Bind(NULL); + + Com_sprintf(filename, MAX_QPATH, "cubemaps/%s/%03d.dds", tr.world->baseName, backEnd.viewParms.targetFboCubemapIndex); + R_SaveDDS(filename, data, CUBE_MAP_SIZE, CUBE_MAP_SIZE, 6); + } + } + + if (r_exportCubemaps->integer) + { + ri.Cvar_Set("r_exportCubemaps", "0"); + ri.Free(data); } } diff --git a/code/renderergl2/tr_image_dds.c b/code/renderergl2/tr_image_dds.c index 8ad406fd..b509014d 100644 --- a/code/renderergl2/tr_image_dds.c +++ b/code/renderergl2/tr_image_dds.c @@ -451,3 +451,48 @@ void R_LoadDDS ( const char *filename, byte **pic, int *width, int *height, GLen 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.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/code/renderergl2/tr_init.c b/code/renderergl2/tr_init.c index 265ae20b..41761b4e 100644 --- a/code/renderergl2/tr_init.c +++ b/code/renderergl2/tr_init.c @@ -142,6 +142,7 @@ cvar_t *r_specularMapping; cvar_t *r_deluxeMapping; cvar_t *r_parallaxMapping; cvar_t *r_cubeMapping; +cvar_t *r_exportCubemaps; cvar_t *r_specularIsMetallic; cvar_t *r_glossIsRoughness; cvar_t *r_baseNormalX; @@ -455,6 +456,7 @@ byte *RB_ReadPixels(int x, int y, int width, int height, size_t *offset, int *pa buffer = ri.Hunk_AllocateTempMemory(padwidth * height + *offset + packAlign - 1); bufstart = PADP((intptr_t) buffer + *offset, packAlign); + qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, bufstart); *offset = bufstart - buffer; @@ -1213,6 +1215,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_exportCubemaps = ri.Cvar_Get("r_exportCubemaps", "0", 0); 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 ); diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h index f083fe9b..f211eda0 100644 --- a/code/renderergl2/tr_local.h +++ b/code/renderergl2/tr_local.h @@ -1792,6 +1792,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_exportCubemaps; extern cvar_t *r_specularIsMetallic; extern cvar_t *r_glossIsRoughness; extern cvar_t *r_baseNormalX;