Thursday, January 10, 2008

I've finally started working on the engine after the holidays.

I've done quite a lot of non graphic stuff. I've improved the engine code here and there and I've added picking for example.

On the graphic side, I've added support for cube maps and thus omidirectional shadows. All lights now also supports gobos, i.e. color textures that are projected from the lights. There is also support for reflections, but I'm still working on dynamic ones.

Scenes with a lot of lights also means a lot of shadow maps. For this reason, I've implemented a shadow map queue. When a shadow map needs an update it's added to the queue and every frame a number of entries in the queue are removed and processed. So only a small number of shadow maps are updated each frame. This of course means that there can be some noticable shadow lag when objects are moved around. For the type of application I have in mind for this engine, that is acceptable.

Omnidirectional shadow mapping

Point- and spotlights with gobos

Lots of lights! All cast shadows and some use gobos.

Thursday, November 29, 2007

Light volumes and more

I've not been able to work much on the engine the last week since I've been busy with school projects.

Some things have been done though. I've updated the deferred rendering system to work with light volumes instead of full-screen quads. This alone provides a huge speedup as long as the lights are reasonably small. This also made me think about light attenuation. Funny enough, this thread at gamdev popped up today. As discussed in the thread, I also wanted to find a way to set a maximum radius for a light, without affecting its atenuation too much. After some playing around with Maple, I found that max(0, 1-1/maxRadius*x)/(1+k*x^2) does the job quite good (this function is suggested in the thread) . I implemented it in my lighting shaders and the result is fine. I also took the opportunity to shave of a few instructions.

Here are some screens:



In the second shot there is 100+ lights. As you can see, the point lights does not cast shadows yet. I will also need to implement a 64 bit HDR pipeline as I get oversaturation and banding artifacts.

I've also ordered a AMD HD3870. While slightly slower than the Nvidia 8800GT, it's slightly cheaper and most importantly: it's available ;)

Tuesday, November 20, 2007

Eliminating noise

The last couple of days I have tried to reduse the noise in the SSAO output. It proved to be a hard problem. My initial attempt was to simply apply a separable gaussian blur. It produced a nice, smooth image. But as I expected it resulted in ugly halos around object edges when combined with the albedo term. Next I tried to combine the gaussian with some edge detection trickery. Looked kind of cool, but unfortunally it just reduced the halos and did not eliminate them.

Then I turned to bilateral upsampling (see Jeremy Shopf's blog). Eliminated halos, but the SSAO input was way to noisy for simple bilinear filtering. My last atempt was a combination of a box blur and a variant of bilateral filtering. The result is acceptable. I'm not satisfied, but it will do for now.

Next up is some speed optimizations and then I'm on to indirect lighting.

SSAO + "bilateral filtering"-hack

Tuesday, November 13, 2007

I've been playing around with screen-space ambient occlusion (SSAO) today, one of the AO-techniques used in Crysis. It's not trivial to get it to look good. I use the randomized normal trick described in the Crytek paper but I only sample on a hemisphere around the pixel normal to avoid self occlusion. I need to optimize the shader quite a bit, but so far this is just an evaluation of the technique and I'm quite pleased with the initial results.

Mandatory screenshots:
SSAO Only:

SSAO + direct lighting

Friday, November 09, 2007

Wheee! Shadows!

Wednesday, October 24, 2007

First screenshots of NebulaX

I have been working on my new engine for some months now and I thought it was time to start blogging again.

Here are some random facts about the new engine:

* Complete rewrite of my old engine.
* Despite its name and contrary to my previous posts: it's 100% API-independent.
* Only XNA 1.1 renderer at the moment
* Pluggable rendering pipeline, but only deferred shading pipeline atm.
* DXEffect-like effect system based on XML
* Shader language independent, only HLSL impl. atm.
* "Super-shader"-style effects for generating shader permutations
* Post-processing framework
* Pluggable scene management system
* Pluggable mesh import pipeline, only COLLADA support atm.
* Optimized math library
* Everything is witten in C# execpt the math lib witch is written in C++/CLI.
* Zero GC collections during runtime!

Sounds like marketing bull, and it is:) There's quite a few places in the code that needs to get cleaned up but this is work in progress.

Below is some screenies showing some deferred shading tests.
One point light and 5 colored spot lights.



Thursday, March 01, 2007

Update at last

I realize I'm one lazy blogger. I'm not even sure I'm allowed to call this a blog with these infrequent updates:)

