专栏首页烙馅饼喽的技术分享Silverlight像素着色器编写简明指南 附送文字描边效果

Silverlight像素着色器编写简明指南 附送文字描边效果

      在玩很多flash网页游戏的时候,看到它们都有非常清晰的宋体字,并且有漂亮的描边效果。如图,这是战将传奇的登录界面中的文字。

对比之下,silverlight要弄文字可让人头痛无比,别的不说,默认的字体怎么看怎么歪瓜裂枣。我就不贴图了,大家都明白。

那么怎么办捏,我们要祭出法宝:像素着色器!

  • 需要的工具:Shazzam Shader Editor 。 这个是调试Silverlight着色器的神器。只要下载安装了它,其他的一切都好办了。
  • 简单介绍一下像素着色器的工作原理。 对某个UIElement应用一个Effect,可以是自定义的。UIElement最终会呈现为一个位图。这个位图会被当成参数传入我们编写的着色器。着色器程序入口有一个参数,是当前的像素位置,另外还有一个注册的传入的位图。程序要求返回一个颜色,就是指定当前像素的颜色。 程序执行一次,只能对传入的当前像素进行着色,但是,有几个像素着色器程序就会执行几次,并且各个像素之间不冲突。所以,GPU硬件往往会并行计算。 因此,如果我们写一个最最简单的着色器,就是不管3721,一律返回红色,那么这个UIElemnet就会被画成一个红色方块。
  • 首先我们打开Shazzam Shader Editor.然后新建一个Shader。这个时候就已经给建立了一个默认的将原输入图像原封不动地输出的Shader。事实上我们只要将return 改为return float4(1,0,0,1),就会输出一个红色矩形。 解释一下主要语句的功能:
    • sampler2D input : register(s0);              注册输入的位图参数。 float          a:register(c1);                     注册一个输入的浮点型参数。 float4        c:register(c2);                      注册一个输入的颜色。  一个float4类型里面包括了4个浮点数。 可以用rgba来访问,比如说, c.r ,c.g 等。 其中颜色的各分量都是 0-1之间而不是 0-255,这个要注意。 以上这三种类型可以在silverlight里当参数传进来。 其中smpler2D就是一个bursh, float就是一个浮点数, float4就是一个Color。 float2    包含两个浮点数的类型, 一般用作坐标。在main函数有一个传入的参数,类型就是float2 . 有x,y两个成员用以访问2个浮点数。传入的坐标的x,y分量都是在0-1之间,也就是说,把位图的宽和高都映射到0-1之间了。 如果我们知道位图的实际宽度的话,用 x,y乘以 宽或高,才能得到实际的像素位置。 tex2D函数:  接收一个 sampler2D 和一个 float2 的坐标 。 返回sampler2D这个位图的制定位置的颜色。
  • 知道了以上这些语句,我们就可以动手写着色器了。 我们的目的,就是要进行文字描边。假定我们只会对TextBlock应用这个着色器,那么有如下事实:TextBlock是一个矩形。文字所在像素的 alpha分量必定大于0,否则必定是透明像素。 我们要做这样一件事,就是如果当前像素的上,下,左,右任意一个像素不透明,那么说明本像素需要被描边,否则就输出文字颜色。 由于需要知道相邻像素,所以还需要传入TextBlock的ActualWidth和ActualHeight。 这样, 当前位置的 x+ 1/width 就是相邻像素的坐标,我们可以用tex2D函数来提取它的颜色值。 还需要输入描边的颜色,还有文字的颜色。 因此,废话不多说了,直接上着色器代码了:
