Adventures under a blood red sky (clouds)
by Thomas \"Man of Ice\" Lund · 09/05/2006 (4:23 am) · 6 comments
I'm one of those guys that do not jump onto the big next tech craze without a need, and thus I'm usually a few steps behind. On the other hand, it has the nice effect of everyone else beating their heads against non-proven tech + most usually die before I waste precious development time on it.
One of those things that I never got into was - believe it or not - shaders. Heck - I've seen the demos around and thought they looked cool. Even downloaded and started up Render Monkey once. But no development of any kind.
Even with Air Ace being developed using TSE, the need for shaders hasnt come up. We mostly use TSE for the large terrain.
As posted earlier, I have been working on/off on some basic cloud rendering. Last week I coded a more generic "cloud area" object, that spawns several clouds inside it and moves them across the sky over time. When they hit the end of the defined area, they are respawned in the other end again.
But the cloouds themselves do still not look like real clouds. And the thought process of how to render nice clouds the way I do them started nagging in my mind to a point where I started to dream about it (after dozens desperate attempts of figuring out the inner workings of the GFX system and blending.
Thus came the need for shaders. From what I read on the net, I could see it being handled much much easier in a shader than in engine code. At least I had a chance to read various external books/websites on shader programming, instead of guessing about texture modulation arguments and whatever :-D Never been much of a low level guy, and this is a bit to low level for me fiddling with gfx card registry settings.
I thus took my cloud code, turned off blending and added hooks for a shader into the renderObject code. One day later, this is what I had:

Impressive!!! My first shader in action - hehe. All it does is pass through the vertex shader and adds a red color in the pixel shader. But hey - it works! From now on, the task is to blend the individual cloud puff textures into a coherent "cloud" mix and getting sunlight to brighten the top side and darken the bottom side of the cloud.
My road to this step didnt go without some smaller problems - which I would like to share with anyone else trying to do this. I cant post code here in a public place, so here are some more general observations.
* When one tried to hook up shaders (not materials) directly into the engine code, one has to send over all the "magic variables" yourself for the shader to get them.
I took some example shaders from RenderMonkey to color pixels red, and then found great this article: http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7595
It made a world of a difference, as I soon discovered the problem of hooking up those magic VC_WORLD_PROJ, VC_EYE_POS variables etc. As the referenced article says, hooking up the various world/eye/projection space isnt necessarily trivial.
It took me the most of a day from the "why the hell doesnt anything render after copying the shaders over" to finding the article and to having found the correct way to initialize the variables correctly.
The best way to do this is through the shaders/shdrConst.h header variables. One can set the registry positions manually, but it soon gets very muddy.
I seriously had hoped things to be initialized by TSE itself (more on that later), leaving some registry areas for user defined data - but everything is open for doing it as you please - totally ignoring the defined names. So what is in registry position C0 in one shader isnt necessarily the same as in another. And the engine code doesnt use the shaderConst header very much, leaving even more confusion to the n00b shader coder :-)
* There is a difference between materials and custom materials
When I later experimented a bit with materials, I found that the non-custom ones are damn easy to use. Kudos to whoever made them at GG. Making custom materials brings one back to the above mentioned problems of having to hook up everything yourself again. Materials make things a bit more easy to use though, so I would suggest to anyone using materials instead of just the shaders if possible. Allowing you to easy making multiple passes and defining textures to be used.
* Start developing using existing materials and existing shaders
Might be obvious, but then again. Attack things on one front at a time. Trying to both write custom shaders, custom materials, code to hook up shaders to your object etc makes your head spin more than once. Take it one step at a time, and solve the issues you run into before moving on to the next level. I kept going back and forth between my own and existing working shaders/materials/objects to see that I did things right.
* Last hint - reuse
Once you got the code down for hooking up one material/shader, save that code and reuse it! The process is the same over and over again. Again a fairly obvious one. I had to many things going on at the same time, so at one point I had different implementations of the same mechanism - and couldnt keep my head straight on which one was working right or not.


