700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Unity移动端 WebGL 四边形线框Shader 实现

Unity移动端 WebGL 四边形线框Shader 实现

时间:2019-12-02 23:38:10

相关推荐

Unity移动端 WebGL 四边形线框Shader 实现

本文不是使用GeometryShader!

移动端和WebGL由于一些限制不能使用GeometryShader,因此不好实现线框Shader。

一、手动绘制

有的人可能会选择用GL画线来实现绘制线框,具体就是读取mesh信息然后绘制线条,但是GL绘制不能调整线条粗细。有的人可能有回使用LineRender或者直接用圆柱体。这样确实可以调整粗细,但是性能堪忧。。。

手动绘制,基本大一点的Mesh就会严重影响性能,不是很可取。

二、通过Mesh传参数

线框用shader实现的难度,就是很难找到三角的边

我的灵感来自Github上的一个工程,UnityWireframeRenderer,感兴趣的可以去看看,感觉真的很厉害。

主要通过修改Mesh的UV,然后通过uv插值,计算出点到边的距离。

因为要创建新的Mesh,所以其实还是有内存消耗的,但是除了内存问题,运行性能完美。我的做法是在这个原理上进行了修改。

Normal传参

原文通过UV传递信息有一个问题,就是需要自己计算第三条边的距离,因为uv变化只能保存两条边的距离。然而normal具有三个值,可以完美保存三条边的插值距离,就不用在shader中额外计算了。

还有一个优点,可以通过normal的值,实现绘制4边形,而不是绘制三角面的线。因为Mesh提前计算的,所以可以提前计算出同义平面上的相交边,然后修改Normal值,然后在Shader中插值时,就不会显示相交边了。

建议Github上搜索原工程看看,上面有注释,很容易理解。

fixed4 _LineColor;float _LineSize;float4 _EmissionColor;float _Intencity;struct appdata{float4 vertex : POSITION;float3 normal : NORMAL;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;float3 normal : TEXCOORD1;};v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);//If we are rendering in shaded mode (showing the original mesh renderer)//we want to ensure that the wireframe-processed mesh appears "on top" of//the original mesh. We achieve this by slightly decreasing the z component//(making the vertex closer to the camera) without actually changing its screen space position//since the w component remains the same, and thus, after w division, the x and y components//won't be affected by our "trick".//So, in essence, this just changes the value that gets written to the Z-Buffero.vertex.z -= 0.001;o.uv = v.uv;o.normal = v.normal;return o;}fixed4 frag (v2f i) : SV_Target{float lineWidthInPixels = _LineSize;float lineAntiaAliasWidthInPixels = 1;float2 normalxVector = float2(ddx(i.normal.x),ddy(i.normal.x)); float2 normalyVector = float2(ddx(i.normal.y),ddy(i.normal.y)); float2 normalzVector = float2(ddx(i.normal.z),ddy(i.normal.z)); float normalxLength = length(normalxVector); float normalyLength = length(normalyVector);float normalzLength = length(normalzVector); float maximumXDistance = lineWidthInPixels * normalxLength;float maximumYDistance = lineWidthInPixels * normalyLength;float maximumZDistance = lineWidthInPixels * normalzLength;float minimumXDistance = i.normal.x;float minimumYDistance = i.normal.y;float minimumZDistance = i.normal.z;float normalizedXDistance = minimumXDistance / maximumXDistance;float normalizedYDistance = minimumYDistance / maximumYDistance;float normalizedZDistance = minimumZDistance / maximumZDistance;float closestNormalizedDistance = min(normalizedXDistance,normalizedYDistance);closestNormalizedDistance = min(closestNormalizedDistance,normalizedZDistance);float lineAlpha = 1.0 - smoothstep(1.0,1.0 + (lineAntiaAliasWidthInPixels/lineWidthInPixels),closestNormalizedDistance);lineAlpha *= _LineColor.a;return fixed4(_LineColor.rgb + _EmissionColor.rgb * _Intencity,lineAlpha);}

这是Shader 的主要部分,我的修改也是基于原工程,可以对比着看。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。