标题: 一些特殊画面效果的实现-All Hail Camera.RenderWithShader(一) [打印本页] 作者: 会飞的鱼 时间: 2011-12-9 15:35 标题: 一些特殊画面效果的实现-All Hail Camera.RenderWithShader(一) That day of internet outage is probably one of the happiest days for me using the Unity3d engine. On that fateful day Camera.RenderWithShader was born which lived on to become the backbone of almost all of our post processing effects. The best way to explain how this makes a world of difference in our projects is to just give examples of how we handled post processing effects before and after replacement shaders.
Jetpack Brontosa***s
What We Did
We haven’t posted a graphics postmortem for Jetpack Brontosa***s yet. This post will simplify the techniques we used in order to demonstrate how we accomplished the “multiple dimension” effect. Each object in Jetpack Brontosa***s has at least three renderers associated with it. One for the nightmare/death dimension, one for the dream/living dimension, and one for the mask that determines which dimension gets rendered to the screen. The renderers are divided into each dimension by using different layers. We have a different camera for each dimension. One camera is set to render all the renderers in the nightmare dimension, one camera is set for the dream dimension, and one for the mask. These cameras output their renders to separate render textures. Then we combine the two dimensions based on the color in the mask.
The implementation required each of the three renderers to have its own game object, material, and layer. As a result, the complexity of the scenes increased, producing redundant information and human errors.
What We Could Have Done
If we had the ability to use replacement shaders during Jetpack Brontosa***s production, everyone’s life would have been easier. Most of the renderers in Jetpack Brontosa***s used a vertex color shader. Because the renderers shared the same shader, using a replacement shader is an easy change.
An important thing to note here is that all of the tags have the same Key/Value pair.
The dream replacement shader:
Shader “Bronto/Dream Replace” {
SubShader {
Tags {“RenderEffect”=“Multidimensional”}
Pass {
ColorMaterial AmbientAndDiffuse
Lighting Off
SetTexture [_DreamTex] {
Combine texture * primary, primary
}
}
}
}
The death replacement shader:
Shader “Bronto/Death Replace” {
SubShader {
Tags {“RenderEffect”=“Multidimensional”}
Pass {
ColorMaterial AmbientAndDiffuse
Lighting Off
SetTexture [_DeathTex] {
Combine texture * primary, primary
}
}
}
}
The mask replacement shader:
Shader “Bronto/Mask Replace” {
SubShader {
Tags {“RenderEffect”=“Multidimensional”}
Pass {
Lighting Off
Color [_MaskColor]
}
}
}
Now we have one shader that has texture and color information for all of dimensions in a single material. No need for more than one renderer per object anymore!
The shader used by the material for the renderers (this shader is also used for rendering the object to the scene view):
Shader “Bronto/Multidimensional Object” {
_MaskColor (“Mask Color”, Color) = (1,0,0,1) // Alpha used for interpolating between the two textures in the scene view
}
SubShader {
Tags {“RenderEffect”=“Multidimensional”}
Pass {
ColorMaterial AmbientAndDiffuse
Lighting Off
SetTexture [_DreamTex] {
Combine texture
}
SetTexture [_DeathTex] {
constantColor [_MaskColor]
combine previous lerp(constant) texture
}
SetTexture [_DeathTex] {
combine previous * primary
}
}
}
}
For ingame rendering the material shader is never used. The only shaders used are the replacement shaders.
Now we have a script on the scene’s camera that renders the scene with each replacement shader and then composites them. The scene’s camera should be set to render nothing in its culling mask.
#pragma strict
@script ExecuteInEditMode
@script RequireComponent (Camera)
// The culling mask that should be used for rendering
var cullingMask : LayerMask;
// The replacement shaders
var dreamReplacementShader : Shader;
var deathReplacementShader : Shader;
var maskReplacmentShader : Shader;
// The magic composite material
var dimensionCompositeMaterial : Material;
// The render textures for each dimension
private var dreamRT : RenderTexture;
private var deathRT : RenderTexture;
private var maskRT : RenderTexture;
// The camera that renders the replacement shaders (Don’t access this directly, use GetPPCamera())