Unity Shader - 实现类似镜面反射、水面扰动效果
前几天,家里出了一些问题,搞得心情很不好,面试我也取消了。
唉,反正那个伤心啊,不过,昨天处理好了。
所以说啊,家和万事兴。
加油加油!!!
所以心情好了,我又写博客了。
另外说一下:图形我今年2019.5才开始正式学习。
所以每个shader效果有些实现方法可能不是很好的,欢迎大神多多指点。
进入主题吧:
今天实现:Unity Shader - 实现类似镜面反射、水面扰动效果
Quad 效果
Cube 效果
思路
平面的过渡效果,可参考我之前写的一个,模型按平面渡效果:Unity Shader - 模型过滤效果
Noise 噪点实现类型水面可参考我之前写的:Unity Shader - Noise 噪点应用,实现类似流水的表面效果
模板缓存来只绘制镜面的内容:Unity Shader - 模板简单测试 - 实现镂空/遮罩、描边
上面两个效果组合,就差不多可以得到上面的效果了。
两个pass现实
第一个pass:绘制镜面模型
将模型的顶点按传进来的平面的法线、任一点,来对本体模型镜面顶点
这样再去绘制,就看起来又镜面的效果了
同时我们在镜像体绘制时,添加了纹理柏林噪点偏移UV,看起来有点像水流效果
但我们的镜面体的显示只能在那个地板模型中才绘制,所以我们给地板shader添加了Stencil处理(Stencil的功能实例看上面链接)
镜面详细讲解一下:
- 首先我们需要将镜面的法线、任意平面点传入shader(*.cs脚本:下面将法线、坐标传入shader我列出来)
- 然后利用平面信息将顶点镜像处理,具体看下图
第二个pass:绘制本体模型
绘制模型本体
但需要处理,上面Unity Shader - 模型过滤效果 的过渡效果,因为超过镜面底下,我们就不显示了(可以按需求来处理)
然后再对纹理UV扰动想水流似的,基本就这样就完了
将法线、坐标传入shader
// jave.lin 2019.08.15
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class UpdateProps : MonoBehaviour
{private static int nHash;private static int pHash;public GameObject obj;public GameObject plane;private Material objMat;// Start is called before the first frame updatevoid Start(){objMat = obj.GetComponent<MeshRenderer>().sharedMaterial;nHash = Shader.PropertyToID("n");pHash = Shader.PropertyToID("p");}// Update is called once per framevoid Update(){// n==normal of plane// p==position of planevar n = plane.transform.up;var p = plane.transform.position;objMat.SetVector(nHash, n);objMat.SetVector(pHash, p);}
}
镜面的模板shader
// jave.lin 2019.08.15
Shader "Test/MirrorGroundStencil"
{Properties{_MainTex ("Texture", 2D) = "white" {}_Color ("Color", Color) = (1,1,1,1)}SubShader{Tags { "Queue"="Geometry+1" "RenderType"="Opaque" }Stencil {Ref 1Comp AlwaysPass Replace}Pass {CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata {float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f {float4 vertex : SV_POSITION;float2 uv : TEXCOORD0;};sampler2D _MainTex;float4 _MainTex_ST;fixed4 _Color;v2f vert (appdata v) {v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);return o;}fixed4 frag (v2f i) : SV_Target {fixed4 col = tex2D(_MainTex, i.uv);return col * _Color;}ENDCG}}
}
需要绘制镜面效果的完整Shader
注释我写的相当详细了
// jave.lin 2019.08.15
Shader "Test/PerlinNoiseMirror" {Properties {[NoScaleOffset] _MainTex ("MainTex", 2D) = "white" {} // 主纹理[NoScaleOffset] _NoiseTex ("NoiseTex", 2D) = "white" {} // 噪点图_NoiseScaleX ("NoiseScaleX", Range(0, 1)) = 0.1 // 水平噪点放大系数_NoiseScaleY ("NoiseScaleY", Range(0, 1)) = 0.1 // 垂直放大系数_NoiseSpeedX ("NoiseSpeedX", Range(0, 10)) = 1 // 水平扰动速度_NoiseSpeedY ("NoiseSpeedY", Range(0, 10)) = 1 // 垂直扰动速度_NoiseBrightOffset ("NoiseBrightOffset", Range(0, 0.9)) = 0.25 // 噪点图整体的数值偏移_NoiseFalloff ("NoiseFalloff", Range(0, 1)) = 1 // 扰动衰减_MirrorRange ("MirrorRange", Range(0, 3)) = 1 // 镜面范围(最大范围,超出该范围就不反射)_MirrorAlpha ("MirrorAlpha", Range(0, 1)) = 1 // 镜面图像不透明度_MirrorFadeAlpha ("_MirrorFadeAlpha", Range(0,1)) = 0.5 // 镜面范围值边缘位置的不透明度,如果调整为0,意思越接近该最大范围的透明就越接近该值:0}CGINCLUDE#include "UnityCG.cginc"#include "Lighting.cginc"#include "AutoLight.cginc"struct appdata {float4 vertex : POSITION;float2 uv : TEXCOORD0;float3 normal : NORMAL;};struct v2f {float4 vertex : SV_POSITION;float2 uv : TEXCOORD0;float3 wPos : TEXCOORD1;};struct v2f_m {float4 vertex : SV_POSITION;float2 uv : TEXCOORD0;float4 normal : TEXCOORD1;float4 wPos : TEXCOORD2;};sampler2D _MainTex;sampler2D _NoiseTex;fixed _NoiseScaleX, _NoiseScaleY;fixed _NoiseSpeedX, _NoiseSpeedY;fixed _NoiseBrightOffset;fixed _NoiseFalloff;float _MirrorRange, _MirrorAlpha, _MirrorFadeAlpha;float3 n, p; // 镜面法线,镜面任意点v2f vert_normal (appdata v) {v2f o;o.wPos = mul(unity_ObjectToWorld, v.vertex).xyz;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.uv;return o;}fixed4 frag_normal (v2f i) : SV_Target {float3 dir = i.wPos.xyz - p; // 平面与插值点的指向half d = dot(dir, n); // 与反向镜面的距离if (d < 0) discard; // 如果平面背面,那就丢弃return tex2D(_MainTex, i.uv);}v2f_m vert_mirror (appdata v) {v2f_m o;o.wPos = mul(unity_ObjectToWorld, v.vertex);float3 nn = -n; // 法线反向float3 dp = o.wPos.xyz - p; // 平面点与世界空间的点的向量(即:从平面的点指向世界空间点的方向)half nd = dot(n, dp); // 计算出点与平面的垂直距离o.wPos.xyz += nn * (nd * 2); // 将垂直距离反向2倍的距离,就是镜像的位置o.vertex = mul(unity_MatrixVP, o.wPos);o.normal.xyz = UnityObjectToWorldNormal(v.normal);fixed t = nd / _MirrorRange; // 将位置与镜面最大范围比利作为fade alpha的插值系数fixed a = lerp(_MirrorAlpha, _MirrorAlpha * _MirrorFadeAlpha, t);o.normal.w = a; // 透明度我们存于o.normal.wo.wPos.w = nd; // 距离存于o.wPos.wo.uv = v.uv;return o;}fixed4 frag_mirror (v2f_m i) : SV_Target {if (i.wPos.w > _MirrorRange) discard; // 超过镜像范围也丢弃if (i.normal.w <= 0) discard; // 透明度为0丢弃float3 dir = i.wPos.xyz - p; // 平面与插值点的指向half d = dot(dir, n); // 与反向镜面的距离if (d > 0) discard; // 如果超过了平面,那就丢弃fixed2 ouvxy = fixed2( // 噪点图采样,用于主纹理的UV偏移的tex2D(_NoiseTex, i.uv + fixed2(_Time.x * _NoiseSpeedX, 0)).r,tex2D(_NoiseTex, i.uv + fixed2(0, _Time.x * _NoiseSpeedY)).r);ouvxy -= _NoiseBrightOffset; // 0~1 to ==> -_NoiseBrightOffset~ 1 - _NoiseBrightOffsetouvxy *= fixed2(_NoiseScaleX, _NoiseScaleY); // 扰动放大系数float scale = i.wPos.w / _MirrorRange; // 用距离来作为扰动衰减scale = lerp(scale, 1, (1 - _NoiseFalloff)); // 距离越近扰动越是衰减(即:与镜面距离越近,基本是不扰动的,所以我们可以看到边缘与镜面的像素是吻合的)ouvxy *= scale;fixed4 col = tex2D(_MainTex, i.uv + ouvxy); // 加上扰动UV后再采样主纹理return fixed4(col.rgb, i.normal.w);}ENDCGSubShader {Tags { "Queue"="Geometry+2" "RenderType"="Opaque" }Pass {Cull frontZTest AlwaysZWrite OffBlend SrcAlpha OneMinusSrcAlphaStencil {Ref 1Comp Equal}CGPROGRAM#pragma vertex vert_mirror#pragma fragment frag_mirrorENDCG}Pass {CGPROGRAM#pragma vertex vert_normal#pragma fragment frag_normalENDCG}}
}
Source Project
TestShaderToy_NoiseAndMirror 提取码: j1kh 复制这段内容后打开百度网盘手机App,操作更方便哦
打开:PerlinNoiseMirror.unity 场景即可
(今天要去探亲,我就过几天再回来学习shader,然后再博客)
Unity Shader - 实现类似镜面反射、水面扰动效果相关推荐
- 着色器编程_unity中的基础纹理,使用Unity Shader实现基础纹理的渲染效果
学习通过使用Unity Shader实现基础纹理的渲染效果 目录 学习通过使用Unity Shader实现基础纹理的渲染效果 问1:详细描述一下漫反射纹理.高度纹理.法线纹理.渐变纹理和遮罩纹理? 问 ...
- Unity Shader深度相关知识总结与效果实现
鸣谢:puppet_master (VIA CSDN)贡献此文 前言 前言废话依旧比较多,感觉我是个写游戏体验评测的,233.最近想起了<恶灵附身>这款游戏的几个效果: <恶灵附身& ...
- 如何用Unity Shader制作类似《炉石传说》卡牌的动态效果?
此篇为鄙人在卡牌项目中,尝试模仿<炉石传说>卡面特效所制作的特效Shader总结回顾,几经修改,最终成为了现在的样子,因为使用简单,效果明显,虽然距离<炉石传说>的卡面特效还有 ...
- Unity Shader 实现简单的压扁效果
有点累啊,一个CoverMap搞了一周多,还是太嫩了,还有好多东西等着我去学呢,今天就写个简单的东西吧--一个把模型压扁的效果,参考博客Unity Shader - 一些玩具Shader.话不多说,先 ...
- Unity Shader学习案例一: 流光效果
Unity Shader Lab新手宝典简单Shader案例一:流光效果 + 相关基础知识说明 Shader "Samples/Light Flow"//shader名称 {Pro ...
- Unity Shader学习笔记/Urp/水墨风效果
实现简易的水墨风效果大致分为三部分: 1.将原始的rgb贴图转化为灰度图 float4 baseMap = SAMPLE_TEXTURE2D(_BaseMap, sampler_BaseMap, IN ...
- Unity Shader实现PPT 30多种切换效果
目录 原文 效果 Unity代码 00基础工具 Tools.cginc 01Fade 淡入淡出 02Push 推入 03Fade 擦除 04Split 分割 Unity工程 原文 原文 是用 GLSL ...
- unity shader 入门 全透明与半透明效果实现
片元函数的fixed4类型的返回值的第4位即为阿尔法值,0代表完全不显示(透明),1代表完全显示.中间的数值代表半透明.但只修改这个值是不能直接修改透明度的,因为还要对队列等进行修改. 本文介绍透明度 ...
- 【Unity Shader】渲染纹理实现镜子效果
1 基本概念 1.1 什么是渲染到纹理? 全称是Render To Texture,<入门精要>好像又把渲染目标纹理,即Render Target Texture也叫做RTT,但我认为&l ...
最新文章
- physx选择显卡还是cpu_工控机如何选购cpu,工控机cpu选择盒装好还是散装好
- 如何设置采购收货直接转到供应商库存?
- spring aop切面中获取代理bean的名字以及bean
- 初识前端——个人总结
- 以太网交换机与路由—Vecloud微云
- 技术开发人员适应其他部门提需求的一个经验
- QEventLoop的简单使用(一)
- Linux下最简单的修改文件名后缀的命令行技巧
- 揭秘 | 小米最新款12PRO智能动态刷新率技术原理
- Cloud一分钟 | Gartner发布2018年第二季度全球服务器市场报告;中信银行联合腾讯云推出手机银行智能语音产品...
- ArcGIS Engine开发:框架/结构+对象库
- 查看tensor的形状,行列大小
- php drive mssql,wamp下对MS SQLSERVER的连接配置,PHP+THINKPHP5通过
- [面试] 算法(七)—— 逆序输出链表
- Redis 6.0 源码阅读笔记(2) -- Redis 多线程原理
- C6678/C6657+ZYNQ/K7/A7 FPGA+AD+北斗的软硬件设计方案
- 手机PDF文档如何解密去除不能编辑的限制?
- Protobuf使用手册--中文版
- Zookeeper数据同步流程
- 噪音分贝测试软件在线,分贝测试(在线分贝测试仪)
热门文章
- Arcgis --- 坡向批处理
- 差分——(2)二维差分
- ardupilot更新油门组合值
- 一体化闸门控制机如何使用
- springsecurity投票器
- 鸿蒙手机如何录屏,安卓手机如何屏幕录制视屏?手机视频录制方法
- LVM逻辑卷组的管理
- (Loadrunner)Abnormal termination, caused by mdrv process termination.(转)
- 又谈SQL-to-SQL翻译器
- java application.xml_第4章 零XML配置的Spring Boot Application