写在前面:写shader写累了就写写博客吧,每天都是充满bug的一天> <
使用版本:Unity3D 2019.4 (LTS) (LTS意思是长期支持,尽量选择LTS版本,兼容性比较好)

效果示意

Inspector

Glass


注:所有Texture均来自冯乐乐《UnityShader入门精要》项目配套源码1

代码示意

Glass.shader1

Shader "Glass"
{Properties{_BumpMap("Normal Map",2D) = "bump"{}        _Distortion("Distortion",range(0,100)) = 10//折射系数_RefractAmount("Refract Amount",range(0,1)) = 1[KeywordEnum(Cubemap, MatCap)] _Reflect("Reflect", Float) = 0_Cubemap("Environment Map",cube) = "_Skybox"{}}SubShader{Tags { "RenderType" = "Opaque" "Queue" = "Transparent" "LightMode" = "Always"}// GrabPass{"_RefractionTex"}Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile _REFLECT_CUBEMAP _REFLECT_MATCAP#include "UnityCG.cginc"#include "Lighting.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;float3 normal:NORMAL;float4 tangent:TANGENT;};struct v2f{float2 uv : TEXCOORD0;float4 pos : SV_POSITION;float4 scrPos : TEXCOORD4;float4 TtoW0:TEXCOORD1;float4 TtoW1:TEXCOORD2;float4 TtoW2:TEXCOORD3;};sampler2D _BumpMap;float4 _BumpMap_ST;samplerCUBE _Cubemap;float _Distortion;fixed _RefractAmount;sampler2D _RefractionTex;float4 _RefractionTex_TexelSize;v2f vert(appdata v){v2f o;o.pos = UnityObjectToClipPos(v.vertex);// o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);o.uv = TRANSFORM_TEX(v.uv, _BumpMap);//得到屏幕采样坐标o.scrPos = ComputeGrabScreenPos(o.pos);float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;float3 worldNormal = UnityObjectToWorldNormal(v.normal);float3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);float3 worldBinormal = cross(worldTangent, worldNormal) * v.tangent.w;o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);return o;}fixed4 frag(v2f i) : SV_Target{float3 worldPos = float3(i.TtoW0.w,i.TtoW1.w,i.TtoW2.w);float3x3 TtoW = float3x3(i.TtoW0.xyz, i.TtoW1.xyz, i.TtoW2.xyz);fixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(worldPos));fixed3 tanNormal = UnpackNormal(tex2D(_BumpMap, i.uv));fixed3 worldNormal = mul(TtoW, tanNormal);float3 viewNormal = mul((float3x3)UNITY_MATRIX_V, worldNormal);float2 offset = tanNormal.xy * _Distortion * _RefractionTex_TexelSize.xy;i.scrPos.xy += offset;fixed3 refractCol = tex2Dproj(_RefractionTex, i.scrPos).xyz;fixed3 reflectDir = reflect(-worldViewDir, worldNormal);fixed4 cubemapCol = texCUBE(_Cubemap, reflectDir);fixed4 matcapLookup = tex2D(_RefractionTex, viewNormal.xy * 0.5 + 0.5);fixed3 reflectCol;#if _REFLECT_CUBEMAPreflectCol = cubemapCol.rgb;#elif _REFLECT_MATCAPreflectCol = matcapLookup.rgb;#endiffixed3 color = refractCol * _RefractAmount + reflectCol * (1 - _RefractAmount);return fixed4(color,1.0);}ENDCG}}
}

CommandBufferBlurRefraction.cs2

using UnityEngine;
using UnityEngine.Rendering;
using System.Collections.Generic;[ExecuteInEditMode]
public class CommandBufferBlurRefraction : MonoBehaviour
{private Camera m_Cam;// private Dictionary<Camera, CommandBuffer> m_Cameras = new Dictionary<Camera, CommandBuffer>();public void OnWillRenderObject(){var cam = Camera.current;if (!cam)return;cam.RemoveAllCommandBuffers();CommandBuffer buf = null;buf = new CommandBuffer();buf.name = "Grab screen and blur";//新建一张纹理,得到对应的纹理IDint screenCopyID = Shader.PropertyToID("_RefractionTex");//初始化这张纹理,其中纹理的大小为摄像机视野大小buf.GetTemporaryRT(screenCopyID, -1, -1, 0, FilterMode.Bilinear);//将当前的渲染目标纹理拷贝到你的纹理上buf.Blit(BuiltinRenderTextureType.CurrentActive, screenCopyID);buf.SetGlobalTexture("_RefractionTex", screenCopyID);buf.ReleaseTemporaryRT(screenCopyID);cam.AddCommandBuffer(CameraEvent.AfterSkybox, buf);}
}

知识点

Unity Shader自定义材质面板的小技巧3

适用场景

仅仅想在材质面板里定义少数变量,不想多写一个C#函数从头自定义材质面板的时候。

提到的drawer

//in Properties
[KeywordEnum(Cubemap, MatCap)] _Reflect("Reflect", Float) = 1……//in Pass
#pragma multi_compile _REFLECT_CUBEMAP _REFLECT_MATCAP//in frag
#if _REFLECT_CUBEMAP
reflectCol = cubemapCol.rgb;#elif _REFLECT_MATCAP
reflectCol = matcapLookup.rgb * cubemapCol.rgb;#endif

Unity官方文档原文:

KeywordEnum allows you to choose which of a set of shader keywords to enable. It displays a float as a popup menu, and the value of the float determines which shader keyword Unity enables. Unity enables a shader keyword with the name . Up to 9 names can be provided.(uppercase property name)_(uppercase enum value name)

大意就是,这个drawer画了一个选项框,最多支持9个选项,并且可以用浮点数初始化选项。浮点数默认从零开始。
在Properties中初始化后,我们还要在Pass中引入选项,这样才能在后文中定义选择该选项时Shader的行为,具体格式如上。
在本shader中,我在片元着色器上使用#if和#elif来控制选择不同选项时shader的不同行为。最后记得#endif,不然会出现Syntax Error。

使用CommandBuffer来抓取RT

原本我是使用了GrabPass,但这个在实际项目中是禁止使用的。换成了CommandBuffer后效果也是一样的。参考的CommandBuffer功能太多,在帮助之下删成了上文那个样子o> <o
捋一下思路就是,获取相机->清除相机buffer->新建一个临时纹理并初始化,将抓到的贴图装进去->拷贝临时纹理到指定纹理上->新建相机缓冲区并载入->清除临时纹理
这时候就有人问了,如果不载入指定纹理会发生什么呢?我也不知道qaq,试了一下效果都是一样的。

Matcap(未完待续)

关于Shader,Cubemap的部分在《UnityShader入门精要》中有详细讲解,这里不再复述,主要是Matcap的部分,作为第一次接触的方法,详细了解一下。
我对Matcap的理解是,它其实就是一种采样方式,根据法线的xy分量在贴图中选取对应的点来渲染。注意要把法线从模型空间转移到观察空间,再取观察空间中法线的xy分量进行计算。如果使用法线贴图的话,流程就是切线空间->模型空间->观察空间,代码如下:

fixed3 tanNormal = UnpackNormal(tex2D(_BumpMap, i.uv));
fixed3 worldNormal = mul(TtoW, tanNormal);
float3 viewNormal = mul((float3x3)UNITY_MATRIX_V, worldNormal);

Matcap的采样方式如下,之所以viewNormal.xy * 0.5 + 0.5是为了将法线分量范围从[-1,1]转换为[0,1],也就是uv坐标的范围。

fixed4 matcapLookup = tex2D(_RefractionTex, viewNormal.xy * 0.5 + 0.5);

当然,我的代码还是有问题的,问题在于Mapcap如果是用的长方体的话,法线在同一个面是相同的,只能采样到同一个位置,看起来就是纯色的,所以需要用到曲率,但我现在还没有时间,等到有时间了再更新~先mark一个解决办法在这里。

结束语:居然写了三个小时……一边写一边捋思路真的太难了。有空把之前写过的也捋一下吧,不然真的会忘qaq


  1. https://github.com/candycat1992/Unity_Shaders_Book ↩︎ ↩︎

  2. https://blog.csdn.net/Jaihk662/article/details/113780524 ↩︎

  3. https://blog.csdn.net/candycat1992/article/details/51417965 ↩︎

【UnityShader】使用Cubemap/Matcap制作玻璃相关推荐

  1. CityEngine制作玻璃材质反光效果

    当我们走在城市的大街上,经常会看到很多栋写字楼,其外墙大多都是玻璃材质的,使得建筑更有质感.在本文中,我们利用CityEngine实现玻璃材质反光效果.首先,需要确定做什么样的效果?一是玻璃效果(即透 ...

  2. PhotoShop教程:制作玻璃水晶质感文字

    最终效果图: 现在开始分析制作步骤吧! 1.新建文档 600x800px  如图: 先选定颜色,把前景色和背景色设置好,如图 2.背景效果达到我提供的效果或接近都可以 3.接下来,我们要用到笔刷: 喷 ...

  3. ps制作玻璃效果(整体透明且上为白色半透明下为无色透明)的PNG格式背景图片

    1.首先 ctrl+n新建图层,图层大小此时举例宽设置为 50px 高100px ," 背景内容" 选择" 透明"  ,单击" 确定" 2. ...

  4. Unity-shader学习笔记(七)

    文章目录 Unity-shader学习笔记(七) 15 更复杂的光照 15.1 Unity的渲染路径 15.1.1 前向渲染路径 15.1.1.1 前向渲染路径的原理 15.1.1.2 Unity中的 ...

  5. Unity Shader 入门精要——镜面效果、玻璃效果

    渲染纹理 在之前的学习中,一个摄像机的渲染结果会输出到颜色缓冲中,并显示到我们的屏幕上.现代的GPU允许我们把整个三维场景渲染到一个中间缓冲中,即渲染目标纹理(RenderTarget Texture ...

  6. 3ds Max制作客厅场景实例教程

    附件系列 (图01) 让我们回顾一下场景:一个房间包括下列一件件家具, 在中间的一张小桌子,在房间的角落的一个小桌子,有一个垃圾桶和一个带镜子的边桌,有一个烛台.还有一个挂钟,窗帘,沙发和带手臂的椅子 ...

  7. 3D建模教程讲解!PBR场景制作破损的图书馆

    今天给大家带来3D建模教程分享!PBR场景制作破损的图书馆,一起来看下吧! 它是一个图书馆场景的制作.我会按照我的思路来介绍一下这个场景是怎么完成的,希望大家喜欢! 这个场景使用PBR流程完成,使用3 ...

  8. 水晶图标制作方法(转载)

        找了好多,终于找了个简单易学的.嘿嘿,很实用,特别是对我这种美工不好的人来说!不废话了! 实际上玻璃质感的小图标制作起来十分快捷,基本上用不上什么技法 ,善用你的图层属性就可以达到效果,估计看 ...

  9. 漂亮的水晶图标制作方法

    漂亮的水晶图标制作方法[@more@] 实际上玻璃透明质感的小图标制作起来十分快捷,基本上用不上什么技法 ,善用你的图层属性就可以达到效果,估计看完这篇教程后就会十分轻松的制作玻璃感小图标甚至大幅图片 ...

  10. (十六)unity shader之——————高级纹理之渲染纹理(镜子、玻璃效果)

    在之前的学习中,一个摄像机的渲染结果会输出到颜色缓冲中,并显示到我们的屏幕上.现在的GPU允许我们把整个三维场景渲染到一个中间缓冲中,即渲染目标纹理(Render Target Texture,RTT ...

最新文章

  1. 【点云StatisticalOutlierFilter】python-pcl:去除离群点
  2. 深度学习也利用进化论!李飞飞谈创建具身智能体,学动物进化法则
  3. 吴恩达机器学习笔记 —— 16 异常点检测
  4. python工作好找吗-Python好找工作吗 不看会后悔
  5. 21-Heartbeat配置文件authkey重要参数讲解
  6. 字符串匹配算法(三):KMP(KnuthMorrisPratt)算法
  7. C语言万年历 年历月历日历都要,c语言万年历
  8. 重学ASP.NET Core 中的标记帮助程序
  9. 深度解读「无影云电脑远程办公解决方案」
  10. HTML5 新特性
  11. thread.sleep是让哪个线程休眠_java多线程必看:java线程的生命周期
  12. jQuery EasyUI -ComboBox(下拉列表框)使用
  13. 使用Kmeans聚类分析对复杂的数据进行分类
  14. oracle 导入文件 年月日,oracle导入文件时,日期格式问题
  15. 【HDU 5033】【经典单调栈问题】Building
  16. 关于APP测试用例点
  17. 标签打印软件如何输出双面打印的文档
  18. 唱响艾泽拉斯_情感篇
  19. win10怎么显示文件后缀_win10系统中使用win7照片查看器(无需下载安装)
  20. Scala中的集合排序总结

热门文章

  1. 1688淘口令链接API接口-item_password-获得淘口令真实url 接口,淘口令API接口
  2. 浩辰云建筑2021功能详细介绍
  3. Qt开发技术:Qt绘图系统(二)QPainter详解
  4. YourTTS论文阅读
  5. Chrome最新版下载地址
  6. Android Native报错定位(addr2line工具的使用)
  7. 网络攻防|一次实战中的向日葵 RCE Bypass 360
  8. 深度学习:鞍点与海森矩阵的问题
  9. 翁凯java进阶_翁凯-----java课程入门与进阶1
  10. 安卓中将Java文件转换成Dex文件