|
*** very important
General information about lightmaps and their use in the 3DSTATE Engine.
--------------------------------------------------------------------------
Lightmaps are very important for achieving more
realistic graphics quality. Lightmaps are regular bitmaps. The reason they are called
lightmaps is because they contain information regarding shadowed and lit areas.
Although they are mainly used for creating light and shadows, they can also be used for other special effects.
Since version 4.2 polygons can have two bitmaps. Usually the second bitmap is a lightmap.
When rendering using the 3D card the two bitmaps will be blended into one.
The blending is done by multiplying one bitmap with another according to this formula:
For each pixel new_rgb=rgb1*rgb2/255;
For example rgb1=(255, 10, 10) == bright red.
rgb2=(128, 128,128) ==grey.
new_rgb= (128, 5,5) == half of rgb1 == a darker red.
Note that the new_rgb will never be brighter than rgb1 or rgb2.
Here is an example of common use of lightmaps:
Assume we have a small brick bitmap tiled on the floor in our virtual world.
This usually looks unrealistic since in the real world we will have many light
and shadow effects. Light from a lamp, from the door, from an openedd window etc ...
In the real world we should also have many shadows. If there are chairs in the room
they should create some shadow on the floor and so on.
The idea is that we take an additional bitmap that will include information
about the lit and shadowed area. This bitmap is not tiled. The combination
of the lightmap bitmap and our tiled brick bitmap will give a realistic
image of the floor.
Q: How do we create this second bitmap that has all the information about
the lit and shadowed area ?
A: It is very simple we just call STATE_polygon_create_lightmap() (there are function for object and group as well)
and the bitmap is created automatically according the light source that
are defined in the world. (To define light sources use the STATE_light_ API
Q: Whats the big deal about having a second texture, after all if we have
the lightmap bitmap and the original bitmap then we can merge them together
using any 2D painting program (Photo Shop, Corel Photo Paint etc ...)
Then we can take the result bitmap and use it for our polygon. This way
there is no need for two bitmaps for our polygon.
A: If we have a big wall or a floor then in order to get a good graphics quality
We will have to use a huge bitmap (1024x1024 as an example == 2MB in 16bit color depth). If we use a tiled bitmap and a lightmap
as a second bitmap we could do quite well with two bitmaps of 128x128 that is
2x 128x128 == 2x16K==32K (64K in 16bit color depth). This way we consume just 1/32
of bitmaps memory.
Q: Are lightmaps supported in software rendering ?
A: The second bitmap is ignored when doing software rendering. Even though
the functions for creating lightmaps are very useful in software rendering.
As mentioned in the previous question, functions like STATE_polygon_create_lightmap()
can be used in off-line to create the lightmap then by using a 2D painting program
the lightmap can be blended with the texture.
Q: There are three methods for creating light.
1) Using the functions: STATE_engine_create_shadow() and STATE_engine_create_dynamic_shadow()
2) Through the Light API (STATE_light_ ....)
3) Using lightmaps.
The qustions is: what difference is there between the three and when should each one be used.
Another question is why have three methods, that is confusing. It would be preferred to have
just one set of functions.
A: Creating nice lights and shadows is one of the important steps in creating
realistic 3D environments. In real-time applications not only we want it to look good
we also it to run in high frames per second rate.There is no one lighting method that
can give best results in all the cases. Thats why there are several methods.
Generally speaking we could give the following guidelines:
Use lightmaps when: Use lightmaps for big polygons such as floors and walls.
Lightmaps are only good for static light (light that comes from an open window
but not one that comes from a moving flashlight).
If lightmaps are used only where they have a strong impact (big polygons)
then the effect on the FPS is small (about 10%).
Use STATE_engine_create_dynamic_shadow() to create dynamic lights (and shadow)
for example to make a light spot from a moving flashlight. This function could be very fast
if it is used correctly. For example projecting the flashlight glass lid (one polygon)
on top of the six polygons of the room will be very fast (Order 1X6=6). On the other hand
projecting.
Use STATE_light API functions for both dynamic and static lights.
The light API will give good results only when a high polygon count object is lit.
The reason is that light is only calculated for the vertices (Goraud shading)
so using it to light floors or walls will only result a darker or a brighter floor
but it wont create nice light spots and shadows. We suggest that lightmaps will be used
for big polygons like walls and floors and the light API will be used to
illuminate objects with many small polygons.
In games like Unreal small lightmaps are used for the walls and floors and when the
room is lit (someone is shooting a rocket for example) then they use Goraud
shading (The light API) to increase the overall brightness.
Q: What are the light sources that are used to build a lightmap.
A: Each pixel in the light map is calculated according to the total intensity of all the light sources
at that point. The light sources are the same light sources that are used by
STATE light API (STATE_light_create()
STATE_polygon_create_lightmap()
=================================
Creates a bitmap that includes lighting information for that polygon.
The light that reaches the polygon is calculated according to the light
sources in the world (STATE_light_create() ...) and the geometry of the world
(different objects can block the light from some source lights.
Arguments:
sample_rate: Determines the size of the lightmap according to the size of the polygon in the 3D world.
For example, if we have a floor in the size of 1000x1000 virtual units and the sample rate
argument is set to 100 then every pixel in the light map will match to a square of 100x100 virtual units on the floor.
that means that that the light map bitmap that will be created will be created will be in the size of 10x10.
Though it is a very small bitmap it still contains 100 light samples. Compare it to the four samples one gets
when using Goraud shading (values are calculated only the vertices).
If a value of 0 is given for sample_rate then all the bitmaps will be in the size of max_bm_side X max_bm_side
max_bm_side: The maximum alowed height or width of the created bitmap.
For example a value of 256 will allow bitmaps like 128x256 but not 512x128.
Many 3D cards (like Voodoo 3 ) dont support bitmaps bigger than 256.
Thats why it is not recommended to give higher values.
If your application will run primarily in software mode then bigger bitmaps can be freely used.
min_lightmap_size:
In many cases tiny lightmaps are not useful (for example 1x1 or 2x2 size bitmaps)
We can decide that if the number of pixels in the lightmap is less than min_lightmap_size
then no lightmap will be created for the specific polygon.
force_ray_tracing: YES or NO. Gives much more accurate lighting that takes into account obstacles between
the lit surface and the source of light. Usually you will set it to YES.
The disadvantage is that creating the lightmap will be slower when.
Consider giving NO only when you plan to calculate lightmap dynamically.
bitmap_number: defines whether the light map will be set
as the first bitmap or the second bitmap (possible values are 1 or 2).
Returns a handle to the lightmap bitmap handle.
See also: STATE_group_create_lightmap(), STATE_object_create_lightmap()
STATE_polygon_set_second_bitmap(), STATE_bitmap_merge(), STATE_polygon_switch_between_primary_and_secondary_bitmaps()
STATE_polygon_merge_bitmaps()
STATE_engine_reduce_number_of_bitmaps()
Example:
double location[3]={0,0,0};
STATE_polygon_get_center(floor_poloygon, location);
location[2]+=100; put the light 100 units above the floor
DWORD my_light=STATE_light_create("light1", location);
STATE_light_set_distance_reach(my_light,150); This will create a nice light spot on the floor
DWORD lightmap=STATE_polygon_create_lightmap(floor_polygon, 256, 4, 8, YES, 1); The meaning of the arguments is: Create a light map that wont be bigger
than 256x256. If there are less than 4 pixels then dont create a bitmap.
Every pixel in the light map should correspond with a 8x8 square area on
the polygon. Check for objects that cast shadow over the polygon. The
light bitmap will be set as the primary bitmap.
|