文章目录

  • 先尝试GL类来制作
    • Shader
    • CSharp
      • 画个三角型
      • 画个全屏的Quad
      • 发现GL没有RenderTarget之类的
  • 使用CommandBuffer来绘制全屏的Quad
  • GL渲染到目标
  • 另外优化
  • Project
  • References

先尝试GL类来制作

Shader

// jave.lin 2020.04.12 - 绘制一个全屏的Quad
Shader "Custom/DrawFullScreenQuad" {SubShader {Pass {ZTest Always ZWrite Off Cull OffCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct appdata {float4 vertex : POSITION;fixed4 color : COLOR;};struct v2f {float4 vertex : SV_POSITION;fixed4 color : COLOR;};v2f vert (appdata v) {v2f o;o.vertex = v.vertex;o.color = v.color;return o;}fixed4 frag (v2f i) : SV_Target { return i.color; }ENDCG}}
}

CSharp

画个三角型

        GL.PushMatrix();mat.SetPass(0);GL.LoadOrtho();GL.Begin(GL.TRIANGLE_STRIP);// 注意顶点顺序,组合为:顺时针即可,Unity 逆时针为正面GL.Color(new Color(1, 0, 0, 1));//redGL.Vertex3(0, 0, 1);GL.Color(new Color(0, 1, 0, 1));//greenGL.Vertex3(1, 0, 1);GL.Color(new Color(0, 0, 1, 1));//blueGL.Vertex3(0.5f, 0.5f, 1);GL.End();GL.Flush();

运行效果

借用我之前写的一篇:

里面有个图片要注意的是,Unity的三角面正面判定

