Thursday, February 28, 2013

Stuck on lighting

I've continued working as usual and made fine progress, but I can't give you any updates because for the past two days I've been completely stuck on the lighting shaders.

I starting implementing multiple lights. The idea was that things like your torch, a static light, a spell would serves as secondary light sources on top of the general lighting conditions. I started implementing point lights for this.

Here is where the problems started.

First I had problems with light intensity. Eventually I managed to normalize some values in shader so that all objects react uniformly to light, even scaled ones.

But the second problem is bigger. Imagine an upright barrel. It has it round side facing you and the cap of it is on top. I encountered the problem where the cap would react far sooner and far harder to the spot light. Eventually I started playing around with export options from Blender and after hundreds of trials and errors I removed the rotation of the barrel and this helped. But nothing would help the stone stool. After updating to a newer version of Blender, the same options + lack of rotation did the trick. It also removed some nasty flare up on the sides of rolling barrels which I believe could be seen in some videos too.

I thought the issue fixed until I tested with a tipped over barrel. The issue was back, this time with the cap facing the camera reacting less the sides.

Here is a picture showing this: 

The spot light is red and placed at the camera position. The barrel above the cross-hair is facing the camera, yet the caps receive almost no light and the top receives it instead  Like some sort of weird rotation. Which does not happen if I drop the barrel in the same position, but upright:

Above is the normal situation, with the sides reacting more than the cap. Before the Blender rotation fix, my original issue looked exactly like the above picture, but with the side black and the cap red.

This issue is driving me crazy. I won't be posting updates or working on something else until I either fix this issue or figure out why it is happening and don't fix it, be it a day, a month, a year...

Tuesday, February 26, 2013

Changelog 26/Feb/2013

In late 2012 I announced a feature freeze. Then the winter hiatus came and those plans were scraped. Now I am somewhat back to that stage, not really a feature freeze, but a general cleanup and solidification for the library.

As an extra note I will be moving to pixel shader 3.0 for the parts that are needed. With pixel shader 2.0 there are increasingly more places where multipass would be needed and I really don't have the resources, especially time wise to maintain two different rendering paths.

So for these changelog posts I will be listing the changes that went in one by one. If there are still some issues left on the current bullet point, I will be listing them in bold. And as these issues get resolved, I will be updating posts, writing after the bold section with bold green/blue.

  • Finished restructuring material resources on disk for the new free-form paradigm. Textures are now located under ${GAME_DIR}/data/textures. Models are under ${GAME_DIR}/data/models. There is also a default structure, but you can now use whatever to locate resources. A good convention helps though. Materials also have an ID, a string name that is somewhat like an variable name meant for humans to easily recognize the material.
Textures are really starting to eat a lot of space. Need to study all DXT & co compression methods and start using them.

  • Started doing more with my spherical harmonics. The first thing I did was to give the world a dynamic tint. This will depend on the place in the world, time of the day, etc. For now take a look at the ambient lighting only (without normal mapping) for the engine:

And now let's see the full ambient lighting as the game uses it with the red tint:

What is missing from this picture? SSAO! hopefully I can add it during the next week.

  • Implemented FXAA. Or under its technical name, "blur-X-blur-A-A". It is very blurry. I don't know if you want to combine traditional AA with FXAA, but the engine now supports even that and the results are even more blurrier. I don't like FXAA. The cynics among us call it a glorified blur. I looked over the algorithm and it is more than that, but the results are still the same. Why use it? It is cheap. Depending on you setup and needs, it can even be considered "free". It also has very poor temporal antialiasing especially with transparent textures. You can turn on FXAA on the fly. Here are two before/after shots:

While you can turn on FXAA on the fly, traditional AA is setup once before device creation so you can't change it on the fly. Need to implement this.

  • Implemented SMAA. I think. Of course I am not reinventing the wheel and doing things like this from scratch. I take a demo with the reference implementation for the technique and integrate parts of it into my engine. This time the process was not that smooth. First I had problems compiling under debug mode, because the shader was complaining that it went over the pixel shader 3 instruction limit. The reference demo had no such issues. The second problem is that the number of render targets in engine and the flow from one to another is slowly getting out of hand. I had some troubles fitting in the SMAA render targets into the rendering pipeline. I hope it is good. The third issue was that it did not look as good as in the reference demo. I debugged and debugged but I couldn't fix it. Later, at the toilets, I had an Eureka moment. What if the content project from the demo has some extra flags in the project file. And it did. I found flags to make the shaders compile in debug mode. I also added some flags to the two images that are needed for SMAA and this improved somewhat the situation. Adding mipmaps also helped. I'm not sure if mipmaps are needed. The results are not 100% identical to the reference demo, but they are fine for now. I'll continue to investigate. Here is an image without AA:

Now with SMAA:

And finally the same in the reference implementation:

