资讯详情

Unity渲染(四):Shader着色器基础入门之获取当前屏幕贴图

Unity渲染(4):Shader着色器基础入门获取当前屏幕贴图

通过这里,你将学习如何获得当前屏幕的地图和地图UV,通常用于屏幕的后处理。

上一章:Shader着色器基础入门模糊(Blur)

开发环境:Unity5.0或者更高


在这里插入图片描述

获取屏幕贴图和uv,让屏幕的某个区域变亮

概述

1. 获取屏幕贴图 2. 获取屏幕UV 3. 完整代码 

1.1 获取屏幕贴图

Unity 内置GrabPass 获取屏幕贴图,语法如下,代码写在SubShader里面。

Unity-GrabPass官方说明

GrabPass{ 
        "定制地图名称"} 

此Pass其功能是获取当前帧缓冲的内容。我们可以打开它FrameDebugger看到


1.2 获取屏幕UV

Unity为屏幕上获取物体提供了一个接口uv坐标 ComputeGrabScreenPos (float4 clipPos) ComputeGrabScreenPos 官方说明

他需要输入一个float4.这个坐标是切割空间的坐标shader可以通过UnityObjectToClipPos()接口获取 函数定义为UnityCG.cginc, 使用前需要介绍此文件

#include "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; #ifdef UNITY_SINGLE_PASS_STEREO     o.xy = TransformStereoScreenSpaceTex(o.xy, pos.w); #endif     o.zw = pos.zw;     return o; } 

代码说明

  1. #if UNITY_UV_STARTS_AT_TOP 因为在DX平台和OpenGl平台,坐标轴不同,DX左上角定义(0,0),OpenGl定义(0,0)在左下角。防止图像翻转并添加此代码
  2. 首先,我们需要知道如何将坐标从切割空间转换为屏幕空间。中间过程有两个步骤。首先,透视除法将进行xyz除以w重量,让值x,y,z的范围都处于[-1,1]之间,所谓透视除法,主要针对透视投影,正交投影w=1。然后将此坐标转换为屏幕空间,x坐标[-1,1]->[0,屏宽] ,y坐标[-1,1]->[0,屏幕高度]因于以下公式

切割空间转向屏幕空间公式

但我们需要的是UV只需转换坐标[,1]即可,相当于上述公式的pixelWidth = 1,pixelHeight = 1, 当相机为正交投影时:上述公式clipw = 1 则带入可得到Unity源码中的float4 o = pos * 0.5f; o.xy = float2(o.x, o.y*scale) + o.w;, 当相机为透视投影时 源码使用TransformStereoScreenSpaceTex(o.xy, pos.w);进行处理,里面的代码是

float2 TransformStereoScreenSpaceTex(float2 uv, float w)
{ 
        
    float4 scaleOffset = unity_StereoScaleOffset[unity_StereoEyeIndex];
    return uv.xy * scaleOffset.xy + scaleOffset.zw * w;
}

原理是将透视投影的相机平头截体向中间缩放挤压,变成和正交投影一样,在和正交投影一样处理。

最后我们需要再采样的时候将uv.xy / uv.w 因为我们再上面假设clipw =1了


1.3 完整代码

Shader "Toturial/ScreenGrab"
{ 
        
Properties
    { 
        
        _MainTex("MainTex",2D) = "white"{ 
        }
    }

    SubShader
    { 
        
        GrabPass{ 
        "_bTexture"}
        Tags{ 
        "Queue"="Transparent"}
        Pass
        { 
        
            CGPROGRAM
            #include "UnityCG.cginc"
            #pragma vertex vert
            #pragma fragment frag

            sampler2D _MainTex;
            sampler2D _bTexture;

            struct a2v
            { 
        
                float4 vertex : POSITION;
            };

            struct v2f
            { 
        
                float4 pos   : SV_POSITION;
                float4 grabPos : TEXCOORD1;
            };

            v2f vert(a2v v)
            { 
        
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.grabPos = ComputeScreenPos(o.pos);
                return o;
            }

            fixed4 frag(v2f i) : SV_TARGET
            { 
        
                fixed4 screenColor = tex2D(_bTexture, i.grabPos.xy / i.grabPos.w);
                return screenColor * 2;

            }

            ENDCG
        }
    }
}

最终得到效果

最终效果

标签: 紫外线油浸式uv电容器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台