z-fighting在unity中的解决方式
2016-09-01 17:37
253 查看
如果在画面中,发现有画面闪烁的问题。那么大多数情况下是z-fighting引起的,
解决方案:
1, 在每个场景中,找到那个MainCamera,然后在Inspector上,找到MainCamera的属性,Clipping Planes,需要做的是尽量放大near的值,尽量减小far的值。根据我的实验结果,同样改动Near值的幅度比Far值的幅度相对来说效果会更好。如Near从1到20可能修正了某个z-fighting,但是Far从1000改到500也还是没有用。这个在实践中可以注意。
2, 如果场景没有办法改动上述的值,那么还有的方式就是找到产生z-fighting的模型,让模型产生这个现象的两个面尽量离开一些距离,究竟多少距离只有通过实验才知道。
3, 如果可能,程序上就可以用Polygon Offset,这个是OpenGL的接口,
[cpp] view plain copy
drawOnePlane();
//Draw other plane in the almost same position, before use offset, it will fighting with the one we has drawn.
glEnable( GL_POLYGON_OFFSET_FILL );
glPolygonOffset( g_OffsetFactor, g_OffsetUnit );
drawOtherPlane();
glPolygonOffset( 0.0f, 0.0f );
glDisable( GL_POLYGON_OFFSET_FILL );
4、如果是D3D,那么这篇文章提到3中方式,最后一种方式是跟上面的OpenGL思路一样的。
http://software.intel.com/zh-cn/articles/alternatives-to-using-z-bias-to-fix-z-fighting-issues/
a, project matrix
[cpp] view plain copy
// ZFighting Solution #1 - Projection Matrix
D3DXMATRIX mProjectionMat; // Holds default projection matrix
D3DXMATRIX mZBiasedProjectionMat; // Holds ZBiased projection matrix
// Globals used for Projection matrix
float g_fBaseNearClip = 1.0f;
float g_fBaseFarClip = 100.0f;
// Code indicates no change. ie states 'near and far clipping planes pushed out' but only far appears pushed
float g_fNearClipBias = 0.0f;
float g_fFarClipBias = 0.5f;
// Projection Matrix work around
// Best if calculation are done outside of render function.
// The "zbiased" projection has it near and far clipping
// planes pushed out...
D3DXMatrixPerspectiveFovLH( &mZBiasedProjectionMat, D3DX_PI/4,(mProjectionMat._22/mProjectionMat._11),
g_fBaseNearClip + g_fNearClipBias,
g_fBaseFarClip + g_fFarClipBias );
. . .
// Original projection is loaded
m_pd3dDevice ->SetTransform( D3DTS_PROJECTION, & mProjectionMat);
// Billboards are rendered...
// The "zbiased" projection is loaded ...
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mZBiasedProjectionMat);
// Posters are rendered...
// Original projection is reloaded...
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, & mProjectionMat);
. . .
b, view port matrix
[cpp] view plain copy
// ZFighting Solution #2 - Viewport
D3DVIEWPORT9 mViewport; // Holds viewport data
D3DVIEWPORT9 mNewViewport; // Holds new viewport data
// Global used for Viewport
// Hard coded for ZBIAS of 1 using this formula
// MinZ - 256/(2^24-1) and
// MaxZ - 256/(2^24-1)
// 2^24 comes from the amount of Zbits and the 256 works
// for Intel (R) Integrated Graphics, but can be any
// multiple of 16.
float g_fViewportBias = 0.0000152588f;
// Projection Matrix work around
// Viewport work around
m_pd3dDevice->GetViewport(&mViewport);
// Copy old Viewport to new
mNewViewport = mViewport;
// Change by the bias
mNewViewport.MinZ -= g_fViewportBias;
mNewViewport.MaxZ -= g_fViewportBias;
. . .
// Original viewport is reloaded …
m_pd3dDevice->SetViewport(&mViewport);
// Billboards are rendered …
// The new viewport is loaded …
m_pd3dDevice->SetViewport(&mNewViewport);
// Posters are rendered …
// Original viewport is reloaded …
m_pd3dDevice->SetViewport(&mViewport);
. . .
c, depth - bias
[cpp] view plain copy
BOOL m_bDepthBiasCap; // TRUE, if device has DepthBias Caps
// Globals used for Depth Bias
float g_fSlopeScaleDepthBias = 1.0f;
float g_fDepthBias = -0.0005f;
float g_fDefaultDepthBias = 0.0f;
// Check for devices which support the new depth bias caps
if ((pCaps->RasterCaps & D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS) &&
(pCaps->RasterCaps & D3DPRASTERCAPS_DEPTHBIAS))
{
m_bDepthBiasCap = true; // TRUE, if DepthBias Caps
}
// Billboards are rendered...
// DepthBias work around
if ( m_bDepthBiasCap ) // TRUE, if DepthBias supported
{
// Used to determine how much bias can be applied
// to co-planar primitives to reduce z fighting
// bias = (max * D3DRS_SLOPESCALEDEPTHBIAS) + D3DRS_DEPTHBIAS,
// where max is the maximum depth slope of the triangle being rendered.
m_pd3dDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(g_fSlopeScaleDepthBias));
m_pd3dDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW(g_fDepthBias));
}
// Posters are rendered...
if ( m_bDepthBiasCap ) // TRUE, if DepthBias supported
{
// DepthBias work around
// set it back to zero (default)
m_pd3dDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(g_fDefaultDepthBias));
m_pd3dDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW(g_fDefaultDepthBias));
}
. . .
5,这里还有一篇文章教到怎么样在面上画出线的,相信你也会遇到同样的问题。当然,核心还是用depth-bias,但是,人家把怎么做和做的时候要注意的问题都写上了(主要就是用bias的时候值不要取的太大,否则线框是渲染出来了,但是也同时多出线来了,因为本来是该本剪切的,经过修正可能就不被剪切了)。值得一看。
http://www.catalinzima.com/samples/12-months-12-samples-2008/drawing-wireframes-without-z-fighting/
背景原理:
z-fighting的出现是的不同面上的像素在z-buffer中的值相近,导致前台取像素的时候一会去这个面的,一会取那个面的。改变照相机的near、far属性会涉及到z-buffer中的值的精度。因为在各个平台上z-buffer位数不同,因此改变near和far能给z-buffer中的值的浮点数部分尽量留出空间,消除z-fighting。
这个是wiki上的z-fighting的例子,可以看到不同色彩的面,因为z-buffer的精度设置的小,然后两个面放置的比较近,因此出现了相关的穿插显示的问题。
解决方案:
1, 在每个场景中,找到那个MainCamera,然后在Inspector上,找到MainCamera的属性,Clipping Planes,需要做的是尽量放大near的值,尽量减小far的值。根据我的实验结果,同样改动Near值的幅度比Far值的幅度相对来说效果会更好。如Near从1到20可能修正了某个z-fighting,但是Far从1000改到500也还是没有用。这个在实践中可以注意。
2, 如果场景没有办法改动上述的值,那么还有的方式就是找到产生z-fighting的模型,让模型产生这个现象的两个面尽量离开一些距离,究竟多少距离只有通过实验才知道。
3, 如果可能,程序上就可以用Polygon Offset,这个是OpenGL的接口,
[cpp] view plain copy
drawOnePlane();
//Draw other plane in the almost same position, before use offset, it will fighting with the one we has drawn.
glEnable( GL_POLYGON_OFFSET_FILL );
glPolygonOffset( g_OffsetFactor, g_OffsetUnit );
drawOtherPlane();
glPolygonOffset( 0.0f, 0.0f );
glDisable( GL_POLYGON_OFFSET_FILL );
4、如果是D3D,那么这篇文章提到3中方式,最后一种方式是跟上面的OpenGL思路一样的。
http://software.intel.com/zh-cn/articles/alternatives-to-using-z-bias-to-fix-z-fighting-issues/
a, project matrix
[cpp] view plain copy
// ZFighting Solution #1 - Projection Matrix
D3DXMATRIX mProjectionMat; // Holds default projection matrix
D3DXMATRIX mZBiasedProjectionMat; // Holds ZBiased projection matrix
// Globals used for Projection matrix
float g_fBaseNearClip = 1.0f;
float g_fBaseFarClip = 100.0f;
// Code indicates no change. ie states 'near and far clipping planes pushed out' but only far appears pushed
float g_fNearClipBias = 0.0f;
float g_fFarClipBias = 0.5f;
// Projection Matrix work around
// Best if calculation are done outside of render function.
// The "zbiased" projection has it near and far clipping
// planes pushed out...
D3DXMatrixPerspectiveFovLH( &mZBiasedProjectionMat, D3DX_PI/4,(mProjectionMat._22/mProjectionMat._11),
g_fBaseNearClip + g_fNearClipBias,
g_fBaseFarClip + g_fFarClipBias );
. . .
// Original projection is loaded
m_pd3dDevice ->SetTransform( D3DTS_PROJECTION, & mProjectionMat);
// Billboards are rendered...
// The "zbiased" projection is loaded ...
m_pd3dDevice->SetTransform(D3DTS_PROJECTION, &mZBiasedProjectionMat);
// Posters are rendered...
// Original projection is reloaded...
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, & mProjectionMat);
. . .
b, view port matrix
[cpp] view plain copy
// ZFighting Solution #2 - Viewport
D3DVIEWPORT9 mViewport; // Holds viewport data
D3DVIEWPORT9 mNewViewport; // Holds new viewport data
// Global used for Viewport
// Hard coded for ZBIAS of 1 using this formula
// MinZ - 256/(2^24-1) and
// MaxZ - 256/(2^24-1)
// 2^24 comes from the amount of Zbits and the 256 works
// for Intel (R) Integrated Graphics, but can be any
// multiple of 16.
float g_fViewportBias = 0.0000152588f;
// Projection Matrix work around
// Viewport work around
m_pd3dDevice->GetViewport(&mViewport);
// Copy old Viewport to new
mNewViewport = mViewport;
// Change by the bias
mNewViewport.MinZ -= g_fViewportBias;
mNewViewport.MaxZ -= g_fViewportBias;
. . .
// Original viewport is reloaded …
m_pd3dDevice->SetViewport(&mViewport);
// Billboards are rendered …
// The new viewport is loaded …
m_pd3dDevice->SetViewport(&mNewViewport);
// Posters are rendered …
// Original viewport is reloaded …
m_pd3dDevice->SetViewport(&mViewport);
. . .
c, depth - bias
[cpp] view plain copy
BOOL m_bDepthBiasCap; // TRUE, if device has DepthBias Caps
// Globals used for Depth Bias
float g_fSlopeScaleDepthBias = 1.0f;
float g_fDepthBias = -0.0005f;
float g_fDefaultDepthBias = 0.0f;
// Check for devices which support the new depth bias caps
if ((pCaps->RasterCaps & D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS) &&
(pCaps->RasterCaps & D3DPRASTERCAPS_DEPTHBIAS))
{
m_bDepthBiasCap = true; // TRUE, if DepthBias Caps
}
// Billboards are rendered...
// DepthBias work around
if ( m_bDepthBiasCap ) // TRUE, if DepthBias supported
{
// Used to determine how much bias can be applied
// to co-planar primitives to reduce z fighting
// bias = (max * D3DRS_SLOPESCALEDEPTHBIAS) + D3DRS_DEPTHBIAS,
// where max is the maximum depth slope of the triangle being rendered.
m_pd3dDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(g_fSlopeScaleDepthBias));
m_pd3dDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW(g_fDepthBias));
}
// Posters are rendered...
if ( m_bDepthBiasCap ) // TRUE, if DepthBias supported
{
// DepthBias work around
// set it back to zero (default)
m_pd3dDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, F2DW(g_fDefaultDepthBias));
m_pd3dDevice->SetRenderState(D3DRS_DEPTHBIAS, F2DW(g_fDefaultDepthBias));
}
. . .
5,这里还有一篇文章教到怎么样在面上画出线的,相信你也会遇到同样的问题。当然,核心还是用depth-bias,但是,人家把怎么做和做的时候要注意的问题都写上了(主要就是用bias的时候值不要取的太大,否则线框是渲染出来了,但是也同时多出线来了,因为本来是该本剪切的,经过修正可能就不被剪切了)。值得一看。
http://www.catalinzima.com/samples/12-months-12-samples-2008/drawing-wireframes-without-z-fighting/
背景原理:
z-fighting的出现是的不同面上的像素在z-buffer中的值相近,导致前台取像素的时候一会去这个面的,一会取那个面的。改变照相机的near、far属性会涉及到z-buffer中的值的精度。因为在各个平台上z-buffer位数不同,因此改变near和far能给z-buffer中的值的浮点数部分尽量留出空间,消除z-fighting。
这个是wiki上的z-fighting的例子,可以看到不同色彩的面,因为z-buffer的精度设置的小,然后两个面放置的比较近,因此出现了相关的穿插显示的问题。
![](http://upload.wikimedia.org/wikipedia/en/5/5f/ZfightingCB.png)
相关文章推荐
- z-fighting在unity中的解决方式
- z-fighting在unity中的解决方式
- Unity 使用C/C++ 跨平台终极解决方式(PC,iOS,Android,以及支持C/C++的平台)
- Unity 3D本地公布WebPlayer版时"Failed to download data file"解决方式
- Unity接入sdk时(和android交互),提示IOException错误解决方式。
- 理解并解决IE的内存泄漏方式[翻译3]
- 当程序用ado的jet4.0方式连接的时候,对于设有access数据库密码的mdb的访问居然报错“无法启动应用程序,工作组信息文件丢失,或是已被其他用户已独占方式打开”,而用odbc方式不报错,小阴沟里翻船,郁闷中然后查文档解决之
- 理解并解决IE的内存泄漏方式
- 关于"打开方式"--"选择程序" 被拒绝访问的解决方法
- JSP中,AJAX使用POST方式提交中文乱码问题解决
- MSSQL在另一台机子上恢复别人备份引起的问题及解决方式!
- 用页传值方式解决模态窗口的Response.WriteFile文件下载
- 理解并解决IE的内存泄漏方式[翻译4]
- ms-sql登录验证方式错误解决办法
- DataList,Repeater分页问题可以采用三种方式解决:
- 解决用序列化方式实现对象拷贝时出的异常解决方法
- 理解并解决IE的内存泄漏方式[翻译]
- 安装完vs.2005之后,重新安装iis后无法使用http方式访问asp.net工程的页面的问题的解决方法
- Asp.net未处理异常的2种解决方式(个人总结篇)
- 右键发送到"桌面快捷方式"等没了的解决办法