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);
}
예제 #2
0
/*
*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);*/

    }
}