1. 我们先来看Lens FLare这个例子:

       经过了这一章后边几节基本上不再有什么新的东西了,都是对前两个例子的变换。

       唯一值得一提的是一个纹理缩放公式: 

1 texCoord = (texCoord-0.5)*(Scale) + 0.5;

      不停的对可渲染纹理中的图像进行缩放,当Scale取负值的时候,就是带符号的缩放,实际上就是就是把图像旋转了180°。

      下边我们来看Vertex Shader的代码:   

 1 float4x4 view_proj_matrix;
 2 struct VS_OUTPUT
 3 {
 4 float4 Pos: POSITION;
 5 float2 texCoord: TEXCOORD0;
 6 float2 texCoord1: TEXCOORD1;
 7 float2 texCoord2: TEXCOORD2;
 8 float2 texCoord3: TEXCOORD3;
 9 float2 texCoord4: TEXCOORD4;
10 };
11 VS_OUTPUT vs_main(float4 Pos: POSITION)
12 {
13 VS_OUTPUT Out;
14 // Simply output the position without transforming it
15 Out.Pos = float4(Pos.xy, 0, 1);
16 // Texture coordinates are setup so that the full texture
17 // is mapped completely onto the screen
18 float2 texCoord;
19 texCoord.x = 0.5 * (1 + Pos.x - 1/128);
20 texCoord.y = 0.5 * (1 - Pos.y - 1/128);
21 Out.texCoord = texCoord;
22 // Compute the scaled texture coordinates for the ghost images
23 Out.texCoord1 = (texCoord-0.5)*(-2.0) + 0.5;
24 Out.texCoord2 = (texCoord-0.5)*(2.0) + 0.5;
25 Out.texCoord3 = (texCoord-0.5)*(-0.6) + 0.5;
26 Out.texCoord4 = (texCoord-0.5)*(0.6) + 0.5;
27 return Out;
28 }

    一个普通的不能在普通的RTT了,Full texture纹理坐标还是要进行计算的(代码19-20行),因为它要用于进行计算缩放纹理坐标(scaled texture coordinates,代码23-26行)。

    下边我们再看Pixel Shader代码:

 1 float viewport_inv_height;
 2 float viewport_inv_width;
 3 float Glow_Factor;
 4 sampler Texture0;
 5 sampler Texture1;
 6 float4 ps_main (float2 texCoord: TEXCOORD0,
 7 float2 texCoord1: TEXCOORD1,
 8 float2 texCoord2: TEXCOORD2,
 9 float2 texCoord3: TEXCOORD3,
10 float2 texCoord4: TEXCOORD4) : COLOR
11 {
12 // Sample all ghost pictures
13 float4 col1 = tex2D(Texture0, texCoord1)*tex2D(Texture1, texCoord1).a;
14 float4 col2 = tex2D(Texture0, texCoord2)*tex2D(Texture1, texCoord2).a;
15 float4 col3 = tex2D(Texture0, texCoord3)*tex2D(Texture1, texCoord3).a;
16 float4 col4 = tex2D(Texture0, texCoord4)*tex2D(Texture1, texCoord4).a;
17 // Combine the ghost images together
18 return (col1+col2+col3+col4)*Glow_Factor;
19 }

       上边的Pixel Shader代码:

       第一行的 float viewport_inv_height;

         第二行的 float viewport_inv_width; 

         第六行的 float4 ps_main 的第一个参数float2 texCoord: TEXCOORD0都可以去掉, float2 texCoord: TEXCOORD0只在Vertex Shader中有作用,Pixel Shader中没有任何作用。

         然后我们再来看

         13 float4 col1 = tex2D(Texture0, texCoord1)*tex2D(Texture1, texCoord1).a;

         14 float4 col2 = tex2D(Texture0, texCoord2)*tex2D(Texture1, texCoord2).a;

         15 float4 col3 = tex2D(Texture0, texCoord3)*tex2D(Texture1, texCoord3).a;

         16 float4 col4 = tex2D(Texture0, texCoord4)*tex2D(Texture1, texCoord4).a;

          Q1:为什么Texture1的采样坐标不是float2 texCoord: TEXCOORD0呢(Texture0坐标是Full texture纹理坐标,Texture1是缩放后的纹理坐标)????

          A1:  我们拿绘制Ghost的第一个Pass中的采样来举例,如果使用Full texture纹理坐标会发生什么情况,正好做一个实验,如下图:

          第一幅图是未对缩放后的图片进行Mask处理,上边有很多的条纹(因为我们纹理采样使用的时clamp模式)

                                                                                                              未对缩放后的图片进行透明度Mask处理

            第二幅图是对缩放后的图片进行Mask处理,但是使用的是Full texture纹理坐标:

            这个很容易理解,因为用来Mask的图像是在Full texture空间中进行的,所以它只对屏幕空间圆心处的像素进行保留,其他位置全部Mask掉;

                                                                      

         第三副图片就是该书中所采取的,利用缩放的纹理坐标采样Ghost,然后对缩放的纹理进行Mask,可以保证,在缩放后空间内,利用缩放后的Ghost图像正确的对图像进行Mask! ,消除硬边(实际上效果也不是很理想:(,有的地方也消除的不好)。

        Q2:值得注意的是,图像上放大的纹理,实际上纹理坐标是缩小的,图像缩小的纹理,实际上纹理坐标是放大的 :)

        A2:在Vertex shader中将纹理坐标进行了缩放,该纹理坐标被Route进了Pixel Shader中;

        然后在Pixel Shader中对纹理进行采样,不管我们的纹理坐标范围是多少,这个2维范围内的纹理都将按照对应的纹理地址模式被绘制到屏幕!!(理解这句是关键)

        如果在Vertex Shader中纹理坐标变换为X(0,2),Y(0,2),Route进Pixel Shader中,我们其实将该纹理进行X(0,2),Y(0,2)的采样,并将该采样范围的图像绘制到屏幕上;实际在屏幕上绘制了4遍,但是在我们看起来,图像是缩小了(clamp模式下,只有左上角部分有图像,其他部分是两个边颜色的Clamp);

       如果在Vertex Shader中纹理坐标变换为X(0,0.5),Y(0,0.5),Route进Pixel Shader中,我们其实将该纹理进行X(0,0.5),Y(0,0.5)的采样,并将该采样范围的图像绘制到屏幕上;实际在屏幕上绘制了四分之一的图像,但是在我们看起来,图像是放大了(这里我们就不管是不是Clamp了,因为根本不需要这个地址模式就可以确定纹理坐标范围内的颜色);

       (以上举例是以纹理坐标原点为中心的,以纹理为中心一个道理——这是我能想到的最好的解释方式了,If you have a better one, please let me know;)

       2. 然后我们再来看Put them together这个例子,实际上就是将Glare,Streak,Lens Flare放在一起,所有的Renderable texture,Pass,纹理资源,变量等等统统糅合在一起——这个简直就是噩梦:( ,组织数据繁琐一些,然后对Pixel Shader稍作修改。      

 //This is the final Pixel Shader Code...................
//We need to apply some changes....
1
sampler Texture0; //This is for Ghost Image 2 3 sampler Texture1; //This is for Blooming 4 sampler Texture2; 5 sampler Texture3; 6 7 sampler Texture4; //This is for Streak 8 sampler Texture5; // 9 sampler Texture6; // 10 sampler Texture7; // 11 12 float Streak_Factor; 13 float Ghost_Factor; 14 float Glow_Factor1; 15 float Glow_Factor2; 16 float Glow_Factor3; 17 18 float4 ps_main(float2 texCoord: TEXCOORD0) : COLOR 19 { 20 float4 col; 21 22 // Glow 23 col = float4((tex2D(Texture1,texCoord).xyz)*Glow_Factor1,1.0) + 24 float4((tex2D(Texture2,texCoord).xyz)*Glow_Factor2,0) + 25 float4((tex2D(Texture3,texCoord).xyz)*Glow_Factor3,0); 26 27 // Ghost 28 col += float4((tex2D(Texture0,texCoord).xyz),0); 29 30 // Streak 31 32 col += 33 float4((tex2D(Texture4,texCoord).xyz)*Streak_Factor,0) + 34 float4((tex2D(Texture5,texCoord).xyz)*Streak_Factor,0) + 35 float4((tex2D(Texture6,texCoord).xyz)*Streak_Factor,0) + 36 float4((tex2D(Texture7,texCoord).xyz)*Streak_Factor,0); 37 38 return col; 39 }

      注意line23, 只把在第一个颜色的α值设置为1,其他都为0,这样最终颜色的α值是1,根据http://www.cnblogs.com/infintyward/p/3244888.html中讲过的混合原理,将最终返回的颜色与后缓存进行混合。

      最终效果图如下。

                           

 

 

 

           //end

posted on 2013-08-10 18:37  infinityward  阅读(401)  评论(0编辑  收藏  举报