Sign in to follow this  
streamer

smoot movement of light

Recommended Posts

Hello In my game I do a custom tile based lighting. But a problem is when a player moves to a new tile, light that surrounds him moves +-1 tile by x or y axis. I don't know how can I do some smooth light transitions. Here is an example Click here. How can I get that light smootly follow the player, not in steps (tile by tile)? [Edited by - streamer on June 5, 2005 4:04:17 PM]

Share this post


Link to post
Share on other sites
In Golem, I placed lights in the world on a world-coordinate basis, then used simple distance algorithms to light each corner of the tile. Each tile represented a block of 64x64 units in world coordinates. Since a light could occupy any of these world coordinates, the lighting remained smooth as the light moved. The biggest mistake you can make is to try to keep everything in 'tile coordinates', which results in the blocky lighting. Refine your coordinate system finer than the 'tile coordinate' level for best results. Makes it easier to do smooth scrolling, too, since the player object (and thus the following camera) can move on finer increments than whole tiles.

Share this post


Link to post
Share on other sites
Hmmm I don't think I understand you. Do you mean that every tile is segmented in 64x64 grid? If I do that I'll have a performace drawback...
My game scrolls just fine - smootly, one by one pixel. Player and NPC-s have two type of coordinates. First coordinate is tile based, and second is offset coordinate of player inside of tile. If player "steps" out of tile he will "step" into a neighbour tile. I think that this is good solution because when I draw map, every tile draws everything that have inside them.

Quote:
The biggest mistake you can make is to try to keep everything in 'tile coordinates', which results in the blocky lighting.

So I need to update tiles to be of more triangles? Because I made every tile of two triangle...Max I can do (because I am bounded to 4 vertex) is 'blocky' lighting which follow player tile by tile.

Share this post


Link to post
Share on other sites
Arey you using 3d or 2d?

Do you want 2D lighting so that anything within a radius of the player the same brightness even if it is tall or deep?

Do you plan to use the same technique for lights in the game?

Share this post


Link to post
Share on other sites
Quote:
Original post by streamer
Hmmm I don't think I understand you. Do you mean that every tile is segmented in 64x64 grid? If I do that I'll have a performace drawback...
My game scrolls just fine - smootly, one by one pixel. Player and NPC-s have two type of coordinates. First coordinate is tile based, and second is offset coordinate of player inside of tile. If player "steps" out of tile he will "step" into a neighbour tile. I think that this is good solution because when I draw map, every tile draws everything that have inside them.

Quote:
The biggest mistake you can make is to try to keep everything in 'tile coordinates', which results in the blocky lighting.

So I need to update tiles to be of more triangles? Because I made every tile of two triangle...Max I can do (because I am bounded to 4 vertex) is 'blocky' lighting which follow player tile by tile.


Sounds like you've got the right idea, with your scrolling pixel by pixel. Now, just allow your lights to move pixel by pixel. Then use the distance (in pixels) from the light to each corner of a tile, assign light values based on this distance, then interpolate those light values across the tile. 3D APIs make this simple to do.

Share this post


Link to post
Share on other sites
Quote:
Original post by SimmerD
Arey you using 3d or 2d?

Do you want 2D lighting so that anything within a radius of the player the same brightness even if it is tall or deep?

Do you plan to use the same technique for lights in the game?



Yes and no :) Distanced objects are more shaded, closer more brightened, but for now I have not any graphics that are so tall to have reduce they amount of light. Tallest graphic for now are cc. max 10x tallest as player. So I don't need to shade graphic's height when rendering.
This light effect looks prety cool when combined with mass amount of light effects, specialy when light moves.

And I'm combining a 2D and 3D.

Share this post


Link to post
Share on other sites
Quote:
Original post by VertexNormal
Sounds like you've got the right idea, with your scrolling pixel by pixel. Now, just allow your lights to move pixel by pixel. Then use the distance (in pixels) from the light to each corner of a tile, assign light values based on this distance, then interpolate those light values across the tile. 3D APIs make this simple to do.


Yeah that sounds right. But then instead 2 triangles I'll need to draw 64 triangles per tile. That'll slow down a game a lot because I use 4 layers for graphic for now, then I'll implement a few more layers, and that's too much.
Anyway, I'll give it a try.
By the way, is there any possible solution to use a texture with circular shades of gray, and mask a scene somehow to have an effect where brighter area of texture will show mush beneath it and darker less?

Share this post


Link to post
Share on other sites
Hmmm then I'm definitly missing something :) Are you rendering a whole screen in one step (in other words f.e: a whole screen is in one vertwx buffer) or are you d rendering on tile by tile basis (every tile one render call)?
I have about 1000 separate render calls per frame (every call, some things are rendered).

And what do you mean design things correctly?

Share this post


