Sorry your browser is not supported!

You are using an outdated browser that does not support modern web technologies, in order to use this site please update to a new browser.

Browsers supported include Chrome, FireFox, Safari, Opera, Internet Explorer 10+ or Microsoft Edge.

Dark GDK / About lights and shadows and animated objects

Author
Message
taylor design
16
Years of Service
User Offline
Joined: 28th May 2008
Location: Germany
Posted: 11th Sep 2011 05:13
Oh yeah!

It can be really really annoying to work with lights, shadows, animated objects and shaders. Let's collect some facts before we can start.

- DarkGDK cube map does not work at all. This is why Evolved shaders and others are very tricky to translate to DarkGDK.
- Most shaders don't work with (bone-) animations
- Lighting with shaders can be tricky, because a lot of math is involved
- Stencil shadows are just ugly as it often comes to z-fighting
- Multiple lights are rarely touched
- Setting up the model, scene and shader to work all together in a decent way is hard work to do

Maybe there are some more to add, but these are the main reasons, why I do post this information here.

Let me give you a helping hand when you are struggling with these things! I want to give you a very detailed view into each topic here. Look at the attached picture, which shows the final result, you can get in DarkGDK. The object is animated by "dbSetObjectFrame", using the shader to render the complete scene.

Attachments

Login to view attachments
taylor design
16
Years of Service
User Offline
Joined: 28th May 2008
Location: Germany
Posted: 11th Sep 2011 05:34 Edited at: 11th Sep 2011 06:14
Let's start right a way!

- By the way, I'm German. Forgive me my bad English! -

Setting up DarkGDK is the same as always. Now this is what you basically do to build your own test scene now. I recommend you to create your own classes to hold the variables, this is very handy.

Use the stdafx.h to collect all your core functions you need on the lowest level.

stdafx.h



stdafx.cpp



Here is the SkinUtil. A collection of (static) functions.

SkinUtil.h



SkinUtil.cpp



I'm going to use these utility functions later to setup the scene.

main.cpp



This way, you are ready to run you own class with all DarkGDK features and expand it to your own needs, what we do in the next posts
taylor design
16
Years of Service
User Offline
Joined: 28th May 2008
Location: Germany
Posted: 11th Sep 2011 05:50
Setup the basic scene!

What we are missing now is our main class, in the sample here it is called "SkinSDK". This is just included once in the top of the main.cpp.

This class is very important, it holds all the variables we need for lights, cameras and more. What do we want to control/watch at?

- Screen
- Camera
- Grid floor
- Sky
- Model (animated)
- ShadowMap

All these things are included in your main class. I am posting the header here right now, but you will find the .cpp-file later, after we have put all things together. It won't work before setting up all classes.

SkinSDK.h


SkinScreen.h


SkinScreen.cpp


SkinCamera.h


SkinCamera.cpp


SkinGrid.h


SkinGrid.cpp


SkinSky.h


SkinSky.cpp
taylor design
16
Years of Service
User Offline
Joined: 28th May 2008
Location: Germany
Posted: 11th Sep 2011 05:58 Edited at: 11th Sep 2011 06:01
Here is the sky shader. It is very short and simple, but works like a charm for the sky. No tweaks are needed to set. Just attach the effect to your sky sphere, like it is shown in SkinSky.cpp.

Sky.fx



A sample sky sphere map to test with, is attached here.

Attachments

Login to view attachments
taylor design
16
Years of Service
User Offline
Joined: 28th May 2008
Location: Germany
Posted: 11th Sep 2011 06:10 Edited at: 11th Sep 2011 06:15
The animated 3d model

We have a textured grid floor, a nice sky background, now we want the object! This simple SkinModel class loads and plays the model object.

SkinModel.h



SkinModel.cpp



The "Vladimir" model, exported from the game "League of Legends" as DirectX format to use it inside my Skin-Tools, is attached as sample object you can use to test your code.

Attachments