1 sampler2D input : register(s0);  //输入的textblock
      2 
      3 float w:register(C0);                      //宽度
      4 
      5 float h:register(C1);                     //高度
      6 
      7 float4 fontcolor:register(C2);    //字体颜色
      8 
      9 float4 bordercolor:register(C3);   //描边颜色
     10 
     11 float4 main(float2 uv : TEXCOORD) : COLOR 
     12 { 
     13     //float3 rgb= bordercolor.rgb ;
     14 
     15     float4 Color; 
     16     Color= tex2D( input , uv.xy);    //提取当前像素颜色
     17     
     18     int i;
     19     
     20     
     21     for( i=1;i<2;i++ )                           //修改此循环,可以改动描边的宽度,不过,这里就1次就够了
     22     {
     23         if( Color.a==0   )
     24         {
     25             float4 c2;
     26             c2= tex2D( input, uv.xy +float2 (0,i/h) );    //提取下方像素
     27             
     28             if(  c2.a>0 )
     29             {
     30                 Color=bordercolor;       //描边
     31             }
     32             else
     33             {
     34                 c2= tex2D( input, uv.xy +float2 (0,-i/h) );    //提取上方像素 。。。如此这般,共提取4次。
     35                 if(  c2.a>0 )
     36                 {
     37                     Color=bordercolor;
     38                 }
     39                 else
     40                 {
     41                     c2= tex2D( input, uv.xy +float2 (i/w,0) );
     42                     if(  c2.a>0 )
     43                     {
     44                         Color=bordercolor;
     45                     }
     46                     else
     47                     {
     48                         c2= tex2D( input, uv.xy +float2 (-i/w,0) );
     49                         if(  c2.a>0 )
     50                         {
     51                             Color=bordercolor;
     52                         }
     53                     }
     54                 }
     55             }
     56         }
     57         else
     58         {
     59             float4 tempcolor = fontcolor;
     60             
     61             
     62             if( Color.a<0.1)            //由于SL对字体的反锯齿处理,这里有一个非常讨厌的现象:有半透明像素存在,经过测试,如果透明度在0.1一下,则判断为边,否则为字。
     63             {
     64                 tempcolor=bordercolor;
     65             }
     66             
     67             Color=tempcolor;
     68         }
     69     }
     70     
     71 
     72 
     73     return Color; 
     74 }
     75

 然后,按照深蓝的教程,将着色器代码转为Effect,即可使用。效果如下,哈哈,和flash是一模一样的吧

代码下载

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Silverlight像素着色器文字描边效果-改

            上次的描边着色器有两个问题,导致效果不太理想。现在我们来设法改进这两点。 问题一: 当TextBlock的呈现宽度和高度没有正确赋值时,将无法...

    用户1687945
  • 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 操作符重载和隐式类型转换

    C#中,某些类型会定义隐式类型转换和操作符重载。Unity中,有些对象也定义了隐式类型转换和操作符重载。典型情况有:UnityEngine.Object。Uni...

    用户1687945
  • 记一个脚本解释器的开发

    最近可以有1个月左右的空闲,可以稍微整理一下这个脚本解释器的开发过程。 一、缘由   2014年左右,我们使用AIR技术,开发了一个3D战争类型的手游。那时候手...

    用户1687945
  • 走进Java接口测试之日志框架Logback

    对于一个成熟的接口测试框架,日志管理这个是必不可少的。在开发和调试阶段,日志可以帮助我们更快的定位问题;而在测试的运维过程中,日志系统又可以帮助我们记录大部分的...

    高楼Zee
  • 走进Java接口测试之从0到1搭建数据驱动框架(完结篇)

    在前面的几篇文章中,我们介绍了从需求到设计,再到部分功能实现,本篇作为完结篇,我们一起来完成剩下的功能实现,主要为日志管理和性能监控以及有同学提出测试用例多参数...

    高楼Zee
  • linux中samba共享文件-cyl

     说明: comment:提示,在windows的网络邻居上显示为备注。 path:linux上共享目录 valid users: 允许访问...

    柴银磊
  • 【云计算奇妙学习之旅】第二期:云计算

    在上一期的分享中,我们了解到云计算是什么,以及它的发展历程和前景,那本期我们继续分享云计算它是怎样部署呢,它有哪些服务模式,以及华为的云计算又包含什么呢?

    誉天小鹿
  • 看了让人极度舒适的Markdown文章

    毕小朋,CSDN 博客专家,百度阅读 IT 类畅销书作者,著有《精通 Android Studio》;平时喜欢写作,热爱分享,个人博客访问量迄今已超过 280 ...

    用户1682855
  • WePY-小程序框架设计

    摘要 去年11月初,微信小程序开始公测,小程序是一种新的开放能力,开发者可以一用Web相关技术快速开发小程序。这次分享内容包括:小程序开发基础内容;WePY框架...

    IT大咖说
  • Go语言开发,月薪如何达到3万?

    一种编程值多少钱除了自身的技术能力之外,主要还是看市场对于这种编程语言的需求,现在很多的招聘单位对于go语言的岗位上薪资都在3万以上,但是具体看细节要求除了对于...

    程序员互动联盟

扫码关注云+社区

领取腾讯云代金券