画个全屏的Quad

    private void DrawFullScreenQuadTesting(){//var camWPos = cam.transform.position;mat.SetPass(0);GL.Begin(GL.TRIANGLE_STRIP);// 注意顶点顺序,组合为:顺时针即可,Unity 逆时针为正面GL.Color(new Color(1, 0, 0, 1));//redGL.Vertex3(-1, -1, 0);GL.Color(new Color(0, 1, 0, 1));//greenGL.Vertex3(1, -1, 0);GL.Color(new Color(0, 0, 1, 1));//blueGL.Vertex3(-1, 1, 0);GL.Color(new Color(1, 1, 0, 1));//yellowGL.Vertex3(1, 1, 0);GL.End();}

运行效果:

发现GL没有RenderTarget之类的

全屏的效果算是弄出来的,但是向要GL调用底层绘制的内容想指定一下渲染目标,结果发现没有。。。哈哈,白忙活了。。。连RenderTarget都没有。
这么说Unity GL貌似没啥用了,除了可以话一些Line来调试用。
看来要实现RT功能只能CommandBuffer或是Camera来设置RenderTarget并绘制了。
使用姿势不对,其实可以使用RenderTexture.active来设置当前渲染目标

使用CommandBuffer来绘制全屏的Quad

为何需要全屏Quad并Render到RT的功能,因为后面制作SSSM(Screen Space Shadow Map)做准备的。

CommandBuffer 相关的内容,我写过4篇,可以查看我References的。

CSharp

using UnityEngine;
using UnityEngine.Rendering;
// jave.lin 2020.04.13 - 绘制全屏Quad
public class CmdBuffDrawFullScreen : MonoBehaviour
{public Camera cam;public Material mat;[SerializeField] private RenderTexture sssmRT;private Mesh mesh;private CommandBuffer cmdBuff;private void Start(){cam.depthTextureMode |= DepthTextureMode.Depth;mesh = new Mesh();mesh.vertices = new Vector3[] {// 这里的第三个z分量最好不要在这里设置,最好在shader中判断是GL还是DX平台来设置为近截面的z值就好new Vector3(-1,1,0),    // blnew Vector3(-1,-1,0),   // tlnew Vector3(1,-1,0),    // trnew Vector3(1,1,0),     // br};mesh.uv = new Vector2[]{new Vector2(0,0),       // blnew Vector2(0,1),       // tlnew Vector2(1,1),       // trnew Vector2(1,0),       // br};mesh.triangles = new int[] {0, 1, 2,0, 2, 3};}private void OnPreRender(){if (sssmRT == null || sssmRT.width != Screen.width || sssmRT.height != Screen.height){if (sssmRT) RenderTexture.ReleaseTemporary(sssmRT);sssmRT = RenderTexture.GetTemporary(Screen.width, Screen.height, 0);//, RenderTextureFormat.R8);sssmRT.name = "sssmRT";if (cmdBuff == null){cmdBuff = new CommandBuffer();cmdBuff.name = "After Depth TEX";}cmdBuff.Clear();cmdBuff.SetRenderTarget(sssmRT);cmdBuff.ClearRenderTarget(true, true, Color.white);cmdBuff.DrawMesh(mesh, Matrix4x4.identity, mat);cam.RemoveCommandBuffer(CameraEvent.AfterDepthTexture, cmdBuff);cam.AddCommandBuffer(CameraEvent.AfterDepthTexture, cmdBuff);}}private void OnDestroy(){if (sssmRT) RenderTexture.ReleaseTemporary(sssmRT);if (cam != null && cmdBuff != null){cam.RemoveCommandBuffer(CameraEvent.AfterDepthTexture, cmdBuff);cmdBuff.Release();}}private void OnRenderImage(RenderTexture source, RenderTexture destination){Graphics.Blit(sssmRT, (RenderTexture)null);}
}

其中需要注意的地方

        mesh.vertices = new Vector3[] {// 这里的第三个z分量最好不要在这里设置,最好在shader中判断是GL还是DX平台来设置为近截面的z值就好new Vector3(-1,1,0),    // blnew Vector3(-1,-1,0),   // tlnew Vector3(1,-1,0),    // trnew Vector3(1,1,0),     // br};

留意注意:这里的第三个z分量最好不要在这里设置,最好在shader中判断是GL还是DX平台来设置为近截面的z值就好

Shader

// jave.lin
Shader "Custom/CmdBuffDrawFullScreenQuadMat" {SubShader {ZTest Always ZWrite Off Cull OffPass {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 _CameraDepthTexture;v2f vert (appdata v) {v2f o;// jave.lin : 在这里我们处理GL与DX的差异// GL的Z:-1~1,DX的Z:0~1#if defined (SHADER_TARGET_GLSL)v.vertex.z = -1;#elsev.vertex.z = 0;#endifo.vertex = v.vertex;o.uv = v.uv;return o;}fixed4 frag (v2f i) : SV_Target {float depth = tex2D(_CameraDepthTexture, i.uv).r;#if defined (UNITY_REVERSED_Z)depth = 1 - depth;#endifreturn depth;}ENDCG}}
}

shader的vert函数中注意这么一段:

             // CSharp层脚本的第三个z分量最好不要在这里设置// 最好在shader中判断是GL还是DX平台来设置为近截面的z值就好// jave.lin : 在这里我们处理GL与DX的差异// GL的Z:-1~1,DX的Z:0~1#if defined (SHADER_TARGET_GLSL)v.vertex.z = -1;#elsev.vertex.z = 0;#endif

运行效果

GL渲染到目标

CSharp,主要调用的是:RenderTexture.active = RT;

using UnityEngine;
// jave.lin 2020.04.22 - 绘制一个全屏的Quad
public class DrawFullScreenQuadGL_Correct : MonoBehaviour
{private static int _TestFullscreenTex_hash = Shader.PropertyToID("_TestFullscreenTex");public enum TransformType{None,       // 无,就是VS不处理任何变化,a2v的坐标当做clip space的坐标用Generic     // 一般化}public Camera cam;public TransformType transType;public Material noneTransformMat;public Material genericTransformMat;public bool drawMergeColor = true;public Material depthMergeFullscreenColorMat;private RenderTexture rt;private void Start(){cam.depthTextureMode |= DepthTextureMode.DepthNormals;}private void OnRenderObject(){if (rt == null || rt.width != Screen.width || rt.height != Screen.height){if (rt != null) RenderTexture.ReleaseTemporary(rt);rt = RenderTexture.GetTemporary(Screen.width, Screen.height, 0);}RenderTexture src = RenderTexture.active;if (drawMergeColor){RenderTexture.active = rt;}if (transType == TransformType.None) NoneTransformDraw();else GenericTransformDraw();if (drawMergeColor){RenderTexture.active = src;}}private void OnRenderImage(RenderTexture source, RenderTexture destination){if (drawMergeColor){depthMergeFullscreenColorMat.SetTexture(_TestFullscreenTex_hash, rt);Graphics.Blit(source, destination, depthMergeFullscreenColorMat);}else{Graphics.Blit(source, destination);}}private void OnDestroy(){if (rt != null) {RenderTexture.ReleaseTemporary(rt);rt = null;}}private void NoneTransformDraw(){noneTransformMat.SetPass(0);GL.Begin(GL.TRIANGLE_STRIP);// 注意顶点顺序,组合为:顺时针即可,Unity 逆时针为正面GL.Color(new Color(1, 0, 0, 1));//redGL.Vertex3(-1, -1, 0);GL.Color(new Color(0, 1, 0, 1));//greenGL.Vertex3(1, -1, 0);GL.Color(new Color(0, 0, 1, 1));//blueGL.Vertex3(-1, 1, 0);GL.Color(new Color(1, 1, 0, 1));//yellowGL.Vertex3(1, 1, 0);GL.End();}private void GenericTransformDraw(){genericTransformMat.SetPass(0);GL.PushMatrix();GL.LoadOrtho();GL.Begin(GL.QUADS);// 注意顶点顺序,组合为:顺时针即可,Unity 逆时针为正面GL.Color(new Color(1, 0, 0, 1));//redGL.Vertex3(0, 0, 0); // blGL.Color(new Color(0, 1, 0, 1));//greenGL.Vertex3(0, 1, 0); // tlGL.Color(new Color(0, 0, 1, 1));//blueGL.Vertex3(1, 1, 0); // trGL.Color(new Color(1, 1, 0, 1));//yellowGL.Vertex3(1, 0, 0); // brGL.End();GL.PopMatrix();}
}

另外优化

后期渲染我们一般的会使用4个顶点,两个三角形来绘制全屏图像。

但后来发现这部分竟然还可以优化,说是因为tile-based渲染相关。

所以可以使用一个三角形来替代一个Quad(两个三角形)的方式来优化。

引用一张图:

在 Unity Shader URP 中,可以看到:Common.hlsl 中的 GetFullScreenTriangleTexCoordGetFullScreenTriangleVertexPosition

也有类似的优化处理

// Generates a triangle in homogeneous clip space, s.t.
// v0 = (-1, -1, 1), v1 = (3, -1, 1), v2 = (-1, 3, 1).
float2 GetFullScreenTriangleTexCoord(uint vertexID)
{#if UNITY_UV_STARTS_AT_TOPreturn float2((vertexID << 1) & 2, 1.0 - (vertexID & 2));
#elsereturn float2((vertexID << 1) & 2, vertexID & 2);
#endif
}float4 GetFullScreenTriangleVertexPosition(uint vertexID, float z = UNITY_NEAR_CLIP_VALUE)
{float2 uv = float2((vertexID << 1) & 2, vertexID & 2);return float4(uv * 2.0 - 1.0, z, 1.0);
}

具体查看:用三角形代替四边形-后处理优化

Project

backup : UnityShader_RenderImageLikeTesting_2018.3.0f2

References

GL

  • GL
  • GL.Begin
  • GL.Vertex3
  • Material.SetPass

CommandBuffer相关的之前几篇:

  • Unity Graphics Command Buffers 图形指令缓存
  • Unity Shader PostProcessing - 6 - GaussianBlur 高斯模糊+CommandBuffer使用做一些其他的特效
  • Unity CommandBuffer或是Camera重定向RenderTarget的ColorBuffer & DepthBuffer
  • Unity Shader - 实现武器热扭曲拖尾效果(不需要GrabPass)

Unity Shader - 模仿RenderImage制作全屏Quad,可以制作自定义后处理的流程相关推荐

  1. uniapp 判断页面是否是横竖屏,解决微信小程序video组件全屏播放视频遮盖自定义播放控件问题

    如果res.deviceOrientation 等于landscape 的话是竖屏,portrait则是横屏.因为用户每旋转一次屏幕就会触发里面的onShow钩子,因此在页面显示或横竖屏变化都会触发这 ...

  2. Unity Shader GrabPass 抓屏幕 截屏

    Shader 抓屏 截屏 常用途径: 1.截取全屏作为截图储存 (常用). 2.截取全屏,模糊处理当作背景. 3.接入屏幕中某些指定的画面. 抓屏命令: GradPass{"Name&quo ...

  3. VB.NET在WinForm中嵌入谷歌浏览器_制作全屏显示网页程序_并读取INI配置文件_根据配置文件显示不同的网页---VB.NET工作笔记016

    我们做了个项目,科技馆的,需要把绚丽的网页,全屏放到浏览器上显示,但是....他们做的这个网页...我去,只支持谷歌这样的浏览器,在IE这样的浏览器模式下,显示有问题... 不知道是不是因为,没有使用 ...

  4. QT制作全屏播放器以及出现的问题

    使用QT做播放器使用widget::winid可以获取播放器组件的windows句柄并以命令行的方式调起另一个程序使用D3D将内存缓冲区的图像打在上面.但是在做全屏是出现了问题,如果让播放器组件自己独 ...

  5. HTML5七夕情人节表白网页制作 (全屏爱心相册) HTML+CSS+JS

    ❤ 精彩专栏推荐

  6. Unity Shader - Custom SSSM(Screen Space Shadow Map) 自定义屏幕空间阴影图

    文章目录 思路 实践 获取光源空间ShadowMap[A] 获取屏幕空间的深度图[B] 获取SSSM(Screen Space Shadow Map) 绘制一个全屏的Quad[C] 输出SSSM RT ...

  7. 一款全屏展示的流量卡官网单页模板源码

    介绍: 一款fullpage.js制作全屏展示的流量卡官网单页模板 这个是一个单页源码没有后台的,下载之后自行通过源码修改文字图片即可 具体的就不多介绍了,用的上的伙伴就下载拿走吧! 网盘下载地址: ...

  8. 全屏自适应游戏开始界面

    功能效果展示 运行环境 Win7,Win8,Win10 Reworld版本 体验版 vc_redist.x64 运行环境 针对零基础读者的补充 下载安装 Reworld对应版本 Reworld官网链接 ...

  9. 阿里巴巴卖家如何修改html,阿里巴巴店铺装修之全屏广告轮换特效代码分享及说明...

    原标题:阿里巴巴店铺装修之全屏广告轮换特效代码分享及说明 阿里巴巴店铺装修中离不开全屏轮换广告,由于阿里店铺装修原配的轮换图有点呆板,所以通过自己编写的特效代码来制作全屏轮换广告还是很有必要的. (源 ...

最新文章

  1. druid seata 配置_五分钟体验分布式事务框架Seata
  2. python语言入门m-Python学习基础篇 -1
  3. MySql 数据库 - 安装时提示缺失VCRUNTIME140_1.dll文件导致的无法启动此程序解决方法,vc++2015-2019运行库集合包获取
  4. pyqt5项目(计算器)
  5. QT如何实现对于字符串数学公式计算
  6. 新手学java_新手如何学习Java
  7. 《C++ Primer》7.3.4节练习
  8. ValueError: Program dot not found in path.python下运行pygraphviz出现报错
  9. fastjson 添加key value_FastJson迁移至Jackson
  10. 在Win7系统下, 使用VS2015 打开带有日文注释程序出现乱码的解决方案
  11. Android-JNI开发系列《十一》实践-利用Android C源码实现GIF图片的播放
  12. 项目中为什么用Docker?
  13. 【上岸合肥工业大学】计算机考研经验分享(初试+复试)
  14. 树莓派怎么切换输入法_树莓派 Raspberry Pi 设置显示中文方法安装输入法
  15. How to Become a Straight-A student
  16. 英语作文计算机用途80词,初3英语作文_关于介绍电脑的英语作文,初三,80词左右。急!!!...
  17. CTF-PHP反序列化漏洞1-基础知识
  18. ToC产品和ToB产品的区别To C/To B/To G分别是什么
  19. UIPATH Orchestrator配置
  20. CISCO端口带宽限制配置

热门文章

  1. HTML5详细学习资料
  2. C/C++教程 第二十七章 —— 脚本开发
  3. Linux之(6)Kconfig基础知识
  4. MS08067安全实验室『网络安全实战周训练营』现正免费报名,明晚八点上线!持续有课~...
  5. 机器学习(32)之典型相关性分析(CCA)详解 【文末有福利......】
  6. 自动驾驶专题介绍 ———— 惯性导航
  7. 使用matlab对图像进行二维傅里叶变换
  8. ET6运行指南(vs版)
  9. new String 详解
  10. 多普达D600 问题集锦