I've been increasingly frustrated with Racer over the last few years because all our materials seem to look a bit unrealistic.
There is no argument that Racer can look good, and good textures are still half the battle, but now we have HDR and nice tone mapping, true realism is still missing a bit.
I'd looked at using blurred envmaps on materials and reflecting them to give more realism, but technically this is throwing MORE energy into the material which is wrong. How would we balance that?
I'd looked at ambient specular, which is just another way of saying 'diffuse light from over there specular' multiplied out a million times for all the subtle light from every direction in the sky etc. But again, how do you make sure you preserve energy?
Ruud added energy conservation but it didn't feel like it'd work within our existing materials. You could still get wildly wrong looking materials.
Then I kept reading a lot about modern game engines (which use full HDR, energy conserving systems) using gloss maps a lot, and this seemed to answer a lot of my problems with Racer track materials. Specular gets some nice looking results, but things like asphalt and kerbs and walls, everything really, just still looks a bit unrealistic.
I've used lots of non realtime renderers over the years for all sorts of realistic stills/animation rendering, but since we just 'use' them rather than actually write the code for them to work I've never really appreciated how we get the real result from a mathematical/energy point of view, just been a keen observer of how things *should* look to be realistic.
I'm still unsure how to write these shaders properly but I know what materials should respond like and so that is the goal with these changes. Get materials that look to respond right to the environment they are in!
So I decided to add these lines to my standard_bump_f.cg shader, calling it standard_bump_glossy_f.cg:
So basically what is happening here is:
reflectiveness (the specular value) is the inverse of the diffuse texture (note that if you tint the texture with the rgb values in the shader then that won't be taken into account)
We then multiply that result by the alpha channel of the diffuse texture... this just gives us more freedom to get the 'look' we want. I guess you could think of it as an occlusion map for specular, or maybe both, or just to balance the final appearance of the specular value... after all, inverting the diffuse texture isn't perfect, you might want to tweak it some more!
Check here for the logic behind that change:
http://filmicgames.com/archives/233
My only concern here is that when checking the output of reflectiveNess it doesn't seem to appear like a negative of the diffuse (outColor.rgb=reflectiveNess until you turn the headlights of a car on for example, and the result where the headlights hit seems sensible... (guess maybe the reflectiveNess is missing out on being tone-mapped properly etc, so the value is quite low in rendering?!)
The second change is the shininess (or glossiness) is able to be authored across our material. Much nicer for things like asphalt, kerbs, anything really that isn't a pure homogenous material. In this case we use the alpha channel of the normal map to define the glossiness.
So we ask the shader to take the normal map alpha channel, normalise it from 0 > 1 (instead of 0 > 255), then multiply the shader gloss value by that map.
This means we specify the glossiest value on our material in the shader (shininess=100 for example), and then the alpha map then scales the shininess from 100 > 0, using white > black on the texture.
Energy conservation needs to be turned on, because otherwise the specular value won't intensify appropriately where the material is more glossy, and also the diffuse value won't be reduced to conserve the energy (or overall intensity) of the material.
This is done in lighting.cg file by uncommenting the #define line.
The end results of this on asphalt roads look really nice (relatively quick textures here, if you spent real time you'd get a better look again)
The current missing link in this is that ideally specular needs to respond with a fresnel effect. Currently energy isn't conserved very well using the currently system where power is equal at all viewing angles, so the road example which looks ok in the video above, starts to look too powerful when viewed from above in midday sun (like a road of little mirrors haha!), and then at dusk driving into the sunset it looks far too subtle and not powerful enough.
Filmic games covers this subject a little bit here:
http://filmicgames.com/archives/557
I think many tracks might not look good if we suddenly upgrade Racer to use energy conservation, fresnel specular etc. So maybe it'd be good to write in the required support for new shaders that can take advantage of these realistic material responses.
Ie, if I could just make energy conservation run on just my standard_bump_glossy_f.cg shader, and also turn on fresnel for the specular for just this shader, that would be really useful... that way legacy content can stay looking as it does but we can just use these new shaders where we want the upgraded features.
The only gap in my understanding at this stage is how the ambient values are impacted. I'm guessing that fresnel/IOR already impact specular/diffuse properties in response to the gloss value, and so I also assume that ambient needs altering appropriately too. Ie, maybe at shallow viewing angles we will find the ambient value becomes dominant and gives the subtle 'ambient specular' response I was looking for before?
Hopefully Ruud can help out with some of these issues, but if not I give a shout out to anyone who thinks they can get specular fresnel working with the default fresnel coefficients (or defined ones if they are provided). I had no luck doing this as I had no TEXCOORDs free or in an appropriate format for the fresnel function to work from fresnel.cg.
Maybe this shader isn't needed everywhere, but for a lot of materials that we see a LOT of the time, up close and personal (like the asphalt we drive on), using this kind of shading really livens things up and gives us a lot more realism!
Cheers for reading this far, and your comments/views on these kinds of changes would be much appreciated!
Thanks
Dave
There is no argument that Racer can look good, and good textures are still half the battle, but now we have HDR and nice tone mapping, true realism is still missing a bit.
I'd looked at using blurred envmaps on materials and reflecting them to give more realism, but technically this is throwing MORE energy into the material which is wrong. How would we balance that?
I'd looked at ambient specular, which is just another way of saying 'diffuse light from over there specular' multiplied out a million times for all the subtle light from every direction in the sky etc. But again, how do you make sure you preserve energy?
Ruud added energy conservation but it didn't feel like it'd work within our existing materials. You could still get wildly wrong looking materials.
Then I kept reading a lot about modern game engines (which use full HDR, energy conserving systems) using gloss maps a lot, and this seemed to answer a lot of my problems with Racer track materials. Specular gets some nice looking results, but things like asphalt and kerbs and walls, everything really, just still looks a bit unrealistic.
I've used lots of non realtime renderers over the years for all sorts of realistic stills/animation rendering, but since we just 'use' them rather than actually write the code for them to work I've never really appreciated how we get the real result from a mathematical/energy point of view, just been a keen observer of how things *should* look to be realistic.
I'm still unsure how to write these shaders properly but I know what materials should respond like and so that is the goal with these changes. Get materials that look to respond right to the environment they are in!
So I decided to add these lines to my standard_bump_f.cg shader, calling it standard_bump_glossy_f.cg:
Code:
// Specular map
float3 reflectiveNess=(1-baseCol.rgb)*baseCol.a;
Ks*=reflectiveNess;
shininess*=saturate(bumpColor.a);
So basically what is happening here is:
reflectiveness (the specular value) is the inverse of the diffuse texture (note that if you tint the texture with the rgb values in the shader then that won't be taken into account)
We then multiply that result by the alpha channel of the diffuse texture... this just gives us more freedom to get the 'look' we want. I guess you could think of it as an occlusion map for specular, or maybe both, or just to balance the final appearance of the specular value... after all, inverting the diffuse texture isn't perfect, you might want to tweak it some more!
Check here for the logic behind that change:
http://filmicgames.com/archives/233
My only concern here is that when checking the output of reflectiveNess it doesn't seem to appear like a negative of the diffuse (outColor.rgb=reflectiveNess until you turn the headlights of a car on for example, and the result where the headlights hit seems sensible... (guess maybe the reflectiveNess is missing out on being tone-mapped properly etc, so the value is quite low in rendering?!)
The second change is the shininess (or glossiness) is able to be authored across our material. Much nicer for things like asphalt, kerbs, anything really that isn't a pure homogenous material. In this case we use the alpha channel of the normal map to define the glossiness.
So we ask the shader to take the normal map alpha channel, normalise it from 0 > 1 (instead of 0 > 255), then multiply the shader gloss value by that map.
This means we specify the glossiest value on our material in the shader (shininess=100 for example), and then the alpha map then scales the shininess from 100 > 0, using white > black on the texture.
Energy conservation needs to be turned on, because otherwise the specular value won't intensify appropriately where the material is more glossy, and also the diffuse value won't be reduced to conserve the energy (or overall intensity) of the material.
This is done in lighting.cg file by uncommenting the #define line.
Code:
// Energy conserving diffuse/specular?
#define ENERGY_CONSERVE
The end results of this on asphalt roads look really nice (relatively quick textures here, if you spent real time you'd get a better look again)
The current missing link in this is that ideally specular needs to respond with a fresnel effect. Currently energy isn't conserved very well using the currently system where power is equal at all viewing angles, so the road example which looks ok in the video above, starts to look too powerful when viewed from above in midday sun (like a road of little mirrors haha!), and then at dusk driving into the sunset it looks far too subtle and not powerful enough.
Filmic games covers this subject a little bit here:
http://filmicgames.com/archives/557
I think many tracks might not look good if we suddenly upgrade Racer to use energy conservation, fresnel specular etc. So maybe it'd be good to write in the required support for new shaders that can take advantage of these realistic material responses.
Ie, if I could just make energy conservation run on just my standard_bump_glossy_f.cg shader, and also turn on fresnel for the specular for just this shader, that would be really useful... that way legacy content can stay looking as it does but we can just use these new shaders where we want the upgraded features.
The only gap in my understanding at this stage is how the ambient values are impacted. I'm guessing that fresnel/IOR already impact specular/diffuse properties in response to the gloss value, and so I also assume that ambient needs altering appropriately too. Ie, maybe at shallow viewing angles we will find the ambient value becomes dominant and gives the subtle 'ambient specular' response I was looking for before?
Hopefully Ruud can help out with some of these issues, but if not I give a shout out to anyone who thinks they can get specular fresnel working with the default fresnel coefficients (or defined ones if they are provided). I had no luck doing this as I had no TEXCOORDs free or in an appropriate format for the fresnel function to work from fresnel.cg.
Maybe this shader isn't needed everywhere, but for a lot of materials that we see a LOT of the time, up close and personal (like the asphalt we drive on), using this kind of shading really livens things up and gives us a lot more realism!
Cheers for reading this far, and your comments/views on these kinds of changes would be much appreciated!
Thanks
Dave