diff --git a/docs/Complete_list_of_command_line_parameters.htm b/docs/Complete_list_of_command_line_parameters.htm index 6d0b735f..b2fb5201 100644 --- a/docs/Complete_list_of_command_line_parameters.htm +++ b/docs/Complete_list_of_command_line_parameters.htm @@ -257,6 +257,7 @@ td.formatted_questions ol { margin-top: 0px; margin-bottom: 0px; }
  • -lomem: Low memory but slower lighting mode
  • -lowquality: Low quality floodlight (appears to currently break floodlight)
  • -minsamplesize N: Sets minimum lightmap resolution in luxels/qu
  • +
  • -nobouncestore: Do not store BSP, lightmap and shader files between bounces
  • -nocollapse: Do not collapse identical lightmaps
  • -nodeluxe, -nodeluxemap: Disable deluxemapping
  • -nofastpoint: Disable fast point light calculation
  • diff --git a/tools/quake3/q3map2/help.cpp b/tools/quake3/q3map2/help.cpp index a2023ab4..d017fb0d 100644 --- a/tools/quake3/q3map2/help.cpp +++ b/tools/quake3/q3map2/help.cpp @@ -224,6 +224,7 @@ static void HelpLight() {"-lomem", "Low memory but slower lighting mode"}, {"-lowquality", "Low quality floodlight (appears to currently break floodlight)"}, {"-minsamplesize ", "Sets minimum lightmap resolution in luxels/qu"}, + {"-nobouncestore", "Do not store BSP, lightmap and shader files between bounces"}, {"-nocollapse", "Do not collapse identical lightmaps"}, {"-nodeluxe, -nodeluxemap", "Disable deluxemapping"}, {"-nofastpoint", "Disable fast point light calculation"}, diff --git a/tools/quake3/q3map2/light.cpp b/tools/quake3/q3map2/light.cpp index 6d8a4517..780f9c49 100644 --- a/tools/quake3/q3map2/light.cpp +++ b/tools/quake3/q3map2/light.cpp @@ -1785,7 +1785,7 @@ static void SetupGrid(){ does what it says... */ -static void LightWorld( bool fastAllocate ){ +static void LightWorld( bool fastAllocate, bool bounceStore ){ Vector3 color; float f; int b, bt; @@ -1917,10 +1917,12 @@ static void LightWorld( bool fastAllocate ){ while ( bounce > 0 ) { /* store off the bsp between bounces */ - StoreSurfaceLightmaps( fastAllocate ); - UnparseEntities(); - Sys_Printf( "Writing %s\n", source ); - WriteBSPFile( source ); + StoreSurfaceLightmaps( fastAllocate, bounceStore ); + if( bounceStore ){ + UnparseEntities(); + Sys_Printf( "Writing %s\n", source ); + WriteBSPFile( source ); + } /* note it */ Sys_Printf( "\n--- Radiosity (bounce %d of %d) ---\n", b, bt ); @@ -1939,7 +1941,10 @@ static void LightWorld( bool fastAllocate ){ SetupEnvelopes( false, fastbounce ); if ( lights.empty() ) { Sys_Printf( "No diffuse light to calculate, ending radiosity.\n" ); - return; + if( bounceStore ){ // already stored, just quit + return; + } + break; // break to StoreSurfaceLightmaps } /* add to lightgrid */ @@ -1982,8 +1987,9 @@ static void LightWorld( bool fastAllocate ){ bounce--; b++; } + /* ydnar: store off lightmaps */ - StoreSurfaceLightmaps( fastAllocate ); + StoreSurfaceLightmaps( fastAllocate, true ); } @@ -1998,6 +2004,7 @@ int LightMain( Args& args ){ int lightmapMergeSize = 0; bool lightSamplesInsist = false; bool fastAllocate = true; + bool bounceStore = true; /* note it */ @@ -2445,6 +2452,11 @@ int LightMain( Args& args ){ Sys_Printf( "Storing bounced light (radiosity) only\n" ); } + while ( args.takeArg( "-nobouncestore" ) ) { + bounceStore = false; + Sys_Printf( "Not storing BSP, lightmap and shader files between bounces\n" ); + } + while ( args.takeArg( "-nocollapse" ) ) { noCollapse = true; Sys_Printf( "Identical lightmap collapsing disabled\n" ); @@ -2814,7 +2826,7 @@ int LightMain( Args& args ){ SetupTraceNodes(); /* light the world */ - LightWorld( fastAllocate ); + LightWorld( fastAllocate, bounceStore ); /* write out the bsp */ UnparseEntities(); diff --git a/tools/quake3/q3map2/lightmaps_ydnar.cpp b/tools/quake3/q3map2/lightmaps_ydnar.cpp index 28d1cb42..81a44d82 100644 --- a/tools/quake3/q3map2/lightmaps_ydnar.cpp +++ b/tools/quake3/q3map2/lightmaps_ydnar.cpp @@ -2336,7 +2336,7 @@ static void FillOutLightmap( outLightmap_t *olm ){ stores the surface lightmaps into the bsp as byte rgb triplets */ -void StoreSurfaceLightmaps( bool fastAllocate ){ +void StoreSurfaceLightmaps( bool fastAllocate, bool storeForReal ){ int i, j, k, x, y, lx, ly, sx, sy, mappedSamples; int style, lightmapNum, lightmapNum2; float samples, occludedSamples; @@ -2816,7 +2816,7 @@ void StoreSurfaceLightmaps( bool fastAllocate ){ collapse non-unique lightmaps ----------------------------------------------------------------- */ - if ( !noCollapse && !deluxemap ) { + if ( storeForReal && !noCollapse && !deluxemap ) { /* note it */ Sys_Printf( "collapsing..." ); @@ -2890,481 +2890,491 @@ void StoreSurfaceLightmaps( bool fastAllocate ){ sort raw lightmaps by shader ----------------------------------------------------------------- */ - /* note it */ - Sys_Printf( "sorting..." ); + if ( storeForReal ) { + /* note it */ + Sys_Printf( "sorting..." ); - timer.start(); + timer.start(); - /* allocate a new sorted list */ - if ( sortLightmaps == NULL ) { - sortLightmaps = safe_malloc( numRawLightmaps * sizeof( int ) ); + /* allocate a new sorted list */ + if ( sortLightmaps == NULL ) { + sortLightmaps = safe_malloc( numRawLightmaps * sizeof( int ) ); + } + + /* fill it out and sort it */ + for ( i = 0; i < numRawLightmaps; i++ ) + sortLightmaps[ i ] = i; + std::sort( sortLightmaps, sortLightmaps + numRawLightmaps, CompareRawLightmap() ); + + Sys_Printf( "%d.", int( timer.elapsed_sec() ) ); } - /* fill it out and sort it */ - for ( i = 0; i < numRawLightmaps; i++ ) - sortLightmaps[ i ] = i; - std::sort( sortLightmaps, sortLightmaps + numRawLightmaps, CompareRawLightmap() ); - - Sys_Printf( "%d.", int( timer.elapsed_sec() ) ); - /* ----------------------------------------------------------------- allocate output lightmaps ----------------------------------------------------------------- */ - /* note it */ - Sys_Printf( "allocating..." ); + if ( storeForReal ) { + /* note it */ + Sys_Printf( "allocating..." ); - timer.start(); + timer.start(); - /* kill all existing output lightmaps */ - if ( outLightmaps != NULL ) { - for ( i = 0; i < numOutLightmaps; i++ ) - { - free( outLightmaps[ i ].lightBits ); - free( outLightmaps[ i ].bspLightBytes ); - } - free( outLightmaps ); - outLightmaps = NULL; - } - - numLightmapShaders = 0; - numOutLightmaps = 0; - numBSPLightmaps = 0; - numExtLightmaps = 0; - - /* find output lightmap */ - for ( i = 0; i < numRawLightmaps; i++ ) - { - lm = &rawLightmaps[ sortLightmaps[ i ] ]; - FindOutLightmaps( lm, fastAllocate ); - } - - /* set output numbers in twinned lightmaps */ - for ( i = 0; i < numRawLightmaps; i++ ) - { - /* get lightmap */ - lm = &rawLightmaps[ sortLightmaps[ i ] ]; - - /* walk lightmaps */ - for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ ) - { - /* get twin */ - lm2 = lm->twins[ lightmapNum ]; - if ( lm2 == NULL ) { - continue; + /* kill all existing output lightmaps */ + if ( outLightmaps != NULL ) { + for ( i = 0; i < numOutLightmaps; i++ ) + { + free( outLightmaps[ i ].lightBits ); + free( outLightmaps[ i ].bspLightBytes ); } - lightmapNum2 = lm->twinNums[ lightmapNum ]; - - /* find output lightmap from twin */ - lm->outLightmapNums[ lightmapNum ] = lm2->outLightmapNums[ lightmapNum2 ]; - lm->lightmapX[ lightmapNum ] = lm2->lightmapX[ lightmapNum2 ]; - lm->lightmapY[ lightmapNum ] = lm2->lightmapY[ lightmapNum2 ]; + free( outLightmaps ); + outLightmaps = NULL; } - } - Sys_Printf( "%d.", int( timer.elapsed_sec() ) ); + numLightmapShaders = 0; + numOutLightmaps = 0; + numBSPLightmaps = 0; + numExtLightmaps = 0; + + /* find output lightmap */ + for ( i = 0; i < numRawLightmaps; i++ ) + { + lm = &rawLightmaps[ sortLightmaps[ i ] ]; + FindOutLightmaps( lm, fastAllocate ); + } + + /* set output numbers in twinned lightmaps */ + for ( i = 0; i < numRawLightmaps; i++ ) + { + /* get lightmap */ + lm = &rawLightmaps[ sortLightmaps[ i ] ]; + + /* walk lightmaps */ + for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ ) + { + /* get twin */ + lm2 = lm->twins[ lightmapNum ]; + if ( lm2 == NULL ) { + continue; + } + lightmapNum2 = lm->twinNums[ lightmapNum ]; + + /* find output lightmap from twin */ + lm->outLightmapNums[ lightmapNum ] = lm2->outLightmapNums[ lightmapNum2 ]; + lm->lightmapX[ lightmapNum ] = lm2->lightmapX[ lightmapNum2 ]; + lm->lightmapY[ lightmapNum ] = lm2->lightmapY[ lightmapNum2 ]; + } + } + + Sys_Printf( "%d.", int( timer.elapsed_sec() ) ); + } /* ----------------------------------------------------------------- store output lightmaps ----------------------------------------------------------------- */ - /* note it */ - Sys_Printf( "storing..." ); + if ( storeForReal ) { + /* note it */ + Sys_Printf( "storing..." ); - timer.start(); + timer.start(); - /* count the bsp lightmaps and allocate space */ - const size_t gameLmSize = g_game->lightmapSize * g_game->lightmapSize * sizeof( Vector3b ); - if ( numBSPLightmaps == 0 || externalLightmaps ) { - bspLightBytes.clear(); - } - else - { - bspLightBytes = decltype( bspLightBytes )( numBSPLightmaps * gameLmSize, 0 ); - } - - /* walk the list of output lightmaps */ - for ( i = 0; i < numOutLightmaps; i++ ) - { - /* get output lightmap */ - olm = &outLightmaps[ i ]; - - /* fill output lightmap */ - if ( lightmapFill ) { - FillOutLightmap( olm ); + /* count the bsp lightmaps and allocate space */ + const size_t gameLmSize = g_game->lightmapSize * g_game->lightmapSize * sizeof( Vector3b ); + if ( numBSPLightmaps == 0 || externalLightmaps ) { + bspLightBytes.clear(); } - else if( lightmapPink ){ - for ( x = 0; x < olm->customHeight * olm->customWidth; ++x ){ - if ( !bit_is_enabled( olm->lightBits, x ) ) { /* not filled */ - olm->bspLightBytes[x] = { 255, 0, 255 }; + else + { + bspLightBytes = decltype( bspLightBytes )( numBSPLightmaps * gameLmSize, 0 ); + } + + /* walk the list of output lightmaps */ + for ( i = 0; i < numOutLightmaps; i++ ) + { + /* get output lightmap */ + olm = &outLightmaps[ i ]; + + /* fill output lightmap */ + if ( lightmapFill ) { + FillOutLightmap( olm ); + } + else if( lightmapPink ){ + for ( x = 0; x < olm->customHeight * olm->customWidth; ++x ){ + if ( !bit_is_enabled( olm->lightBits, x ) ) { /* not filled */ + olm->bspLightBytes[x] = { 255, 0, 255 }; + } } } - } - /* is this a valid bsp lightmap? */ - if ( olm->lightmapNum >= 0 && !externalLightmaps ) { - /* copy lighting data */ - lb = bspLightBytes.data() + ( olm->lightmapNum * gameLmSize ); - memcpy( lb, olm->bspLightBytes, gameLmSize ); + /* is this a valid bsp lightmap? */ + if ( olm->lightmapNum >= 0 && !externalLightmaps ) { + /* copy lighting data */ + lb = bspLightBytes.data() + ( olm->lightmapNum * gameLmSize ); + memcpy( lb, olm->bspLightBytes, gameLmSize ); - /* copy direction data */ - if ( deluxemap ) { - lb = bspLightBytes.data() + ( ( olm->lightmapNum + 1 ) * gameLmSize ); - memcpy( lb, olm->bspDirBytes, gameLmSize ); + /* copy direction data */ + if ( deluxemap ) { + lb = bspLightBytes.data() + ( ( olm->lightmapNum + 1 ) * gameLmSize ); + memcpy( lb, olm->bspDirBytes, gameLmSize ); + } } - } - /* external lightmap? */ - if ( olm->lightmapNum < 0 || olm->extLightmapNum >= 0 || externalLightmaps ) { - /* make a directory for the lightmaps */ - Q_mkdir( dirname ); + /* external lightmap? */ + if ( olm->lightmapNum < 0 || olm->extLightmapNum >= 0 || externalLightmaps ) { + /* make a directory for the lightmaps */ + Q_mkdir( dirname ); - /* set external lightmap number */ - olm->extLightmapNum = numExtLightmaps; + /* set external lightmap number */ + olm->extLightmapNum = numExtLightmaps; - /* write lightmap */ - sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, numExtLightmaps ); - Sys_FPrintf( SYS_VRB, "\nwriting %s", filename ); - WriteTGA24( filename, olm->bspLightBytes->data(), olm->customWidth, olm->customHeight, true ); - numExtLightmaps++; - - /* write deluxemap */ - if ( deluxemap ) { + /* write lightmap */ sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, numExtLightmaps ); Sys_FPrintf( SYS_VRB, "\nwriting %s", filename ); - WriteTGA24( filename, olm->bspDirBytes->data(), olm->customWidth, olm->customHeight, true ); + WriteTGA24( filename, olm->bspLightBytes->data(), olm->customWidth, olm->customHeight, true ); numExtLightmaps++; - if ( debugDeluxemap ) { - olm->extLightmapNum++; + /* write deluxemap */ + if ( deluxemap ) { + sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, numExtLightmaps ); + Sys_FPrintf( SYS_VRB, "\nwriting %s", filename ); + WriteTGA24( filename, olm->bspDirBytes->data(), olm->customWidth, olm->customHeight, true ); + numExtLightmaps++; + + if ( debugDeluxemap ) { + olm->extLightmapNum++; + } } } } - } - if ( numExtLightmaps > 0 ) { - Sys_Printf( "\n" ); - } - - /* delete unused external lightmaps */ - for ( i = numExtLightmaps; i; i++ ) - { - /* determine if file exists */ - sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, i ); - if ( !FileExists( filename ) ) { - break; + if ( numExtLightmaps > 0 ) { + Sys_Printf( "\n" ); } - /* delete it */ - remove( filename ); - } + /* delete unused external lightmaps */ + for ( i = numExtLightmaps; i; i++ ) + { + /* determine if file exists */ + sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, i ); + if ( !FileExists( filename ) ) { + break; + } - Sys_Printf( "%d.", int( timer.elapsed_sec() ) ); + /* delete it */ + remove( filename ); + } + + Sys_Printf( "%d.", int( timer.elapsed_sec() ) ); + } /* ----------------------------------------------------------------- project the lightmaps onto the bsp surfaces ----------------------------------------------------------------- */ - /* note it */ - Sys_Printf( "projecting..." ); + if ( storeForReal ) { + /* note it */ + Sys_Printf( "projecting..." ); - timer.start(); + timer.start(); - /* walk the list of surfaces */ - for ( size_t i = 0; i < bspDrawSurfaces.size(); ++i ) - { - /* get the surface and info */ - ds = &bspDrawSurfaces[ i ]; - info = &surfaceInfos[ i ]; - lm = info->lm; - olm = NULL; - - /* handle surfaces with identical parent */ - if ( info->parentSurfaceNum >= 0 ) { - /* preserve original data and get parent */ - parent = &bspDrawSurfaces[ info->parentSurfaceNum ]; - memcpy( &dsTemp, ds, sizeof( *ds ) ); - - /* overwrite child with parent data */ - memcpy( ds, parent, sizeof( *ds ) ); - - /* restore key parts */ - ds->fogNum = dsTemp.fogNum; - ds->firstVert = dsTemp.firstVert; - ds->firstIndex = dsTemp.firstIndex; - memcpy( ds->lightmapVecs, dsTemp.lightmapVecs, sizeof( dsTemp.lightmapVecs ) ); - - /* set vertex data */ - dv = &bspDrawVerts[ ds->firstVert ]; - dvParent = &bspDrawVerts[ parent->firstVert ]; - for ( j = 0; j < ds->numVerts; j++ ) - { - memcpy( dv[ j ].lightmap, dvParent[ j ].lightmap, sizeof( dv[ j ].lightmap ) ); - memcpy( dv[ j ].color, dvParent[ j ].color, sizeof( dv[ j ].color ) ); - } - - /* skip the rest */ - continue; - } - - /* handle vertex lit or approximated surfaces */ - else if ( lm == NULL || lm->outLightmapNums[ 0 ] < 0 ) { - for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ ) - { - ds->lightmapNum[ lightmapNum ] = -3; - ds->lightmapStyles[ lightmapNum ] = ds->vertexStyles[ lightmapNum ]; - } - } - - /* handle lightmapped surfaces */ - else + /* walk the list of surfaces */ + for ( size_t i = 0; i < bspDrawSurfaces.size(); ++i ) { - /* walk lightmaps */ - for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ ) - { - /* set style */ - ds->lightmapStyles[ lightmapNum ] = lm->styles[ lightmapNum ]; + /* get the surface and info */ + ds = &bspDrawSurfaces[ i ]; + info = &surfaceInfos[ i ]; + lm = info->lm; + olm = NULL; - /* handle unused style */ - if ( lm->styles[ lightmapNum ] == LS_NONE || lm->outLightmapNums[ lightmapNum ] < 0 ) { - ds->lightmapNum[ lightmapNum ] = -3; - continue; - } + /* handle surfaces with identical parent */ + if ( info->parentSurfaceNum >= 0 ) { + /* preserve original data and get parent */ + parent = &bspDrawSurfaces[ info->parentSurfaceNum ]; + memcpy( &dsTemp, ds, sizeof( *ds ) ); - /* get output lightmap */ - olm = &outLightmaps[ lm->outLightmapNums[ lightmapNum ] ]; + /* overwrite child with parent data */ + memcpy( ds, parent, sizeof( *ds ) ); - /* set bsp lightmap number */ - ds->lightmapNum[ lightmapNum ] = olm->lightmapNum; + /* restore key parts */ + ds->fogNum = dsTemp.fogNum; + ds->firstVert = dsTemp.firstVert; + ds->firstIndex = dsTemp.firstIndex; + memcpy( ds->lightmapVecs, dsTemp.lightmapVecs, sizeof( dsTemp.lightmapVecs ) ); - /* deluxemap debugging makes the deluxemap visible */ - if ( deluxemap && debugDeluxemap && lightmapNum == 0 ) { - ds->lightmapNum[ lightmapNum ]++; - } - - /* calc lightmap origin in texture space */ - lmx = (float) lm->lightmapX[ lightmapNum ] / (float) olm->customWidth; - lmy = (float) lm->lightmapY[ lightmapNum ] / (float) olm->customHeight; - - /* calc lightmap st coords */ + /* set vertex data */ dv = &bspDrawVerts[ ds->firstVert ]; - ydv = &yDrawVerts[ ds->firstVert ]; + dvParent = &bspDrawVerts[ parent->firstVert ]; for ( j = 0; j < ds->numVerts; j++ ) { - if ( lm->solid[ lightmapNum ] ) { - dv[ j ].lightmap[ lightmapNum ][ 0 ] = lmx + ( 0.5f / (float) olm->customWidth ); - dv[ j ].lightmap[ lightmapNum ][ 1 ] = lmy + ( 0.5f / (float) olm->customWidth ); + memcpy( dv[ j ].lightmap, dvParent[ j ].lightmap, sizeof( dv[ j ].lightmap ) ); + memcpy( dv[ j ].color, dvParent[ j ].color, sizeof( dv[ j ].color ) ); + } + + /* skip the rest */ + continue; + } + + /* handle vertex lit or approximated surfaces */ + else if ( lm == NULL || lm->outLightmapNums[ 0 ] < 0 ) { + for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ ) + { + ds->lightmapNum[ lightmapNum ] = -3; + ds->lightmapStyles[ lightmapNum ] = ds->vertexStyles[ lightmapNum ]; + } + } + + /* handle lightmapped surfaces */ + else + { + /* walk lightmaps */ + for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ ) + { + /* set style */ + ds->lightmapStyles[ lightmapNum ] = lm->styles[ lightmapNum ]; + + /* handle unused style */ + if ( lm->styles[ lightmapNum ] == LS_NONE || lm->outLightmapNums[ lightmapNum ] < 0 ) { + ds->lightmapNum[ lightmapNum ] = -3; + continue; + } + + /* get output lightmap */ + olm = &outLightmaps[ lm->outLightmapNums[ lightmapNum ] ]; + + /* set bsp lightmap number */ + ds->lightmapNum[ lightmapNum ] = olm->lightmapNum; + + /* deluxemap debugging makes the deluxemap visible */ + if ( deluxemap && debugDeluxemap && lightmapNum == 0 ) { + ds->lightmapNum[ lightmapNum ]++; + } + + /* calc lightmap origin in texture space */ + lmx = (float) lm->lightmapX[ lightmapNum ] / (float) olm->customWidth; + lmy = (float) lm->lightmapY[ lightmapNum ] / (float) olm->customHeight; + + /* calc lightmap st coords */ + dv = &bspDrawVerts[ ds->firstVert ]; + ydv = &yDrawVerts[ ds->firstVert ]; + for ( j = 0; j < ds->numVerts; j++ ) + { + if ( lm->solid[ lightmapNum ] ) { + dv[ j ].lightmap[ lightmapNum ][ 0 ] = lmx + ( 0.5f / (float) olm->customWidth ); + dv[ j ].lightmap[ lightmapNum ][ 1 ] = lmy + ( 0.5f / (float) olm->customWidth ); + } + else + { + dv[ j ].lightmap[ lightmapNum ][ 0 ] = lmx + ( ydv[ j ].lightmap[ 0 ][ 0 ] / ( superSample * olm->customWidth ) ); + dv[ j ].lightmap[ lightmapNum ][ 1 ] = lmy + ( ydv[ j ].lightmap[ 0 ][ 1 ] / ( superSample * olm->customHeight ) ); + } + } + } + } + + /* store vertex colors */ + dv = &bspDrawVerts[ ds->firstVert ]; + for ( j = 0; j < ds->numVerts; j++ ) + { + /* walk lightmaps */ + for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ ) + { + Vector3 color; + /* handle unused style */ + if ( ds->vertexStyles[ lightmapNum ] == LS_NONE ) { + color.set( 0 ); } else { - dv[ j ].lightmap[ lightmapNum ][ 0 ] = lmx + ( ydv[ j ].lightmap[ 0 ][ 0 ] / ( superSample * olm->customWidth ) ); - dv[ j ].lightmap[ lightmapNum ][ 1 ] = lmy + ( ydv[ j ].lightmap[ 0 ][ 1 ] / ( superSample * olm->customHeight ) ); + /* get vertex color */ + color = getVertexLuxel( lightmapNum, ds->firstVert + j ); + + /* set minimum light */ + if ( lightmapNum == 0 ) { + for ( k = 0; k < 3; k++ ) + value_maximize( color[ k ], minVertexLight[ k ] ); + } + } + + /* store to bytes */ + if ( !info->si->noVertexLight ) { + dv[ j ].color[ lightmapNum ].rgb() = ColorToBytes( color, info->si->vertexScale ); } } } - } - /* store vertex colors */ - dv = &bspDrawVerts[ ds->firstVert ]; - for ( j = 0; j < ds->numVerts; j++ ) - { - /* walk lightmaps */ - for ( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ ) - { - Vector3 color; - /* handle unused style */ - if ( ds->vertexStyles[ lightmapNum ] == LS_NONE ) { - color.set( 0 ); - } - else + /* surfaces with styled lightmaps and a style marker get a custom generated shader (fixme: make this work with external lightmaps) */ + if ( olm != NULL && lm != NULL && lm->styles[ 1 ] != LS_NONE && g_game->load != LoadRBSPFile ) { //% info->si->styleMarker > 0 ) + char key[ 32 ], styleStage[ 512 ], styleStages[ 4096 ], rgbGen[ 128 ], alphaGen[ 128 ]; + + + /* setup */ + sprintf( styleStages, "\n\t// Q3Map2 custom lightstyle stage(s)\n" ); + dv = &bspDrawVerts[ ds->firstVert ]; + + /* depthFunc equal? */ + const bool dfEqual = ( info->si->styleMarker == 2 || info->si->implicitMap == EImplicitMap::Masked ); + + /* generate stages for styled lightmaps */ + for ( lightmapNum = 1; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ ) { - /* get vertex color */ - color = getVertexLuxel( lightmapNum, ds->firstVert + j ); - - /* set minimum light */ - if ( lightmapNum == 0 ) { - for ( k = 0; k < 3; k++ ) - value_maximize( color[ k ], minVertexLight[ k ] ); + /* early out */ + style = lm->styles[ lightmapNum ]; + if ( style == LS_NONE || lm->outLightmapNums[ lightmapNum ] < 0 ) { + continue; } - } - /* store to bytes */ - if ( !info->si->noVertexLight ) { - dv[ j ].color[ lightmapNum ].rgb() = ColorToBytes( color, info->si->vertexScale ); - } - } - } + /* get output lightmap */ + olm = &outLightmaps[ lm->outLightmapNums[ lightmapNum ] ]; - /* surfaces with styled lightmaps and a style marker get a custom generated shader (fixme: make this work with external lightmaps) */ - if ( olm != NULL && lm != NULL && lm->styles[ 1 ] != LS_NONE && g_game->load != LoadRBSPFile ) { //% info->si->styleMarker > 0 ) - char key[ 32 ], styleStage[ 512 ], styleStages[ 4096 ], rgbGen[ 128 ], alphaGen[ 128 ]; - - - /* setup */ - sprintf( styleStages, "\n\t// Q3Map2 custom lightstyle stage(s)\n" ); - dv = &bspDrawVerts[ ds->firstVert ]; - - /* depthFunc equal? */ - const bool dfEqual = ( info->si->styleMarker == 2 || info->si->implicitMap == EImplicitMap::Masked ); - - /* generate stages for styled lightmaps */ - for ( lightmapNum = 1; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ ) - { - /* early out */ - style = lm->styles[ lightmapNum ]; - if ( style == LS_NONE || lm->outLightmapNums[ lightmapNum ] < 0 ) { - continue; - } - - /* get output lightmap */ - olm = &outLightmaps[ lm->outLightmapNums[ lightmapNum ] ]; - - /* lightmap name */ - if ( lm->outLightmapNums[ lightmapNum ] == lm->outLightmapNums[ 0 ] ) { - strcpy( lightmapName, "$lightmap" ); - } - else{ - sprintf( lightmapName, "maps/%s/" EXTERNAL_LIGHTMAP, mapName.c_str(), olm->extLightmapNum ); - } - - /* get rgbgen string */ - if ( rgbGenValues[ style ] == NULL ) { - sprintf( key, "_style%drgbgen", style ); - rgbGenValues[ style ] = entities[ 0 ].valueForKey( key ); - if ( strEmpty( rgbGenValues[ style ] ) ) { - rgbGenValues[ style ] = "wave noise 0.5 1 0 5.37"; + /* lightmap name */ + if ( lm->outLightmapNums[ lightmapNum ] == lm->outLightmapNums[ 0 ] ) { + strcpy( lightmapName, "$lightmap" ); + } + else{ + sprintf( lightmapName, "maps/%s/" EXTERNAL_LIGHTMAP, mapName.c_str(), olm->extLightmapNum ); + } + + /* get rgbgen string */ + if ( rgbGenValues[ style ] == NULL ) { + sprintf( key, "_style%drgbgen", style ); + rgbGenValues[ style ] = entities[ 0 ].valueForKey( key ); + if ( strEmpty( rgbGenValues[ style ] ) ) { + rgbGenValues[ style ] = "wave noise 0.5 1 0 5.37"; + } } - } - strClear( rgbGen ); - if ( !strEmpty( rgbGenValues[ style ] ) ) { - sprintf( rgbGen, "\t\trgbGen %s // style %d\n", rgbGenValues[ style ], style ); - } - else{ strClear( rgbGen ); + if ( !strEmpty( rgbGenValues[ style ] ) ) { + sprintf( rgbGen, "\t\trgbGen %s // style %d\n", rgbGenValues[ style ], style ); + } + else{ + strClear( rgbGen ); + } + + /* get alphagen string */ + if ( alphaGenValues[ style ] == NULL ) { + sprintf( key, "_style%dalphagen", style ); + alphaGenValues[ style ] = entities[ 0 ].valueForKey( key ); + } + if ( !strEmpty( alphaGenValues[ style ] ) ) { + sprintf( alphaGen, "\t\talphaGen %s // style %d\n", alphaGenValues[ style ], style ); + } + else{ + strClear( alphaGen ); + } + + /* calculate st offset */ + const Vector2 lmxy = dv[ 0 ].lightmap[ lightmapNum ] - dv[ 0 ].lightmap[ 0 ]; + + /* create additional stage */ + if ( lmxy.x() == 0.0f && lmxy.y() == 0.0f ) { + sprintf( styleStage, "\t{\n" + "\t\tmap %s\n" /* lightmap */ + "\t\tblendFunc GL_SRC_ALPHA GL_ONE\n" + "%s" /* depthFunc equal */ + "%s" /* rgbGen */ + "%s" /* alphaGen */ + "\t\ttcGen lightmap\n" + "\t}\n", + lightmapName, + ( dfEqual ? "\t\tdepthFunc equal\n" : "" ), + rgbGen, + alphaGen ); + } + else + { + sprintf( styleStage, "\t{\n" + "\t\tmap %s\n" /* lightmap */ + "\t\tblendFunc GL_SRC_ALPHA GL_ONE\n" + "%s" /* depthFunc equal */ + "%s" /* rgbGen */ + "%s" /* alphaGen */ + "\t\ttcGen lightmap\n" + "\t\ttcMod transform 1 0 0 1 %1.5f %1.5f\n" /* st offset */ + "\t}\n", + lightmapName, + ( dfEqual ? "\t\tdepthFunc equal\n" : "" ), + rgbGen, + alphaGen, + lmxy.x(), lmxy.y() ); + + } + + /* concatenate */ + strcat( styleStages, styleStage ); } - /* get alphagen string */ - if ( alphaGenValues[ style ] == NULL ) { - sprintf( key, "_style%dalphagen", style ); - alphaGenValues[ style ] = entities[ 0 ].valueForKey( key ); - } - if ( !strEmpty( alphaGenValues[ style ] ) ) { - sprintf( alphaGen, "\t\talphaGen %s // style %d\n", alphaGenValues[ style ], style ); + /* create custom shader */ + if ( info->si->styleMarker == 2 ) { + csi = CustomShader( info->si, "q3map_styleMarker2", styleStages ); } else{ - strClear( alphaGen ); + csi = CustomShader( info->si, "q3map_styleMarker", styleStages ); } - /* calculate st offset */ - const Vector2 lmxy = dv[ 0 ].lightmap[ lightmapNum ] - dv[ 0 ].lightmap[ 0 ]; + /* emit remap command */ + //% EmitVertexRemapShader( csi->shader, info->si->shader ); - /* create additional stage */ - if ( lmxy.x() == 0.0f && lmxy.y() == 0.0f ) { - sprintf( styleStage, "\t{\n" - "\t\tmap %s\n" /* lightmap */ - "\t\tblendFunc GL_SRC_ALPHA GL_ONE\n" - "%s" /* depthFunc equal */ - "%s" /* rgbGen */ - "%s" /* alphaGen */ - "\t\ttcGen lightmap\n" - "\t}\n", - lightmapName, - ( dfEqual ? "\t\tdepthFunc equal\n" : "" ), - rgbGen, - alphaGen ); - } - else - { - sprintf( styleStage, "\t{\n" - "\t\tmap %s\n" /* lightmap */ - "\t\tblendFunc GL_SRC_ALPHA GL_ONE\n" - "%s" /* depthFunc equal */ - "%s" /* rgbGen */ - "%s" /* alphaGen */ - "\t\ttcGen lightmap\n" - "\t\ttcMod transform 1 0 0 1 %1.5f %1.5f\n" /* st offset */ - "\t}\n", - lightmapName, - ( dfEqual ? "\t\tdepthFunc equal\n" : "" ), - rgbGen, - alphaGen, - lmxy.x(), lmxy.y() ); - - } - - /* concatenate */ - strcat( styleStages, styleStage ); + /* store it */ + //% Sys_Printf( "Emitting: %s (%d", csi->shader, strlen( csi->shader ) ); + int cont = bspShaders[ ds->shaderNum ].contentFlags; + int surf = bspShaders[ ds->shaderNum ].surfaceFlags; + ds->shaderNum = EmitShader( csi->shader, &cont, &surf ); + //% Sys_Printf( ")\n" ); } - /* create custom shader */ - if ( info->si->styleMarker == 2 ) { - csi = CustomShader( info->si, "q3map_styleMarker2", styleStages ); + /* devise a custom shader for this surface (fixme: make this work with light styles) */ + else if ( olm != NULL && lm != NULL && !externalLightmaps && + ( olm->customWidth != g_game->lightmapSize || olm->customHeight != g_game->lightmapSize ) ) { + /* get output lightmap */ + olm = &outLightmaps[ lm->outLightmapNums[ 0 ] ]; + + /* do some name mangling */ + sprintf( lightmapName, "maps/%s/" EXTERNAL_LIGHTMAP "\n\t\ttcgen lightmap", mapName.c_str(), olm->extLightmapNum ); + + /* create custom shader */ + csi = CustomShader( info->si, "$lightmap", lightmapName ); + + /* store it */ + //% Sys_Printf( "Emitting: %s (%d", csi->shader, strlen( csi->shader ) ); + int cont = bspShaders[ ds->shaderNum ].contentFlags; + int surf = bspShaders[ ds->shaderNum ].surfaceFlags; + ds->shaderNum = EmitShader( csi->shader, &cont, &surf ); + //% Sys_Printf( ")\n" ); } + + /* use the normal plain-jane shader */ else{ - csi = CustomShader( info->si, "q3map_styleMarker", styleStages ); - } - - /* emit remap command */ - //% EmitVertexRemapShader( csi->shader, info->si->shader ); - - /* store it */ - //% Sys_Printf( "Emitting: %s (%d", csi->shader, strlen( csi->shader ) ); - int cont = bspShaders[ ds->shaderNum ].contentFlags; - int surf = bspShaders[ ds->shaderNum ].surfaceFlags; - ds->shaderNum = EmitShader( csi->shader, &cont, &surf ); - //% Sys_Printf( ")\n" ); - } - - /* devise a custom shader for this surface (fixme: make this work with light styles) */ - else if ( olm != NULL && lm != NULL && !externalLightmaps && - ( olm->customWidth != g_game->lightmapSize || olm->customHeight != g_game->lightmapSize ) ) { - /* get output lightmap */ - olm = &outLightmaps[ lm->outLightmapNums[ 0 ] ]; - - /* do some name mangling */ - sprintf( lightmapName, "maps/%s/" EXTERNAL_LIGHTMAP "\n\t\ttcgen lightmap", mapName.c_str(), olm->extLightmapNum ); - - /* create custom shader */ - csi = CustomShader( info->si, "$lightmap", lightmapName ); - - /* store it */ - //% Sys_Printf( "Emitting: %s (%d", csi->shader, strlen( csi->shader ) ); - int cont = bspShaders[ ds->shaderNum ].contentFlags; - int surf = bspShaders[ ds->shaderNum ].surfaceFlags; - ds->shaderNum = EmitShader( csi->shader, &cont, &surf ); - //% Sys_Printf( ")\n" ); - } - - /* use the normal plain-jane shader */ - else{ - int cont = bspShaders[ ds->shaderNum ].contentFlags; + int cont = bspShaders[ ds->shaderNum ].contentFlags; int surf = bspShaders[ ds->shaderNum ].surfaceFlags; ds->shaderNum = EmitShader( info->si->shader, &cont, &surf ); + } } - } - Sys_Printf( "%d.", int( timer.elapsed_sec() ) ); + Sys_Printf( "%d.", int( timer.elapsed_sec() ) ); + } /* finish */ Sys_Printf( "done.\n" ); - /* calc num stored */ - numStored = bspLightBytes.size() / 3; - efficiency = ( numStored <= 0 ) - ? 0 - : (float) numUsed / (float) numStored; + if ( storeForReal ) { + /* calc num stored */ + numStored = bspLightBytes.size() / 3; + efficiency = ( numStored <= 0 ) + ? 0 + : (float) numUsed / (float) numStored; - /* print stats */ - Sys_Printf( "%9d luxels used\n", numUsed ); - Sys_Printf( "%9d luxels stored (%3.2f percent efficiency)\n", numStored, efficiency * 100.0f ); - Sys_Printf( "%9d solid surface lightmaps\n", numSolidLightmaps ); - Sys_Printf( "%9d identical surface lightmaps, using %d luxels\n", numTwins, numTwinLuxels ); - Sys_Printf( "%9d vertex forced surfaces\n", numSurfsVertexForced ); - Sys_Printf( "%9d vertex approximated surfaces\n", numSurfsVertexApproximated ); - Sys_Printf( "%9d BSP lightmaps\n", numBSPLightmaps ); - Sys_Printf( "%9d total lightmaps\n", numOutLightmaps ); - Sys_Printf( "%9d unique lightmap/shader combinations\n", numLightmapShaders ); + /* print stats */ + Sys_Printf( "%9d luxels used\n", numUsed ); + Sys_Printf( "%9d luxels stored (%3.2f percent efficiency)\n", numStored, efficiency * 100.0f ); + Sys_Printf( "%9d solid surface lightmaps\n", numSolidLightmaps ); + Sys_Printf( "%9d identical surface lightmaps, using %d luxels\n", numTwins, numTwinLuxels ); + Sys_Printf( "%9d vertex forced surfaces\n", numSurfsVertexForced ); + Sys_Printf( "%9d vertex approximated surfaces\n", numSurfsVertexApproximated ); + Sys_Printf( "%9d BSP lightmaps\n", numBSPLightmaps ); + Sys_Printf( "%9d total lightmaps\n", numOutLightmaps ); + Sys_Printf( "%9d unique lightmap/shader combinations\n", numLightmapShaders ); - /* write map shader file */ - WriteMapShaderFile(); + /* write map shader file */ + WriteMapShaderFile(); + } } diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h index b69da85b..b110bbe5 100644 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@ -1649,7 +1649,7 @@ int ImportLightmapsMain( Args& args ); void SetupSurfaceLightmaps(); void StitchSurfaceLightmaps(); -void StoreSurfaceLightmaps( bool fastAllocate ); +void StoreSurfaceLightmaps( bool fastAllocate, bool storeForReal ); /* exportents.c */