Unity Shader学习:SSR屏幕空间反射

本文在前向渲染模式下实现,延迟渲染更适合SSR,这里只简单的实现下,未作更深入的优化。

思路:沿视线和法线的反射向量步进光线,判断打到物体(这里用的是深度比较),采样这个点物体的颜色作为反射的颜色,使用dither进行了优化和模糊。

原文:https://blog.csdn.net/puppet_master/article/details/80808486



c#部分:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SSR : MonoBehaviour {public Material mat;private Camera cam;[Range(0,1000f)]public float maxRayMarchingDistance = 500f;[Range(0,256)]public int maxRayMarchingStep = 64;[Range(0,2f)]public float rayMarchingStepSize = 0.05f;[Range(0,2f)]public float depthThickness = 0.01f;[Range(0,3)]public int downSample = 1;[Range(0f,3f)]public int samplerScale = 1;private void OnEnable(){cam.depthTextureMode = DepthTextureMode.DepthNormals;}private void Awake (){cam = GetComponent<Camera>();}private void Start(){mat.SetTexture("_DitherMap", GenerateDitherMap());}private void OnRenderImage(RenderTexture source, RenderTexture destination){if (mat){int width = source.width >> downSample;int height = source.height >> downSample;mat.SetFloat("_MaxRayMarchingDistance", maxRayMarchingDistance);mat.SetInt("_MaxRayMarchingStep", maxRayMarchingStep);mat.SetFloat("_RayMarchingStepSize", rayMarchingStepSize);mat.SetFloat("_DepthThickness", depthThickness);//得到光线追踪的反射图RenderTexture reflectRT = RenderTexture.GetTemporary(width, height, 0, source.format);RenderTexture tempBlurRT = RenderTexture.GetTemporary(width, height, 0, source.format);Graphics.Blit(source, reflectRT, mat, 0);//对反射图高斯模糊mat.SetVector("_Offsets", new Vector4(0, samplerScale, 0, 0));Graphics.Blit(reflectRT, tempBlurRT, mat, 1);mat.SetVector("_Offsets", new Vector4(samplerScale, 0, 0, 0));Graphics.Blit(tempBlurRT, reflectRT, mat, 1);//合并mat.SetTexture("_ReflectTex", reflectRT);            Graphics.Blit(source, destination, mat, 2);RenderTexture.ReleaseTemporary(reflectRT);RenderTexture.ReleaseTemporary(tempBlurRT);}}//游骑兵工作室的DitherMapprivate Texture2D GenerateDitherMap(){int texSize = 4;Texture2D ditherMap = new Texture2D(texSize, texSize, TextureFormat.Alpha8, false, true);ditherMap.filterMode = FilterMode.Point;Color32[] colors = new Color32[texSize * texSize];colors[0] = GetDitherColor(0.0f);colors[1] = GetDitherColor(8.0f);colors[2] = GetDitherColor(2.0f);colors[3] = GetDitherColor(10.0f);colors[4] = GetDitherColor(12.0f);colors[5] = GetDitherColor(4.0f);colors[6] = GetDitherColor(14.0f);colors[7] = GetDitherColor(6.0f);colors[8] = GetDitherColor(3.0f);colors[9] = GetDitherColor(11.0f);colors[10] = GetDitherColor(1.0f);colors[11] = GetDitherColor(9.0f);colors[12] = GetDitherColor(15.0f);colors[13] = GetDitherColor(7.0f);colors[14] = GetDitherColor(13.0f);colors[15] = GetDitherColor(5.0f);ditherMap.SetPixels32(colors);ditherMap.Apply();return ditherMap;}private Color32 GetDitherColor(float value){byte byteValue = (byte)(value / 16.0f * 255);return new Color32(byteValue, byteValue, byteValue, byteValue);}
}

shader部分:

Shader "Unlit/SSR"
{Properties{_MainTex ("Texture", 2D) = "white" {}}SubShader{//1.reflectPass{ZTest OffZWrite OffCull OffCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;               };struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;float3 viewRay:TEXCOORD1;};sampler2D _MainTex;float4 _MainTex_ST;sampler2D _DitherMap;float _MaxRayMarchingDistance;float _MaxRayMarchingStep;float _RayMarchingStepSize;float _DepthThickness;sampler2D _CameraDepthNormalsTexture;bool checkDepthCollision(float3 viewPos,out float2 screenPos) {float4 clipPos = mul(unity_CameraProjection, float4(viewPos, 1.0));clipPos = clipPos / clipPos.w;screenPos = float2(clipPos.x*0.5 + 0.5, clipPos.y*0.5 + 0.5);float4 depthNormalTex = tex2Dlod(_CameraDepthNormalsTexture, float4(screenPos,0,0));//解码深度图,得到视空间深度float depth = DecodeFloatRG(depthNormalTex.zw)*_ProjectionParams.z+0.2;//防止远近裁面的闪动,原因暂时未知//判断当前反射点是否在屏幕外或超过了当前深度值//只取距离视空间深度附近的采样点,防止采样到背面在屏幕上没颜色的点return screenPos.x > 0.0 && screenPos.y > 0.0 && screenPos.x < 1.0 && screenPos.y < 1.0 && -viewPos.z >=depth&&depth+_DepthThickness>=-viewPos.z ;}bool viewSpaceRayMarching(float3 rayOri, float3 rayDir, out float2 hitScreenPos,float2 ditherUV) {//dither扰动采样点float2 offsetUV = fmod(floor(ditherUV), 4.0);float ditherValue = tex2D(_DitherMap, offsetUV*0.25).a;rayOri += ditherValue * rayDir;int maxStep = _MaxRayMarchingStep;hitScreenPos = float2(0, 0);UNITY_LOOPfor (int i = 0; i < maxStep; i++){float3 currentPos = rayOri + rayDir * _RayMarchingStepSize*i;if (_RayMarchingStepSize*i >_MaxRayMarchingDistance){return false;}//反射前进点超出深度,表示打到了物体if (checkDepthCollision(currentPos, hitScreenPos)) {        return true;}}return false;}v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);float4 clipPos = float4(v.uv * 2 - 1.0, 1.0, 1.0);float4 viewRay = mul(unity_CameraInvProjection, clipPos);o.viewRay = viewRay.xyz / viewRay.w;return o;}fixed4 frag (v2f i) : SV_Target{float linear01Depth;float3 viewNormal;float4 cdn = tex2D(_CameraDepthNormalsTexture, i.uv);DecodeDepthNormal(cdn, linear01Depth, viewNormal);float3 viewPos = linear01Depth * i.viewRay;float3 viewDir = normalize(viewPos);viewNormal = normalize(viewNormal);float3 reflectDir = reflect(viewDir, viewNormal);float2 hitScreenPos = float2(0, 0);float4 reflectTex = float4(0, 0, 0, 0);if (viewSpaceRayMarching(viewPos,reflectDir,hitScreenPos,i.vertex.xy)){reflectTex = tex2D(_MainTex, hitScreenPos);}return float4(reflectTex);}ENDCG}//2.blurPass{ZTest OffZWrite OffCull OffCGPROGRAM#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;float4 uv01 : TEXCOORD1;float4 uv23 : TEXCOORD2;float4 uv45 : TEXCOORD3;};sampler2D _MainTex;float4 _MainTex_TexelSize;float4 _Offsets;v2f vert(appdata v) {v2f o;_Offsets *= _MainTex_TexelSize.xyxy;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.uv;o.uv01 = v.uv.xyxy + _Offsets.xyxy*float4(1, 1, -1, -1);o.uv23 = v.uv.xyxy + _Offsets.xyxy*float4(1, 1, -1, -1)*2.0;o.uv45 = v.uv.xyxy + _Offsets.xyxy*float4(1, 1, -1, -1)*3.0;return o;}float4 frag(v2f i) :SV_Target{float4 color = float4(0,0,0,0);color += 0.40*tex2D(_MainTex, i.uv);color += 0.15*tex2D(_MainTex, i.uv01.xy);color += 0.15*tex2D(_MainTex, i.uv01.zw);color += 0.10*tex2D(_MainTex, i.uv23.xy);color += 0.10*tex2D(_MainTex, i.uv23.zw);color += 0.05*tex2D(_MainTex, i.uv45.xy);color += 0.05*tex2D(_MainTex, i.uv45.zw);return color;}ENDCG}//3.combinePass{ZTest OffZWrite OffCull OffCGPROGRAM#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;sampler2D _ReflectTex;v2f vert(appdata v) {v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = v.uv;return o;}float4 frag(v2f i) :SV_Target{float4 ori = tex2D(_MainTex,i.uv);float4 reflect = tex2D(_ReflectTex, i.uv);return ori+reflect;}ENDCG}}
}

Unity Shader学习:SSR屏幕空间反射相关推荐

  1. Unity shader学习之屏幕后期处理效果之高斯模糊

    高斯模糊,见 百度百科. 也使用卷积来实现,每个卷积元素的公式为: 其中б是标准方差,一般取值为1. x和y分别对应当前位置到卷积中心的整数距离. 由于需要对高斯核中的权重进行归一化,即使所有权重相加 ...

  2. Unity Shader学习:SSAO屏幕环境光遮蔽

    Unity Shader学习:SSAO屏幕环境光遮蔽 主要思路:1.随机采样像素法线半球周围的像素,平均对比与该像素深度是否处在暗处.2.双边滤波去噪点.3.后期AO图与原图混合. 原文链接:http ...

  3. Unity Shader 学习笔记(33) 全局光照(GI)、反射探针、线性空间和伽马空间、高动态范围(HDR)

    Unity Shader 学习笔记(33) 全局光照(GI).反射探针.线性空间和伽马空间.高动态范围(HDR) 参考书籍:<Unity Shader 入门精要> [<Real-Ti ...

  4. Unity Shader学习:动态模糊(shutter angle方式)

    Unity Shader学习:动态模糊 动态模糊一般有帧混合和motion vector两种,这里主要介绍motion vector的方法. Keijiro源码:https://github.com/ ...

  5. Unity Shader学习:水墨效果

    Unity Shader学习:水墨效果 偶然在网上看到9级铁甲蛹大神的水墨风格后处理觉得挺有意思,参照着实现一下,还是涉及到之前油画效果的算法,叫什么滤波暂时不清楚,应该用来处理手绘效果挺多的. 水墨 ...

  6. 《Unity Shader入门精要》学习笔记第5章 开始Unity Shader学习之旅

    本文章用于帮助自己学习,因此只记录一些个人认为比较重要或者还不够熟悉的内容. 原作者:http://blog.csdn.net/candycat1992/article/ 第五章 开始Unity Sh ...

  7. Unity Shader学习:动态雾

    Unity Shader学习:动态雾 先将相机近裁面四个角向量传给shader,再通过观察空间下的深度值和相机位置算出像素在世界坐标系的位置,通过世界空间高度值来设定雾的范围和浓度,然后通过噪声和uv ...

  8. Unity Shader学习:油画效果

    Unity Shader学习:油画效果 油画效果在学习浅墨大神的文章时看到的比较有趣,但是原文中也没详细的算法介绍如何实现,这里就先直接拿来用吧,UI和屏幕后处理都可以用,算法也看的不是很明白,好像是 ...

  9. Unity Shader学习-高光反射

    Unity Shader学习-高光反射 高光反射计算公式 高光反射 = 光源的色彩和强度 * 材质的高光反射系数 * pow(max(0,视角方向 · 反射方向),_Gloss) 视角方向 = ref ...

最新文章

  1. 博客园的“随笔、文章、新闻、日记有啥区别”
  2. Centos7 修改运行级别
  3. 基于SSM实现学籍管理系统
  4. lighttpd配置支持https
  5. JAVA传递子类参数,在Java中,是否可以通过传递超类方法中使用的参数的子类来覆盖方法?...
  6. MySQL里的wait_timeout
  7. sftp服务器同步文件到本地,服务器之间通过sftp的方式同步文件,并入库到本地数据的表中...
  8. matlab 分号;_MATLAB使用教程(二)—新手来看
  9. spring整合中application.xml配置
  10. 支付宝核心工程师谈如何成为一名优秀的程序员?
  11. Atiitt 使用java语言编写sql函数或存储过程
  12. 计算机在酒店与应用中的展望,对酒店计算机信息管理系统的分析与展望
  13. 淘宝API店铺所有商品接口价格、标题、销量参数调用示例
  14. 【CF #797 Div3】A-E
  15. Android 仿微信通讯录 导航分组列表-上】使用ItemDecoration为RecyclerView打造带悬停头部的分组列表
  16. 机器人手眼标定 (四轴六轴都适用)
  17. Redisson的看门狗watchDog机制是怎么实现的?
  18. 实时语义分割网络 BiSeNet(附代码解读)
  19. 根据LocalDate或者DateUtils计算两个日期之间的天数差
  20. (附源码)Springboot税收风险管理系统 毕业设计 231058

热门文章

  1. BEV感知:BEV开山之作LSS(lift,splat,shoot)原理代码串讲
  2. 旅游网站建站用什么系统好?
  3. PLM系统如何帮企业提升能力
  4. Away3D:《Flash 3D基础向导》已出版
  5. 3分钟让你轻松了解CRM 1
  6. (转)了解一下,各种图片格式的区别
  7. python语言基本排序算法_排序算法(Python)
  8. 【python和机器学习入门2】决策树3——使用决策树预测隐形眼镜类型
  9. 关于用友的CELL控件
  10. CS244W: Machine Learning with Graphs (3) ——网络中的Motifs和结构