Anyway, in my last post I mentioned that I might release some code for my GUI system. Sorry, won't happen anytime soon. The reason?
The usual. School eating up my time.

I'm taking a course in AI. And it has turned out to be one of the best courses I've taken so far.
The first assignment was to implement a Checkers program, and to be approved we had to enter a tournament. I teamed up with Jesper Ek (again) and Jacob Persson and we set out with a reasonable goal: to win the competition.

And that we did.

Our program, Black Doctor, won six games in a row but unfortunately lost the last one. That was enough to win the tournament, however.

Some info about the program:
* Written in C++, multi-platform
* Bitboard representation of game board.
* Alpha-Beta (iterative + recursive) and MTD(f) searching
* Transposition table
* Quiescense
* Dynamic time management
* Simple opening book and endgame database (3-pieces)
* ~1M nodes/sec on a 1.7MHz Pentium M

No screenie this time. Console UI's just aren't that sexy...

Thursday, December 14, 2006

Going sloooow.

Since I just have a few hours a week to spare for engine coding, not much is happening atm. I simply have too much in school.

That said, at least I'm doing some progress:)
I have a nice and flexible GUI system up and running. It works pretty much like the usual winforms stuff (or any other GUI:)) and I have the most common controls implemented.
It's fully skinnable and easy to customize and extend. Since I'm too lazy for drawing my own skin, I "borrowed" a texture from this guy:)

I plan to add some more stuff (including 360-controller support) and polish the code and make this public with source and all. Probably some time after Christmas.

Hopefully they don't add GUI support to XNA too soon. Would make all this pretty pointless ;)

Thursday, November 09, 2006

I have begun coding on my new engine, entitled NebulaX.
Today I threw together a simple text rendering component and started working on a complete GUI library. Most stuff is directly ported from my old engine and altered to fit the pretty cool game component and content pipeline stuff in XNA.

I've also got myself a XBox 360 gamepad for my PC. Need that to test my input code.

A few days ago I found a cool open source project: Mono.XNA, witch is going to be an implementation of XNA using Mono and Tao.

So, all you "I-use-C++-instead-of-C#-since-I-want-platform-independence" people, stop whining and start using 21th century technology:)

Monday, October 23, 2006

Long time, no see.. erhm.. update.

I haven't worked on the engine for quite some time now. I've had lots of other stuff to do.
This semester I've taken a course in mobile computer graphics. A really great course that have given me a lot of useful knowledge about graphics hardware.

In course we had to do a mobile game project using the M3G (JSR-184) Java API, and once again I teamed up with Jesper Ek. We decided to do something different and we ended up doing a OpenGL accelerated J2SE implementation of M3G. There was a competition to award the greatest game. We obviously didn't win, since we didn't make a game:) We received a Technical Achievement Award, however. The jury consisted of people from the industry, including folks from Sony Ericsson, TAT and LUGG.

You can check out the project here, and the other game entries here (some are really cool!).

What about my engine then?

It's discontinued. Yep. Discontinued.

I have decided to not develop it any further and instead start on a completely new engine using Microsoft XNA!

My old engine was 100% graphics API independent and that's of course a good thing. However, being a single developer with very little spare time, that resulted in slowing down the project considerably. By selecting only one API, I will be able to speed up the development and focus on the cool stuff.

XNA is of course the obvious choice.
It still lacks some important functionality, but I'm very confident that that will be addressed when it's finally released. Micsosoft seems very serious about XNA and I think it has a bright future.

And yeah, I've "upgraded" to the new Blogger beta, so I changed to a new blog template. Sweet.

Saturday, June 17, 2006

Today I added refraction to the water. Pretty standard stuff where the reflection and refraction textures are blended together based on the fresnel term.

I've also improved the texturing a bit. If you look at the second image in my last post, you can see that the terrain at "medium" distance from the camera is blurry. I now use yet another detail texture in this region and the result is that the terrain appears to have detail at all distances.

Tuesday, June 13, 2006





Well, It has been a while since I had time to work on the engine, but today I had some time left.
A few days ago a found a tool called L3DT. It's a very cool and capable terrain generator and it inspired me to improve the texturing of the terrain.

Near the camera I use the same splatting technique as before but the textures are tiled at a much higher density so the ground look really highly detailed even if you look straight down. This ofcourse causes ugly repetition patterns further away. To hide this I blend in a large (1024x1024) color texture on terrain far from the camera.

