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-Buffer
    o.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 的主要部分,我的修改也是基于原工程,可以对比着看。

 

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Unity 中打包 WebGL 游戏时,涉及到的着色器(Shader)需要进行一些特殊处理才能正确运行。下是一个简单的步骤: 1. 确保你的着色器和材质Unity 编辑器中正确显示和运行。确保着色器代码中没有使用不支持 WebGL 的功能。 2. 在 Unity 编辑器中选择 File -> Build Settings 打开构建设置窗口。 3. 在构建设置窗口中,选择 WebGL 平台并点击 Switch Platform 切换到 WebGL 平台。 4. 在 WebGL 设置中,选择 Player Settings 打开游戏玩家设置。 5. 在玩家设置中,确保在“Other Settings”部分,“Scripting Backend”设置为“IL2CPP”。这是为了确保 WebGL 构建使用 IL2CPP 脚本编译器。 6. 在玩家设置中,找到“Publishing Settings”部分的“WebGL Template”设置。选择一个你喜欢的模板,或者点击“New Template”创建自定义模板。 7. 完成上述设置后,点击 Build 按钮开始构建 WebGL 游戏。 8. 构建完成后,在指定的输出文件夹中会生成一个网页文件夹。将该文件夹上传到 Web 服务器上,或者通过本地文件系统打开 index.html 文件来运行游戏。 注意事项: - WebGL 平台上的性能可能会受限,因此确保优化你的着色器和代码以提高性能。 - 一些高级的着色器特性可能不被支持或以不同的方式工作。在开发过程中请测试并确保一切正常。 - 在处理跨域请求时可能会遇到问题,需要在服务器上进行正确的设置。 希望这些步骤能帮助你成功打包和运行 WebGL 游戏!如有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值