Unity中URP下的半透明效果实现


前言

URP下的半透明效果的实现方式,和BRP下的实现是一样的。

我们在上一篇文章实现了菲涅尔效果的基础上,继续添加半透明效果。


一、实现半透明的步骤

1、修改Blend模式,使之透明

Blend One One

2、打开深度写入,防止透明对象穿模

ZWrite On

3、在Tags中,修改渲染类型和渲染队列为半透明 Transparent

Tags
{
	//告诉引擎,该Shader只用于 URP 渲染管线
	"RenderPipeline"="UniversalPipeline"
	//渲染类型
	"RenderType"="Transparent"
	//渲染队列
	"Queue"="Transparent"
}
  • 我们的菲尼尔效果变透明了
    在这里插入图片描述

二、对透明效果实现从下到上的透明渐变

  • 实现思路
    要实现模型从上到下的渐变效果,我们一般使用模型的本地坐标。

1、 我们在 Varying 中,定义一个vertexOS,用于把顶点的本地空间坐标传给片元着色器

float3 vertexOS : TEXCOORD0;

2、 在顶点着色器中,把Attribute中的模型顶点本地坐标 传入给 vertexOS

3、 我们输出看一下模型顶点本地坐标的xyz

  • i.vertexOS.x
    在这里插入图片描述
  • i.vertexOS.y
    在这里插入图片描述
  • i.vertexOS.z
    在这里插入图片描述

4、使用模型顶点本地坐标中的 y 坐标实现效果

我们要实现从下到上,从透明渐变到不透明的效果,则把 y 坐标取反即可(这里每个人的不一样,自己调试)

return i.vertexOS.y * -1;

在这里插入图片描述

5、定义一个可调节参数 _Offset ,调节透明开始的位置

return i.vertexOS.y * -1 + _Offset;

  • 这样就可调节调节透明开始的位置
    请添加图片描述

6、使用saturate(x)限制蒙版区域在(0,1)之间

saturate(i.vertexOS.y * -1 + _Offset);

7、与之前的菲涅尔效果相乘输出

saturate(i.vertexOS.y * -1 + _Offset) * fresnel1

请添加图片描述

8、修改透明效果为斜着透明(凭个人喜好添加)

经测试,我这里使用 模型顶点本地坐标的 x 可以调试出这种效果(每个人的模型可能不一样)

  • i.vertexOS.y * -1 + i.vertexOS.x * -1
    在这里插入图片描述

return saturate(i.vertexOS.y * -1 + i.vertexOS.x * -1 + _Offset) * fresnel1;

请添加图片描述

9、使头部的菲涅尔效果更加明显,脚部的菲尼尔效果正常

这样的效果,我们很容易联想到使用线性插值的方法实现

  • 上面计算的计算结果作为 插值数a

half fresnel = 1 - saturate(NdotL);
//菲涅尔自定义
half4 fresnel1 = pow(fresnel,_Fresnel.x) * _Fresnel.y * _FresnelColor;
//透明渐变效果
float alphaMask = saturate(i.vertexOS.y * -1 + i.vertexOS.x * -1 + _Offset);
fresnel1 = alphaMask * fresnel1;

  • 使菲涅尔效果更加明显 作为 插值数b

_FresnelColor * alphaMask * fresnel1

  • 把alphaMask作为被插值的变量

fresnel1 = lerp(fresnel1,_FresnelColor * alphaMask * fresnel1,alphaMask * _Fresnel.z);

请添加图片描述

三、最终测试代码

