So for Snapshot 3 I'm trying to get rid of the old, buggy and perfectly unscalable grass implementation. Using some simple polygons with grass textures was one of the first thing I ever did in XNA and unfortunately the current grass system is not a lot more advanced than just that. I need a system that can handle potentially infinitely large maps.
But today I'm not going to focus on the core of grass implementations, which is mostly just screwing around with buffers. I'm going to focus more on the Construction Set and pipeline side of things, making sure they are up to par.
So first, let's open up the spartan model manager and add the grass model:
Well, that worked. There is a new model in the system and... it won't do us any good. Let's update both the manager and the pipeline!
One of the main problems that I'm having with my engine is the reliance on the XNA content pipeline. I phased it out before XNA died, and that sure turned out to be the right choice. But even though I'm not relying on the content pipeline, somebody needs to import the model at least once. And that somebody is the content pipeline. I am using a specially compiled version of the engine, which loads all models thought the content pipeline, converts them and after you don't need the original models or the content pipeline anymore. Not this is a major engine pipeline problem. You want to add a new model to the system? You need to open up the engine project in Visual Studio, add the model to a project in a special place, compile the special version of the engine, run it once to get the conversion going, then start using the normal version of the code. For now there is no avoiding adding the model to the project, but the rest of the phases must be removed.
Let's try to fix this...
So after some coding, I delete the new model and use the manager to add it again:
After adding the model, I can now input the path. Pressing the small "R" button will try to look for the content pipeline model and do the conversion for you and then load the model. If it can't find it, it will just load the already converted model from disk. Much cleaner, and you don't have to worry about special versions of the engine or what not.
Next we use the material manager to add a new texture for the grass:
Here there are no pipeline issues. All I need to do is drop the textures into the game install folder, and the editor can load them.
There is one final problem. How does a model know which material to use. In the past this was hardcoded, but I update the module code to handle this, including loading and saving of these relations. No more hardcoding, but the model editor has no GUI for these tasks yet, so you need to do it the XML file. I edit the XML to include the relations for each model, from the barrel to the skybox, making the module completely self-contained.
Finally, I add two lines of code to the engine which are literally if the key '9' has been pressed, add the grass model:
Awesome! We now have a grass object created in the world! It is fully physics enabled though. My engine has no support for non-physics enabled objects, so I hack together support for this and I also write a shader that handles transparency:
Rendering transparent objects is not that easy, especially if you want them to look antialiased. XNA unfortunately has no support for alpha to coverage, so we need something else. There is a method to improve rendering quality based on dual pass and alpha blending, but the problem is that this method needs individual parameters for each texture. You need to experimentally fine tune these parameters for each texture and also the artist developing these textures should take care to create textures which play along nicely with this method. In order to make debugging this easier, I create keyboard shortcuts that allow you to modify parameters on the fly to see the result, together with a debug mode that highlights the edges of the grass that will be smoothed out so you can figure out the optimal parameters in real time, one texture at a time:
In the above screenshot, the white areas of the grass will be the ones affected by the improved grass rendering algorithm, while the rest won't be.
Next we update the shader to include some subtle and simple grass animation. I can't show animations with pictures, but I can show you the funny effect of applying these shaders to normal geometry:
Finally, we write a very simple and ugly algorithm to populate the world with grass. Here are 3 shots, one during nighttime,showing a landscape with grass:
This looks very ugly. A considerably smarter placement algorithm will be needed that populates grass without such obvious repeating patterns.
The next step is going to be to create s system that merges all the grass bushes into large vertex buffers because in the above screenshots I am rending 47000 grass bushes individually without any frustum culling or optimization and the framerate is non interactive. After I need to write a streaming system that pulls in only as much grass as needed and update the world generator to write grass to the saved map.
- Module system updated to handle more properties for models.
- Model manager slightly improved.
- Improved model import pipeline.
- Experimental: the options dialog can change MSAA without triggering a device reset.
- The options dialog is in live sync with all other methods of changing device settings.
- Changing some setting in the option dialog no longer centers the mouse and the game window is not longer shifted a couple of pixels in position.
- The engine reports framerates when in system hub mode properly.
- B006: Changing terrain quality in the options dialog when no terrain is loaded no longer crashes the engine. Fixed.
- B007: Playing around with window frame and fullscreen can easily crash the engine.