12 第1页 | 共2 页下一页
返回列表 发新帖
查看: 5349|回复: 11
打印 上一主题 下一主题

一些特殊画面效果的实现-All Hail Camera.RenderWithShader(一)

[复制链接]

5552

主题

2

听众

8万

积分

首席设计师

Rank: 8Rank: 8

纳金币
-1
精华
11

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2011-12-9 15:35:25 |只看该作者 |倒序浏览
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” {

   Properties {

      _DreamTex (“Dream Dimension Texture”, 2D) = “white” {}

      _DeathTex (“Death Dimension Texture”, 2D) = “white” {}

      _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())

private var ppCamera:Camera;
/**

* Handle any needed pre processing

*/

function OnPreCull() {

   // Start from nothing

   CleanRenderTextures();

   

   // Reference to ppCamera’s camera

   var cam:Camera = GetPPCamera();

   

   // Set up camera

   cam.CopyFrom(this.camera);

   cam.cullingMask = this.cullingMask;

   cam.clearFlags = CameraClearFlags.Skybox;

   cam.backgroundColor = Color(0.0,0.0,0.0,0.0);

   

   // Render Dream Dimension

   dreamRT = RenderTexture.GetTemporary(Screen.width, Screen.height, 16);

   cam.targetTexture = dreamRT;

   cam.RenderWithShader(this.dreamReplacementShader, “RenderEffect”);

   

   // Render Death Dimension

   deathRT = RenderTexture.GetTemporary(Screen.width, Screen.height, 16);

   cam.targetTexture = deathRT;

   cam.RenderWithShader(this.deathReplacementShader, “RenderEffect”);

   

   // Render Death Dimension

   maskRT = RenderTexture.GetTemporary(Screen.width, Screen.height, 16);

   cam.targetTexture = maskRT;

   cam.RenderWithShader(this.maskReplacementShader, “RenderEffect”);

}
/**

* Post Processing magic

* @param source

* @param destination

*/

function OnRenderImage(source:RenderTexture, destination:RenderTexture)

{

   // We do nothing with the source render texture, the camera didn’t do anything to it anyway!

      

   // Magically composite the render textures together into the final render

   // The shader used in the dimensionCompositeMaterial for compositing these textures is outside the scope of this post

   // Will have a post about CG full screen post processing effects sometime in the future

   RenderTexture.active = destination;

   dimensionCompositeMaterial.SetTexture(“_DreamRender”, dreamRT);

   dimensionCompositeMaterial.SetTexture(“_DeathRender”, deathRT);

   dimensionCompositeMaterial.SetTexture(“_MaskRender”, maskRT);

   GL.PushMatrix ();

      GL.LoadOrtho ();

      for (var i:int = 0; i < dimensionCompositeMaterial.passCount; i++) {

         dimensionCompositeMaterial.SetPass (i);

         DrawQuad();

      }

   GL.PopMatrix ();

   

   // Clean up

   CleanRenderTextures();

}
/**

* Cleanup if we get disabled

*/

function OnDisable()

{

   CleanResources();

}
/**

* Camera that renders the replacement shaders

* ppCamera getter

* @return

*/

private function GetPPCamera():Camera

{

   // Create the shader camera if it doesn’t exist yet

   if(!ppCamera) {

      ppCamera = new GameObject(“PPCamera”, Camera);

      ppCamera.camera.enabled = false;

      ppCamera.hideFlags = HideFlags.HideAndDontSave;

   }

   

   return ppCamera.camera;

}
/**

* Cleanup all resources used for Post Processing

*/

private function CleanResources()

{

   if(ppCamera)

   {

      DestroyImmediate(ppCamera);

   }

   CleanRenderTextures();

}
/**

* Cleanup Temporary RenderTexture resources

*/

private function CleanRenderTextures()

{

   if(deathRT != null) {

      RenderTexture.ReleaseTemporary(deathRT);

      deathRT = null;

   }

   if(dreamRT != null) {

      RenderTexture.ReleaseTemporary(dreamRT);

      dreamRT = null;

   }

   if(maskRT != null) {

      RenderTexture.ReleaseTemporary(maskRT);

      maskRT = null;

   }

}
分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

1023

主题

3

听众

359

积分

设计实习生

Rank: 2

纳金币
335582
精华
0

最佳新人

沙发
发表于 2012-3-6 23:31:10 |只看该作者
先垫一块,再说鸟
回复

使用道具 举报

462

主题

1

听众

31万

积分

首席设计师

Rank: 8Rank: 8

纳金币
2
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

板凳
发表于 2012-3-25 23:19:52 |只看该作者
好`我顶``顶顶
回复

使用道具 举报

462

主题

1

听众

31万

积分

首席设计师

Rank: 8Rank: 8

纳金币
2
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

地板
发表于 2012-4-8 23:18:18 |只看该作者
路过……
回复

使用道具 举报

tc    

5089

主题

1

听众

33万

积分

首席设计师

Rank: 8Rank: 8

纳金币
-1
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

5#
发表于 2012-4-10 23:18:25 |只看该作者
呵呵,很漂亮啊
回复

使用道具 举报

1023

主题

3

听众

359

积分

设计实习生

Rank: 2

纳金币
335582
精华
0

最佳新人

6#
发表于 2012-4-21 23:18:13 |只看该作者
凡系斑竹滴话要听;凡系朋友滴帖要顶!
回复

使用道具 举报

tc    

5089

主题

1

听众

33万

积分

首席设计师

Rank: 8Rank: 8

纳金币
-1
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

7#
发表于 2012-7-9 23:20:55 |只看该作者
加精、加亮滴铁子,尤其要多丁页丁页
回复

使用道具 举报

1023

主题

3

听众

359

积分

设计实习生

Rank: 2

纳金币
335582
精华
0

最佳新人

8#
发表于 2012-7-23 23:26:33 |只看该作者
我就看看,我不说话
回复

使用道具 举报

3795

主题

2

听众

5万

积分

版主

Rank: 7Rank: 7Rank: 7

纳金币
53202
精华
32

活跃会员 优秀版主 推广达人 突出贡献 荣誉管理 论坛元老

9#
发表于 2012-7-24 09:29:35 |只看该作者

高手速来赐教!kismet里面怎么加一个延迟DELAY??



unity特效大家PP_武功盖世呀








【严重分享】Unity3D_3.0破解版[安装包][下载]






高手请赐教!用模型做的特效动画材质丢失








antares_universe(vizio)可视化编辑
回复

使用道具 举报

462

主题

1

听众

31万

积分

首席设计师

Rank: 8Rank: 8

纳金币
2
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

10#
发表于 2012-12-3 23:27:26 |只看该作者
再看一看,再顶楼主
回复

使用道具 举报

12 第1页 | 共2 页下一页
返回列表 发新帖
您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2024-11-19 10:20 , Processed in 2.303412 second(s), 32 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部