candycat1992 / Unity_Shaders_Book

:book: 书籍《Unity Shader入门精要》源代码
5.52k stars 1.62k forks source link

请教12章motionBlur的问题。 #61

Open yty opened 8 years ago

yty commented 8 years ago

作者您好, ———— 感觉目前的运动模糊方案有缺陷。 请这样测试,为了更便于观察,我们把Blur Amount的范围增加到0.95,并设置为0.95.

然后关闭Translating脚本,然后你快速的在inspector里改变camera的Y旋转, 你会发现box有残影无法消除掉。如后面附带的图片。

而如果是不移动镜头,去移动box自身的快速运动,则会更明显。。。 这是为什么呢?

shaderq

yty commented 8 years ago

补充,我看官方的motionBlur最大值限定的是0.92,但设置成0.92也是残留的,如图。

shaderq2

另外我在gl里测试,只要等上1秒左右,是可以完全清除残留的。 shaderq3

不清楚gl的这种交替使用rendertexture的方式和目前书中的这种累加Rendertexture方式是否不等同。。

gl下大致伪码如下:

currRT = 1 - currRT; if (currRT == 0) rt0.begin(); else rt1.begin();

shader.begin(); if (currRT == 0) shader.setUniformTexture("tex0", rt1); else shader.setUniformTexture("tex0", rt0); drawPlane(); shader.end();

DrawScene();

if (currRT == 0) rt0.end(); else rt1.end();

shader代码是这样

uniform sampler2D tex0; void main(void) { vec4 hv = texture2D(tex0, t0).rgba; gl_FragColor = hv*0.9; }

candycat1992 commented 8 years ago

我今天看了下这个问题,的确很奇怪,从公式来看的确不应该有永久性的残影出现,暂时发现残影和背景色也有关系,例如对于书里的测试场景来说,背景如果是纯黑或者纯白就不会有残影。你可以在gl里面测试下换一个背景色,不要用纯黑,例如用灰色(127,127,127)去测试下,看是不是也出现残影了。我这里会继续查一些资料和实验,看能不能找到原因

RobertPeng commented 7 years ago

请问这个是什么原因找到了么?

ljcduo commented 6 years ago

我按楼主的方法测试一遍,测试不出来这种现象呀,难道是Unity版本修复了吗。我用的版本是2017.2

GreenPan commented 6 years ago

截至目前,还是存在的,我也是2017.2 3 而且即使不需要到0.9,在我这里0.5就会出现(实际上0.3/0.4都有). 不论是只移动物体还是只移动相机都会有. 相机为了观测使用的是正交,背景颜色取得是新Scene下天空盒默认地板色,线性空间,PS使用8位模式. 有没有可能跟显示器有关啊(〃'▽'〃)

restary commented 6 years ago

个人认为这个残影就是程序执行的必然结果,逻辑上是正确的。因为每次的结果是上一帧的加权求和。例如一个运动的方块,第一帧的图像在后续的帧中的权重如下:(当权重为90%的时候) 2F : 0.9 3F : 0.9^2 4F : 0.9^3 以此类推

yty commented 6 years ago

@restary 我觉得不是必然结果,这个后来我在editor下设置camera的clearColor的alpha,就会让这个残留消失。但是用代码去设置仍然不行。感觉是u3d的bug.

QiuG8 commented 5 years ago

小弟覺得這是浮點數精度的問題

先了解 何謂運動模糊? 為什麼使用這種混和因子?

那是因為用後紋理去混合前紋理 看看混合公式 這導致後紋理顏色逼近前紋理的顏色

這也是脫尾現象發生的原因(看起來有殘影) 這裡拿起筆畫出3-4頁框很容易懂

如此 混合因子值越低(=1-模糊係數),也就是模糊係數越高的情況下 模糊的效果越佳 因為每次混合的變化率不大 殘影更加明顯

雖然按照這個公式 始終會讓前張紋理慢慢混合完畢 導致拖尾消失

但為什麼沒消失? 想一下

模糊係數過大會怎樣? 這會導致小數位越來越多

以黑色(0,0,0)背景 白色方塊(1,1,1)為例子 緩緩移動白色方塊 模糊係數定在0.9

殘影部分就是 (0,0,0)0.1+(1,1,1)0.9

再混合一次 (0,0,0)0.1+(0.9,0.9,0.9)0.9

這樣一直連續下去直到完全混合成黑色(殘影消失)

有沒有發現 模糊係數太高會導致小數過多 需求的精度越大

看一下OnRenderImage函數送入的源紋理是RGBHalf類型的 目標紋理是RGB32

RGB32 每個通道只有8bit 模糊係數開太大的情況下已經不夠用了 無法保證計算正確性

所以 將目標紋理緩衝的各通道精度開大一點

accumulationTexture.format = RenderTextureFormat.ARGBHalf;---------->多加這一行!

如果不夠用 再開更大

accumulationTexture.format = RenderTextureFormat.ARGBFloat;

每個通道32bit 模糊係數開道0.99也不是問題了

yty commented 5 years ago

@QiuG8 今天又看了一下这个问题,用float的RenderTexture结果还是一样的。你是在什么版下测试成功的呢?

nbnbzc commented 4 years ago

我用Unity 2019.3.15f专业版,似乎没遇到这个问题哎!