Login to view attachments
taylor design
16
Years of Service
User Offline
Joined: 28th May 2008
Location: Germany
Posted: 11th Sep 2011 06:25 Edited at: 11th Sep 2011 06:26
Shadows! I want them, damn it!

To complete the C++ code for DarkGDK, we want to add the shadow map. If you follow these code, the stencil shadows should excatly match your shadow map, making it your choise, which shadow routine you want to use.

SkinShadowMap.h



SkinShadowMap.cpp



As you can see, there was nothing special at the hole story right now. I am posting the complete code here, so you can look directly inside the program and don't search for hidden secrets, there is none. The only "secret" is to let these things working together with the shaders, which is a bit more complicated. I am going to explain that in more detail, as until now you can find alot information about these basics.
taylor design
16
Years of Service
User Offline
Joined: 28th May 2008
Location: Germany
Posted: 11th Sep 2011 07:12 Edited at: 11th Sep 2011 07:38
Ok wait ... we need the shaders, NOW!

This is the interesting part, but I did not want you to miss any information you need to reach this point. Now you are ready for the next level!

I found out how you get your shadow map in DarkGDK for static objects and for those with bone-animations. Frame rates are pretty high, processing is done alot by the GPU, due to the fact we let the shaders do the hard work for us.

Shader for Bone-Animations

If you use "dbSetShadowShadingOn" and activate the shader flag, DarkGDK is using "stencilshadowbone.FX" to render the bone-animation in the shader. This shader is using the BoneMatrixPalette.



In order to use them in the shader calculation, we need the bone indices and and weights, too. Your vertex shader have to use these input parameters:



It is important to use float3 - not float4 - for the position vector! The weights and indices are stored in TEXCOORD1 and TEXCOORD2. These values are set automatically from DarkGDK! We just have to use them.

For any vertex, we get the POSITION. But not the animated vertex position. So we calculate the final vertex position the same way it is done in the "stencilshadowbone.FX". This code just transforms the IN.Position into the final animated vertex position. The (world) normal is calculated, too. The resulting position and normal are used in the same way static objects are shaded.



Btw, you can use FX Composer from NVidia together with DarkGDK! The diffuse vertex and pixel shader shown here use the default "Lambert" effect from the FX Composer.

Include lighting from FX Composer

Download FX Composer: http://developer.nvidia.com/fx-composer

Start a new project, right click into the material list and choose "Add Material From New Effect...". Activate HLSL FX and click Next. Now you see the basic lighting effects. My shader is based on the "Lambert" effect. The only problem is the "WorldInverseTranspose". But you can solve this but simply using the default "World" matrix, which is allready present for us automatically. Some articles in the web describe, why this is used, in short this is because your objects could be non-uniform scaled. As was are in game-related contents, we don't need non-uniform scales. So replace the WorldITXf from FX Composer with the following "rotate" matrix.



The complete shader explained in parts

Options for the shadow map:



SMAP_SIZE, the size of the shadow map, which must match the size inside your DarkGDK code later. Could be done as a tweakable, too, but I like to share shaders and set main options by #define.

SHADOW_INTESITY, how much light is in the shadow area.

REDUCE_ALIASING, advanced methode for smoother shadow edges.

Un-tweaks, automatically set from DarkGDK.



The tweaks, which you can adjust by code and in real-time.



The tricky thing is to calculate the "ProjMatrix", which is the Light-View-Projection-Matrix. We set up a second camera later in DarkGDK. This camera renders the shadow map. This camera position is set to the light position and has the same direction as the light. That's why it is often called a "Light-Camera". The View-Projection matrix from the Light-Camera is than passed in DarkGDK to the shader into "ProjMatrix".

The bone matrices



The texture samplers

taylor design
16
Years of Service
User Offline
Joined: 28th May 2008
Location: Germany
Posted: 11th Sep 2011 07:34 Edited at: 11th Sep 2011 07:55
The data structure



As mentioned before, TEXCOORD1 and TEXCOORD2 are used to pass the bone weights and indices per vertex into the shader.

This is the structure filled from the vertex shader.



