Shaders must die

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

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!

11 Responses to 'Shaders must die'

  1. tulcod

    “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

  2. Aras Pranckevičius

    @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).

  3. Dock

    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.

  4. Aras Pranckevičius

    @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.

  5. hcpizzi

    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!!

  6. ReJ

    Jad: I would not call it repeating, it’s something TODO :)

    Number of engines actually do that already. But definitely a TODO for Unity.

  7. Lost in the Triangles » Blog Archive » Shaders must die, part 2

    [...] « Shaders must die [...]

  8. Lost in the Triangles » Blog Archive » Shaders must die, part 3

    [...] the series (see Part 1, Part [...]

  9. hornet

    …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 :)

  10. Spudd86

    http://code.google.com/p/openshadinglanguage/

  11. Aras Pranckevičius

    Yes, OpenShadingLanguage has some very nice ideas. It’s more targeted at offline CPU rendering right now though.

Leave a Reply