//URP下的菲涅尔效果
//URP下的透明效果
Shader "MyShader/URP/P3_2_5"
{
    Properties
    {
        _FresnelColor("FresnelColor",Color) = (0,0,0,0)
        _Fresnel("Fade(X) Intensity(Y) Top(Z) Offset(W)",Vector) = (4,1,1,0)
    }
    SubShader
    {
        Tags
        {
            //告诉引擎,该Shader只用于 URP 渲染管线
            "RenderPipeline"="UniversalPipeline"
            //渲染类型
            "RenderType"="Transparent"
            //渲染队列
            "Queue"="Transparent"
        }
        Blend One One ZWrite On
        Pass
        {
            
            
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
           
            #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"

            struct Attributes
            {
                float3 vertexOS : POSITION;
                float3 normalOS : NORMAL;
            };

            struct Varyings
            {
                float3 vertexOS : TEXCOORD0;
                float4 vertexCS : SV_POSITION;
                float3 vertexWS : TEXCOORD1;
                float3 normalWS : TEXCOORD2;
            };

            CBUFFER_START(UnityPerMaterial)
            half4 _FresnelColor;
            half4 _Fresnel;
            float _Offset;
            CBUFFER_END
            
            Varyings vert (Attributes v)
            {
                Varyings o;
                o.vertexOS = v.vertexOS;
                o.vertexWS = TransformObjectToWorld(v.vertexOS);
                o.vertexCS = TransformWorldToHClip(o.vertexWS);
                o.normalWS = TransformObjectToWorldNormal(v.normalOS);
                
                return o;
            }

            half4 frag (Varyings i) : SV_Target
            {
                
                //dot(N,L)
                half3 N = normalize(i.normalWS);
                half3 L = normalize(_WorldSpaceCameraPos - i.vertexWS);
                half NdotL = dot(N,L);
                //菲涅尔效果 1 - dot(N,L)
                half fresnel = 1 - saturate(NdotL);
                //菲涅尔自定义
                half4 fresnel1 = pow(fresnel,_Fresnel.x) * _Fresnel.y * _FresnelColor;
                
                //透明渐变效果
                float alphaMask = saturate(i.vertexOS.y * -1 + i.vertexOS.x * -1 + _Fresnel.w);
                fresnel1 = alphaMask * fresnel1;

                //头部菲涅尔效果和下部菲涅尔效果做出区别
                fresnel1 = lerp(fresnel1,_FresnelColor * alphaMask * fresnel1,alphaMask * _Fresnel.z);
                
                return fresnel1;
            }
            ENDHLSL
        }
    }
}

### Unity URP实现半透明效果的方法 在Unity Universal Render Pipeline (URP) 中,实现半透明效果涉及多个方面的配置和调整。以下是具体的实现方法: #### 1. 修改Blend模式以支持透明度 为了使材质具有半透明效果,需要修改Shader中的`Blend Mode`参数。通过设置合适的混合模式,可以让对象的部分区域变得透明或半透明。通常使用的混合模式为 `SrcAlpha OneMinusSrcAlpha`,这表示源颜色的alpha值会决定最终像素的颜色贡献比例。 ```hlsl // 在SubShader Pass中添加如下代码片段来启用Blend功能 Blend SrcAlpha OneMinusSrcAlpha ZWrite Off // 关闭深度写入以防遮挡其他物体 ``` 这段代码的作用在于开启混合并指定如何计算目标帧缓冲区内的新颜色[^1]。 #### 2. 配置Render Queue 对于半透明对象来说,默认渲染队列可能无法满足需求,因此需手动将其放置到更高的渲染优先级位置。“Transparent”是一个常见的选择,它确保这些对象会在所有不透明几何体之后被绘制出来。 ```hlsl Tags { "Queue"="Transparent" } ``` 此标签告诉Unity该Pass应该参与哪个阶段的渲染过程[^4]。 #### 3. 设置Material属性 创建一个新的材质,在Inspector面板里找到对应字段输入数值控制透明程度。一般情况下,“_Color”的RGBA分量可以直接影响整体外观;如果希望更精细地调节,则可以在纹理贴图上叠加额外的信息层作为蒙版依据。 例如: - 使用Albedo Map的同时引入一张单独存储Opacity Information的地图; - 或者利用Vertex Color携带局部变化数据等等。 #### 4. 调整摄像机背景行为(可选) 当项目中有特殊需求比如导出图像文件时保留清晰边界而非模糊渐变过渡的话,还需要进一步处理场景视口外沿部分的表现形式。按照特定指导完成相关设定后即可获得预期成果[^2]。 综上所述,以上步骤能够帮助开发者成功构建适用于大多数情况的基础版本半透明白模解决方案。当然实际应用过程中还可能存在更多复杂状况等待解决,这就要求我们不断学习探索新的技术和思路去克服遇到的各种挑战。 ```python # Python 示例仅用于说明逻辑流程,并非必要组成部分 def setup_transparent_material(material): material.SetOverrideTag("RenderType", "Transparent") material.SetInt("_SrcBlend", (int)(UnityEngine.Rendering.BlendMode.SrcAlpha)) material.SetInt("_DstBlend", (int)(UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha)) material.SetInt("_ZWrite", 0) # 假设material为已实例化的Material对象 setup_transparent_material(your_material_instance) ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楠溪泽岸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值