I've also changed from vertex lighting to a normal map. This makes the lighting independent of the LOD and reduces popping artifacts. It also makes the distant terrain look more detailed.

I use L3DT to generate all texture data I need, since it does that a lot better than my own hack;)

Friday, May 26, 2006

Well, Jesper and I have finished the final assignment in the ASR course. This time it was about shadows.

We implemented both shadow mapping and z-fail shadow volumes. All done on the GPU. The geometry needs to be preprocessed for shadow volume extraction to work entirely on the GPU.

The shot shows "soft" shadow mapping with 3x3 PCF.

Nothing special, but I have to fill my blog with something when I don't have time to work on the engine:)

Btw, my lecturers got their paper "High Dynamic Range Texure Compression For Graphics Hardware" accepted to SIGGRAPH 2006. Really sweet stuff!

Tuesday, May 16, 2006

Well, I'm back from India. It was a great vacation and it feels a bit strange to be home, but I guess it's time to get back to normal life.

The image is a shot from an ocean water simulation I did for an assignment in the ASR course. It features two superpositioned Gerstner waves calculated in a vertex shader.

In the pixel shader I use three scrolling normal maps to add fine detail to the water. There's also cubemap reflection and refraction with fresnel terms. Finally there's a simple HDR hack to add some shininess to the highlights.

When I have time to work on the engine, I'll probably update the water with a similar approach.

Saturday, April 22, 2006

As some might have noticed, I haven't updated the blog for some time now. The reason is that I'm on vacation in India with my girlfriend. I'll be staying here for three weeks so there will be no coding for a while:)

I just wanted to thank everybody who have left comments and sent me email. It's very encouraging and makes me want to keep on going!

In a few hours we're leaving for Kerala. It's supposed to be a real paradise and I think we'll have a great time!

Monday, April 10, 2006

Yesterday I did a quick test of grass rendering.
The grass waves slowly in the wind and is rendered as thousands of camera facing billboards. The nice thing is that everything is done on the GPU. The billboards are stored in one single static vertex buffer and the transformation to face the camera and the animation is done in a vertex shader.
I'm also using a neat trick to "fade" the grass out over distance without the need of alpha sorting.

It's not that good looking right now, but it's just a quick test. Putting it on real terrain with more variation of foliage and good texturing and lighting will hopefully make it look better.

Friday, April 07, 2006

I got stuck when trying to redesign my engine to better support materials that depend on multiple render passes. So I started working on a cloud system instead:)

The system if fully dynamic and the clouds move and deform. The lighting is a (rather) simple trick but looks quite nice. I got the basic idea from an article by Michael Gehling in last months GDMag. I just modified it to suit my needs. The main problem I have is that it's very hard to tweak the system to look good in all situations. Settings that look good at dawn look crap at noon and vice versa. But I think I can solve that by interpolating settings over the day-night cycle.

Another problem is that things are getting rather costly as you can see on the fps counter:) So far I've done no optimizations what so ever so I think I can squeeze quite a few more fps out of this baby.

Here's a few new screenshots:




Tuesday, April 04, 2006





I've added water to the engine. So far there's only reflections but refractions are coming up.

Now I need to render the scene multiple times per frame. The geometry that is going to show up in reflections is first rendered to a texture. This texure is then used in a second pass where the scene is rendered as normal but the reflection texture is projected onto the water plane. The same has to be done for refractions. The reflection pass is done with a lower LOD setting to increase speed, and the distortion of the water makes it very hard to notice the decreased LOD anyway.

I'm not totally happy with the way these multiple render passes are handled by the engine, so I think I have to redesign a bit. That's why I left out refractions for now.

Monday, April 03, 2006





For the second assignment in the ASR course we took a dive into the beautiful world of Global Illumination.

We had to write a Monte Carlo path tracer. The math is a bit involved but it all boils down to a very simple algorithm. Take a loot at this slide for more information.

What you gain in simplicity you loose in speed. Since we approximate the rendering equation with random sampling (Monte Carlo integration) we need to sample a lot to reduce noise. The first image was redered at a resolution of 1024 x 1024 with 625 samples per pixel. It took 72 minutes to complete. The second one uses 2304 samples per pixels and took about 6 hours to render:)

I really like the second image. Note the caustics formed by light passing through the glass objects. Quite pretty! Kudos to Jesper for setting up that scene!

Thursday, March 30, 2006

I've completed the atmospheric scattering implementation, and now the terrain is also affected by the scattering. Here's a few screenshots: