本篇文章我会介绍一下我自己在Unity中实现的SSR效果

出发点是理解SSR效果的原理,因此最终效果不是非常完美的(代码都是够用就行),但是从学习的角度来说足以学习到SSR中的核心算法。

如果对核心算法没有兴趣,可以直接使用Unity官方的PostProcessing库,其中包含了一个SSR效果。(其实现来自于casual effects)

参考资料:

https://github.com/Unity-Technologies/PostProcessing

http://www.kode80.com/blog/2015/03/11/screen-space-reflections-in-unity-5/

http://casual-effects.blogspot.com/2014/08/screen-space-ray-tracing.html

完成的工程:

https://github.com/yangrc1234/ScreenSpaceReflection

目前只在2017.1、DirectX下实现,没有进行其他测试。除非以后有需求,否则可能不会更新这个repo,毕竟官方已经有解决方案了,没必要重复造轮子。这个repo用于学习目的就行了。

一些shader的宏、变量可能是2017.1才有的,如果老版本编译不过欢迎提issue。

第一部分包含屏幕空间反射的定义、以及一个最初步的实现。

屏幕空间反射

屏幕空间反射是一个后处理效果。通过对屏幕空间的画面,按一定方式投射光线,采样光线路径上的像素,得到一个点上的反射颜色。

比如说,对于一个像素A,我们去计算它的反射。要计算反射,我们必须要知道视线方向和该点的空间位置以及的法线方向,从而计算出光线的方向。

视线方向好说,空间位置,我们可以从深度贴图中还原出来。法线方向意味着屏幕空间反射只能在Deferred Rendering下进行。在Deferred Rendering下我们可以轻松的从GBuffer中得到一个点的法线方向。

获取这些信息后,我们就可以开始投射光线了。每次光线步进,我们都将当前位置的点再投影到屏幕空间上,去采样屏幕上的像素。如果我们计算得到(如何计算等下再说)该像素是光线路径上的一点,我们就可以将该点返回作为结果了。

以下是实际代码:

    [ImageEffectOpaque]
private void OnRenderImage(RenderTexture source, RenderTexture destination) {
mat.SetTexture("_BackfaceTex", GetBackfaceTexture());
mat.SetMatrix("_WorldToView", GetComponent<Camera>().worldToCameraMatrix); //emmmmm不知道为什么UNITY_MATRIX_V在这里变成了一个单位矩阵。需要手动设置world to view的矩阵。
Graphics.Blit(source, destination, mat,0);
}
			v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
float4 cameraRay = float4(v.uv * 2.0 - 1.0, 1.0, 1.0); //作为一个后期特效,我们可以通过uv坐标,来获得相机光线方向。注意坐标z为1.0,这里的cameraRay是从原点到far clip plane的光线
cameraRay = mul(unity_CameraInvProjection, cameraRay); //将相机光线从clip space转移到view space
o.csRay = cameraRay / cameraRay.w;
return o;
} fixed4 frag (v2f i) : SV_Target
{
float decodedDepth = Linear01Depth(tex2D(_CameraDepthTexture, i.uv).r);
float3 csRayOrigin = decodedDepth * i.csRay; //因为i.csRay是指着far clip plane的光线,此时csRayOrigin是view space的光线起点
float3 wsNormal = tex2D(_CameraGBufferTexture2, i.uv).rgb * 2.0 - 1.0; //世界坐标系下的法线
float3 csNormal = normalize(mul((float3x3)_WorldToView, wsNormal)); //将转换到view space float2 hitPixel;
float3 debugCol; if (traceRay( //检测相交
csRayOrigin,
normalize(reflect(csRayOrigin, csNormal)),
hitPixel, //out
debugCol)) //out
{
reflection = (1 - rayPercent) * tex2D(_MainTex, hitPixel);
}
//return float4(debugCol, 1);
return tex2D(_MainTex, i.uv) + tex2D(_CameraGBufferTexture1,i.uv) * half4(reflection,1);
}

在traceRay方法中,我们进行实际的光线投射、相交检测。

traceRay的签名中我设置了一个debugCol的参数,当我需要debug这个函数时,我将需要debug的内容放到debugCol中,在main里输出debugCol的颜色。这只是我个人的习惯。

对于反射颜色的计算,我只是简单的获取了那个像素的颜色,然后加到输出里去而已。事实上,因为我们是在Deferred rendering模式下,我们可以获取到该点的所有的用于着色的信息,用这些信息我们可以进行一次完整的基于物理着色。在PostProcessing中的SSR就是这么做的,可以参考一下。

