有关Unity3D的OnRenderImage()和Blit()的一些问题

转载 2015年07月07日 15:13:36
大家好!本人最近在使用Unity3D做master阶段的图形学实验平台。在实验过程中会频繁的对多个不同的RenderTexture(以下简称RT)进行一些运算,因此自然会用到Blit这个函数。在实验中,我们遇到了一些非常神奇的问题,希望能跟大家一起讨论一下。
Blit(src,dest,mat,pass)函数的作用,按照Unity官方API的说法是将src这个RT用mat这个材质中的某个pass渲染,然后复制到dest中。如果要给渲染加一些后处理效果(SSAO,HDR,bloom之类的),几乎可以肯定会用到这个函数。根据Unity自带文档中的例子,在OnRenderImage中调用Blit,然后用指定的mat渲染出来。OnRenderImage(src,dest)是Camera的一个回调(message),他会在camera执行渲染时候被调用,官方给的大部分Image Effect的实现都是用了这个回调。不过,经过最近的实验我发在OnRenderImage里面不能多次调用Blit绘制多个不同的RT。这个坑爹的问题困扰了本人很长时间...

也就是说形如:
  1. void OnRenderImage(RenderTexture src, RenderTexture dest ){

  2. Graphics.Blits(someRT, RT1, someMat, 1);
  3. Graphics.Blits(someRT, RT2, some,Mat, 2);
复制代码
这样的操作不会得到预计的效果。

考虑到可能是因为渲染管线在一次Blit之后没有把render Target改成另外一个RT,于是本人进行了多次实验,包括:

1.手动设置camera.targetTexture为要渲染的RT,未果
2.在每次Blit之前加上RenderTexture.active = 要渲染的RT,未果
3.在每次Blit之前设置Graphics.SetRenderTarget()为要渲染的RT,未果

一气之下,本人怒写了一发Blit()的Brute实现...:
  1. static public void Blit(RenderBuffer COLOR,RenderBuffer DEPTH, Material MRTMat,int pass)
  2.         {
  3.                 Graphics.SetRenderTarget(COLOR, DEPTH);
  4.                 RenderQuad (MRTMat, pass);
  5.         }
复制代码
  1. static public void RenderQuad( Material MRTMat,int pass)
  2.         {

  3.                 GL.PushMatrix();
  4.                 GL.LoadOrtho();
  5.                 MRTMat.SetPass(pass);
  6.                 GL.Begin(GL.QUADS);
  7.                 GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(0.0f, 1.0f, 0.1f);
  8.                 GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(1.0f, 1.0f, 0.1f);                
  9.                 GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(1.0f, 0.0f, 0.1f);                
  10.                 GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(0.0f, 0.0f, 0.1f);                
  11.                 GL.End();
  12.                 GL.PopMatrix();
  13. }
复制代码

并且在Update中进行了调用,完全放弃了Unity那种在OnRendermage中做处理的模式。喜大普奔地发现问题竟然解决了...

通过多次试验,我们发现,似乎在执行OnRenderImage这个回调过程中,一旦给摄像机设置了RenderTarget(也就是某个RT),在这一次回调中就不能再更改了。我们在做了一个实验,在编辑器里手动给camera设置renderTarget,然后在OnRenderImage中执行:
  1. Blit(someRT, RT1, mat);
  2. Blit(someRT, RT2, mat);
  3. Blit(someRT, RT3, mat);
  4. Blit(someRT, RT4, mat);
复制代码

这样的操作。最后只有手动设置的那张RT会被渲染,其他的都没有被渲染。不知道这是不是Unity有意为之,还是说算一个Bug。

我们对这个问题的解决方法就是直接在Update中调用自己写的Blit函数,目前一切perfect。有意思的是,我们将所有摄像机都删除,只留下自己写的Blit,statics那里显示的Draw call数竟然是0...

欢迎大家一起就这个问题分享一下自己的看法,求大神讲解下这是为神马啊!!!

 有关Unity3D的OnRenderImage()和Blit()的一些问题

Unity3D 个人免费版不支持Camera.OnRenderImage

昨天在实现一个Unity屏幕特效一直不能成功,后来发现原因是实现该功能需要Unity Pro版本。 具体如下 void Start() { if (SystemInfo.supportsIm...

【Unity Shaders】使用Unity Render Textures实现画面特效——建立画面特效脚本系统

本系列主要参考《Unity Shaders and Effects Cookbook》一书(感谢原书作者),同时会加上一点个人理解或拓展。这里是本书所有的插图。这里是本书所需的代码和资源(当然你也可以...

【猫猫的Unity Shader之旅】之初识屏幕特效

Shader除了可以处理模型的显示效果外,还有一个腻害的功能就是对要渲染的画面进行整体的处理,也就是屏幕特效。常见的比如《鬼泣4》里的动态模糊效果,景深效果,还有一些全局的颜色矫正,比如可以做出像《英...
  • dbtxdxy
  • dbtxdxy
  • 2015年04月20日 01:28
  • 1920

Graphics.BlitMultiTap解析

转载出处:http://www.cnblogs.com/tekkaman/p/4128004.html 【Graphics.BlitMultiTap解析】      上述...

Unity 脚本生命周期流程图

渲染 OnPreCull: 在相机剔除场景之前调用此函数。相机可见的对象取决于剔除。OnPreCull 函数调用发生在剔除之前。 OnBecameVisible/OnBecameInvis...
  • akof1314
  • akof1314
  • 2014年09月16日 20:57
  • 41207

【Unity】技巧集合

转发,请保持地址:http://blog.csdn.net/stalendp/article/details/17114135 这篇文章将收集unity的相关技巧,会不断地更新内容。 1)保存运行中...
  • stalendp
  • stalendp
  • 2013年12月04日 10:27
  • 30625

Unity3D使用RenderCommand渲染外轮廓

外轮廓渲染方式 原来的做法 使用CommandBuffer外轮廓渲染方式我这里所要介绍的外轮廓是使用模糊后处理实现的,不涉及到边缘查找或是顶点扩展这些,简单的说这种方式渲染外轮廓总共分三步: ...

unity实现描边效果

这里总结了几种在unity实现描边效果的方法,首先准备一个模型导入在unity中,使用默认shader,上传一张原始图,以便后面实现功能效果的对比 一、边缘光,这里参照官方的一个...

unity3d 实现残影特效

c#脚本 挂相机下 using UnityEngine; using System.Collections; using System.Collections.Generic; //[Execu...

【转】Unity3.5是一次较大的更新.它包含的新功能和改进会让你爱不释手.

Shuriken粒子系统内建寻路系统升级遮挡裁切和增加LOD系统谷歌Chrome浏览器的Native Client支持线性空间照明和HDR主要的新功能Adobe Flash:现在版本支持Adobe S...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:有关Unity3D的OnRenderImage()和Blit()的一些问题
举报原因:
原因补充:

(最多只允许输入30个字)