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); }
/* *This function calculates a dynamic lightning cast from player. *Do raycasts to all close corners (lightpoints) to the player and *draw triangles on blendmode to the target renderer texture. */ void Lightning::calculateLightSource(GameEngine* game, SDL_Texture *texture, Map map, Player player) { //Setup new texture as render target SDL_SetRenderTarget(game->renderer, texture); SDL_SetRenderDrawBlendMode(game->renderer, SDL_BLENDMODE_NONE); SDL_SetRenderDrawColor(game->renderer, 50, 50, 50, 255); SDL_RenderFillRect(game->renderer, NULL); SDL_SetRenderDrawColor(game->renderer, 255, 255, 255, 255); int length = 2000; vector<Position> lightPos; int player_pos_x = player.position.x+15; int player_pos_y = player.position.y+48; //Go through all lightpoints on map for(int i = 0; i < map.lightPoints.size(); i++) { //Convert ligthpoints to vector2 in local space Vector2 lightVector((float)(map.lightPoints[i].x - player_pos_x), (float)(map.lightPoints[i].y - player_pos_y)); if(lightVector.Length() < 900) { lightVector = lightVector.Normalize(); //Do raycast to all close lightpoints. vector<Raycast::Position> ray; ray = raycast.bresenhamLine(player_pos_y, player_pos_x, (lightVector.Y*length)+player_pos_y, (lightVector.X*length)+player_pos_x); bool passedLightPoint = false; int j = 0; j = (ray[0].y == player_pos_y && ray[0].x == player_pos_x) ? 0 : ray.size()-1; while(true) { int x = ray[j].x; int y = ray[j].y; if(map.isWall(map.mapTilePosition[y/map.getTileSize()][x/map.getTileSize()]) && !passedLightPoint) { break; } else if(ray[j].y == map.lightPoints[i].y && ray[j].x == map.lightPoints[i].x) { Position pos; if(ray[0].y == player_pos_y && ray[0].x == player_pos_x) { pos.x = ray[j-1].x; pos.y = ray[j-1].y; } else { pos.x = ray[j+1].x; pos.y = ray[j+1].y; } pos.lightPoint = true; pos.id = i; lightPos.push_back(pos); passedLightPoint = true; /*if(map.isWall(map.mapTilePosition[(int)(ray[j+4].y/map.getTileSize())][(int)(ray[j+4].x/map.getTileSize())])) break; if(map.isWall(map.mapTilePosition[(int)(ray[j-4].y/map.getTileSize())][(int)(ray[j-4].x/map.getTileSize())])) break;*/ } else if(passedLightPoint) { if(map.isWall(map.mapTilePosition[y/map.getTileSize()][x/map.getTileSize()])) { Position pos; if(ray[0].y == player_pos_y && ray[0].x == player_pos_x) { pos.x = ray[j-1].x; pos.y = ray[j-1].y; } else { pos.x = ray[j+1].x; pos.y = ray[j+1].y; } pos.id = i; pos.lightPoint = false; lightPos.push_back(pos); break; } } if(ray[0].y == player_pos_y && ray[0].x == player_pos_x) { j++; if(j >= ray.size()) break; } else { j--; if(j < 0) break; } } } } /* for(int i = 0; i < lightPos.size(); i++) { for(int j = 0; j < lightPos.size()-1; j++) { Vector2 tempvector1((float)(lightPos[j+1].x - player_pos_x), (float)(lightPos[j+1].y - player_pos_y)); Vector2 tempvector2((float)(lightPos[j].x - player_pos_x), (float)(lightPos[j].y - player_pos_y)); if(floor(tempvector1.Normalize().Direction()) > floor(tempvector2.Normalize().Direction())) { Position tmp = lightPos[j]; lightPos[j] = lightPos[j+1]; lightPos[j+1] = tmp; } } } } */ //Draw light to texture for(int i = 0; i < lightPos.size(); i++) { //int i = 7; /* SDL_RenderDrawLine(game->renderer, lightPos[i].x+game->camera.getXPosition(), lightPos[i].y+game->camera.getYPosition(), player.position.x+15+game->camera.getXPosition(), player.position.y+50+game->camera.getYPosition()); */ for(int j = i; j < lightPos.size(); j++) { if(raycast.raycast_insight(lightPos[i].x, lightPos[i].y, lightPos[j].x, lightPos[j].y, map)) { filledTrigonColor(game->renderer, player_pos_x+game->camera.getXPosition(), player_pos_y+game->camera.getYPosition(), lightPos[i].x+game->camera.getXPosition(), lightPos[i].y+game->camera.getYPosition(), lightPos[j].x+game->camera.getXPosition(), lightPos[j].y+game->camera.getYPosition(), 0xFFFFFFFF); //break; } } // else if(raycast.raycast_insight(lightPos[i].x, lightPos[i].y, lightPos[x].x, lightPos[x].y, map)) /* else { p++; if(p == lightPos.size()) p = 0; }*/ // } /* filledTrigonColor(game->renderer, player_pos_x+game->camera.getXPosition(), player_pos_y+game->camera.getYPosition(), lightPos[i].x+game->camera.getXPosition(), lightPos[i].y+game->camera.getYPosition(), lightPos[p].x+game->camera.getXPosition(), lightPos[p].y+game->camera.getYPosition(), 0xFFFFFFFF);*/ } }