Link to post
Share on other sites
In the New and Improved, Supertronic Whirly-Gig Golem engine (I just made that name up, just now [grin]) I store the map in a large vertex buffer object for the triangle verts, but I render tiles on a tile-by-tile basis in 8 passes, one pass for each terrain type layer. Each tile renders 4 triangle strips of 8 triangles apiece, covering a span of 5x5 vertices in the VBO. These vertices are spaced so that the tile, when drawn, covers the desired number of pixels on-screen. During a pre-processing pass, I calculate the triangle strip indices for each tile and store them in the tile structure. These strips index into the large full-map VBO, so drawing a tile is as simple as 4 draw indexed primitive calls. (Note that this improved version of the engine also achieves even better framerates than the initial Golem engine featured in the above screenshot; in that earlier one, I wasn't using VBOs, and some things were being done in a clunky manner.)

For lighting, in the earlier version (I'm working on shader based lighting right now) I maintained a separate color buffer with a color entry for each vertex in the map. I would combine ambient, directional, and dynamic light values for each vertex into the buffer, upload the color data for the currently visible tiles to the VBO, and draw the triangles using this color data. The light values were a composite of ambient color, directional light (for the 3D heightmapped version of the engine) and dynamic lights. Dynamic lights were calculated for each vertex. To avoid sqrt, I would usually just work with Distance^2, and store light ranges as Range^2. This gives a quadratic rather than a linear falloff to the light pool that, imho, looks better than the linear falloff.

For the first Golem engine, I also maintained a second static light map, for lights that would never move. These lights were placed and precalculated when the map was randomly generated, and values from this static lightmap were simply summed into the final vertex light calculation. This avoided the necessity of having to use dynamic lights for things such as torches, enabling me to place as many static lights as my little heart desired with no additional performance impact. If you have lots of torches and such, this is the way to go; you trade a little extra memory usage for a lot of extra performance savings.

Lighting for walls and objects was obtained directly from the final light map. Walls would obtain the 5 light values for the edge of the tile they occupy, objects would query the map for the nearest vertex and use the light value for that for the entire object. (This looked a little strange with huge objects, though. [grin])

How are you drawing your terrain? Are you using custom-created transition tiles to blend between terrain types, or are you using alpha values to do the blending? This can make a difference. In the initial Golem engine (pictured above) I was using a single 'layer' (ie, no alpha blending, the whole map view was drawn in one pass) with custom tile transitions. Thus, almost every tile was a different texture, requiring a texture switch (which ate up a lot of time) for each tile. With a layered and blended approach such as my new engine uses, I only do 8 texture switches to draw the entire terrain, rather than one per tile, which makes a huge difference even if I do have to draw 8 passes instead of 1. It's those stage switches that eat you alive; modern cards have more than enough fill rate to draw any 'standard' isometric style view at insane speeds.

Share this post


Link to post
Share on other sites
I'm doing something similar, something like your first ver of engine.
My first big headache was when I wroted function for map draw, in which map ellements are drowed and which not. I made it with an unusual approach, with two foor loops, though (simple and obivius but I didn't saw the solution at first glance).
Anyway, every tile is composed of several cell objects: background, static or animated solid object on map, static objects's shadow, animated objects (player, NPC's etc), pickabble stuff, and various type of switches (which can be acctivated in several manner).
Then in the first pass engine draw background, second pass shadows, and then everytnig other.
And my engine uses custom tile transitions for background draw.
If I understand you well, so you have 8 sets of texture (with big resolution, say 32x32 texture apiece). Then in pre-process it is calculeted which tile use which texture set, program will change VBO for every of sets, made changes to UV map, and in a 8 calls you have map rendered on screen. Something like that?
Or you are using a texturestages?
Also in my engine, the map is highly destructable and changeable and also a whole screen is animated. I can't use static lights. They must be done dynamicly.
And also they look good, mostly because light mix with each other, and whole process in fade in-out (for night-day effect) is just a matter of setting up one variable.
Light drawing is done really fast. For 512 dynamic lights I loose just few fps.
And the whole screen is full of alpha blended objects.
I know that lot of separate calls for draw will really eat the performance, but I hadn't come to any reasonable solution for that problem, because of large set of textures.

Share this post


Link to post
Share on other sites
Well VertexNormal I followed some of your opinions and made a tile of 32 triangles instead of 2. Now average textured triangle count on screen is over 20.000 (insted of 1.500) and whole damn DirectX is giving me a better performance and frame rate!
I do initialise 10x more stuff in each call, draw 20x more textured triangles and whole engine runs faster?
And where is a logic in it?

Share this post


Link to post
Share on other sites
Hehe. That's 3D APIs for you. The precise manner in which you do certain things can make a whole lot of difference. One example I encountered recently has to do with the new way I'm doing the blending of terrain in my Golem3D engine. (See my latest journal entry for a run-down of the technique). Basically, I use 8 separate arrays of alpha values, 1 array for each layer of terrain on a tiled heightmap. Due to the size of the arrays, I initially tried using arrays of unsigned char for these alpha maps, but my performance went into the toilet because of internal conversion issues. Using an array of floats instead gave me great FPS. The difference was huge; just a switch from uchar to float meant the difference between 34 FPS and 260 FPS.

3D interfaces can be finicky. If the data is in the wrong format, and a lot of internal conversion is necessary, or if there are lots of state changes, then your performance can go into the toilet even on simple scenes with few triangles. If things are set up and designed correctly, then even enormously complex scenes with hundreds of thousands of triangles can be rendered with lightning speed. I have yet to come even close to mastering all the little bits of knowledge it takes to do it all correctly. [grin]

Share this post


Link to post
Share on other sites
Hehe I had a similar problem. In the early stage of engine I tried to all vertex coordinates turn into ints (because internal coordinates were ints and directx coordinates floats, and I dont wanted to cast from ints to floats). This "great" idea came from thought that this is an 2D engine and everything is handled on pixel basis. So if I have 1024 pixels on x axis and 800 pixels on y, those coordinates are ints not floats. A changed a whole coordinate stuff to integers and got 10 fps :)

Share this post


Link to post
Share on other sites
pff I made it. I created a smooth light movement, and it is elliptical an looks great, BUT awfully slow. Just because of one square root and few multiplies. On a first time I used pow(x) command [smile] but I soon realized that that was the badest thing I puted in code - it slowed down the whole engine. Then sqrt...I found ultra fast routines on internet but that didn't helped. I put the whole square type lighting routine back [smile] and implemented some new things like height maps. It looks awesome [smile]. At least I have some use of more triangles on scene...Anyway if I use custom made rendering, pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE) don't work?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this