There is a small difference between the two samples. The quality of AA is pretty much identical, but the brightness is not the same. I'm curious what causes this. You can turn on SMAA on the fly, but not at the same time as FXAA.

When integrating SMAA I also had to use a few slightly overengineered content provider classes and logging classes. These must be removed and replaced with the solutions provided by the engine.

  • Started moving classes from the game to the library/generic engine. The library has 119 KiB and 3200 lines of code. This is just a small fraction of how large it will be because most of the code is still in the game project. In the spirit of migration away from XNA it does not use the Content Pipeline or XNA Component class, that's why it is so big. About 2000 lines of code handle just DDS loading.
The library also has and attached content project for a few resources like shaders, but since I am inexperienced with solutions using multiple content projects, I couldn't get the to load from here. So temporarily the resources are in the game project. A few images and about 239 KiB of shader code.

  • Gathered most settings that were all over the place in the game code into the GameSettings class that is now part of the library. Some settings are still missing, but here is the list of simple fields from the class:

Monday, February 25, 2013

97 – I am so behind

Today I tried to fix the need for a hardcoded rotation for trees. I did again small incremental changes, the first being to save/load the number of bones in the mesh. Then I wrote a small API to load/save bones to disk. Then I made it that all bones are loaded and taken into consideration when rendering and removing the hardcode gave this result:

Wow! I tried to fix it a lot but I failed. So instead I tried to do something about distant trees. They look a little bit flat. Before: 


Take a very close look at the trees. The effect is very subtle but I think it is an improvement. It is a custom shader that does a very approximate edge glow which is relatively cheap, but I still have it disabled for low quality settings. The shader has no name, I just made it up on the spot.

Maybe I should modulate it a little based on diffuse lighting for the backside of trees. Maybe they are a little bit too bright. Before:


Too bright? Sometimes I wish I still had my DH audience so that questions would get answered :P. I won't bother with it more, it looks good in my eyes.

To bad about the bones issue though...

HA! Fooled you! Giving up is the first sigh of failure! Let's fix this!

The first thing I do is open up the Blender three file and add a new box that has the same general shape as the tree trunk and I test with it. The bones seem to work fine. But the actual tree trunk still doesn't work. After further testing I determine two things: 1. there isn't an uniform up direction for exporting from Blender; it depends from file to file and 2. the rotation of the tree trunk is ignored. But only on the tree. The rest of rotations are not ignored. But at least now I have a certain level of certainty that the bones do work correctly  In order to no longer loose time on this I just apply the rotation to the vertices and this fixes the problem. The real issue might be an import/export bug somewhere.

Then I fix the frustum culling for entities without physics (like tree canopies) and get this result:

The objects in view is a lot lower right now because more things are culled.

Finally, I add 2 more trees. Unfortunately  the canopy shader needs custom parameters for each tree depending on the leaf texture quality. Here is a shot of a random forest:

I still didn't get around to implementing grass streaming, but that does not mean that it does not work. Let's take a look at the engine, with all details turned to max:

Pretty good. Must add that skybox. And grass is certainly the most "last-gen" thing I have. I need to greatly improve it somehow.

Thursday, February 21, 2013

96 – Run forest, run!

Today's post ain't no filler. I am trying to make and interesting landscape that uses a higher number of assets. So one boulder mesh won't be enough. So let's add another, first without textures:

Now let's see the two meshes together, using the same texture:

If you squint you can tell that there are two different meshes, but otherwise it looks like there is only one. To marginally improve this situation, I change the texture on the new boulder:

It is a little bit easier to tell the difference, but still not great. I need better textures (with some baked AO) and better UV mapping. Up close you can tell that the two boulders are different:

I also added huge barrels just for fun in the idea that I'll stop right here and refactor the physics mesh support. Because it is badly needed. Physics impostor meshes are polluting the resource list and the whole system does more than it is was designed to through hacks.

Here is a sample of the barrel landscape:

The barrels use their current mesh as a physics mesh. This is probably too complicated and could do with a reduction is complexity:

The interesting fact is that barrels can have multiple physics forms and representations. The above one is a full detailed static mesh, but my mobile barrels use a simple mobile cylinder. You can see the two interacting when I place a mobile barrel on a huge static one:

The plan was to stop right here and refactor the physics mesh system, but Chris from Electronic Meteor was kind enough to give me a link to the tree models he is using. I could use any mesh and I have a few available (plus the procedural trees I showed before and never touched since then), but using the same mesh allows for easier screenshot comparison. So I also added tree support.

Still, I couldn't just add trees like that. I did a partial refactor. I started with the resource locations. In the beginning I though that a very convention based system, with a rigid structure where you can easily tell where a resource is located was a good idea. This turned out not to be a great idea. It complicates the pipeline and ultimately flexibility is better.

So I transitioned over all terrain clutter resources and the new one were added using this paradigm. All other resources are yet to be converted. This was done by small incremental changes, each time processing all resources in order to not to break the pipeline and existing resources.

