I'm currently studying opengl shaders but I can't figure out something: how to apply different shaders to the objects, for example, a teapot rendered using toon shader and another one in the same scene using a very reflective surface and other distorted from a noise function, like in this video
http://www.youtube.com/watch?v=1ogg4ZfdBqU
Another one is applying a bloom shader in a scene and a motion blur shader afterwards. How to achieve those effects when you can only have one vertex shader and one fragment shader? Is there any trick such as using more than one shader program?
Answer
The simple answer is you change them between each draw call. Set a shader, draw a teapot, set another shader, draw another teapot.
For more complex stuff where you need to apply multiple shaders to just one object such as blur, glow and so on. You basically have everything rendered to texture(s). Then you render a quad over your entire screen with that texture applied while using another shader.
For example if you want to render a glow effect, you first need to render your regular non-glowing scene, then render just the colored silhouette of the stuff that you want to glow on a texture then you switch to a blur shader and render your quad with that texture attached over your non-glowing scene.
There is another technique called Deferred shading where you render the scene without lighting and apply it later in screen space. The core goal is to reduce the expense of per pixel lighting.
Normally you render a color buffer which is put on the screen. With deferred shading you instead render a color buffer as well as a normal and depth buffer in one shader pass (you can store the normal vectors and the depth in a texture like with normal and height mapping).
This means that, for every pixel, you know the position of the nearest piece of non transparent geometry (depth or distance from eye) the color and the normal. Because of this you can apply lighting to each pixel on the screen instead of to each visible pixel of every object you render. Remember that some object will be drawn over the top of other objects if the scene isn't perfectly rendered in front to back order.
For shadows you actually render just the depth buffer from the point of view of your light then use that depth information to work out where the light strikes. That's called shadow mapping (there is also another approach called shadow volumes that works out a silhouette of the geometry and extrudes it, but your still going to be using shaders.).
With more modern OpenGL (3.0+) you use a Framebuffer Object with Renderbuffers Objects attached. Since renderbuffers can be treated like a texture. You might do things like have 1 shader render to multiple different renderbuffers (so you don't have to render your texture then your normals then the glow components) but the underlying practice is still the same.
Also it's desirable to minimize the number of shader switches as much as possible to save on overhead. So some engines will group everything with the same material together so it can all be drawn at once.
No comments:
Post a Comment