diff options
Diffstat (limited to 'src/renderer')
-rw-r--r-- | src/renderer/tr_bsp.c | 4 | ||||
-rw-r--r-- | src/renderer/tr_cmds.c | 2 | ||||
-rw-r--r-- | src/renderer/tr_flares.c | 2 | ||||
-rw-r--r-- | src/renderer/tr_image.c | 21 | ||||
-rw-r--r-- | src/renderer/tr_image_jpg.c | 276 | ||||
-rw-r--r-- | src/renderer/tr_init.c | 215 | ||||
-rw-r--r-- | src/renderer/tr_local.h | 32 | ||||
-rw-r--r-- | src/renderer/tr_noise.c | 2 | ||||
-rw-r--r-- | src/renderer/tr_shade.c | 39 | ||||
-rw-r--r-- | src/renderer/tr_shader.c | 9 | ||||
-rw-r--r-- | src/renderer/tr_surface.c | 8 | ||||
-rw-r--r-- | src/renderer/tr_world.c | 1 |
12 files changed, 348 insertions, 263 deletions
diff --git a/src/renderer/tr_bsp.c b/src/renderer/tr_bsp.c index caf62033..563bb36d 100644 --- a/src/renderer/tr_bsp.c +++ b/src/renderer/tr_bsp.c @@ -156,9 +156,6 @@ static void R_LoadLightmaps( lump_t *l ) { //FIXME: HACK: maps with only one lightmap turn up fullbright for some reason. //this avoids this, but isn't the correct solution. tr.numLightmaps++; - } else if ( tr.numLightmaps >= MAX_LIGHTMAPS ) { // 20051020 misantropia - ri.Printf( PRINT_WARNING, "WARNING: number of lightmaps > MAX_LIGHTMAPS\n" ); - tr.numLightmaps = MAX_LIGHTMAPS; } // if we are in r_vertexLight mode, we don't need the lightmaps at all @@ -166,6 +163,7 @@ static void R_LoadLightmaps( lump_t *l ) { return; } + tr.lightmaps = ri.Hunk_Alloc( tr.numLightmaps * sizeof(image_t *), h_low ); for ( i = 0 ; i < tr.numLightmaps ; i++ ) { // expand the 24 bit on-disk to 32 bit buf_p = buf + i * LIGHTMAP_SIZE*LIGHTMAP_SIZE * 3; diff --git a/src/renderer/tr_cmds.c b/src/renderer/tr_cmds.c index a9e88918..833c0f07 100644 --- a/src/renderer/tr_cmds.c +++ b/src/renderer/tr_cmds.c @@ -145,7 +145,7 @@ void R_IssueRenderCommands( qboolean runPerformanceCounters ) { } // at this point, the back end thread is idle, so it is ok - // to look at it's performance counters + // to look at its performance counters if ( runPerformanceCounters ) { R_PerformanceCounters(); } diff --git a/src/renderer/tr_flares.c b/src/renderer/tr_flares.c index 7a5a8174..afef22a4 100644 --- a/src/renderer/tr_flares.c +++ b/src/renderer/tr_flares.c @@ -35,7 +35,7 @@ constant, irrespective of distance, but the intensity should be proportional to projected area of the light source. A surface that has been flagged as having a light flare will calculate the depth -buffer value that it's midpoint should have when the surface is added. +buffer value that its midpoint should have when the surface is added. After all opaque surfaces have been rendered, the depth buffer is read back for each flare in view. If the point has not been obscured by a closer surface, the diff --git a/src/renderer/tr_image.c b/src/renderer/tr_image.c index 0cb18759..1fa8042d 100644 --- a/src/renderer/tr_image.c +++ b/src/renderer/tr_image.c @@ -561,6 +561,27 @@ static void Upload32( unsigned *data, scan = ((byte *)data); samples = 3; + if( r_greyscale->integer ) + { + for ( i = 0; i < c; i++ ) + { + byte luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]); + scan[i*4] = luma; + scan[i*4 + 1] = luma; + scan[i*4 + 2] = luma; + } + } + else if( r_greyscale->value ) + { + for ( i = 0; i < c; i++ ) + { + float luma = LUMA(scan[i*4], scan[i*4 + 1], scan[i*4 + 2]); + scan[i*4] = LERP(scan[i*4], luma, r_greyscale->value); + scan[i*4 + 1] = LERP(scan[i*4 + 1], luma, r_greyscale->value); + scan[i*4 + 2] = LERP(scan[i*4 + 2], luma, r_greyscale->value); + } + } + if(lightMap) { if(r_greyscale->integer) diff --git a/src/renderer/tr_image_jpg.c b/src/renderer/tr_image_jpg.c index baf2a6fd..7390e143 100644 --- a/src/renderer/tr_image_jpg.c +++ b/src/renderer/tr_image_jpg.c @@ -31,10 +31,43 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * You may also wish to include "jerror.h". */ -#define JPEG_INTERNALS -#include "../jpeg-6b/jpeglib.h" +#ifdef USE_INTERNAL_JPEG +# define JPEG_INTERNALS +#endif -void R_LoadJPG( const char *filename, unsigned char **pic, int *width, int *height ) { +#include <jpeglib.h> + +#ifndef USE_INTERNAL_JPEG +# if JPEG_LIB_VERSION < 80 +# error Need system libjpeg >= 80 +# endif +#endif + +static void R_JPGErrorExit(j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + + (*cinfo->err->format_message) (cinfo, buffer); + + /* Let the memory manager delete any temp files before we die */ + jpeg_destroy(cinfo); + + ri.Error(ERR_FATAL, "%s\n", buffer); +} + +static void R_JPGOutputMessage(j_common_ptr cinfo) +{ + char buffer[JMSG_LENGTH_MAX]; + + /* Create the message */ + (*cinfo->err->format_message) (cinfo, buffer); + + /* Send it to stderr, adding a newline */ + ri.Printf(PRINT_ALL, "%s\n", buffer); +} + +void R_LoadJPG(const char *filename, unsigned char **pic, int *width, int *height) +{ /* This struct contains the JPEG decompression parameters and pointers to * working space (which is allocated as needed by the JPEG library). */ @@ -54,9 +87,10 @@ void R_LoadJPG( const char *filename, unsigned char **pic, int *width, int *heig struct jpeg_error_mgr jerr; /* More stuff */ JSAMPARRAY buffer; /* Output row buffer */ - unsigned row_stride; /* physical row width in output buffer */ - unsigned pixelcount, memcount; - unsigned char *out; + unsigned int row_stride; /* physical row width in output buffer */ + unsigned int pixelcount, memcount; + unsigned int sindex, dindex; + byte *out; int len; union { byte *b; @@ -83,6 +117,8 @@ void R_LoadJPG( const char *filename, unsigned char **pic, int *width, int *heig * address which we place into the link field in cinfo. */ cinfo.err = jpeg_std_error(&jerr); + cinfo.err->error_exit = R_JPGErrorExit; + cinfo.err->output_message = R_JPGOutputMessage; /* Now we can initialize the JPEG decompression object. */ jpeg_create_decompress(&cinfo); @@ -102,9 +138,11 @@ void R_LoadJPG( const char *filename, unsigned char **pic, int *width, int *heig /* Step 4: set parameters for decompression */ - /* In this example, we don't need to change any of the defaults set by - * jpeg_read_header(), so we do nothing here. + /* + * Make sure it always converts images to RGB color space. This will + * automatically convert 8-bit greyscale images to RGB as well. */ + cinfo.out_color_space = JCS_RGB; /* Step 5: Start decompressor */ @@ -125,9 +163,14 @@ void R_LoadJPG( const char *filename, unsigned char **pic, int *width, int *heig if(!cinfo.output_width || !cinfo.output_height || ((pixelcount * 4) / cinfo.output_width) / 4 != cinfo.output_height - || pixelcount > 0x1FFFFFFF || cinfo.output_components > 4) // 4*1FFFFFFF == 0x7FFFFFFC < 0x7FFFFFFF + || pixelcount > 0x1FFFFFFF || cinfo.output_components != 3 + ) { - ri.Error (ERR_DROP, "LoadJPG: %s has an invalid image size: %dx%d*4=%d, components: %d\n", filename, + // Free the memory to make sure we don't leak memory + ri.FS_FreeFile (fbuffer.v); + jpeg_destroy_decompress(&cinfo); + + ri.Error(ERR_DROP, "LoadJPG: %s has an invalid image format: %dx%d*4=%d, components: %d\n", filename, cinfo.output_width, cinfo.output_height, pixelcount * 4, cinfo.output_components); } @@ -157,42 +200,23 @@ void R_LoadJPG( const char *filename, unsigned char **pic, int *width, int *heig buf = out; - // If we are processing an 8-bit JPEG (greyscale), we'll have to convert - // the greyscale values to RGBA. - if(cinfo.output_components == 1) - { - int sindex = pixelcount, dindex = memcount; - unsigned char greyshade; - - // Only pixelcount number of bytes have been written. - // Expand the color values over the rest of the buffer, starting - // from the end. - do - { - greyshade = buf[--sindex]; - - buf[--dindex] = 255; - buf[--dindex] = greyshade; - buf[--dindex] = greyshade; - buf[--dindex] = greyshade; - } while(sindex); - } - else - { - // clear all the alphas to 255 - int i; + // Expand from RGB to RGBA + sindex = pixelcount * cinfo.output_components; + dindex = memcount; - for ( i = 3 ; i < memcount ; i+=4 ) - { - buf[i] = 255; - } - } + do + { + buf[--dindex] = 255; + buf[--dindex] = buf[--sindex]; + buf[--dindex] = buf[--sindex]; + buf[--dindex] = buf[--sindex]; + } while(sindex); *pic = out; /* Step 7: Finish decompression */ - (void) jpeg_finish_decompress(&cinfo); + jpeg_finish_decompress(&cinfo); /* We can ignore the return value since suspension is not possible * with the stdio data source. */ @@ -270,7 +294,15 @@ init_destination (j_compress_ptr cinfo) static boolean empty_output_buffer (j_compress_ptr cinfo) { - return TRUE; + my_dest_ptr dest = (my_dest_ptr) cinfo->dest; + + jpeg_destroy_compress(cinfo); + + // Make crash fatal or we would probably leak memory. + ri.Error(ERR_FATAL, "Output buffer for encoded JPEG image has insufficient size of %d bytes\n", + dest->size); + + return FALSE; } /* @@ -282,14 +314,8 @@ empty_output_buffer (j_compress_ptr cinfo) * for error exit. */ -static int hackSize; - -static void -term_destination (j_compress_ptr cinfo) +static void term_destination(j_compress_ptr cinfo) { - my_dest_ptr dest = (my_dest_ptr) cinfo->dest; - size_t datacount = dest->size - dest->pub.free_in_buffer; - hackSize = datacount; } @@ -324,143 +350,40 @@ jpegDest (j_compress_ptr cinfo, byte* outfile, int size) dest->size = size; } -void SaveJPG(char * filename, int quality, int image_width, int image_height, unsigned char *image_buffer) { - /* This struct contains the JPEG compression parameters and pointers to - * working space (which is allocated as needed by the JPEG library). - * It is possible to have several such structures, representing multiple - * compression/decompression processes, in existence at once. We refer - * to any one struct (and its associated working data) as a "JPEG object". - */ - struct jpeg_compress_struct cinfo; - /* This struct represents a JPEG error handler. It is declared separately - * because applications often want to supply a specialized error handler - * (see the second half of this file for an example). But here we just - * take the easy way out and use the standard error handler, which will - * print a message on stderr and call exit() if compression fails. - * Note that this struct must live as long as the main JPEG parameter - * struct, to avoid dangling-pointer problems. - */ - struct jpeg_error_mgr jerr; - /* More stuff */ - JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ - int row_stride; /* physical row width in image buffer */ - unsigned char *out; - - /* Step 1: allocate and initialize JPEG compression object */ - - /* We have to set up the error handler first, in case the initialization - * step fails. (Unlikely, but it could happen if you are out of memory.) - * This routine fills in the contents of struct jerr, and returns jerr's - * address which we place into the link field in cinfo. - */ - cinfo.err = jpeg_std_error(&jerr); - /* Now we can initialize the JPEG compression object. */ - jpeg_create_compress(&cinfo); - - /* Step 2: specify data destination (eg, a file) */ - /* Note: steps 2 and 3 can be done in either order. */ - - /* Here we use the library-supplied code to send compressed data to a - * stdio stream. You can also write your own code to do something else. - * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that - * requires it in order to write binary files. - */ - out = ri.Hunk_AllocateTempMemory(image_width*image_height*4); - jpegDest(&cinfo, out, image_width*image_height*4); - - /* Step 3: set parameters for compression */ - - /* First we supply a description of the input image. - * Four fields of the cinfo struct must be filled in: - */ - cinfo.image_width = image_width; /* image width and height, in pixels */ - cinfo.image_height = image_height; - cinfo.input_components = 4; /* # of color components per pixel */ - cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ - /* Now use the library's routine to set default compression parameters. - * (You must set at least cinfo.in_color_space before calling this, - * since the defaults depend on the source color space.) - */ - jpeg_set_defaults(&cinfo); - /* Now you can set any non-default parameters you wish to. - * Here we just illustrate the use of quality (quantization table) scaling: - */ - jpeg_set_quality(&cinfo, quality, TRUE /* limit to baseline-JPEG values */); - /* If quality is set high, disable chroma subsampling */ - if (quality >= 85) { - cinfo.comp_info[0].h_samp_factor = 1; - cinfo.comp_info[0].v_samp_factor = 1; - } - - /* Step 4: Start compressor */ - - /* TRUE ensures that we will write a complete interchange-JPEG file. - * Pass TRUE unless you are very sure of what you're doing. - */ - jpeg_start_compress(&cinfo, TRUE); - - /* Step 5: while (scan lines remain to be written) */ - /* jpeg_write_scanlines(...); */ - - /* Here we use the library's state variable cinfo.next_scanline as the - * loop counter, so that we don't have to keep track ourselves. - * To keep things simple, we pass one scanline per call; you can pass - * more if you wish, though. - */ - row_stride = image_width * 4; /* JSAMPLEs per row in image_buffer */ - - while (cinfo.next_scanline < cinfo.image_height) { - /* jpeg_write_scanlines expects an array of pointers to scanlines. - * Here the array is only one element long, but you could pass - * more than one scanline at a time if that's more convenient. - */ - row_pointer[0] = & image_buffer[((cinfo.image_height-1)*row_stride)-cinfo.next_scanline * row_stride]; - (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); - } - - /* Step 6: Finish compression */ - - jpeg_finish_compress(&cinfo); - /* After finish_compress, we can close the output file. */ - ri.FS_WriteFile( filename, out, hackSize ); - - ri.Hunk_FreeTempMemory(out); - - /* Step 7: release JPEG compression object */ - - /* This is an important step since it will release a good deal of memory. */ - jpeg_destroy_compress(&cinfo); - - /* And we're done! */ -} - /* ================= SaveJPGToBuffer + +Encodes JPEG from image in image_buffer and writes to buffer. +Expects RGB input data ================= */ -int SaveJPGToBuffer( byte *buffer, int quality, - int image_width, int image_height, - byte *image_buffer ) +size_t RE_SaveJPGToBuffer(byte *buffer, size_t bufSize, int quality, + int image_width, int image_height, byte *image_buffer, int padding) { struct jpeg_compress_struct cinfo; struct jpeg_error_mgr jerr; JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ + my_dest_ptr dest; int row_stride; /* physical row width in image buffer */ + size_t outcount; /* Step 1: allocate and initialize JPEG compression object */ cinfo.err = jpeg_std_error(&jerr); + cinfo.err->error_exit = R_JPGErrorExit; + cinfo.err->output_message = R_JPGOutputMessage; + /* Now we can initialize the JPEG compression object. */ jpeg_create_compress(&cinfo); /* Step 2: specify data destination (eg, a file) */ /* Note: steps 2 and 3 can be done in either order. */ - jpegDest(&cinfo, buffer, image_width*image_height*4); + jpegDest(&cinfo, buffer, bufSize); /* Step 3: set parameters for compression */ cinfo.image_width = image_width; /* image width and height, in pixels */ cinfo.image_height = image_height; - cinfo.input_components = 4; /* # of color components per pixel */ + cinfo.input_components = 3; /* # of color components per pixel */ cinfo.in_color_space = JCS_RGB; /* colorspace of input image */ jpeg_set_defaults(&cinfo); @@ -476,23 +399,40 @@ int SaveJPGToBuffer( byte *buffer, int quality, /* Step 5: while (scan lines remain to be written) */ /* jpeg_write_scanlines(...); */ - row_stride = image_width * 4; /* JSAMPLEs per row in image_buffer */ - + row_stride = image_width * cinfo.input_components + padding; /* JSAMPLEs per row in image_buffer */ + while (cinfo.next_scanline < cinfo.image_height) { /* jpeg_write_scanlines expects an array of pointers to scanlines. * Here the array is only one element long, but you could pass * more than one scanline at a time if that's more convenient. */ - row_pointer[0] = & image_buffer[((cinfo.image_height-1)*row_stride)-cinfo.next_scanline * row_stride]; + row_pointer[0] = &image_buffer[((cinfo.image_height-1)*row_stride)-cinfo.next_scanline * row_stride]; (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); } /* Step 6: Finish compression */ jpeg_finish_compress(&cinfo); - + + dest = (my_dest_ptr) cinfo.dest; + outcount = dest->size - dest->pub.free_in_buffer; + /* Step 7: release JPEG compression object */ jpeg_destroy_compress(&cinfo); /* And we're done! */ - return hackSize; + return outcount; +} + +void RE_SaveJPG(char * filename, int quality, int image_width, int image_height, byte *image_buffer, int padding) +{ + byte *out; + size_t bufSize; + + bufSize = image_width * image_height * 3; + out = ri.Hunk_AllocateTempMemory(bufSize); + + bufSize = RE_SaveJPGToBuffer(out, bufSize, quality, image_width, image_height, image_buffer, padding); + ri.FS_WriteFile(filename, out, bufSize); + + ri.Hunk_FreeTempMemory(out); } diff --git a/src/renderer/tr_init.c b/src/renderer/tr_init.c index 89fcf3e3..10ea222c 100644 --- a/src/renderer/tr_init.c +++ b/src/renderer/tr_init.c @@ -152,6 +152,9 @@ cvar_t *r_saveFontData; cvar_t *r_marksOnTriangleMeshes; +cvar_t *r_aviMotionJpegQuality; +cvar_t *r_screenshotJpegQuality; + cvar_t *r_maxpolys; int max_polys; cvar_t *r_maxpolyverts; @@ -362,15 +365,62 @@ FIXME: the statics don't get a reinit between fs_game changes /* ================== +RB_ReadPixels + +Reads an image but takes care of alignment issues for reading RGB images. + +Reads a minimum offset for where the RGB data starts in the image from +integer stored at pointer offset. When the function has returned the actual +offset was written back to address offset. This address will always have an +alignment of packAlign to ensure efficient copying. + +Stores the length of padding after a line of pixels to address padlen + +Return value must be freed with ri.Hunk_FreeTempMemory() +================== +*/ + +byte *RB_ReadPixels(int x, int y, int width, int height, size_t *offset, int *padlen) +{ + byte *buffer, *bufstart; + int padwidth, linelen; + GLint packAlign; + + qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign); + + linelen = width * 3; + padwidth = PAD(linelen, packAlign); + + // Allocate a few more bytes so that we can choose an alignment we like + buffer = ri.Hunk_AllocateTempMemory(padwidth * height + *offset + packAlign - 1); + + bufstart = (byte *) PAD((intptr_t) buffer + *offset, packAlign); + qglReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, bufstart); + + *offset = bufstart - buffer; + *padlen = padwidth - linelen; + + return buffer; +} + +/* +================== RB_TakeScreenshot ================== */ -void RB_TakeScreenshot( int x, int y, int width, int height, char *fileName ) { - byte *buffer; - int i, c, temp; +void RB_TakeScreenshot(int x, int y, int width, int height, char *fileName) +{ + byte *allbuf, *buffer; + byte *srcptr, *destptr; + byte *endline, *endmem; + byte temp; + + int linelen, padlen; + size_t offset = 18, memcount; - buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*3+18); - + allbuf = RB_ReadPixels(x, y, width, height, &offset, &padlen); + buffer = allbuf + offset - 18; + Com_Memset (buffer, 0, 18); buffer[2] = 2; // uncompressed type buffer[12] = width & 255; @@ -379,47 +429,62 @@ void RB_TakeScreenshot( int x, int y, int width, int height, char *fileName ) { buffer[15] = height >> 8; buffer[16] = 24; // pixel size - qglReadPixels( x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); + // swap rgb to bgr and remove padding from line endings + linelen = width * 3; + + srcptr = destptr = allbuf + offset; + endmem = srcptr + (linelen + padlen) * height; + + while(srcptr < endmem) + { + endline = srcptr + linelen; - // swap rgb to bgr - c = 18 + width * height * 3; - for (i=18 ; i<c ; i+=3) { - temp = buffer[i]; - buffer[i] = buffer[i+2]; - buffer[i+2] = temp; + while(srcptr < endline) + { + temp = srcptr[0]; + *destptr++ = srcptr[2]; + *destptr++ = srcptr[1]; + *destptr++ = temp; + + srcptr += 3; + } + + // Skip the pad + srcptr += padlen; } + memcount = linelen * height; + // gamma correct - if ( glConfig.deviceSupportsGamma ) { - R_GammaCorrect( buffer + 18, glConfig.vidWidth * glConfig.vidHeight * 3 ); - } + if(glConfig.deviceSupportsGamma) + R_GammaCorrect(allbuf + offset, memcount); - ri.FS_WriteFile( fileName, buffer, c ); + ri.FS_WriteFile(fileName, buffer, memcount + 18); - ri.Hunk_FreeTempMemory( buffer ); + ri.Hunk_FreeTempMemory(allbuf); } /* ================== RB_TakeScreenshotJPEG ================== -*/ -void RB_TakeScreenshotJPEG( int x, int y, int width, int height, char *fileName ) { - byte *buffer; +*/ - buffer = ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*4); +void RB_TakeScreenshotJPEG(int x, int y, int width, int height, char *fileName) +{ + byte *buffer; + size_t offset = 0, memcount; + int padlen; - qglReadPixels( x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer ); + buffer = RB_ReadPixels(x, y, width, height, &offset, &padlen); + memcount = (width * 3 + padlen) * height; // gamma correct - if ( glConfig.deviceSupportsGamma ) { - R_GammaCorrect( buffer, glConfig.vidWidth * glConfig.vidHeight * 4 ); - } - - ri.FS_WriteFile( fileName, buffer, 1 ); // create path - SaveJPG( fileName, 90, glConfig.vidWidth, glConfig.vidHeight, buffer); + if(glConfig.deviceSupportsGamma) + R_GammaCorrect(buffer + offset, memcount); - ri.Hunk_FreeTempMemory( buffer ); + RE_SaveJPG(fileName, r_screenshotJpegQuality->integer, width, height, buffer + offset, padlen); + ri.Hunk_FreeTempMemory(buffer); } /* @@ -525,8 +590,10 @@ the menu system, sampled down from full screen distorted images void R_LevelShot( void ) { char checkname[MAX_OSPATH]; byte *buffer; - byte *source; + byte *source, *allsource; byte *src, *dst; + size_t offset = 0; + int padlen; int x, y; int r, g, b; float xScale, yScale; @@ -534,17 +601,16 @@ void R_LevelShot( void ) { Com_sprintf(checkname, sizeof(checkname), "levelshots/%s.tga", tr.world->baseName); - source = ri.Hunk_AllocateTempMemory( glConfig.vidWidth * glConfig.vidHeight * 3 ); + allsource = RB_ReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, &offset, &padlen); + source = allsource + offset; - buffer = ri.Hunk_AllocateTempMemory( 128 * 128*3 + 18); + buffer = ri.Hunk_AllocateTempMemory(128 * 128*3 + 18); Com_Memset (buffer, 0, 18); buffer[2] = 2; // uncompressed type buffer[12] = 128; buffer[14] = 128; buffer[16] = 24; // pixel size - qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGB, GL_UNSIGNED_BYTE, source ); - // resample from source xScale = glConfig.vidWidth / 512.0f; yScale = glConfig.vidHeight / 384.0f; @@ -553,7 +619,8 @@ void R_LevelShot( void ) { r = g = b = 0; for ( yy = 0 ; yy < 3 ; yy++ ) { for ( xx = 0 ; xx < 4 ; xx++ ) { - src = source + 3 * ( glConfig.vidWidth * (int)( (y*3+yy)*yScale ) + (int)( (x*4+xx)*xScale ) ); + src = source + (3 * glConfig.vidWidth + padlen) * (int)((y*3 + yy) * yScale) + + 3 * (int) ((x*4 + xx) * xScale); r += src[0]; g += src[1]; b += src[2]; @@ -573,8 +640,8 @@ void R_LevelShot( void ) { ri.FS_WriteFile( checkname, buffer, 128 * 128*3 + 18 ); - ri.Hunk_FreeTempMemory( buffer ); - ri.Hunk_FreeTempMemory( source ); + ri.Hunk_FreeTempMemory(buffer); + ri.Hunk_FreeTempMemory(allsource); ri.Printf( PRINT_ALL, "Wrote %s\n", checkname ); } @@ -707,36 +774,70 @@ RB_TakeVideoFrameCmd const void *RB_TakeVideoFrameCmd( const void *data ) { const videoFrameCommand_t *cmd; - int frameSize; - int i; + byte *cBuf; + size_t memcount, linelen; + int padwidth, avipadwidth, padlen, avipadlen; + GLint packAlign; cmd = (const videoFrameCommand_t *)data; - qglReadPixels( 0, 0, cmd->width, cmd->height, GL_RGBA, - GL_UNSIGNED_BYTE, cmd->captureBuffer ); + qglGetIntegerv(GL_PACK_ALIGNMENT, &packAlign); + + linelen = cmd->width * 3; + + // Alignment stuff for glReadPixels + padwidth = PAD(linelen, packAlign); + padlen = padwidth - linelen; + // AVI line padding + avipadwidth = PAD(linelen, AVI_LINE_PADDING); + avipadlen = avipadwidth - linelen; + + cBuf = (byte *) PAD((intptr_t) cmd->captureBuffer, packAlign); + + qglReadPixels(0, 0, cmd->width, cmd->height, GL_RGB, + GL_UNSIGNED_BYTE, cBuf); + + memcount = padwidth * cmd->height; // gamma correct - if( glConfig.deviceSupportsGamma ) - R_GammaCorrect( cmd->captureBuffer, cmd->width * cmd->height * 4 ); + if(glConfig.deviceSupportsGamma) + R_GammaCorrect(cBuf, memcount); - if( cmd->motionJpeg ) + if(cmd->motionJpeg) { - frameSize = SaveJPGToBuffer( cmd->encodeBuffer, 90, - cmd->width, cmd->height, cmd->captureBuffer ); - ri.CL_WriteAVIVideoFrame( cmd->encodeBuffer, frameSize ); + memcount = RE_SaveJPGToBuffer(cmd->encodeBuffer, linelen * cmd->height, + r_aviMotionJpegQuality->integer, + cmd->width, cmd->height, cBuf, padlen); + ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, memcount); } else { - frameSize = cmd->width * cmd->height; - - for( i = 0; i < frameSize; i++) // Pack to 24bpp and swap R and B + byte *lineend, *memend; + byte *srcptr, *destptr; + + srcptr = cBuf; + destptr = cmd->encodeBuffer; + memend = srcptr + memcount; + + // swap R and B and remove line paddings + while(srcptr < memend) { - cmd->encodeBuffer[ i*3 ] = cmd->captureBuffer[ i*4 + 2 ]; - cmd->encodeBuffer[ i*3 + 1 ] = cmd->captureBuffer[ i*4 + 1 ]; - cmd->encodeBuffer[ i*3 + 2 ] = cmd->captureBuffer[ i*4 ]; + lineend = srcptr + linelen; + while(srcptr < lineend) + { + *destptr++ = srcptr[2]; + *destptr++ = srcptr[1]; + *destptr++ = srcptr[0]; + srcptr += 3; + } + + Com_Memset(destptr, '\0', avipadlen); + destptr += avipadlen; + + srcptr += padlen; } - - ri.CL_WriteAVIVideoFrame( cmd->encodeBuffer, frameSize * 3 ); + + ri.CL_WriteAVIVideoFrame(cmd->encodeBuffer, avipadwidth * cmd->height); } return (const void *)(cmd + 1); @@ -932,6 +1033,7 @@ void R_Register( void ) r_stereoEnabled = ri.Cvar_Get( "r_stereoEnabled", "0", CVAR_ARCHIVE | CVAR_LATCH); r_ignoreFastPath = ri.Cvar_Get( "r_ignoreFastPath", "1", CVAR_ARCHIVE | CVAR_LATCH ); r_greyscale = ri.Cvar_Get("r_greyscale", "0", CVAR_ARCHIVE | CVAR_LATCH); + ri.Cvar_CheckRange(r_greyscale, 0, 1, qfalse); // // temporary latched variables that can only change over a restart @@ -1024,6 +1126,9 @@ void R_Register( void ) r_marksOnTriangleMeshes = ri.Cvar_Get("r_marksOnTriangleMeshes", "0", CVAR_ARCHIVE); + r_aviMotionJpegQuality = ri.Cvar_Get("r_aviMotionJpegQuality", "90", CVAR_ARCHIVE); + r_screenshotJpegQuality = ri.Cvar_Get("r_screenshotJpegQuality", "90", CVAR_ARCHIVE); + r_maxpolys = ri.Cvar_Get( "r_maxpolys", va("%d", MAX_POLYS), 0); r_maxpolyverts = ri.Cvar_Get( "r_maxpolyverts", va("%d", MAX_POLYVERTS), 0); diff --git a/src/renderer/tr_local.h b/src/renderer/tr_local.h index ad32c260..a1978c3a 100644 --- a/src/renderer/tr_local.h +++ b/src/renderer/tr_local.h @@ -780,7 +780,6 @@ void R_Modellist_f (void); extern refimport_t ri; #define MAX_DRAWIMAGES 2048 -#define MAX_LIGHTMAPS 256 #define MAX_SKINS 1024 @@ -917,7 +916,7 @@ typedef struct { shader_t *sunShader; int numLightmaps; - image_t *lightmaps[MAX_LIGHTMAPS]; + image_t **lightmaps; trRefEntity_t *currentEntity; trRefEntity_t worldEntity; // point currentEntity at this when rendering world @@ -1062,7 +1061,6 @@ extern cvar_t *r_colorMipLevels; // development aid to see texture mip usage extern cvar_t *r_picmip; // controls picmip values extern cvar_t *r_finish; extern cvar_t *r_drawBuffer; -extern cvar_t *r_glDriver; extern cvar_t *r_swapInterval; extern cvar_t *r_textureMode; extern cvar_t *r_offsetFactor; @@ -1115,8 +1113,6 @@ extern cvar_t *r_saveFontData; extern cvar_t *r_marksOnTriangleMeshes; -extern cvar_t *r_GLlibCoolDownMsec; - //==================================================================== float R_NoiseGet4f( float x, float y, float z, float t ); @@ -1302,19 +1298,19 @@ typedef struct stageVars typedef struct shaderCommands_s { - glIndex_t indexes[SHADER_MAX_INDEXES] ALIGN(16); - vec4_t xyz[SHADER_MAX_VERTEXES] ALIGN(16); - vec4_t normal[SHADER_MAX_VERTEXES] ALIGN(16); - vec2_t texCoords[SHADER_MAX_VERTEXES][2] ALIGN(16); - color4ub_t vertexColors[SHADER_MAX_VERTEXES] ALIGN(16); - int vertexDlightBits[SHADER_MAX_VERTEXES] ALIGN(16); + glIndex_t indexes[SHADER_MAX_INDEXES] QALIGN(16); + vec4_t xyz[SHADER_MAX_VERTEXES] QALIGN(16); + vec4_t normal[SHADER_MAX_VERTEXES] QALIGN(16); + vec2_t texCoords[SHADER_MAX_VERTEXES][2] QALIGN(16); + color4ub_t vertexColors[SHADER_MAX_VERTEXES] QALIGN(16); + int vertexDlightBits[SHADER_MAX_VERTEXES] QALIGN(16); - stageVars_t svars ALIGN(16); + stageVars_t svars QALIGN(16); - color4ub_t constantColor255[SHADER_MAX_VERTEXES] ALIGN(16); + color4ub_t constantColor255[SHADER_MAX_VERTEXES] QALIGN(16); shader_t *shader; - float shaderTime; + float shaderTime; int fogNum; int dlightBits; // or together of all vertexDlightBits @@ -1699,10 +1695,10 @@ void RE_StretchPic ( float x, float y, float w, float h, float s1, float t1, float s2, float t2, qhandle_t hShader ); void RE_BeginFrame( stereoFrame_t stereoFrame ); void RE_EndFrame( int *frontEndMsec, int *backEndMsec ); -void SaveJPG(char * filename, int quality, int image_width, int image_height, unsigned char *image_buffer); -int SaveJPGToBuffer( byte *buffer, int quality, - int image_width, int image_height, - byte *image_buffer ); +void RE_SaveJPG(char * filename, int quality, int image_width, int image_height, + unsigned char *image_buffer, int padding); +size_t RE_SaveJPGToBuffer(byte *buffer, size_t bufSize, int quality, + int image_width, int image_height, byte *image_buffer, int padding); void RE_TakeVideoFrame( int width, int height, byte *captureBuffer, byte *encodeBuffer, qboolean motionJpeg ); diff --git a/src/renderer/tr_noise.c b/src/renderer/tr_noise.c index a9707a4a..b4c4082d 100644 --- a/src/renderer/tr_noise.c +++ b/src/renderer/tr_noise.c @@ -32,8 +32,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA static float s_noise_table[NOISE_SIZE]; static int s_noise_perm[NOISE_SIZE]; -#define LERP( a, b, w ) ( a * ( 1.0f - w ) + b * w ) - static float GetNoiseValue( int x, int y, int z, int t ) { int index = INDEX( ( int ) x, ( int ) y, ( int ) z, ( int ) t ); diff --git a/src/renderer/tr_shade.c b/src/renderer/tr_shade.c index d4375b5e..93ec88ba 100644 --- a/src/renderer/tr_shade.c +++ b/src/renderer/tr_shade.c @@ -460,9 +460,18 @@ static void ProjectDlightTexture_altivec( void ) { { float luminance; - luminance = (dl->color[0] * 255.0f + dl->color[1] * 255.0f + dl->color[2] * 255.0f) / 3; + luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; floatColor[0] = floatColor[1] = floatColor[2] = luminance; } + else if(r_greyscale->value) + { + float luminance; + + luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; + floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value); + floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value); + floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value); + } else { floatColor[0] = dl->color[0] * 255.0f; @@ -613,10 +622,19 @@ static void ProjectDlightTexture_scalar( void ) { if(r_greyscale->integer) { float luminance; - - luminance = (dl->color[0] * 255.0f + dl->color[1] * 255.0f + dl->color[2] * 255.0f) / 3; + + luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; floatColor[0] = floatColor[1] = floatColor[2] = luminance; } + else if(r_greyscale->value) + { + float luminance; + + luminance = LUMA(dl->color[0], dl->color[1], dl->color[2]) * 255.0f; + floatColor[0] = LERP(dl->color[0] * 255.0f, luminance, r_greyscale->value); + floatColor[1] = LERP(dl->color[1] * 255.0f, luminance, r_greyscale->value); + floatColor[2] = LERP(dl->color[2] * 255.0f, luminance, r_greyscale->value); + } else { floatColor[0] = dl->color[0] * 255.0f; @@ -965,11 +983,22 @@ static void ComputeColors( shaderStage_t *pStage ) if(r_greyscale->integer) { int scale; + for(i = 0; i < tess.numVertexes; i++) + { + scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); + tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale; + } + } + else if(r_greyscale->value) + { + float scale; for(i = 0; i < tess.numVertexes; i++) { - scale = (tess.svars.colors[i][0] + tess.svars.colors[i][1] + tess.svars.colors[i][2]) / 3; - tess.svars.colors[i][0] = tess.svars.colors[i][1] = tess.svars.colors[i][2] = scale; + scale = LUMA(tess.svars.colors[i][0], tess.svars.colors[i][1], tess.svars.colors[i][2]); + tess.svars.colors[i][0] = LERP(tess.svars.colors[i][0], scale, r_greyscale->value); + tess.svars.colors[i][1] = LERP(tess.svars.colors[i][1], scale, r_greyscale->value); + tess.svars.colors[i][2] = LERP(tess.svars.colors[i][2], scale, r_greyscale->value); } } } diff --git a/src/renderer/tr_shader.c b/src/renderer/tr_shader.c index bfcd47d3..22e340c6 100644 --- a/src/renderer/tr_shader.c +++ b/src/renderer/tr_shader.c @@ -31,7 +31,6 @@ static char *s_shaderText; static shaderStage_t stages[MAX_SHADER_STAGES]; static shader_t shader; static texModInfo_t texMods[MAX_SHADER_STAGES][TR_MAX_TEXMODS]; -static qboolean deferLoad; #define FILE_HASH_SIZE 1024 static shader_t* hashTable[FILE_HASH_SIZE]; @@ -1035,7 +1034,7 @@ static qboolean ParseStage( shaderStage_t *stage, char **text ) } // decide which agens we can skip - if ( stage->alphaGen == CGEN_IDENTITY ) { + if ( stage->alphaGen == AGEN_IDENTITY ) { if ( stage->rgbGen == CGEN_IDENTITY || stage->rgbGen == CGEN_LIGHTING_DIFFUSE ) { stage->alphaGen = AGEN_SKIP; @@ -1372,7 +1371,7 @@ surfaceparm <name> */ static void ParseSurfaceParm( char **text ) { char *token; - int numInfoParms = sizeof(infoParms) / sizeof(infoParms[0]); + int numInfoParms = ARRAY_LEN( infoParms ); int i; token = COM_ParseExt( text, qfalse ); @@ -1825,7 +1824,7 @@ static qboolean CollapseMultitexture( void ) { return qfalse; } } - if ( stages[0].alphaGen == CGEN_WAVEFORM ) + if ( stages[0].alphaGen == AGEN_WAVEFORM ) { if ( memcmp( &stages[0].alphaWave, &stages[1].alphaWave, @@ -3071,8 +3070,6 @@ void R_InitShaders( void ) { Com_Memset(hashTable, 0, sizeof(hashTable)); - deferLoad = qfalse; - CreateInternalShaders(); ScanAndLoadShaderFiles(); diff --git a/src/renderer/tr_surface.c b/src/renderer/tr_surface.c index cc7f0f3a..f14501f7 100644 --- a/src/renderer/tr_surface.c +++ b/src/renderer/tr_surface.c @@ -616,10 +616,10 @@ static void LerpMeshVertexes_altivec(md3Surface_t *surf, float backlerp) { short *oldXyz, *newXyz, *oldNormals, *newNormals; float *outXyz, *outNormal; - float oldXyzScale ALIGN(16); - float newXyzScale ALIGN(16); - float oldNormalScale ALIGN(16); - float newNormalScale ALIGN(16); + float oldXyzScale QALIGN(16); + float newXyzScale QALIGN(16); + float oldNormalScale QALIGN(16); + float newNormalScale QALIGN(16); int vertNum; unsigned lat, lng; int numVerts; diff --git a/src/renderer/tr_world.c b/src/renderer/tr_world.c index 97c9c87e..feebb2ef 100644 --- a/src/renderer/tr_world.c +++ b/src/renderer/tr_world.c @@ -332,6 +332,7 @@ void R_AddBrushModelSurfaces ( trRefEntity_t *ent ) { return; } + R_SetupEntityLighting( &tr.refdef, ent ); R_DlightBmodel( bmodel ); for ( i = 0 ; i < bmodel->numSurfaces ; i++ ) { |