At one point I was sick and tired of the cloud code, so I started a second feature. Air Ace has a fairly large environment, but it does have a limit. So we have to have a way of restricting a player to not go outside a defined area. I remembered some old resources for TGE that drew a forcefield, and thats what I wanted - draw some "wall" when the player got close to the mission area boundary. I decided to allow the player to fly through the wall, and then have a certain amount of time to get back again.
Time to reuse my learned knowledge about shaders/materials :-)
I used my 1337 coders art Photoshop skills to make the above images. I wanted to have one material on one side of the wall, and another material with a different texture+shader on the other.
After drawing up some vertex buffers with triangles and matching up texture coordinates, it was time to look at the shaders again.
The inner side of the box should not be visible during normal play. And when you got to close, the wall should gradually appear with a "dont try to fly through here" texture. Thus the shader takes a alpha value from the engine based on plane distance to the nearest wall.
On the other side, I need to give the player a chance to return to the mission area. The wall should thus always be in view - but with a different "come back here" texture.
After a little fiddling with things, I finally got it all working. Check out the video here
airaceonline.arcadersplanet.com/movies/Mission_boundary.wmv
The main trouble I had here was the way I had set up the vertexbuffer. I used the same buffer to hold the triangles for the "inside" and the "outside" triangles, and then fed the primitive drawing route a start position and a number of prims to draw. But it didnt work. Dunno if thats a bug, or just me doing something wrong. In the end I split the vertex buffer into 2, and draw all the prims inside - one buffer for each material.
I'm still not entirely satisfied, but it starts looking OK. I would like to fix the shaders, so only a small area of the wall is visible. E.g. having a radius around the player position that is rendered - everything else invisible. That is a task for later for me - a little beyond my shader skills for now :-)
Air Ace is starting to look really good now. We are getting more and more features completed, and are working on the looks and initial impressions like better plane models, great looking menus and such. The new menu system is for a plan of its own. Look forward to seeing what Phil has cooked up! Its ultra cool to look at, and everyone who has seen it go "wow!".
Until next time!
One of those things that I never got into was - believe it or not - shaders. Heck - I've seen the demos around and thought they looked cool. Even downloaded and started up Render Monkey once. But no development of any kind.
Even with Air Ace being developed using TSE, the need for shaders hasnt come up. We mostly use TSE for the large terrain.
As posted earlier, I have been working on/off on some basic cloud rendering. Last week I coded a more generic "cloud area" object, that spawns several clouds inside it and moves them across the sky over time. When they hit the end of the defined area, they are respawned in the other end again.
But the cloouds themselves do still not look like real clouds. And the thought process of how to render nice clouds the way I do them started nagging in my mind to a point where I started to dream about it (after dozens desperate attempts of figuring out the inner workings of the GFX system and blending.
Thus came the need for shaders. From what I read on the net, I could see it being handled much much easier in a shader than in engine code. At least I had a chance to read various external books/websites on shader programming, instead of guessing about texture modulation arguments and whatever :-D Never been much of a low level guy, and this is a bit to low level for me fiddling with gfx card registry settings.
I thus took my cloud code, turned off blending and added hooks for a shader into the renderObject code. One day later, this is what I had:

Impressive!!! My first shader in action - hehe. All it does is pass through the vertex shader and adds a red color in the pixel shader. But hey - it works! From now on, the task is to blend the individual cloud puff textures into a coherent "cloud" mix and getting sunlight to brighten the top side and darken the bottom side of the cloud.
My road to this step didnt go without some smaller problems - which I would like to share with anyone else trying to do this. I cant post code here in a public place, so here are some more general observations.
* When one tried to hook up shaders (not materials) directly into the engine code, one has to send over all the "magic variables" yourself for the shader to get them.
I took some example shaders from RenderMonkey to color pixels red, and then found great this article: http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7595
It made a world of a difference, as I soon discovered the problem of hooking up those magic VC_WORLD_PROJ, VC_EYE_POS variables etc. As the referenced article says, hooking up the various world/eye/projection space isnt necessarily trivial.
It took me the most of a day from the "why the hell doesnt anything render after copying the shaders over" to finding the article and to having found the correct way to initialize the variables correctly.
The best way to do this is through the shaders/shdrConst.h header variables. One can set the registry positions manually, but it soon gets very muddy.
I seriously had hoped things to be initialized by TSE itself (more on that later), leaving some registry areas for user defined data - but everything is open for doing it as you please - totally ignoring the defined names. So what is in registry position C0 in one shader isnt necessarily the same as in another. And the engine code doesnt use the shaderConst header very much, leaving even more confusion to the n00b shader coder :-)
* There is a difference between materials and custom materials
When I later experimented a bit with materials, I found that the non-custom ones are damn easy to use. Kudos to whoever made them at GG. Making custom materials brings one back to the above mentioned problems of having to hook up everything yourself again. Materials make things a bit more easy to use though, so I would suggest to anyone using materials instead of just the shaders if possible. Allowing you to easy making multiple passes and defining textures to be used.
* Start developing using existing materials and existing shaders
Might be obvious, but then again. Attack things on one front at a time. Trying to both write custom shaders, custom materials, code to hook up shaders to your object etc makes your head spin more than once. Take it one step at a time, and solve the issues you run into before moving on to the next level. I kept going back and forth between my own and existing working shaders/materials/objects to see that I did things right.
* Last hint - reuse
Once you got the code down for hooking up one material/shader, save that code and reuse it! The process is the same over and over again. Again a fairly obvious one. I had to many things going on at the same time, so at one point I had different implementations of the same mechanism - and couldnt keep my head straight on which one was working right or not.


