/** * @sa R_ModLoadSurfaces */ void R_CreateSurfaceLightmap (mBspSurface_t * surf) { int smax, tmax; byte *samples, *directions; if (!(surf->flags & MSURF_LIGHTMAP)) return; smax = (surf->stextents[0] / surf->lightmap_scale) + 1; tmax = (surf->stextents[1] / surf->lightmap_scale) + 1; if (!R_AllocLightmapBlock(smax, tmax, &surf->light_s, &surf->light_t)) { /* upload the last block */ R_UploadLightmapBlock(); if (!R_AllocLightmapBlock(smax, tmax, &surf->light_s, &surf->light_t)) Com_Error(ERR_DROP, "R_CreateSurfaceLightmap: Consecutive calls to R_AllocLightmapBlock(%d,%d) failed (lightmap_scale: %i, stextends: %f %f)\n", smax, tmax, surf->lightmap_scale, surf->stextents[0], surf->stextents[1]); } surf->lightmap_texnum = r_lightmaps.lightmap_texnums[r_lightmaps.lightmap_count]; surf->deluxemap_texnum = r_lightmaps.deluxemap_texnums[r_lightmaps.deluxemap_count]; samples = r_lightmaps.sample_buffer; samples += (surf->light_t * r_lightmaps.size + surf->light_s) * LIGHTMAP_BLOCK_BYTES; directions = r_lightmaps.direction_buffer; directions += (surf->light_t * r_lightmaps.size + surf->light_s) * DELUXEMAP_BLOCK_BYTES; if (!surf->samples) /* make it fullbright */ R_BuildDefaultLightmap(surf, samples, directions, r_lightmaps.size * LIGHTMAP_BLOCK_BYTES); else /* or light it properly */ R_BuildLightmap(surf, samples, directions, r_lightmaps.size * LIGHTMAP_BLOCK_BYTES); }
/** * @brief Uploads sorted lightmaps from start to (end - 1) and * puts them in the new maps sized to width/height */ static void R_UploadPackedLightmaps(uint32_t width, uint32_t height, r_bsp_model_t *bsp, GSList *start, GSList *end) { // edge case, no blocks left if (!width || !height || !start) { return; } // allocate the image r_image_t *lightmap = R_AllocLightmap(width, height); r_image_t *deluxemap = R_AllocDeluxemap(width, height); r_image_t *stainmap = NULL; if (r_stainmap->integer) { stainmap = R_AllocStainmap(width, height); } // temp buffers byte *sample_buffer = Mem_Malloc(width * height * 3); byte *direction_buffer = Mem_Malloc(width * height * 3); do { r_bsp_surface_t *surf = (r_bsp_surface_t *) start->data; const size_t stride = width * 3; const size_t lightmap_offset = (surf->lightmap_t *width + surf->lightmap_s) * 3; byte *sout = sample_buffer + lightmap_offset; byte *dout = direction_buffer + lightmap_offset; if (surf->lightmap_input) { byte *stout = NULL; if (r_stainmap->integer) { surf->stainmap = stainmap; stout = surf->stainmap_buffer = Mem_LinkMalloc(surf->lightmap_size[0] * surf->lightmap_size[1] * 3, bsp); } R_BuildLightmap(bsp, surf, surf->lightmap_input, sout, dout, stout, stride); } else { R_BuildDefaultLightmap(bsp, surf, sout, dout, stride); } surf->lightmap = lightmap; surf->deluxemap = deluxemap; start = start->next; } while (start != end); // upload! R_UploadImage(lightmap, GL_RGB, sample_buffer); R_UploadImage(deluxemap, GL_RGB, direction_buffer); // copy to the stainmap if (r_stainmap->integer) { R_UploadImage(stainmap, GL_RGB, sample_buffer); } Mem_Free(sample_buffer); Mem_Free(direction_buffer); }
/* * R_PackLightmaps */ static int R_PackLightmaps( int num, int w, int h, int size, int stride, qboolean deluxe, const char *name, const qbyte *data, mlightmapRect_t *rects ) { int i, x, y, root; qbyte *block; int lightmapNum; int rectX, rectY, rectSize; int maxX, maxY, max, xStride; double tw, th, tx, ty; mlightmapRect_t *rect; maxX = r_maxLightmapBlockSize / w; maxY = r_maxLightmapBlockSize / h; max = min( maxX, maxY ); ri.Com_DPrintf( "Packing %i lightmap(s) -> ", num ); if( !max || num == 1 || !mapConfig.lightmapsPacking /* || !r_lighting_packlightmaps->integer*/ ) { // process as it is R_BuildLightmap( w, h, deluxe, data, r_lightmapBuffer, w * LIGHTMAP_BYTES ); lightmapNum = R_UploadLightmap( name, r_lightmapBuffer, w, h ); if( rects ) { rects[0].texNum = lightmapNum; // this is not a real texture matrix, but who cares? rects[0].texMatrix[0][0] = 1; rects[0].texMatrix[0][1] = 0; rects[0].texMatrix[1][0] = 1; rects[0].texMatrix[1][1] = 0; } ri.Com_DPrintf( "\n" ); return 1; } // find the nearest square block size root = ( int )sqrt( (float)num ); if( root > max ) root = max; // keep row size a power of two for( i = 1; i < root; i <<= 1 ) ; if( i > root ) i >>= 1; root = i; num -= root * root; rectX = rectY = root; if( maxY > maxX ) { for(; ( num >= root ) && ( rectY < maxY ); rectY++, num -= root ) ; //if( !glConfig.ext.texture_non_power_of_two ) { // sample down if not a power of two for( y = 1; y < rectY; y <<= 1 ) ; if( y > rectY ) y >>= 1; rectY = y; } } else { for(; ( num >= root ) && ( rectX < maxX ); rectX++, num -= root ) ;