Unity3D 双面渲染Shader实现

您所在的位置:网站首页 决战羽毛球游戏技巧教学 Unity3D 双面渲染Shader实现

Unity3D 双面渲染Shader实现

2024-06-28 04:38:58| 来源: 网络整理| 查看: 265

概述

在建模软件中可以为每个顶点设置法线,三个顶点可以组成一个三角面,三角面的法线是根据其顶点的法线插值而来,这个法线朝向就代表了这个平面的正面。 而在现代大部分引擎和游戏中,会默认只显示平面的正面,即对每个三角面进行一次面法线和摄像机出射向量的点积,判断正负,如果当前平面是背面朝向摄像机,则不渲染该面片。 Unity 的standard shader就是这样,我们只要创建一个平面就能看出这种效果。

创建一个平面,默认此平面正面朝上。 请添加图片描述 我们调整角度从下往上看,平面完全不渲染了。除了一个选中的什么都看不见(当然大家都知道这个选中框肯定不会在游戏中渲染出来) 请添加图片描述

这种作法主要是为了提高性能,因为除了极个别图形例如上面的单纯平面之外,很多模型的面片背面是完全看不见的。 想象一下正方形就可以得知,正方形六个面每个的背面,都完全被包裹起来隐藏在正方形内部,正常情况是完全看不见的,那么此时直接不渲染背面也完全没有影响,还能足足减少一半需要渲染的面片。

但是总有时候是会需要渲染背面面片的,常见情况有渲染一些破损的模型,可以从模型外部看到内部,或者是半透明的效果,也需要能看到一个模型的内部。

这种效果俗称为双面渲染,意思就是同时渲染模型正面和背面,在unity3d里实现双面渲染相当简单,第一种做法是用两个pass,第一个渲染正面第二个渲染背面。

第一个pass如下,因为破损的模型不太好找,我们直接用一张贴图加上clip函数来实现可以看到一个模型内部的效果。 首先开启 Cull Back来只渲染正面

Cull Back void surf(Input IN, inout SurfaceOutputStandard o) { clip(tex2D(_Mask, IN.uv_Mask).a - _MaskClipValue); fixed4 c = tex2D(_BackTex, IN.uv_BackTex) * _Color; o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; }

此时的效果很怪,因为只渲染了正面,但是此时是可以看到背面的。 请添加图片描述 接下来我们把背面渲染出来,代码几乎和上面的一模一样,只是cull back改成cull front。 最后得到双面渲染效果。 请添加图片描述

除了直接渲染两个pass之外,还可以使用VFACE这个语义来直接获取顶点朝向,大于0则为朝向摄像机,小于0为背向摄像机。但是该语义需要支持shader model 3.0。 使用vface语义的话就不可避免的需要写if语句,虽然在shader里做if判断会影响性能 但是比跑两个pass还是要好,而且两个pass要跑两次clip 主要修改就是两个pass变成一个pass,还有要使用Cull Off关闭背面裁剪。

void surf(Input IN, inout SurfaceOutputStandard o) { clip(tex2D(_Mask, IN.uv_Mask).a - _MaskClipValue); fixed4 frontC = tex2D(_FrontTex, IN.uv_FrontTex) * _Color; fixed4 backC = tex2D(_BackTex, IN.uv_FrontTex) * _Color; //虽然要做if判断会影响性能 但是比跑两个pass还是要好,而且两个pass如果里面有clip操作的话要跑两次clip if (IN.face > 0) { o.Albedo = frontC.rgb; o.Alpha = frontC.a; } else { o.Albedo = backC.rgb; o.Alpha = backC.a; } o.Metallic = _Metallic; o.Smoothness = _Glossiness; }

参数面板 请添加图片描述

完整代码

完整代码如下 两个pass的方法

Shader "Custom/twoSide2" { Properties { _Color ("Color", Color) = (1,1,1,1) _FrontTex ("FrontTex", 2D) = "white" {} _BackTex ("BackTex", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Mask ("Mask", 2D) = "white" {} _Metallic ("Metallic", Range(0,1)) = 0.0 _MaskClipValue ("MaskClipValue", range(0,1)) = 0 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 Cull Back CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 sampler2D _FrontTex; sampler2D _Mask; struct Input { float2 uv_FrontTex; float2 uv_Mask; }; half _Glossiness; half _Metallic; fixed4 _Color; float _MaskClipValue; void surf(Input IN, inout SurfaceOutputStandard o) { clip(tex2D(_Mask, IN.uv_Mask).a - _MaskClipValue); fixed4 c = tex2D(_FrontTex, IN.uv_FrontTex) * _Color; o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG Cull Front CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 sampler2D _BackTex; sampler2D _Mask; struct Input { float2 uv_BackTex; float2 uv_Mask; }; half _Glossiness; half _Metallic; fixed4 _Color; float _MaskClipValue; void surf(Input IN, inout SurfaceOutputStandard o) { clip(tex2D(_Mask, IN.uv_Mask).a - _MaskClipValue); fixed4 c = tex2D(_BackTex, IN.uv_BackTex) * _Color; o.Albedo = c.rgb; o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG } FallBack "Diffuse" }

完整代码2 使用vface语义的代码

Shader "LX/twoSide1" { Properties { _Color ("Color", Color) = (1,1,1,1) _FrontTex ("FrontTex", 2D) = "white" {} _BackTex ("BackTex", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 _Mask ("Mask", 2D) = "white" {} _MaskClipValue ("MaskClipValue", range(0,1)) = 0 } SubShader { Tags { "RenderType"="Opaque" } LOD 200 Cull Off CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 sampler2D _FrontTex; sampler2D _BackTex; sampler2D _Mask; struct Input { float2 uv_FrontTex; float2 uv_BackTex; float2 uv_Mask; fixed face : VFACE; }; half _Glossiness; half _Metallic; fixed4 _Color; float _MaskClipValue; void surf(Input IN, inout SurfaceOutputStandard o) { clip(tex2D(_Mask, IN.uv_Mask).a - _MaskClipValue); fixed4 frontC = tex2D(_FrontTex, IN.uv_FrontTex) * _Color; fixed4 backC = tex2D(_BackTex, IN.uv_FrontTex) * _Color; //虽然要做if判断会影响性能 但是比跑两个pass还是要好,而且两个pass如果里面有clip操作的话要跑两次clip if (IN.face > 0) { o.Albedo = frontC.rgb; o.Alpha = frontC.a; } else { o.Albedo = backC.rgb; o.Alpha = backC.a; } o.Metallic = _Metallic; o.Smoothness = _Glossiness; } ENDCG } FallBack "Diffuse" }

另外代码也传到github仓库里了,大家也可以关注一下哦~ 我的github

注:此shader只是演示了如何实现一个最简单的双面渲染效果,实际项目中肯定是要对以前使用的shader进行改造使其支持双面渲染的,所以肯定还有其他地方要修改。



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