Then I updated the physics impostor system. They no longer pollute the resource list. If you want an object to use a physics impostor, you just set a flag for that mesh and you use it as usual. The engine takes care of all the details behind the background, automatically using the impostor when needed. By default, the physics impostor mash has the same name as the mesh on disk, but with a ".physics" added to the end, before the extension.

So with these two changes, let's add the a tree, first just an untextured trunk:

Oooo... What is this? After some digging, I determine that this is related to bones. My system is very poor at handling bones because I wrote it before I understood the concept. I still need to study bones and after this post I'll be sure to write a proper bone handling system, but for now I just hack it away by adding a rotation:

The next obstacle comes when I try to add the canopy. My system can't handle meshes made out of submeshes that have multiple meshparts. I edit the model in Blender, making each submesh have a single meshpart.

And now another obstacle appears. These tree meshes have vertex colors. I used vertex colors before, but my latest shaders don't support this and neither does the mesh importer. So I update it to ignore the colors. I also log the colors and notice something strange. The colors are all very dark, close to black. What kind of three will this turn out to be with black vertex colors? Maybe I need to use the negative color. Anyway, ignoring colors, we finally get the full mesh:

Next is to load up the textures:

Rendering the canopy requires a similar shader to the grass one, that does not render and does not update the depth buffer for transparent pixels. For grass to work properly with this technique, you need to render grass twice for maximal quality. Strangely for trees, rendering the canopy once or twice makes little difference. I can tells which one is from screenshots, but for the untrained eyes this makes no difference, so I might skip the second render pass for performance reasons. Here is the tree with transparency:

You can also see the trunk texture. Amusingly, this texture eats up 28 MiB on disk and is a total waste for this model :).

And the finals step is to disable face-culling for the canopy to get a richer looking tree. Here is a landscape:

Performance is not great. The main reason is that I decided for the canopy to not have physics. My engine is very physics based. Everything has physics. And when the engine finds the canopy without physics, it gets confused and it can not do frustum culling for the canopies. So all canopies are rendered two times even if not in view. And I am using antialiasing. And a high quality terrain renderer.

The results are very promising, but as you can see, there are tons of smaller issues to fix. I need to do this before I can continue.

Wednesday, February 20, 2013

Screens of the day 31 - Them normals be hard yo (part 2)

Today, in part two, we'll try and fix the nasty exaggerated normal mapping effect.

To not overly spam the hell out of you, I will be including just the non-normal mapped result and the normal mapped result, skipping the middle one:

This was the number one problem area and the result is better. Let's see it from behind:

Good, good. Now for some grass:

And dirt:

Now I really don't know what to say. Which to prefer? For now, I'll stick to the three terrain rendering qualities: low, medium and high, but in parallel you will be able to choose the softness of the normal mapping. This theoretically would give 6 types of rendering, but low soft and hard soft are identical. A little bit too many options for the standard user. In the future I hope to have even better shaders that blow both soft and hard options right out of the water, thus having fewer options available.

The above option is hard medium. Hard high option is almost identical to what you see in the pictures. But this method has some problems: a nasty repeating pattern can become quite obvious. Hard high tries to hide this pattern, but is slightly slower. Both hard options are faster than the soft ones.

Actually, after dozens of shader permutations I tried, I am very confused. What is normal mapping? Why doesn't it work on facing away polygons? Why does spherical harmonics work? Why was the detail so soft before? What did I do to make it harder? Why is my cat orange? These are all questions that blend together right now. I need to clear my head and take a few days break from normal mapping terrain shaders.

But don't worry, I have material gathered for 3 more posts already!

Screens of the day 30 - Them normals be hard yo (part 1)

I am currently doing frantic clean up and restructuring for the creation of the game library, that is a somewhat more general self contained engine in a box. This will take time, especially since I spent some time dicking around with terrain shaders, so have two filler posts about that. Feel free to skip this post and the next one, because the end results that are more stable will be mentioned in a normal post.

So we saw last time how spherical harmonics can be used to enhance the perception a normal mapping in surfaces that are facing away from the light. An added benefit is that the ambient lighting is dependent on the skybox, making objects more blue on a clear sky and more purple/orange with an intense sunset skybox, but since I did not manage to finish the skyboxes, you can't see this benefit. But even with this effect, the normal mapping is quite subtle.

Let's put into overdrive! Do kids still say that?

So I will be presenting a set of 3 pictures, the first being simple blending, the second normal mapping with spherical harmonics, and the third the new EXTREEEEME normal mapping.

First the high terrain textured zone:

Ahhh, the effect is far too powerful here, but the bumpiness is accentuated.

The back side is a bit better, but still too bright. but notice the difference in bumpiness when compared to the second sample.

Grassy surfaces fare a lot better. And finally, some soil textured surfaces:

So this shader has potential. I need to do something about the exaggerated problematic areas. Which I'll do in part two.