shader实例(五)GrabPass捕捉屏幕纹理
来源:互联网 发布:unity3d卡牌游戏源码 编辑:程序博客网 时间:2024/06/05 02:04
shader实例(五)GrabPass捕捉屏幕纹理
1.固定管线版本:
Shader "Custom/Grab" { Properties { //_MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { // 在所有不透明对象之后绘制自己,更加靠近屏幕 Tags { "Queue" = "Transparent" } // 通道1:捕捉对象之后的屏幕内容放到_GrabTexture纹理中 GrabPass{} // 通道2:设置材质 Pass{ // 使用上面产生的纹理,进行颜色反相(1-原材质色) SetTexture[_GrabTexture]{combine one-texture} } } FallBack "Diffuse"}效果如下,它是取模型背后的屏幕纹理:
2.顶点,片段版本:
Shader "Custom/GrabAllVF" { Properties { //_MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { // 在所有不透明对象之后绘制自己,更加靠近屏幕 Tags{"Queue"="Transparent"} // 通道1:捕捉屏幕内容放到_GrabTexture纹理中 GrabPass{} // 通道2:设置材质 Pass{ Name "pass2" CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" sampler2D _GrabTexture; float4 _GrabTexture_ST; // 片段程序的输入 struct v2f { float4 pos : POSITION; float2 uv : TEXCOORD0; }; v2f vert (appdata_base v) { v2f o; o.pos = mul(UNITY_MATRIX_MVP,v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _GrabTexture); return o; } float4 frag (v2f i) : COLOR { half4 texCol = tex2D(_GrabTexture, float2(1-i.uv.x , 1-i.uv.y)); // 颜色反相,便于观察效果 return 1 - texCol; } ENDCG } } FallBack "Diffuse"}效果如下:取到的是全屏的纹理:
1和2为什么取到的屏幕纹理不一样呢?
3.使用vf的方式,只获取物体后面的屏幕纹理,后面的扭曲效果会用到此方式,代码如下:
Shader "Custom/GrabVF" { Properties { //_MainTex ("Base (RGB)", 2D) = "white" {} } SubShader { // 在所有不透明对象之后绘制自己,更加靠近屏幕 Tags{"Queue"="Transparent"} // 通道1:捕捉对象之后的屏幕内容放到_GrabTexture纹理中 GrabPass{} // 通道2:设置材质 Pass{ Name "pass2" CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" sampler2D _GrabTexture; float4 _GrabTexture_ST; struct v2f { float4 pos : POSITION; // 输入的模型空间中,顶点坐标信息 float4 uv : TEXCOORD0; // 材质信息也包含了xyzw,通常只用xy,但是这里由顶点生成 }; v2f vert (appdata_base v) { v2f o; // 从模型坐标-世界坐标-视坐标-(视觉平截体乘以投影矩阵并进行透视除法)-剪裁坐标 o.pos = mul(UNITY_MATRIX_MVP,v.vertex); // 【自动生成纹理】通过输出的pos计算的纹理信息 // 【解决平台差异】D3D原点在顶部(本机需要让y缩放乘以-1),openGL在底部 #if UNITY_UV_STARTS_AT_TOP float scale = -1.0; #else float scale = 1.0; #endif // pos的范围是【-1,1】+1为【0,2】,乘以0.5变成uv的范围【0,1】 // 不清楚为什么这样写,但是标准的写法就是这样 o.uv.xy = (float2(o.pos.x, o.pos.y*scale) + o.pos.w) * 0.5; o.uv.zw = o.pos.zw; return o; } float4 frag (v2f i) : COLOR { // 对_GrabTexture纹理进行取样,进行2D纹理映射查找,后面传入的一定要四元纹理坐标。 // UNITY_PROJ_COORD传入四元纹理坐标用于给tex2Dproj读取,但是多数平台上,返回一样的值。 // 【自动生成的纹理UV】类型是float4,使用如下方式进行2D纹理映射查找 //half4 texCol = tex2Dproj(_GrabTexture, UNITY_PROJ_COORD(i.uv)); // 也可以使用tex2D进行采样,但是【自动生成的纹理UV】时必须要除以w转为齐次坐标 float last_x = i.uv.x / i.uv.w; float last_y = i.uv.y / i.uv.w; half4 texCol = tex2D(_GrabTexture, float2(last_x, last_y)); // 颜色反相,便于观察效果 return 1 - texCol; } ENDCG } } FallBack "Diffuse"}
注:
2中的确是将屏幕的纹理赋值到样本对象GrabTexture上,所以前面的模型显示整个屏幕的纹理是正常现象。
3中是计算该模型顶点在屏幕坐标的纹理信息,unity封装的UnityCG.cginc代码中有:
inline float4 ComputeGrabScreenPos (float4 pos) { #if UNITY_UV_STARTS_AT_TOP float scale = -1.0; #else float scale = 1.0; #endif float4 o = pos * 0.5f; o.xy = float2(o.x, o.y*scale) + o.w; o.zw = pos.zw; return o; }
与3中给o.uv赋值的代码是一样的。所以在顶点程序中可以这样写:
v2f vert (appdata_base v) { v2f o; // 从模型坐标-世界坐标-视坐标-(视觉平截体乘以投影矩阵并进行透视除法)-剪裁坐标 o.pos = mul(UNITY_MATRIX_MVP,v.vertex); //o.uv = TRANSFORM_TEX(v.texcoord, _GrabTexture);// UV纹理坐标集信息来自屏幕样本对象 float4 screenUV = ComputeGrabScreenPos(o.pos);//计算该模型顶点在屏幕坐标的纹理信息 o.uv = screenUV.xy/screenUV.w; return o; }
以后我们就可以不用再写这段代码了,直接用unity提供的函数ComputeGrabScreenPos,方便!
获取屏幕的纹理,还可以通过摄像机,将渲染的内容写到RenderTexture中,这样就可以不使用grabpass,
一样达到获取屏幕纹理的目标,grabpass比较耗(官方说的,不过我在pc上创建了5000个对象进行测试,没发现太大差异,手机上没测过),
在手机上比较适合这种方式。实现代码如下:
public class ScreenTexture : MonoBehaviour{ public Camera m_camera; // 和主摄像机参数一样的拍照摄像机 private RenderTexture m_tex; // 摄像机渲染的材质 public Material mat; // 要控制的材质 void Start() { m_tex = new RenderTexture(Screen.width, Screen.height, 16); m_camera.targetTexture = m_tex; } void OnPreCull() { mat.SetTexture("_MainTex", m_tex); // 给shader的主材质赋值,为屏幕纹理 } void OnPostRender() { mat.SetTexture("_MainTex", null); }}
阅读全文
0 0
- shader实例(五)GrabPass捕捉屏幕纹理
- Unity Shader Example 3 (GrabPass捕捉屏幕纹理 )
- Unity3d Shader(三) Pass(GrabPass)捕获物体所在位置的屏幕的内容
- Shader山下(二十三)GrabPass与UsePass
- Shader实例:高级纹理应用
- Shader学习笔记(五)纹理映射与viewDir
- unity之shader学习笔记(五)--纹理
- Unity Shader 学习笔记(十一) 混合纹理Shader实例
- unity shader学习笔记(五)——Unity中的基础纹理之凹凸映射
- Unity3D Shader官方教程翻译(十六)----Shader语法 GrabPass
- Unity3D Shader官方教程翻译(十六)----Shader语法 GrabPass
- Unity3D Shader官方教程翻译(十六)----Shader语法 GrabPass
- Unity3D Shader官方教程翻译(十六)----Shader语法 GrabPass
- Unity3D Shader官方教程翻译(十六)----Shader语法 GrabPass
- 【OpenGL】Shader实例分析(五)- 边缘检测
- 【OpenGL】Shader实例分析(五)- 边缘检测
- 【OpenGL】Shader实例分析(五)- 边缘检测
- Material Capture(材质捕捉) shader 学习
- 深入理解java多态性
- wps for linux显示系统缺失字体解决办法
- okhttp封装+拦截器+异常捕获类
- Android数据存储之Sqlite的介绍及使用
- hdu 3605 二分图多重匹配
- shader实例(五)GrabPass捕捉屏幕纹理
- okhttp拦截器的实现
- Hadoop学习笔记(六)实战word count
- OKHTTP3的使用与封装
- zookeeper安装
- 如何从硬盘直接引导 Linux ISO映像
- 具备C语言的能力下,快速学会使用AWK为了做些什么
- servlet 读写文件的坑
- 从CSV读取数字作为字符串