PositionLightSpace is used for the shadow map projection. What is this for? We have a shadow map, fine. And we render the object now. So we need the shadow map AND the depth for the rendered pixel at the same time, because we want to compare them. We have the ProjMatrix, which works like a second camera during the rendering process. Calculating the final pixel and the pixel as it would be seen from the light source (we just want the depth information) at the same time is done with the ProjMatrix. The vertex position is calculated for the current camera (World) and the light camera (ProjMatrix).

The shadow map data structure



We want to have animated shadows, thats why we use TEXCOORD1 and TEXCOORD2 here again.

Static vertex shader

Shader works with "Lambert" calculation here. We just add the calculation of the PositionLightSpace. As you can see, for the final pixel position the "WorldViewProjection" matrix is used, and for the PositionLightSpace, we simply use the "LightWorldViewProjection" now.



Bone-animation vertex shader

Here we do the same, but before lighting we transform the vertex position.



Shadow mapping vertex and pixel shader

OK! This is really simple now ;D



Final pixel shader

This way we get our final result!


Shader technics to switch from DarkGDK



This is the complete shader in small parts. I attached the complete file for easier usage.

Attachments

Login to view attachments
taylor design
16
Years of Service
User Offline
Joined: 28th May 2008
Location: Germany
Posted: 11th Sep 2011 07:53 Edited at: 11th Sep 2011 07:54
Putting it all together!

SkinSDK.cpp



m_NearPlane and m_FarPlane should be adjusted to your current scene. You can imagine a plane, placed at the origin of the lightsource. Than moved by NearPlane/FarPlane in the direction of the light. Between these virtual planes, shadows will be visible. If you light is in far distance to the object, you can use a higher NearPlane to optimize the quality of the shadows.

Start the engine.



Rendering in the main loop.

- Update the LightCamera.
- Switch the object effect technique to "DepthMap"
- Render the shadow map (camera #2)
- Switch back to default object effect technique
- Render the scene (camera #1)



Update the light camera

First of all update the model animation and the current camera position. Then we pass the current light position into the shader. And finally we calcualte the light camera matrix with dbBuildLookAtLHMatrix4 and dbBuildFovLHMatrix4.



That's all

I hope this would help you implementing lighting, shadow maps and bone-animations. If you have any questions, feel free to ask!
Morcilla
21
Years of Service
User Offline
Joined: 1st Dec 2002
Location: Spain
Posted: 13th Sep 2011 19:45
Hey very useful I must say, people oftenly ask this kind of things.
So, great work here, congratulations
I add it to my favourites for the future
Oh maybe you could post the whole example into one single file, so it could be easier to try.
Nevertheless, again, great contribution, thank you!

Matty H
16
Years of Service
User Offline
Joined: 7th Oct 2008
Location: England
Posted: 13th Sep 2011 21:26
Yeah, this looks very good, I will need to put some time aside to go through it properly.

I agree with Morcilla, having everything in one download would be great, although the way it is presented in this thread is very good, great work.

taylor design
16
Years of Service
User Offline
Joined: 28th May 2008
Location: Germany
Posted: 14th Sep 2011 00:09 Edited at: 14th Sep 2011 00:10
That is sweet, thanks!

The code was not cleaned up, I will create a package to download. And I gonna add samples and information about multiple lights later.

Btw, what do you think about the bug from "dbLoadObject"? Please read this article: dbLoadObject BugReport.

It ruins now everything... OMG how sad is that :/
MRPdeveloper
14
Years of Service
User Offline
Joined: 28th Sep 2010
Location: Australia
Posted: 22nd Sep 2011 10:31
would you be able to include the jpg and the dds file for the Floor tile other then that i got it to compile seems to work very well.

Thank you so much i spent weeks on trying to tweak shadows to get them to work nicely and even then i only got it to work with players because if i tried to make the environment use the shadow it would drain the FPS too much, but now i think it will be fine

Login to post a reply

Server time is: 2024-11-19 07:28:03
Your offset time is: 2024-11-19 07:28:03