Tuesday, April 30, 2013

HELL, IT'S ABOUT TIME!

Finally, we got to build something cool with our renderer.

To me, "cool" is not about how realistic things are, but how artistic they are. That's why I build this, for your consideration:



I spent some time doing the swirl effect on that giant sphere in the middle, which turns out to be very sweet. Like many cool effects, this one requires post processing (in this case the opaque texture). Once I got the texture and data required for the texture coordinates look-up, the rest is all in pixel shader, and this is the core part of the effect:


float2 center = float2(0.5,0.5);
float2 toUV = texcoord_screen - center;
float distanceFromCenter = length(toUV);
float2 normToUV = toUV / distanceFromCenter;
float angle = atan2(normToUV.y, normToUV.x);

angle += distanceFromCenter * distanceFromCenter * (20* sin(g_secondsElapsed/10));
float2 newUV;
sincos(angle, newUV.y, newUV.x);
newUV *= distanceFromCenter;
newUV += center;

float4 c1 = tex2D(g_textureSampler, newUV);
        float4 c2 = tex2D(g_textureSampler, texcoord_screen);
        float4  textureSample =  lerp(c1,c2, 0.3); //this is for the partial transparency

As you can see, I set the center to 0.5, 0.5 (which is the center of the screen), instead of the center of that sphere (which could be done by passing the position of the sphere and the world_to_view, view_to_projected transform matrix). I didn't bother to do it because the sphere is big enough that there is no point to do that. I was planning on making that sphere a black hole, parallel to the moon that behind it, but it doesn't look that good since the effect is too small and the black hole needs something more than just a swirl effect.


As for other objects, it's nothing we haven't done before. 

  • The rook and the ground is done by using environment map. 
  • The knight has a normal map with a soft intersection effect. 
  • As for the moon that you can't see, it's using the normal diffuse lighting with a normal map. 
  • The background is a simple plane with lighting disabled in fragment shader.
  • The UI is just ... UI, plus a vignetting effect.
Controls:
WASD - to move all the objects.
UOJKIL - to move the directional light to control the shadow.

Anyways, enough for talking, let's enjoy this image for another minute and call this an end.

Link to the code:






Graphics Programming 12

Finally! Shadows!

To be honest, after doing the depth technique for soft intersection effect, this one is not that hard. All we need to do is to add another pass for the shadow map. The process is almost the same as the depth pass, the only difference is instead of using the world to view, view to projected transform, we use world to light, light to projected transform, since the "depth" in light's view is how we determine which part of the object should be lit or not.

Again, most of the time is spent on debugging, thanks to PIX, I managed to locate most of the bugs pretty fast.

Here is one of the core part of shadowing:

float shadowModifier;
{
float3 position_projected = i_lightProjectedPosition.xyz/ i_lightProjectedPosition.w;
float2 texcoord_screen = (i_lightProjectedPosition.xy * float2(0.5, -0.5)) + 0.5;
float current_depth = i_shadowDepth;
float depth_previous = tex2D(g_shadowMapSampler, texcoord_screen).x;
depth_previous *= g_farClipPlaneDistanceForShadow;
shadowModifier = current_depth < depth_previous + 1.0f;
}

float3 diffuseLighting = lightColor * lightIntensity * strength + g_directionalLightColor.xyz * directionalLightStrength* shadowModifier;
float4 lighting = float4(diffuseLighting, 1.0) + g_ambientLightColor;

Since I have two lights in the scene, I only made shadows influence the directional light, which makes the shadow less "black" and more real.

Here is a screen shot of the scene:


To Control the directional light:
U - back, O - forward, J - left, L - right, I - up, K - down.

WASD - controls all the objects.

The shadow map in PIX:



Link of the code:
Graphics 12

Thursday, April 11, 2013

Graphics Programming 11

Well, 11 is just a small tweak of 10.

The whole post processing thing is just rendering the entire screen into a texture and then do tricks on it.
The key is to use a plane and set its coordinates the same as the screen coordinate. As for UI, its the same,  you can just change its vertex positions in the shader by using uniform values based on the values you set in the config file.

Here is the screenshot of the 11:


And here is the code:
Graphics11

Tuesday, April 9, 2013

Graphics Programming 10

Well, this one is supposed to be easy, but it takes longer than I thought.

The main goal is to create a depth pass that store the opaque bucket depth information into the depth texture which then can be used by the fragment shader or the vertex shader of the "main pass" to achieve something that you can't do by using only one pass. In our case, it's soft intersection, which takes the current depth information of the target object and compare to the depth info of the texture and change the alpha based on the difference.

Another thing, we calculate the depth value by using the z value of the view position and divide it by the distance of the far clip plane. And I did it in the vertex shader and let it being interpolated instead of doing it for each pixel in fragment shader to save some performance, seems to be working so I'm keeping that.

The code took me 2-3 hours to write, and another 3 hours to debug. It's really frustrating to find out nothing works when you first build and run your code. And even more frustrating when you spent 1 hour tracking down one of the problem only to find out there is a typo in the freaking config file that you wrote.

But this was the first time that I appreciated PIX, it did make my life much easier. Debugging in PIX is truly a much faster way to find out your fix works, and it's very satisfying to see your program moving forward bit by bit by sequentially tracking down all those bugs.

Anyway, it's glad to see things working.

Here is the screenshot:

Here is the Screenshot of the depth texture(depth is stored in red channel):

The Actual depth buffer:
Finally, the code:
Graphics10