zoukankan      html  css  js  c++  java
  • unity实现玻璃效果

    一、使用Cubemap,做一个假反射


    shader代码如下:

    Shader "Custom/glassShader" {
    	Properties {
    		_MainColor("Main Color",Color)=(1,1,1,1)
    		_MainTex ("Base (RGB)", 2D) = "white" {}
    		_Cube("Cube",CUBE)=""{}
    	}
    	SubShader {
    		Tags {"RenderType"="Opaque"}
    		LOD 200
    		
    		//cull off
    
    		CGPROGRAM
    		#pragma surface surf Lambert alpha
    
    		fixed4 _MainColor;
    		sampler2D _MainTex;
    		samplerCUBE _Cube;
    
    		struct Input {
    			float2 uv_MainTex;
    			float3 worldRefl;
    		};
    
    		void surf (Input IN, inout SurfaceOutput o) {
    			half4 c = tex2D (_MainTex, IN.uv_MainTex);
    			o.Albedo = c.rgb*_MainColor.rgb;
    			o.Emission=texCUBE(_Cube,IN.worldRefl).rgb;
    			o.Alpha = c.a*_MainColor.a;
    		}
    		ENDCG
    	} 
    
    	FallBack "Diffuse"
    }
    


    二、使用GrabPass,抓取屏幕纹理,实现实时反射

    shader代码如下:

    Shader "Unlit/GrabGlass"
    {
    	Properties
    	{
    		_Color("Main Color",Color)=(1,1,1,1)
    		_MainTex ("Texture", 2D) = "white" {}
    	}
    	SubShader
    	{
    		
    	
    		Tags {"Queue"="Transparent" "RenderType"="Opaque" }//Opaque
    		LOD 100
    
    		//绘制半透明物体 关闭深度缓存
    		ZWrite Off
    		//透明混合
    		Blend SrcAlpha OneMinusSrcAlpha
    
    		//如果没有命名,则可以用_GrabTexture来读取,不过开销很大,应用到特殊效果时才去应用
    		GrabPass
    		{
    				"_GrabTex"
    		}
    
    		Pass
    		{
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			// make fog work
    			#pragma multi_compile_fog
    			
    			#include "UnityCG.cginc"
    
    			struct appdata
    			{
    				float4 vertex : POSITION;
    				float2 uv : TEXCOORD0;
    			};
    
    			struct v2f
    			{
    				float2 uv : TEXCOORD0;
    				UNITY_FOG_COORDS(1)
    				float4 vertex : SV_POSITION;
    			};
    
    			sampler2D _MainTex;
    			float4 _MainTex_ST;
    			fixed4 _Color;
    			sampler2D _GrabTex;
    
    			v2f vert (appdata v)
    			{
    				v2f o;
    				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    				UNITY_TRANSFER_FOG(o,o.vertex);
    				return o;
    			}
    			
    			fixed4 frag (v2f i) : SV_Target
    			{
    				// sample the texture
    				fixed4 col = tex2D(_MainTex, i.uv)*_Color;
    				
    				// apply fog
    				UNITY_APPLY_FOG(i.fogCoord, col);	
    				//调整一下uv
    				float2 uv=i.uv;	
    				uv.x=1-uv.x;
    				return col*tex2D(_GrabTex,uv);
    			}
    			ENDCG
    		}
    	}
    }
    

    效果如下:


    三、使用摄像机实现实时反射

    因为GrabPass,相对来说消耗较大,只建议用于一些特殊效果,于是这里就借助辅助摄像机,来实现实时反射效果,当然这需要多写一个脚本,同时需要在辅助摄像机中屏蔽玻璃本身

    shader代码如下:

    Shader "Unlit/CameraGlass"
    {
    	Properties
    	{
    		_MainTex ("Texture", 2D) = "white" {}
    	}
    	SubShader
    	{
    		Tags { "RenderType"="Opaque" }
    		LOD 100
    
    		Pass
    		{
    			CGPROGRAM
    			#pragma vertex vert
    			#pragma fragment frag
    			// make fog work
    			#pragma multi_compile_fog
    			
    			#include "UnityCG.cginc"
    
    			struct appdata
    			{
    				float4 vertex : POSITION;
    				float2 uv : TEXCOORD0;
    			};
    
    			struct v2f
    			{
    				float2 uv : TEXCOORD0;
    				UNITY_FOG_COORDS(1)
    				float4 vertex : SV_POSITION;
    			};
    
    			sampler2D _MainTex;
    			float4 _MainTex_ST;
    
    			v2f vert (appdata v)
    			{
    				v2f o;
    				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
    				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    				UNITY_TRANSFER_FOG(o,o.vertex);
    				return o;
    			}
    			
    			fixed4 frag (v2f i) : SV_Target
    			{
    				// sample the texture  需要调整一下uv
    				fixed4 col = tex2D(_MainTex, 1-i.uv);
    				// apply fog
    				UNITY_APPLY_FOG(i.fogCoord, col);				
    				return col;
    			}
    			ENDCG
    		}
    	}
    }
    

    脚本代码如下:

    using UnityEngine;
    using System.Collections;
    
    public class RenderGlassTexture : MonoBehaviour {
        
        /// <summary>
        /// 辅助摄像机 
        /// 原理:就是将辅助摄像机所看到的内容渲染到玻璃物体上,所以就实现了实时反射的镜面效果
        /// 因为玻璃也是场景中的物体,所以辅助摄像机也会看见他
        /// 所以最好能将玻璃物体单独放在一个层级中,让辅助摄像机不去渲染他
        /// </summary>
        public Camera cam;
        private RenderTexture renderTex;
        /// <summary>
        /// 玻璃shader
        /// </summary>
        public Shader glassShader;
        /// <summary>
        /// 玻璃材质
        /// </summary>
        private Material m_GlassMaterial;
        protected Material GlassMaterial
        {
            get
            {
                if (m_GlassMaterial == null)
                {
                    m_GlassMaterial = new Material(glassShader);
                }
                return m_GlassMaterial;
            }
        }
    
        // Use this for initialization
    	void Start () {
            renderTex = new RenderTexture(Screen.width, Screen.height, 16);
            cam.targetTexture = renderTex;
    	}
    
        //在摄像机开始裁剪场景之前调用
        void OnPreCull()
        {
            GlassMaterial.SetTexture("_MainTex", renderTex);
        }
    
        //在相机完成场景渲染后调用
        void OnPostRender()
        {
            GlassMaterial.SetTexture("_MainTex", null);
        }
    }
    

    效果如下:


  • 相关阅读:
    基于NIO的同步非阻塞编程完整案例,客户端发送请求,服务端获取数据并返回给客户端数据,客户端获取返回数据
    NIO编程中buffer对象的理解以及API的使用
    使用简单工厂模式写一个简单的计算器!!!
    java数字转字符串前面自动补0或者其他数字
    jQuery Validate自定义金钱验证,是否为金额格式,保留两位小数,并支持千分制货币格式
    javade多任务处理之Executors框架(线程池)实现的内置几种方式与两种基本自定义方式
    【转】asp.net mvc webapi+angular.js案例
    【转】MVC5中的区域(Areas)
    【转】在ASP.NET MVC中,使用Bundle来打包压缩js和css
    scroll pagination.js数据重复加载、分页问题
  • 原文地址:https://www.cnblogs.com/liang123/p/6325895.html
Copyright © 2011-2022 走看看