玻璃效果实现一:GrabPass

本文介绍了如何使用GrabPass技术在移动端创建逼真的玻璃效果,同时提供了低消耗的替代方案。作者强调了GrabPass的高开销,并提醒开发者注意场景应用。后续会分享移动端低消耗的高性能玻璃Shader实现方法。
摘要由CSDN通过智能技术生成

YY一下:为什么这篇文章我这么就才写,是因为大家都用GrabPass取做玻璃效果,其实原理就是多一个特俗pass去渲染。可想而知,其开销也是巨大的,所以我在准备GrabPass的教程的时候,我也准备了另一个制作方式。先来看看GrabPass效果:

因为是抓拍图片渲染贴在玻璃上面,所以我很容易处理扰动效果实现毛玻璃效果;


              

                 fixed4 maincolor=tex2D(_MainTex,i.uv); //玻璃自身颜色采样。
                 fixed4 bump=tex2D(_Bump,i.uv); //玻璃法线贴图纹理采样
                 fixed2 disstortion=UnpackNormal(bump).rg; //将纹理颜色转化为法线方向;
                 i.uvgrab.xy+=disstortion*_Magnitude;//对uvgrab进行扰动。

完整代码如下,只是标准,大家可以自由扩展,(再次提示:GrabPass其实开销并不小,使用一定要注意场景应用)

Shader "Unlit/GrabShader_Glass"
{

//1:把对象下已经绘制的内容抓拍到纹理当中;
//2:使用法线贴图替换纹理中的像素;
//3:把失真的像素渲染到屏幕上;
//特俗Pass:GrabPass ,把当前内容渲染到纹理上,(而不是渲染到屏幕上)且保证玻璃不会被绘制。
    Properties
    {
	    _Color("COlor",color)=(1,1,1,1)
        _MainTex ("Texture", 2D) = "white" {}
		_Bump ("normal",2D)="bump"{}
		_Magnitude("Magnitude",Range(0,1))=0.5    }
    SubShader
    {
        Tags { 
	    //渲染队列的顺序,最后渲染透明;
		"Queue"="Transparent"
		"IgnoreProjector"="true"
		"RenderType"="Opaque" 
		}
        //关闭深度计算可以解决模型显示破面问题
	    ZWrite Off 
		Lighting Off
		Cull Off
		Blend one Zero 
		//在对玻璃前置渲染时,把整个场景(除去玻璃)渲染到_GrabTexture纹理上
		//注意:GrabPass其实开销巨大,相当于一个新的pass;
       GrabPass {"_GrabTexture"}
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
            #include "UnityCG.cginc"
            struct appdata
            {
                half4 vertex : POSITION;
				fixed4 color:COLOR;
			    fixed2 uv : TEXCOORD0;
            };
            struct v2f
            {
				fixed4 color:COLOR;
				fixed2 uv:TEXCOORD0; //MainTex 纹理坐标
                fixed4 uvgrab : TEXCOORD1;//Bump 的纹理坐标;
                UNITY_FOG_COORDS(2)
                half4 vertex : POSITION;
            };
            sampler2D _GrabTexture;//存入拍摄的GrabPass纹理;
			sampler2D _MainTex;
			sampler2D _Bump;
			fixed _Magnitude;
			fixed4 _Color; 
		  //计算每个顶点像素的属性(位置,纹理坐标等等)
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
			//	ComputeGrabScreenPos传入投影空间中的坐标,
			    o.uvgrab = ComputeGrabScreenPos(o.vertex);  
			    o.color= v.color;
				o.uv=v.uv;
              //  o.uv = TRANSFORM_TEX(v.uv, _MainTex);
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }
			//光栅化处理,顶点到片元的属性计算,得到每个片元的颜色值。
            fixed4 frag (v2f i) : SV_Target
            {

			     fixed4 maincolor=tex2D(_MainTex,i.uv); //玻璃自身颜色采样。
				 fixed4 bump=tex2D(_Bump,i.uv); //玻璃法线贴图纹理采样
				 fixed2 disstortion=UnpackNormal(bump).rg; //将纹理颜色转化为法线方向;
				 i.uvgrab.xy+=disstortion*_Magnitude;//对uvgrab进行扰动。
                // sample the texture
                 fixed4 col = tex2Dproj(_GrabTexture, UNITY_PROJ_COORD(i.uvgrab));  //玻璃背后的颜色计算
		
                // apply fog
                UNITY_APPLY_FOG(i.fogCoord, col);
                return col*maincolor*_Color; //合成最终效果
            }
            ENDCG
        }
    }
}

下一篇移动端低消耗高性能玻璃shader实现:http://t.csdnimg.cn/bfvGY

  • 13
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
cv::grabCut是OpenCV中的一个图像分割算法,用于将图像分割为前景和背景。它基于图割算法,通过迭代优化来实现分割效果。具体用法如下: ```cpp void cv::grabCut(cv::InputArray img, // 输入图像 cv::InputOutputArray mask, // 输入输出掩码 cv::Rect rect, // 包含前景的矩形 cv::InputOutputArray bgdModel, // 背景模型 cv::InputOutputArray fgdModel, // 前景模型 int iterCount, // 迭代次数 int mode // 模式 ) ``` 其中,参数说明如下: - img:输入图像。 - mask:输入输出掩码,用于指定前景和背景的区域。 - rect:包含前景的矩形,用于初始化分割。 - bgdModel:背景模型,用于存储背景像素的统计信息。 - fgdModel:前景模型,用于存储前景像素的统计信息。 - iterCount:迭代次数,用于优化分割结果。 - mode:模式,用于指定算法的初始化方式。 具体的使用方法可以参考以下示例代码: ```cpp #include <opencv2/opencv.hpp> int main() { cv::Mat image = cv::imread("input.jpg"); cv::Rect rect(50, 50, 200, 200); cv::Mat mask(image.size(), CV_8UC1, cv::GC_BGD); cv::Mat bgdModel, fgdModel; cv::grabCut(image, mask, rect, bgdModel, fgdModel, 5, cv::GC_INIT_WITH_RECT); cv::Mat result; cv::compare(mask, cv::GC_PR_FGD, result, cv::CMP_EQ); cv::imshow("Result", result); cv::waitKey(0); return 0; } ``` 这段代码将会对输入图像进行分割,将前景部分标记为白色,背景部分标记为黑色,并显示分割结果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值