|
Ogre forum thread: http://www.ogre3d.org/phpBB2/viewtopic.php?p=158286#158286
Table of contents
Intro and notes
FAST_MONSTER_SHADER
lots of tuneable params, in 1-pass, less accurate (see PURE THEORY)
TODO:
- Alpha testing, specular level in diffuse alpha, environment lookup, ambient occlusion map, 2-texture using cheap and nice detail texturing (even for offset-maps), etc. could be still added, happy tweaking pioneers out there.
- Though less fast, multipass solution would allow for more instructions in 1 pass, if all the goodies listed above won't fit into 64 instuction limit of ps2.0 .
WARNING: PURE THEORY :)
This version has 1 defect, which is precision:
Non-linear interpolation of per-vertex lightdir and eyedir(->halfangle) in vertex shader causes distortions when light is about poly-size distance from a large poly (or closer) but this is unperceptible when cam is farther (eg. in most cases).
When cam approaches surface that close, shader switching is the optimal solution though that other shader being nice and accurate, is quite costy, and cannot be realized for 3 lights in 1 pass, because far more calculations (lightdir and eyedir) are in fragment shader, and instruction count is limited to 64 in ps2.0
Remaining options:
- not use this precise one (aka. never let cam that close to a poly)
- use a second shader like this monster, but only for 1 light, and make it multipass (a bit slower)
(I will try if 2 lights can be pushed below instruction count limit though 'cause there might be cases when 2 lights would be enought) - never use more than 1(maybe 2 if I can do it) lights that close, thus monster remains an 1-pass shader, though still quite costy (about -10..-15 FPS max.)
(Also note that distance for attenuation is calculated at per-vertex level - attenuation can't be because it is non-linear, so remains to the frag shader, but as always, I will try how it looks, and if you are fine with just linear attenuation, who knows? Might work as well, and fast ๐
(thanks for all this info on distorsion Sinbad!)
BUGS(?) AND FLAWS:
- Ogre log complains about not being able to hand the shader all uniforms and custom parameters when running the shader with reduced parameter count
- hardly effects performance or quality ๐ - but if you put comments ('//') into material parser before those unused params, all is perfect
- report any bugs, performance bottlenecks, possible optimizations. See CONTACT.
HOW I COMPUTE THINGS (just to be consistent with techicals)
For this shader, I put performance over quality.
This means:
- NdotL, pow((NdotH),exponent)) -> no reflection vector
- less accuracy when light is close to surface (see PURE THEORY on this)
- attenuation has just linear component varying(k1), and is calculated in vertex shader, and interpolated to frag shader automatically
- specular exponents are the same for the 3 lights, change it if u wish
ALSO NOTE WELL:
- I use no material light reflection coefficients, they are doing (1,1,1) to all kinds of lights (diff, amb, spec)
- diffuse texture is modulating diffuse light component only
- there in no such thing as ambient light component here, just big global ambient colour as a general environment lighting imitation
- I attenuate diffuse and specular both, and only them
- at maximum-complexity, it does perpixel offset-mapping with modulative diffuse texturing, and with ambient, diffuse, and specular components, also attenuation
Expect extensions later. - Since I have only 7 texcoords in vs2.0/ps2.0, and for attenuation, I need to pass distance to frag shader, and not calculate it there, to be fast, I need an 8th.
To have attenuation, I decided that it will use the slot of halfvector of light3.
IF YOU USE ATTENUATION, YOU WON'T GET SPECULAR OF THE 3RD LIGHT!
To add, this version suffers from the precision bug (mentioned in THEORY), so expect proper attenuation only when perpixel is proper, too.
(You might change this to let it have specular, IF it does not have diffuse, if wish, but I believe this way is more common.
Or, do you know a situation when specular of 3rd light is needed with atten?)
As you see, this shader is quite efficient (mainly being 1-pass), supports 3 lights, but techniques used are quite simple.
USAGE SUGGESTIONS
PLEASE AVOID OBSCURE/ESOTERIC USAGE PARAMETERS
(like OFFSET on, but ANY_TEXTURE off)
I guess you will try it just to make it sweat, anyway ๐
REQUIREMENTS
(VERY IMPORTANT FOR EFFICIENCY AND CORRECT RESULTS)
- Can be used with no lights just DIFFUSE_TEXTURE, but turn off OFFSET/NORMAL-mapping, ATTENUATION, DIFFUSE, and SPECULAR!
- When doing OFFSET/NORMAL-mapping, leave ANY_TEXTURE and at least LIGHT0 AND DIFFUSE or SPECULAR on !
- DIFFUSE_TEXTURE needs ANY_TEXTURE on. LIGHTx needs at least DIFFUSE or SPECULAR.
DIFFUSE and SPECULAR needs LIGHTx. - When using with fewer than 3 lights, turn off lights in this order: 2,1,0 !
- Use ATTENUATION with AT_LEAST light0 AND diffuse OR specular on !
- Due to technical constraints, using ATTENUATION means no specular from light2 !
- Try to use it with healty parameter-combos, at all time !
YOU'VE BEEN WARNED ๐
Tried working configs: full, full with just offset 0, full but just perpixel, any above with less lights (not 0, see above!), many combos with diffuse, specular, and ambient with above ones zero lights with just texturing (good for debugging, etc.)
So shall be workin' if you keep yourself to the 6 rules above.
If you want to look at the code/know what happens when you turn sg. on/off, I suggest using MSVC8. Though cannot compile, and you get syntax highlighting only for C parts, it grays out unused code for you - real-time, during you write it.
Quite handy if you ask me ๐.
LIMITATIONS, PROS, CONTRAS, FUTURE
The good
- VERY fast, thanks to being 1 pass
(in fact, when run with the same options, faster than every other shader I wrote ๐ - Compile time tuneable options, 1 fast shader for LOTS of scenarios.
Just reload the shader after changing some 0s to 1s in first few lines with a key binding or anything in Ogre.
The bad
- Limited to 3 lights, and with attenuation, you mush make other restrictions, due to its massive instruction count (read on about this)
- Not exact in when lights are close to surfaces which have very few, very large polys (though this is rare case, and you can switch it that situation to another shader)
And the ugly
- Anytime you add another feature, either new limitations arise, to keep it below instruction count, being a ps2.0 shader (64 is way_not_enough), or
- Another ugly thing: this beast needs LOTS of data to traverse between vert and frag shaders, and bingding semantics are limited, again way_tooo_much
(8 texcoords, 1 pos, 1 normal, few worthless extras like color)
So, it can run full speed, full feature wo. attenuation. Thats the deal.
With atten on, you much cut it somewhere. Either set offset and ambient to 0 (you can still have normal-mapping though), or use only 2 lights.
AND apart from that, I need another binding semantic, but I do not have any left, so light2's specular is the sacrifice.
(again, in major number of environments, the 3rd closest lights specular contrib can be omitted, given attenuation is more important, at least I think so)
In closing, about future: more features, and 2 more versions: 1 slow but featurefull multipass one, and 1 slow VERY accurate one, which you can use in front of players looking at 1 poly walls.
Code
Closing and contact
Please send comments, flames, optimizations, suggestions.
the name is guilderstein, email: forgamedev at yahoo.com
Some candy shots
Alias: The_Monster