Shaders must die
It came in as a simple thought, and now I can’t shake it off. So I say:

Ok, now that the controversial bits are done, let’s continue.
Most of this can be (and probably is) wrong, and I haven’t given it enough thought yet. But here’s my thinking about shaders of “regular scene objects”. All of below is about things that need to interact with lighting; I’m not talking about shaders for postprocessing, one-off uses, special effects, GPGPU or kitchen sinks.
Operating on vertex/pixel shader level is a wrong abstraction level
Instead, it should be separated out into “surface shader” (albedo, normal, specularity, …), “lighting model” (Lambertian, Blinn Phong, …) and “light shader” (attenuation, cookies, shadows).
- Probably 90% of the cases would only touch the surface shader (mostly mix textures/colors in various ways), and choose from some precooked lighting models.
- 9% of the cases would tweak the lighting model. Most of the things would settle for “standard” (Blinn-Phong or similar), with some stuff using skin or anisotropic or …
- The “light shader” only needs to be touched once in a blue moon by ninjas. Once the shadowing and attenuation systems are implemented, there’s almost no reason for shader authors to see all the dirty bits.
Yes, current hardware operates on vertex/geometry/pixel shaders, which is a logical thing to do for hardware. After all, these are the primitives it works on when rendering. But those primitives are not the things you work on when authoring how a surface should look or how it should react to a light.
Simple code; no redundant info; sensible defaults
In the ideal world, here’s a simple surface shader (the syntax is deliberately stupid):
Haz Texture;
Albedo = sample Texture;
Or with bump mapping added:
Haz Texture;
Haz NormalMap;
Albedo = sample Texture;
Normal = sample_normal NormalMap;
And this should be all the info you have to provide. This would choose the lighting model based on used things (in this case, Lambertian). It would somehow just work with all kinds of lights, shadows, ambient occlusion and whatnot.
Compare to how much has to be written to implement a simple surface in your current shader technology, so that it would work “with everything”.
From the above shader, proper hardware shaders can be generated for DX9, DX11, DX1337, OpenGL, next-gen and next-next-gen consoles, mobile platforms with capable hardware, etc.
It can be used in accumulative forward rendering, forward rendering with multiple lights per pass, hybrid (light pre-pass / prelight) rendering, deferred rendering etc. Heck, even for a raytracer if you have one at hand.
I want!
Now of course, it won’t be as nice as more complex materials have to be expressed. Some might not even be possible. But shader text complexity should grow with material complexity; and all information that is redundant, implied, inferred or useless should be eliminated. There’s no good reason to stick to conventions and limits of current hardware just because it operates like that.
Shaders must die!
“Most of this can wrong” ??
?
??!
proofread your articles better next time ;)
i kinda agree with you, btw: shaders aren’t in an ideal state right now. but i don’t know if changing the shader language would fix this. rather, there should be some kind of compiler which compiles what you propose to the shaders we’re used to. this compiler could later be extended to support raytracing and all that. i think this makes more sense, since it doesn’t stop you from using traditional shaders, which can be very powerful
@tulcod: whoops, fixed. Yes, I’m not proposing changing the shader language, instead I want to use some “higher level language” that has backends for various hardware shaders. This “higher level language” should not be tied into how the hardware operates though (for most uses).
I could happily live without “shaders” as we know them. Too many programmers I know enjoy the fact that they keep artists ‘away’ a bit too much.
@Jad: Renderman Shading Language has separation of surface, light, volume, imager and displacement shaders. So yeah, I’m only repeating what has been invented ages ago.
I can’t but agree with you. As you say, it’s old concepts, but not too widespread in the realtime arena.
I’d like to implement this at some point. I like to think of it as “declarative shaders”, in contrast to current “imperative shaders”. As with declarative programming, you express WHAT you want, and not HOW you want it.
As you mention, with this approach you can even test different variations, depending on where you run each piece of the puzzle and how you combine them, so as you say you can move from a forward renderer to a deferred just by instructing the tool to do so.
And you can even output the final shaders for hand tuning and optimization if you want to get the most out of them!!
Jad: I would not call it repeating, it’s something TODO :)
Number of engines actually do that already. But definitely a TODO for Unity.
[...] « Shaders must die [...]
[...] the series (see Part 1, Part [...]
…a shader language as such, no matter the granularity, is the wrong abstraction layer for users. They need a nice graphical user-interface for materials, like the one exposed in ue3, and the one that almost made it into unity a couple of years back :)
http://code.google.com/p/openshadinglanguage/
Yes, OpenShadingLanguage has some very nice ideas. It’s more targeted at offline CPU rendering right now though.
As if a node based shader authoring environment is any better than using the shader language directly.
To me an optimal solution would be ShaderLab / Torques Material System with the possibility to hook in own shader functions for specific “slots” so pretty much a bit like the logical seperation of the work instead of the hardware dictated seperation of it.
Such a system works for all kind of users and is flexible to extend yet easy enough to allow any kind of user working with it and on top of that it allows teams to create their own editors on top to work with it if they want to.
The above mentioned OSL is a nice idea but a decade too late at least out of my view. With all the high level shader languages and the shader authoring tools I don’t see a reason for it at all.
It’s awesome that at some point in time (me hopes 3.0 ;-) ) Shaders (in the old form) *will* die – at least in Unity. I totally see your point with the abstraction levels and I’m really looking forward to “working on the abstraction level needed for the problem at hand”. So far, I found shaders “somewhat esoteric” and my feeling is that the reason for that is exactly that I have to dive into an abstraction level I’d just rather not have to deal with. I also don’t write my own engine in C++ and instead use the convenience of Unity and writing down my game logic in C# for that same reason – it will be an awesome day when this will also work for materials (with the possibility of always “doing the really complex stuff” if so needed).
[...] a year ago I had a thought that “Shaders must die” (part 1, part 2, part 3). And what do you know – turns out we’re doing this in Unity 3. We call [...]