Vertex & fragment shaders - tutorial
| Home | Go for the GT5 look using vertex and fragment shaders! |
|
|
|
Introduction
GPU Shaders (normally called vertex and fragment shaders) are supported in Racer through Cg. Cg was created by nVidia to overcome a lot of the troubles when creating shaders for a multitude of graphics hardware. Racer has always targeted for high-end hardware, and Cg probably is one of the areas where that becomes obvious.
This document is not about teaching you Cg; there's enough of that online. I'd recommend getting the book 'The Cg Tutorial' from nVidia, which can be read online for free at http://http.developer.nvidia.com/CgTutorial/cg_tutorial_chapter01.html (see also below)
More information on generic Racer shaders (the name 'shader' here is a bit confusing) can be found here; Cg shaders are only a part of the larger concept of Racer shaders.
External books/pages to read
There's a lot of information on Cg on the internet. nVidia has made available for free the texts of their excellent GPU Gems series. Try the following (they are all for free):
Entry points
Every Cg shader file must have an entry point for its vertex or fragment program. In Racer, this should be 'main' for both the vertex program and the fragment program. Essentially, this means that each shader must be in its own file (you can't add the vertex & fragment shader in the same file).
CG Parameters available in vertex/fragment shaders
Cg shader parameters are searched for in Racer. There are a number of ways to determine semantic meaning but I've chosen a (somewhat less elegant, but simple) way of needing exact variable names. So if the variable below states 'modelViewProj' for example, you really need to use 'uniform float4x4 modelViewProj' as the declaration in your shader; something like 'uniform float4x4 modelVwPrj' will NOT work).
Most variables are only available since Racer v0.7.2.
| Variable name (in shader) | Type | Value |
| atmosMie | float | Atmospheric Mie scattering (responsible for a haze effect). A good default value is 0.001. Bigger values lead to a sort of smog'like effect. |
| atmosRayleigh | float | Atmospheric Rayleigh scattering (responsible for the blue sky effect). A good default value is 0.002. |
| binormal | float3 | Binormal (unused currently) |
| clouds | float | Amount of clouds (0..1, 0=clear sky, 1=overcast) (v0.7.4+) |
| dt | float | Delta time in seconds. Used in motion blur shaders to calculate (screen space) pixel velocity for example. (v0.7.4+) |
| edgeBlendP | float | Edge blending curvature (licensed users only) |
| edgeBlendGamma | float | Edge blending gamma (licensed users only) |
| exposure | float | Exposure for the sky. A good value will be around 2..20. |
| eyePosW | float3 | Eye position in world coordinates (camera world 'from' position) |
| fogColor | float3 | Uniform fog color |
| fogDensity | float | Exponential fog density |
| heat | float | Heat of wheel (degrees Celcius) |
| Ka | float3 | Material ambient color. Final result will normally be lightAmbient*Ka. |
| Kd | float3 | Material diffuse. Use as finalColor=textureColor*Kd. |
| Ke | float3 | Material emission. Use as finalColor=textureColor*Kd+Ke |
| Kr | float | Material reflectivity. Set in a (Racer)shader's 'reflect' property. I.e. shader_carbody.reflect=0.5. |
| Ks | float3 | Material specular property. See lighting.cg for lighting examples (normally, use LightingSun() from lighting.cg to do specular calculations, then add the specular (color, so float3) result to your fragment color. |
| lightDirection | float3 | Sun direction (from object to sun, so exactly like specified in the track's special.ini) |
| lightColor | float3 | Sun color (for example: 0.8 0.4 0.1) |
| modelMatrix | float4x4 | Current transformation matrix of geometry being drawn (identity for track objects, dynamic for moving objects such as cars, wheels). This converts original model coordinates (as created by the 3D modeler) to its world location. |
| modelMatrixInv | float4x4 | Transposed transformation matrix of drawn geometry |
| modelViewProj | float4x4 | ModelView and Projection matrix combined |
| modelView | float4x4 | ModelView matrix |
| modelViewIT | float4x4 | Inverted/transposed ModelView matrix |
| night | float | Night amount (0..1). Goes up to 1 at night time. (v074+) |
| prevModelViewProj | float4x4 | Previous frame's modelViewProj. Used in motion blur shaders to determine screen space pixel velocity. (v074+) |
| shininess | float | Material shininess (for specular calculations) |
| tangent | float3 | Model texture tangents (for bump-mapping) |
| time | float | Simulation time in seconds |
Geometrical parameters
| Variable | Type | Value |
| center | float3 | Center point (in world coordinates) of object being drawn. In the projective shaders this is the light origin (special case) but all other shaders this is the center of the object. For non-split tracks, this allows you to perform animation for example on separate objects like trees. For things like grass animation you're probably better off using the texture coordinate to determine whether to move a vertex or not (example: pos.xz+=tc0.s*0.1). |
| size | float3 | Size of object being drawn. Use this in combination with the center to determine the min/max extents. For example; the height of a vertex relative to the object becomes: float hgt=IN.Position.y-center.y+size.y*0.5; |
Shader library
Racer (v.0.7.2+) comes with a number of global shaders, located in data/renderer/shaders_hdr and shaders_ldr (HDR since v0.7.4). The creation of Cg shaders is not trivial and more something that programmers tend to do. Graphics artists do need some technical knowledge to be able to use Cg effectively, but can rely on most often-used Cg shaders being present.
More on HDR can be found here. The main importance is that HDR shaders are stored in a separate directory; data/renderer/shaders_hdr. They are mostly similar to the LDR shaders. LDR though, is deprecated and will not be maintained. HDR looks so much better and is needed to get to the GT5/PGR look.
The shaders are normally prefixed with standard for default effects (such as normal lighting, bumpmapping, detailmapping) and are prefixed with dyn_standard if they are for movable objects; mostly this means car objects. The dyn (for dynamic) Cg shaders use a variable 'modelMatrix' to apply transformations to vertices & normals. The non-dynamic shaders are faster (since they skip on some matrix multiplications); that's there only reason for existing versus the dynamic versions.
The global shader library consists of the following files (all postfixed with .cg):
Shaders for static objects (non-moving track objects)
| File (.cg) | Description |
| atmosphere | Contains atmospherical functions such as CalculateAtmosphere(), CalculateAtmosphereExtinction(). Included in other shaders, such as standard*.cg. |
| lighting | Contains lighting functions such as LightingSun(). These are default lighting models. Included in other shaders. |
| standard_v/f | A standard OpenGL-like shader that takes into account atmosphere. For moving models such as car bodies, use dyn_standard_v/f instead; it will appear to work at first, but your lighting will be directly badly since the normals aren't transformed in standard_v, whereas in dyn_standard_v, they are (!). |
| sky_v/f | A shader specifically for sky domes. This shader skips on normals and vertex position a bit, so it is not suitable for generic geometry. |
| standard_vc_v/f | The 'standard' shader, only this one adds support for vertex colors (such as used in CarlswoodNT, the default Racer track, a lot). |
| standard_bump_v/f | Bumpmap shader for track (static) objects. The 2nd texture is the bumpmap (this one normally looks blueish, indicating normal=(0,0,1), which is stored as 8 bits as (0,0,0.5) to allow for negative normals as well). |
| standard_blur_f | The inverse of a detail shader. This shader takes 2 textures; first, the diffuse (regular) texturemap. In the 2nd texture unit, a blur texture is expected that will lighten and darken the diffuse map. The neutral value is (0.5,0.5,0.5) (or RGB=(128,128,128)) which will keep the brightness. Any value below 0.5 will darken the diffuse map, any value above 0.5 will lighten it. The default texture scaling for the blurring texture is 0.1, so it is stretched 10 times. An example screenshot of the effect for a 2-layer Racer shader that uses standard_v.cg and standard_blur_f.cg:
The following blur image was taken:
|
| standard_burn_f | Fragment shader only (use in conjunction with standard_v.cg). This does mostly the same thing as standard_f.cg, but burns specularity through the red channel of the texture. This is used in Carlswood for example to map the road; the specularity is burned through the red channel of the road texture, so the specularity isn't a smooth white blot but rather pixely instead. Just using standard_f.cg:
Using standard_burn_f.cg: |
| standard_heat_f | Heat shader for brake discs that heat up. Use standard_v.cg for the vertex shader, and this one for the fragment shader. v0.7.4+ |
| standard_detail_f | Detail texture added. Use standard_v for the vertex shader. The 2nd texture contains the detail texture and texture coordinates are scaled by 8 based on the regular (diffuse) map. So layer0 contains the diffuse (regular) map, layer1 the detail map. (v074+) |
| standard_detail_burn_f | Detail texturemap (as standard_detail_f) with burning through the red channel. Useful for roads. (v074+) |
| standard_reflect_v/f | Reflection shader. As standard_v/f, only adds a reflection cubemap in the 2nd texture unit. Uses this set for static (untransformed) object such as track objects. Car objects will need dyn_standard_reflect_v/f to apply model transformation. (v074+) |
| standard_skinned_v/f | Skinning shaders for animated objects. More info on animation here. |
| standard_wave_v/f | Wave shader for things such as waving flags. Check out the waving flag tutorial for more info.
|
| animate_test_v | An example vertex shader that animates, based on a geometrical center. Useful only if the center of the object tells something about the object. |
Shaders for dynamic objects
These shaders are used for dynamic objects such as cars. For all these you need at least Racer v0.8.0.
| File (.cg) | Description |
| dyn_standard_v | Like standard_v.cg, only this one works for dynamic objects, the car mostly. It uses 'modelMatrix' to transform the normal for example. v0.7.4+ |
| dyn_standard_bump_v/f | Bumpmap shader set. The 2nd texture contains the bumpmap. |
| dyn_standard_bump_reflect_v/f | The mix between dyn_standard_bump_v/f and dyn_standard_reflect_v/f. It uses 3 textures; diffuse map (regular texture), normal (bump) map in the 2nd texture unit and the environment map in the 3rd texture unit. |
| dyn_standard_bump_speca_v/f | Like dyn_standard_bump_v/f, only this one takes its specularity color from the diffuse (1st) texture's alpha channel. Useful for tires that have both smooth and rough parts, such as F1 tires. |
| dyn_standard_reflect_v/f | Adds a reflection map (in the 2nd texture). Use a Racer shader's 'reflect' property to determine the amount of reflectivity (passed as 'Kr' in Cg shaders). |
| dyn_standard_reflect_window_v/f | Like dyn_standard_reflect, only this one adds alpha where reflection is present. To explain this better, check the screenshot below. On the left, the 'window' variant is used. There is a reflection present, so alpha is generated to show the reflection better. For wheels, it is obvious that this is a bad idea. For windows it is better though, since there you want the reflection to get more intense where present. Think of it that for the wheel below, alpha was used to remove part of the model, whereas with windows, you want to draw the entire 3D model, only at a low transparency. For the windows, you don't use alpha to fake missing parts of the 3D model, therefore you want the reflection to come back where present. Note that the picture below used alphafunc, which you don't really want (blending was buggy at the time).
|
Special shaders using in other parts of the render engine
These shaders are not normally used for your cars & tracks, but are explained here for completeness.
| File (.cg) | Description |
| projected_texture_v/f | Used for the projective lights of cars. Note the fragment shader takes the 1st texture of the Racer shader and uses its alpha to cut lighting. This is needed for partially transparent objects such as trees. |
Shader library for debugging
These shaders are normally only used when you need to check things.
| File (.cg) | Description |
| check_shader_f | This shader outputs purple with alpha=0 (color 1,0,1,0) for all pixels. For older tracks that you want to convert to use Cg, you can use this fragment shader to quickly colorize all Cg shaded materials. All the objects that don't have shaders yet will still be textured (drawn using regular Racer shaders) so this Cg shader can help to find the object that still need to have Cg (and/or Racer) shaders. For example, set vertex_shader.file to standard_v.cg and fragment_shader.file to check_shader_f.cg in your track.shd's Racer shader. A full example extract from a track.shd file: vf_standard
{
vertex_shader
{
file=standard_v.cg
}
fragment_shader
{
file=check_shader_f.cg
}
}
shader_guardrail~vf_standard |
Fun with shaders
Check out these articles on specific things done with Cg shaders:
(last updated November 12, 2009 )