风宇冲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 } } }