void ClipMap::ClipStackEntry::initDebugTexture(U32 level) { static U8 colors[10][3] = { {0xFF, 0x00, 0x00}, {0xFF, 0xFF, 0x00}, {0x00, 0xFF, 0x00}, {0x00, 0xFF, 0xFF}, {0x00, 0x00, 0xFF}, {0xFF, 0x00, 0xFF}, {0xFF, 0xFF, 0xFF}, {0xaa, 0x00, 0xaa}, {0xaa, 0xaa, 0x00}, {0x00, 0xaa, 0xaa}, }; GBitmap *debugBmp = new GBitmap(4, 4); ColorI debugClr(colors[level][0], colors[level][1], colors[level][2]); ColorI edgeClr(colors[level][2], colors[level][1], colors[level][0]); for(S32 i=0; i<4; i++) { for(S32 j=0; j<4; j++) { bool edge = i==0 || j==0 || i==3 || j==3; debugBmp->setColor(i,j, edge ? edgeClr : debugClr); } } mDebugTex.set(debugBmp, &GDefaultStaticDiffuseProfile, true, "Clipmap Debug Tex"); }
void blInteriorProxy::addToShadowVolume(ShadowVolumeBSP * shadowVolume, LightInfo * light, S32 level) { if(light->getType() != LightInfo::Vector) return; ColorF ambient = light->getAmbient(); bool shadowedTree = true; InteriorInstance* interior = dynamic_cast<InteriorInstance*>(getObject()); if (!interior) return; Resource<InteriorResource> mInteriorRes = interior->getResource(); // check if just getting shadow detail if(level == SceneLighting::SHADOW_DETAIL) { shadowedTree = false; level = mInteriorRes->getNumDetailLevels() - 1; } Interior * detail = mInteriorRes->getDetailLevel(level); bool hasAlarm = detail->hasAlarmState(); // make sure surfaces do not get processed more than once BitVector surfaceProcessed; surfaceProcessed.setSize(detail->mSurfaces.size()); surfaceProcessed.clear(); ColorI color = light->getAmbient(); // go through the zones of the interior and grab outside visible surfaces for(U32 i = 0; i < detail->getNumZones(); i++) { Interior::Zone & zone = detail->mZones[i]; for(U32 j = 0; j < zone.surfaceCount; j++) { U32 surfaceIndex = detail->mZoneSurfaces[zone.surfaceStart + j]; // dont reprocess a surface if(surfaceProcessed.test(surfaceIndex)) continue; surfaceProcessed.set(surfaceIndex); Interior::Surface & surface = detail->mSurfaces[surfaceIndex]; // outside visible? if(!(surface.surfaceFlags & Interior::SurfaceOutsideVisible)) continue; // good surface? PlaneF plane = detail->getPlane(surface.planeIndex); if(Interior::planeIsFlipped(surface.planeIndex)) plane.neg(); // project the plane PlaneF projPlane; mTransformPlane(interior->getTransform(), interior->getScale(), plane, &projPlane); // fill with ambient? (need to do here, because surface will not be // added to the SVBSP tree) F32 dot = mDot(projPlane, light->getDirection()); if(dot > -gParellelVectorThresh)// && !(GFX->getPixelShaderVersion() > 0.0) ) { if(shadowedTree) { // alarm lighting GFXTexHandle normHandle = gInteriorLMManager.duplicateBaseLightmap(detail->getLMHandle(), interior->getLMHandle(), detail->getNormalLMapIndex(surfaceIndex)); GFXTexHandle alarmHandle; GBitmap * normLightmap = normHandle->getBitmap(); GBitmap * alarmLightmap = 0; // check if they share the lightmap if(hasAlarm) { if(detail->getNormalLMapIndex(surfaceIndex) != detail->getAlarmLMapIndex(surfaceIndex)) { alarmHandle = gInteriorLMManager.duplicateBaseLightmap(detail->getLMHandle(), interior->getLMHandle(), detail->getAlarmLMapIndex(surfaceIndex)); alarmLightmap = alarmHandle->getBitmap(); } } // // Support for interior light map border sizes. // U32 xlen, ylen, xoff, yoff; U32 lmborder = detail->getLightMapBorderSize(); xlen = surface.mapSizeX + (lmborder * 2); ylen = surface.mapSizeY + (lmborder * 2); xoff = surface.mapOffsetX - lmborder; yoff = surface.mapOffsetY - lmborder; // attemp to light normal and alarm lighting for(U32 c = 0; c < 2; c++) { GBitmap * lightmap = (c == 0) ? normLightmap : alarmLightmap; if(!lightmap) continue; // fill it for(U32 y = 0; y < ylen; y++) { for(U32 x = 0; x < xlen; x++) { ColorI outColor(255, 0, 0, 255); #ifndef SET_COLORS ColorI lmColor(0, 0, 0, 255); lightmap->getColor(xoff + x, yoff + y, lmColor); U32 _r = static_cast<U32>( color.red ) + static_cast<U32>( lmColor.red ); U32 _g = static_cast<U32>( color.green ) + static_cast<U32>( lmColor.green ); U32 _b = static_cast<U32>( color.blue ) + static_cast<U32>( lmColor.blue ); outColor.red = mClamp(_r, 0, 255); outColor.green = mClamp(_g, 0, 255); outColor.blue = mClamp(_b, 0, 255); #endif lightmap->setColor(xoff + x, yoff + y, outColor); } } } } continue; } ShadowVolumeBSP::SVPoly * poly = buildInteriorPoly(shadowVolume, detail, surfaceIndex, light, shadowedTree); // insert it into the SVBSP tree shadowVolume->insertPoly(poly); } } }
void blTerrainProxy::light(LightInfo * light) { // If we don't have terrain or its not a directional // light then skip processing. TerrainBlock * terrain = getObject(); if ( !terrain || light->getType() != LightInfo::Vector ) return; S32 time = Platform::getRealMilliseconds(); // reset mShadowVolume = new ShadowVolumeBSP; // build interior shadow volume for(ObjectProxy ** itr = gLighting->mLitObjects.begin(); itr != gLighting->mLitObjects.end(); itr++) { ObjectProxy* objproxy = *itr; if (markObjectShadow(objproxy)) objproxy->addToShadowVolume(mShadowVolume, light, SceneLighting::SHADOW_DETAIL); } lightVector(light); // set the lightmap... terrain->clearLightMap(); // Blur... F32 kernel[3][3] = { {1, 2, 1}, {2, 3, 2}, {1, 2, 1} }; F32 modifier = 1; F32 divisor = 0; for( U32 i=0; i<3; i++ ) { for( U32 j=0; j<3; j++ ) { if( i==1 && j==1 ) { kernel[i][j] = 1 + kernel[i][j] * modifier; } else { kernel[i][j] = kernel[i][j] * modifier; } divisor += kernel[i][j]; } } for( U32 i=0; i < mLightMapSize; i++ ) { for( U32 j=0; j < mLightMapSize; j++ ) { ColorF val; val = _getValue( i-1, j-1 ) * kernel[0][0]; val += _getValue( i-1, j ) * kernel[0][1]; val += _getValue( i-1, j+1 ) * kernel[0][2]; val += _getValue( i, j-1 ) * kernel[1][0]; val += _getValue( i, j ) * kernel[1][1]; val += _getValue( i, j+1 ) * kernel[1][2]; val += _getValue( i+1, j-1 ) * kernel[2][0]; val += _getValue( i+1, j ) * kernel[2][1]; val += _getValue( i+1, j+1 ) * kernel[2][2]; U32 edge = 0; if( j == 0 || j == mLightMapSize - 1 ) edge++; if( i == 0 || i == mLightMapSize - 1 ) edge++; if( !edge ) val = val / divisor; else val = mLightmap[ i * mLightMapSize + j ]; // clamp values mLightmap[ i * mLightMapSize + j ]= val; } } // And stuff it into the texture... GBitmap *terrLightMap = terrain->getLightMap(); for(U32 y = 0; y < mLightMapSize; y++) { for(U32 x = 0; x < mLightMapSize; x++) { ColorI color(255, 255, 255, 255); color.red = mLightmap[x + y * mLightMapSize].red * 255; color.green = mLightmap[x + y * mLightMapSize].green * 255; color.blue = mLightmap[x + y * mLightMapSize].blue * 255; terrLightMap->setColor(x, y, color); } } /* // This handles matching up the outer edges of the terrain // lightmap when it has neighbors if (!terrain->isTiling()) { for (S32 y = 0; y < terrLightMap->getHeight(); y++) { ColorI c; if (terrain->getFile()->mEdgeTerrainFiles[0]) { terrLightMap->getColor(terrLightMap->getWidth()-1,y,c); terrLightMap->setColor(0,y,c); terrLightMap->setColor(1,y,c); } else { terrLightMap->getColor(0,y,c); terrLightMap->setColor(terrLightMap->getWidth()-1,y,c); terrLightMap->setColor(terrLightMap->getWidth()-2,y,c); } } for (S32 x = 0; x < terrLightMap->getHeight(); x++) { ColorI c; if (terrain->getFile()->mEdgeTerrainFiles[1]) { terrLightMap->getColor(x,terrLightMap->getHeight()-1,c); terrLightMap->setColor(x,0,c); terrLightMap->setColor(x,1,c); } else { terrLightMap->getColor(x,0,c); terrLightMap->setColor(x,terrLightMap->getHeight()-1,c); terrLightMap->setColor(x,terrLightMap->getHeight()-2,c); } } } */ delete mShadowVolume; Con::printf(" = terrain lit in %3.3f seconds", (Platform::getRealMilliseconds()-time)/1000.f); }