Hi, recently i worked on a new render system, the old system created at the first stages of the engine just so i could render some geometry.
the old system wasn't generic and fast, it didn't support alpha blend surfaces very well and optimize material and stage binds, also shadows for special media wasn't supported and was hard to add (shadows for translucent surfaces for example).
those things result in lower fps and unrealistic scene, so i decided to create new system to overcome those problems.
the new system manage all scene rendering using special batches, each render object need to generate those batches and feed the system, then the system manage and optimize those batches for fast rendering and lower material and stage binds.
also the system support few render options so it will be easy and fast to render special passes such as shadows, ambient light etc.
the good thing with this system is that it doesn't need to know about the objects being rendered, it works only on those special batches and thats it, so if i need to add new support for 3ds object for example, i just need to make sure it will generate the batches and it will automatically get all the features (shadows, lighting, post process effects etc)
i also improved my lighting and shadowing system to support some new features:
1. light interaction of translucent surfaces
2. shadows for translucent surfaces, for example: glass and smoke will cast shadows depending on how translucent it is, red smoke will cast red shadows.
next time i will upload some screenshots...
Monday, October 27, 2008
Sunday, October 19, 2008
Debug in Release
hi, this time i talk about something i "bump into" while trying to run my engine in release mode (after i changed all engine class design and such) and get a crash into my face, oops not good.
at first i thought it something i mess with, i had no clue where to begin because the change was so big so i start shooting all over with no luck.
so i created exception handler lib which will catch exceptions and just before it will crash it will generate two files:
1) log file about the stack, modules, user, and the must important is the eip, which is the instruction pointer where the crash was happened.
2) mini dump file which is generated using dbghelp.dll, this is basically a snapshot of the program before it crashed, and it can be opened via vs or windbg and it will show you the exact line that cause the crash (very useful)
after having this kind of tool i started debugging and check what the hack cause the crash, i saw that there was uninitialized pointers such as d3ddevice interface, which wasn't make any sense because in the log i saw that textures and other data was loaded.
this turn on the red alert, what is wrong with my code, and why it is working in debug and not in release (and it was working!!)
i watch the engine log and see that the constructor of some managers was called twice which wasn't possible and make sens because they are singletons!! after digging a bit i notice that if you create static inline singletons (scott mayers singletongs) the compiler (which is vs2003 not 2005/2008) generating wrong code when optimization is on, and make the constructor called twice or more if you include the header in more then one object file and you call the static inline function that return the singleton instance/object.
if you move the implementation to the .cpp code the compiler generate "good" code.
because those managers are heavily used i didn't want the overhead of the function calls, so i dig a little bit more and i found a trick that works.
NOTE: this only happened on vc6 and 2003, in 2005 they fix the problem.
so if you are used to create singletons like this:
class CTest
{
public:
static CTest &GetInstance()
{
static CTest instance;
return instance;
}
}
you should now use this trick:
class CTest
{
public:
struct tDummy
{
static CTest &getInst()
{
static CTest instance;
return instance;
}
}
static CTest &GetInstance()
{
static tDummy instance;
return instance.getInst();
}
}
vc2003 deals fine with static var which contained in a non-static inline method.
so what i found is that i didn't mess anything and the code was fine and the compiler wasn't
after all it was good practice to wrote the tools and i think they will be useful in the future - i hope i wont need to use them :)
at first i thought it something i mess with, i had no clue where to begin because the change was so big so i start shooting all over with no luck.
so i created exception handler lib which will catch exceptions and just before it will crash it will generate two files:
1) log file about the stack, modules, user, and the must important is the eip, which is the instruction pointer where the crash was happened.
2) mini dump file which is generated using dbghelp.dll, this is basically a snapshot of the program before it crashed, and it can be opened via vs or windbg and it will show you the exact line that cause the crash (very useful)
after having this kind of tool i started debugging and check what the hack cause the crash, i saw that there was uninitialized pointers such as d3ddevice interface, which wasn't make any sense because in the log i saw that textures and other data was loaded.
this turn on the red alert, what is wrong with my code, and why it is working in debug and not in release (and it was working!!)
i watch the engine log and see that the constructor of some managers was called twice which wasn't possible and make sens because they are singletons!! after digging a bit i notice that if you create static inline singletons (scott mayers singletongs) the compiler (which is vs2003 not 2005/2008) generating wrong code when optimization is on, and make the constructor called twice or more if you include the header in more then one object file and you call the static inline function that return the singleton instance/object.
if you move the implementation to the .cpp code the compiler generate "good" code.
because those managers are heavily used i didn't want the overhead of the function calls, so i dig a little bit more and i found a trick that works.
NOTE: this only happened on vc6 and 2003, in 2005 they fix the problem.
so if you are used to create singletons like this:
class CTest
{
public:
static CTest &GetInstance()
{
static CTest instance;
return instance;
}
}
you should now use this trick:
class CTest
{
public:
struct tDummy
{
static CTest &getInst()
{
static CTest instance;
return instance;
}
}
static CTest &GetInstance()
{
static tDummy instance;
return instance.getInst();
}
}
vc2003 deals fine with static var which contained in a non-static inline method.
so what i found is that i didn't mess anything and the code was fine and the compiler wasn't
after all it was good practice to wrote the tools and i think they will be useful in the future - i hope i wont need to use them :)
Wednesday, October 15, 2008
Lights And Sound Shake Data
hi, on my last posts about sounds i talked about shake data which defines the intensity of the sound at a given time/point, so i thought it will be nice to add sound to lights, but then i want the intensity of the light to be changed based on what we hear.
for example: if we hear sound of blinking light we want the light intensity to blink and sync with that sound - this is where shake data comes in use.
i wrote some helper function that gives me the exact shake value and i use it as scale factor when i compute the light color.
so now i can set sounds for lights and the intensity of the light will be sync with sound shake data and gives really nice and creepy effect :)
watch the video to see it in action:
for example: if we hear sound of blinking light we want the light intensity to blink and sync with that sound - this is where shake data comes in use.
i wrote some helper function that gives me the exact shake value and i use it as scale factor when i compute the light color.
so now i can set sounds for lights and the intensity of the light will be sync with sound shake data and gives really nice and creepy effect :)
watch the video to see it in action:
Saturday, October 4, 2008
Loading Screen
hi, this time i added loading screen feature so we see when the loading process while level data is loaded and cached.
i also added the feature to load new maps on runtime via cvar, so i could check other maps while the core engine i initialize and cached so i wont need to stop and run the project every time i want to check other/new map.
this was mainly an engine redesign process so everything related to level map could be released and initialized on demand.
the loading screen i based on my gui system so its just a matter of designing the loading script and load it and update the variable and call triggers when needed.
here is some of the code in the loading gui script:
windowDef p_load_bar
{
rect 235,431,( "gui::map_loading" * 405 ),26
visible 1
windowDef load_bar
{
rect 0,0,405,26
visible 1
background "gfx/guis/mainmenu/load_bar"
matcolor 0.878,0.423,0,0.5
}
}
this window i the loading progress bar we see while we wait for the level to start, notice the 'gui::map_loading' variable in the rect definition of the window 'p_load_bar', this variable used to control the visibility of window 'load_bar'.
because i have parent/child design, the parent window also scissor his child, that means the child windows can be visible only inside their parent rect.
when i'm loading level/map data i'm setting this variable to the right value [0..1] and when i'm finished i'm triggering the event 'FinishedLoading' that changed the text near the loading to
'click to continue'
also i added script file per map, so i could define map related parameters such as the loading image. thumb image etc.
when i need to load specific map i'm checking if the map has a script file, if so i'm getting the image that i need to load and set it as 'gui::loading_bkgnd' in the loading gui, here is the loadimg window declared inside the script:
windowDef loadimg
{
rect 0,0,640,480
visible 1
background "gui::loading_bkgnd"
matcolor 1,1,1,1
}
the window is responsible to display the loading background image.
here is a screenshot of one of my test levels:
i also added the feature to load new maps on runtime via cvar, so i could check other maps while the core engine i initialize and cached so i wont need to stop and run the project every time i want to check other/new map.
this was mainly an engine redesign process so everything related to level map could be released and initialized on demand.
the loading screen i based on my gui system so its just a matter of designing the loading script and load it and update the variable and call triggers when needed.
here is some of the code in the loading gui script:
windowDef p_load_bar
{
rect 235,431,( "gui::map_loading" * 405 ),26
visible 1
windowDef load_bar
{
rect 0,0,405,26
visible 1
background "gfx/guis/mainmenu/load_bar"
matcolor 0.878,0.423,0,0.5
}
}
this window i the loading progress bar we see while we wait for the level to start, notice the 'gui::map_loading' variable in the rect definition of the window 'p_load_bar', this variable used to control the visibility of window 'load_bar'.
because i have parent/child design, the parent window also scissor his child, that means the child windows can be visible only inside their parent rect.
when i'm loading level/map data i'm setting this variable to the right value [0..1] and when i'm finished i'm triggering the event 'FinishedLoading' that changed the text near the loading to
'click to continue'
also i added script file per map, so i could define map related parameters such as the loading image. thumb image etc.
when i need to load specific map i'm checking if the map has a script file, if so i'm getting the image that i need to load and set it as 'gui::loading_bkgnd' in the loading gui, here is the loadimg window declared inside the script:
windowDef loadimg
{
rect 0,0,640,480
visible 1
background "gui::loading_bkgnd"
matcolor 1,1,1,1
}
the window is responsible to display the loading background image.
here is a screenshot of one of my test levels:
Subscribe to:
Posts (Atom)