风宇冲Unity3D教程学院 第二十三讲GrabPass
Dr.Dobb's Understanding Photomosaics
Shader "Custom/MosaicShader" {
Properties{
_MainTex("Base (RGB)", 2D) = "white" {}
}
SubShader
{
Tags{ "Queue" = "Transparent" }
GrabPass
{
"_MyGrabTexture"
}
pass
{
Name "pass2"
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MyGrabTexture;
float4 _MyGrabTexture_ST;
struct VertexIn
{
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
float4 screenPos : TEXCOORD1;
};
struct VtoF
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float4 screenPos : TEXCOORD1;
};
VtoF vert(VertexIn v)
{
VtoF o;
o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord,_MyGrabTexture);
/*
//source code in UnityCG.cginc
inline float4 ComputeScreenPos(float4 pos) {
//if we do perspective divide here(pos/pos.w), we got pos.x in range (-1, 1)(NDC)
float4 o = pos * 0.5f;
//if we do perspective divide here(o/pos.w), we got o.x in range (-0.5,0.5)
#if defined(UNITY_HALF_TEXEL_OFFSET)
o.xy = float2(o.x, o.y*_ProjectionParams.x) + o.w * _ScreenParams.zw;
#else
o.xy = float2(o.x, o.y*_ProjectionParams.x) + o.w;
#endif
o.zw = pos.zw;
//if we do perspective divide here(o/pos.w), we got o.x in range (0,1)
//o.x / pos.w in range(-0.5, 0.5), o.w / pos.w = 0.5
//(o.x + o.w) / pos.w in range (-0.5 + 0.5, 0.5 + 0.5) = (0,1)
return o;
}
*/
o.screenPos = ComputeScreenPos(o.pos);
return o;
}
float4 frag(VtoF i) : COLOR
{
//perspective divide for screen pos to normalize p to be in the range of (0,1)
fixed4 p = i.screenPos / i.screenPos.w;
float4 tmp = float4(0, 0, 0, 0);
//http://docs.unity3d.com/462/Documentation/Manual/SL-BuiltinValues.html
//_ScreenParams: screen dimension in pixel
//p.x*_ScreenParams.x: get x coordinate on screen, unit: pixel
//floor(p.x*_ScreenParams.x / 10) * 10: 100 -> 100, 101 -> 100, 102 -> 100 ..., 109 -> 100, 110 -> 110
[unroll(10)]
for (float ii = floor(p.x*_ScreenParams.x / 10) * 10; ii < floor(p.x*_ScreenParams.x / 10) * 10 + 10; ii += 1)
{
[unroll(10)]
for (float jj = floor(p.y *_ScreenParams.y / 10) * 10; jj < floor(p.y *_ScreenParams.x / 10) * 10 + 10; jj += 1)
{
//sample pixel color on screen
tmp += tex2D(_MyGrabTexture, float2(ii / _ScreenParams.x, 1 - jj / _ScreenParams.y));
}
}
return tmp / 100;//average samples
}
ENDCG
}
}
}