在Unity中实现屏幕空间反射Screen Space Reflection(1)的更多相关文章

  1. 在Unity中实现屏幕空间反射Screen Space Reflection(4)

    第四部分讲一下如何在2D屏幕空间步进光线. http://casual-effects.blogspot.com/2014/08/screen-space-ray-tracing.html 中的代码感 ...

  2. 在Unity中实现屏幕空间反射Screen Space Reflection(2)

    traceRay函数 在上一篇中,我们有如下签名的traceRay函数 bool traceRay(float3 start, float3 direction, out float2 hitPixe ...

  3. 在Unity中实现屏幕空间反射Screen Space Reflection(3)

    本篇讲一下相交检测的优化.有两个措施. 线段相交检测 之前的检测都是检测光线的终点是否在物体内.我们可以尝试检测光线的线段是否与物体相交. 比如说有一个非常薄的物体,光线差不多垂直于它的表面.如果用普 ...

  4. 高级屏幕空间反射: Screen Space Reflection (SSSR)

    SSSR进一步调优,对标寒霜级技术水平,实现方式为Direct3D 11+自主实现实时渲染引擎,方法为对比测试.实现已经有段时间了,还是简要更新下吧.以下画面中的SSSR效果全部采用1:4 resol ...

  5. 高级屏幕空间反射: Screen Space Reflection (SSR)

    自从CE3首倡SSR以来,发展至今,其质量与当年早已不能同日而语.不仅强调超越性的质量,而且强调超越性的性能.乘着周末有空撸了撸,以下是增强型实时SSR结果图.与我原来的SSR原始实现相比,新的增强型 ...

  6. screen space reflection/soft alpha test/

    http://www.crytek.com/cryengine/presentations/secrets-of-cryengine-3-graphics-technology 很多宝贝里面 不止题目 ...

  7. 在Unity中实现屏幕空间阴影(1)

    接着上篇文章,我们实现了SSR效果. 其中的在屏幕空间进行光线追踪的方法是通用的.借此我们再实现一种屏幕空间的效果,即屏幕空间阴影. 文中的图片来自Catlike coding http://catl ...

  8. 在Unity中实现屏幕空间阴影(2)

    参考文章: https://www.imgtec.com/blog/implementing-fast-ray-traced-soft-shadows-in-a-game-engine/ 完成的工程: ...

  9. 关于Unity中的屏幕适配

    一.Game视图的屏幕分辨率可以先自定义添加,供以后选择,以下是手游经常用到的分辨率: 1.1136X640,iPhone5 2.1920X1080,横屏,主流游戏都是这个分辨率 3.1080X192 ...

随机推荐

  1. MySQL 基于lvm2的备份实战演练 (快照备份)

    前言: lvm2实现热备的原理是基于lvm2的快照功能,lvm2可以实现数据集不大的情况下的热备. 实战过程如下:这里的演示是在一台Mariadb服务器上进行创建快照,将快照中的文件scp到备份服务器 ...

  2. IDEA中Git的更新/提交/还原方法

    记录一下在IDEA上怎样将写的代码提交到GitHub远程库: 下面这个图是基本的提交代码的顺序: 1. 将代码Add到stage暂存区本地修改了代码后,需先将代码add到暂存区,最后才能真正提价到gi ...

  3. C# 7.0 本地方法

    VS 2017 的 C# 7.0 中引入了本地方法,本地方法是一种语法糖,允许我们在方法内定义本地方法.更加类似于函数式语言,但是,本质上还是基于面向对象实现的. 1. 本地方法 先看一个示例: 1 ...

  4. laya3d 文件格式

    先认识下laya3d的一些文件 导出文件说明:               ls        ---    场景文件: Json文件,包含场景中所有节点的数据信息,包含光照贴图信息          ...

  5. 2月4日 考试——迟到的 ACX

    迟到的 ACX 时限:1s 内存限制:128MB题目描述: 今天长沙下雪了,小 ACX 在上学路上欣赏雪景,导致上学迟到,愤怒的佘总给 ACX 巨佬出了一个题目想考考他,现在他找到你,希望你能帮帮他. ...

  6. [codeforces464D]World of Darkraft - 2 概率期望

    D. World of Darkraft - 2 time limit per test 2 seconds memory limit per test 256 megabytes input sta ...

  7. 【刷题】BZOJ 2754 [SCOI2012]喵星球上的点名

    Description a180285幸运地被选做了地球到喵星球的留学生.他发现喵星人在上课前的点名现象非常有趣. 假设课堂上有N个喵星人,每个喵星人的名字由姓和名构成.喵星球上的老师会选择M个串来点 ...

  8. 【BZOJ4817】树点涂色(LCT,线段树,树链剖分)

    [BZOJ4817]树点涂色(LCT,线段树,树链剖分) 题面 BZOJ Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义 ...

  9. 洛谷 P2604 [ZJOI2010]网络扩容 解题报告

    P2604 [ZJOI2010]网络扩容 题目描述 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下,1到N的最大流: 2. ...

  10. ms17-010漏洞扫描工具

    说明: 1.先利用masscan进行445端口探测 2.利用巡风的脚本对开放445端口的IP进行ms17-010漏洞扫描. 3.使用方法:Python2运行后,按提示输入单个IP或者IP网段. # c ...