At one point I was sick and tired of the cloud code, so I started a second feature. Air Ace has a fairly large environment, but it does have a limit. So we have to have a way of restricting a player to not go outside a defined area. I remembered some old resources for TGE that drew a forcefield, and thats what I wanted - draw some "wall" when the player got close to the mission area boundary. I decided to allow the player to fly through the wall, and then have a certain amount of time to get back again.
Time to reuse my learned knowledge about shaders/materials :-)
I used my 1337 coders art Photoshop skills to make the above images. I wanted to have one material on one side of the wall, and another material with a different texture+shader on the other.
After drawing up some vertex buffers with triangles and matching up texture coordinates, it was time to look at the shaders again.
The inner side of the box should not be visible during normal play. And when you got to close, the wall should gradually appear with a "dont try to fly through here" texture. Thus the shader takes a alpha value from the engine based on plane distance to the nearest wall.
On the other side, I need to give the player a chance to return to the mission area. The wall should thus always be in view - but with a different "come back here" texture.
After a little fiddling with things, I finally got it all working. Check out the video here
airaceonline.arcadersplanet.com/movies/Mission_boundary.wmv
The main trouble I had here was the way I had set up the vertexbuffer. I used the same buffer to hold the triangles for the "inside" and the "outside" triangles, and then fed the primitive drawing route a start position and a number of prims to draw. But it didnt work. Dunno if thats a bug, or just me doing something wrong. In the end I split the vertex buffer into 2, and draw all the prims inside - one buffer for each material.
I'm still not entirely satisfied, but it starts looking OK. I would like to fix the shaders, so only a small area of the wall is visible. E.g. having a radius around the player position that is rendered - everything else invisible. That is a task for later for me - a little beyond my shader skills for now :-)
Air Ace is starting to look really good now. We are getting more and more features completed, and are working on the looks and initial impressions like better plane models, great looking menus and such. The new menu system is for a plan of its own. Look forward to seeing what Phil has cooked up! Its ultra cool to look at, and everyone who has seen it go "wow!".
Until next time!
About the author
#2
09/05/2006 (6:13 am)
Very interesting thoughts there :)
#3
09/05/2006 (7:33 am)
This mission area bounds thing is exactly what I need too.... *hint* *hint*... :-) Any chance getting this up as a resource?
#4
I myself have had a shader based cloud renderer working for a while, and would like to colaberate our efforts.
However, you skipped over the part I'm interested in disscussing, which is the actual shader development and integration with TSE(although it's probably better to keep the tech talk out of .plans ;). Details such as vertex (buffer) setup, vert/pix shader functionality, and GFX rendering usage can have a huge impact when working with custom shaders.
09/05/2006 (8:02 am)
Ah, another someone doing cloud rendering in TSE. Neat to see that you finaly went to a shader based system.I myself have had a shader based cloud renderer working for a while, and would like to colaberate our efforts.
However, you skipped over the part I'm interested in disscussing, which is the actual shader development and integration with TSE(although it's probably better to keep the tech talk out of .plans ;). Details such as vertex (buffer) setup, vert/pix shader functionality, and GFX rendering usage can have a huge impact when working with custom shaders.
#5
09/05/2006 (8:26 am)
Cool post!
#6
Like pressing "I" runs a clear with relective etc..
09/05/2006 (9:03 pm)
We need a way to hot toggle shaders.. Like pressing "I" runs a clear with relective etc..

Torque Owner Ben "Djaggernaut" Chavigner
You're not bending under technology pressure but instead find the solution for exactly what you wanted. That's not something easy in a lot of case! :)
BTW, nice signs. ;)