cocos cretor shader effect-the book of shader-5.图案

Patterns 图案

前面章节

  1. TheBookofShader开始
  2. Shaping functions(造型函数)
  3. Color(颜色)
  4. Shapes(形状)
  5. Patterns(图案)

因为着色器按一个个像素执行,那么无论你重复一个图形多少次,计算的数量仍然是个常数。

在这里插入图片描述

本章中我们将综合我们目前所学的并应用在画布上。和前几章一样,我们的策略依然基于乘以空间坐标(0到1之间),这样我们的画的在0到1之间的图形就会重复地形成网格。

网格-小试身手

"网格提供一种基于人的直觉发明事物的框架,并且可以颠覆。自然的混沌肌理提供一种对比和秩序的迹象。从早期罗马浴场里的陶瓷图案到几何镶嵌,人们那时候就习惯用网格来点缀他们的生活。"10 PRINT, Mit Press, (2013)

首先让我们记住 fract() 函数。它返回一个数的分数部分,本质上是除1的余数(mod(x,1.0))。换句话说, fract() 返回小数点后的数。 我们单位化的坐标系变量 (st) 已经是 0.0 到 1.0 之间的了。所以像下面这么做并没有必要:

void main(){
    vec2 st = gl_FragCoord.xy/u_resolution;
    vec3 color = vec3(0.0);
    st = fract(st);
    color = vec3(st,0.0);
    gl_FragColor = vec4(color,1.0);
}

但如果我们放大单位化坐标系 — 比如说3倍 — 我们会得到三组 0 到 1 的线性插值的数列:第一组在 0-1 之间,第二组浮点数在 1-2 之间以及第三组在 2-3 之间的浮点数。

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform float u_time;

float circle(in vec2 _st, in float _radius){
    vec2 l = _st-vec2(0.5);
    return 1.-smoothstep(_radius-(_radius*0.01),
                         _radius+(_radius*0.01),
                         dot(l,l)*4.0);
}

void main() {
	vec2 st = gl_FragCoord.xy/u_resolution;
    vec3 color = vec3(0.0);

    st *= 3.0;      // Scale up the space by 3
    st = fract(st); // Wrap around 1.0

    // Now we have 9 spaces that go from 0-1

    color = vec3(st,0.0);
    //可以尝试取消注释
    //color = vec3(circle(st,0.5));   

	gl_FragColor = vec4(color,1.0);
}

效果

在这里插入图片描述

现在是时候在子空间(网格单元的空间)里画点什么了。取消27行的

试试下面的练习来深入理解:

  • 把空间乘以不同的数。试试用浮点数,还有分别给x和y不同的系数。
  • 把这个平铺技巧做成一个可以反复使用的函数。
  • 把画布分成 3 行 3 列。 指出如何定义行和列的线程的,并用这种方式改变显示着的图形。试着做一个井字棋。

在图案内部应用矩阵

鉴于每个细分或者说单元都是我们正在使用的单位化坐标系的小单元,我们可以对每个内部空间施以矩阵变换来平移,旋转和缩放。

// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform float u_time;

#define PI 3.14159265358979323846

//控制图像的旋转
vec2 rotate2D(vec2 _st, float _angle){
    _st -= 0.5;
    _st =  mat2(cos(_angle),-sin(_angle),
                sin(_angle),cos(_angle)) * _st;
    _st += 0.5;
    return _st;
}

vec2 tile(vec2 _st, float _zoom){
    _st *= _zoom;
    return fract(_st);
}

//创建盒子
float box(vec2 _st, vec2 _size, float _smoothEdges){
    _size = vec2(0.5)-_size*0.5;
    vec2 aa = vec2(_smoothEdges*0.5);
    vec2 uv = smoothstep(_size,_size+aa,_st);
    uv *= smoothstep(_size,_size+aa,vec2(1.0)-_st);
    return uv.x*uv.y;
}

void main(void){
    vec2 st = gl_FragCoord.xy/u_resolution.xy;
    vec3 color = vec3(0.0);

    // 拆分成4个格子
    st = tile(st,4.);

    // 矩阵旋转45度
    st = rotate2D(st,PI*0.25);

    // Draw a square
    color = vec3(box(st,vec2(0.7),0.01));
    // color = vec3(st,0.0);

    gl_FragColor = vec4(color,1.0);
}

在这里插入图片描述

  • 想想怎么让这些图案有趣的动起来。考虑颜色,形状,运动的变换。做三种动画。
  • 通过组合不同的形状重新创造更复杂的图案。
  • 结合多层图案来制作你自己的 Scottish Tartan Patterns.

偏移图案

So let’s say we want to imitate a brick wall. Looking at the wall, you can see a half brick offset on x in every other row. How we can do that?

假如我们想要模仿砖墙。看,下面的墙,你是不是看到一半的砖在x方向上偏移了一半砖的长度,没隔一行偏移一次。我们如何实现?

在这里插入图片描述

第一步我们需要知道某行的线程是奇数还是偶数,以为我们可以通过奇偶来决定是否要在x方向上偏移那一行。

我们需要两段来解决这个问题

要判断我们的线程是一个奇数行或者偶数行,我们要用 2.0 的 mod() 。 然后根据结果是否大于 1.0 来判断。看一下下面的函数,取消最后两行的注释。

在这里插入图片描述

y = mod(x,2.0);
// y = mod(x,2.0) < 1.0 ? 0. : 1. ;
// y = step(1.0,mod(x,2.0));

正如你所见,我们可以用一个 三元算符号 (第二行)来检查 2.0 的mod()(余数)小于 1.0 或者类似地,我们用 step() 函数做相同的操作,但(其实)更快。为什么呢? 因为虽然要知道每个显卡如何优化和编译代码并不容易,但是可以安全地假设内置函数总比非内置的函数快。任何时候你都以调用内置函数,干嘛不用呢!

现在我们有这些找出奇数的方程,这样我们就可以给奇数行一个偏移量,然后就可以把 砖块 做出拼砖的效果。下面代码的第14行便是我们用来“侦测”奇数行,并予之半个单位在x上的偏移的。注意到对偶数行,函数的返回值是 0.0, 0.0 乘以 0.5 得到一个 0.0 的偏移。 但是奇数行我们用函数的返回值, 1.0, 乘以偏移量 0.5,这样便向坐标系的 x 轴偏移了 0.5。

vec2 rotate2D(vec2 st,float angle)
  {
    st-=vec2(.5);
    st=mat2(cos(angle),-sin(angle),sin(angle),cos(angle))*st;
    st+=vec2(.5);
    return st;
  }

  vec2 tile(vec2 st,float zoom)
  {
    st*=zoom;
    st.x+=step(1.,mod(st.y,2.))*.5;
    return fract(st);
  }

  float box(vec2 st,vec2 size,float smoothEdges)
  {
    size=vec2(.5)-size*.5;
    //st=rotate2D(st,sin(cc_time.x)*PI);
    vec2 offset=vec2(smoothEdges*.5);
    vec2 uv=smoothstep(size,size+offset,st);
    uv*=smoothstep(size,size+offset,vec2(1.)-st);
    return uv.x*uv.y;
  }

void main(void){
    vec4 o = vec4(1, 1, 1, 1);

    #if USE_TEXTURE
      CCTexture(texture, v_uv0, o);
    #endif
    o *= v_color;
    ALPHA_TEST(o);


    vec3 _color=vec3(0.);
    vec2 st=v_uv0;
    st=tile(st,4.);
    //可以试着把这个旋转注释下看看效果
    st=rotate2D(st,PI*.25);
    float boxval=box(st,vec2(.7),.01);
    _color=vec3(boxval);

    gl_FragColor = vec4(_color,1.);
}

在这里插入图片描述

Truchet 瓷砖

目前我们学了如何区分奇数行/列或偶数行/列,(类似的),(我们也)可能再用(这个技巧)根据位置来设计元素。 考虑到 Truchet Tiles 的例子,即一个单一设计元素可以以四种不同的方式呈现:

在这里插入图片描述

通过改变对角瓷砖的图案,便可能组成无限种复杂设计的可能。

在这里插入图片描述

仔细观察 rotateTilePattern() 函数, 它把坐标空间细分成四个单元并赋予每一个旋转值。

// Author @patriciogv ( patriciogonzalezvivo.com ) - 2015

#ifdef GL_ES
precision mediump float;
#endif

#define PI 3.14159265358979323846

uniform vec2 u_resolution;
uniform float u_time;

vec2 rotate2D (vec2 _st, float _angle) {
    _st -= 0.5;
    _st =  mat2(cos(_angle),-sin(_angle),
                sin(_angle),cos(_angle)) * _st;
    _st += 0.5;
    return _st;
}

vec2 tile (vec2 _st, float _zoom) {
    _st *= _zoom;
    return fract(_st);
}

vec2 rotateTilePattern(vec2 _st){

    //  Scale the coordinate system by 2x2
    _st *= 2.0;

    //  Give each cell an index number
    //  according to its position
    float index = 0.0;
    index += step(1., mod(_st.x,2.0));
    index += step(1., mod(_st.y,2.0))*2.0;

    //      |
    //  2   |   3
    //      |
    //--------------
    //      |
    //  0   |   1
    //      |

    // Make each cell between 0.0 - 1.0
    _st = fract(_st);

    // Rotate each cell according to the index
    if(index == 1.0){
        //  Rotate cell 1 by 90 degrees
        _st = rotate2D(_st,PI*0.5);
    } else if(index == 2.0){
        //  Rotate cell 2 by -90 degrees
        _st = rotate2D(_st,PI*-0.5);
    } else if(index == 3.0){
        //  Rotate cell 3 by 180 degrees
        _st = rotate2D(_st,PI);
    }

    return _st;
}

void main (void) {
    vec2 st = gl_FragCoord.xy/u_resolution.xy;

    st = tile(st,3.0);
    st = rotateTilePattern(st);

    // Make more interesting combinations
    // st = tile(st,2.0);
    // st = rotate2D(st,-PI*u_time*0.25);
    // st = rotateTilePattern(st*2.);
    // st = rotate2D(st,PI*u_time*0.25);

    // step(st.x,st.y) just makes a b&w triangles
    // but you can use whatever design you want.
    gl_FragColor = vec4(vec3(step(st.x,st.y)),1.0);
}

在这里插入图片描述

  • 注释,取消注释,以及复制第69到72行来创作新的设计。
  • 把黑白三角变成其他元素,例如:半圆,旋转的方形或直线。
  • 编写根据元素自身位置旋转的图形代码。
  • 创作一个根据其位置改变其他属性的图案。
  • 想想其他能用这章原理的案例,不一定是图案. (例: 易经卦)

在这里插入图片描述

cocos源码:

// Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.  

CCEffect %{
  techniques:
  - passes:
    - vert: vs
      frag: fs
      blendState:
        targets:
        - blend: true
      rasterizerState:
        cullMode: none
      properties:
        texture: { value: white }
        alphaThreshold: { value: 0.5 }
        patternType: {value: 1.0}
}%


CCProgram vs %{
  precision highp float;

  #include <cc-global>
  #include <cc-local>

  in vec3 a_position;
  in vec4 a_color;
  out vec4 v_color;

  #if USE_TEXTURE
  in vec2 a_uv0;
  out vec2 v_uv0;
  #endif

  void main () {
    vec4 pos = vec4(a_position, 1);

    #if CC_USE_MODEL
    pos = cc_matViewProj * cc_matWorld * pos;
    #else
    pos = cc_matViewProj * pos;
    #endif

    #if USE_TEXTURE
    v_uv0 = a_uv0;
    #endif

    v_color = a_color;

    gl_Position = pos;
  }
}%


CCProgram fs %{
  precision highp float;
  
  #include <alpha-test>
  #include <texture>
  #include <cc-local>
  #include <cc-global>

  in vec4 v_color;

  #if USE_TEXTURE
  in vec2 v_uv0;
  uniform sampler2D texture;
  #endif

  uniform patternArg{
    float patternType;
  };

  float PI=3.1415726;

  vec2 rotate2D(vec2 st,float angle)
  {
    st-=vec2(.5);
    st=mat2(cos(angle),-sin(angle),sin(angle),cos(angle))*st;
    st+=vec2(.5);
    return st;
  }

  vec2 tile(vec2 st,float zoom)
  {
    st*=zoom;
    st.x+=step(1.,mod(st.y,2.))*.5;
    return fract(st);
  }

  float box(vec2 st,vec2 size,float smoothEdges)
  {
    size=vec2(.5)-size*.5;
    //st=rotate2D(st,sin(cc_time.x)*PI);
    vec2 offset=vec2(smoothEdges*.5);
    vec2 uv=smoothstep(size,size+offset,st);
    uv*=smoothstep(size,size+offset,vec2(1.)-st);
    return uv.x*uv.y;
  }

  float circle(in vec2 _st,in float _radius)
  {
    vec2 d=_st-vec2(.5);
    return 1.-smoothstep(_radius-(_radius*.01),_radius+(_radius-.01),dot(d,d),*4.);
  }

  vec2 rotateTilePattern(vec2 _st)
  {
    _st*=2.0;
    float index=0.;
    index+=step(1.,mod(_st.x,2.));
    index+=step(1.,mod(_st.y,2.))*2.;

    _st=fract(_st);
    if(index==1.)
    {
      _st=rotate2D(_st,PI*.5);
    }
    else if(index==2.)
    {
      _st=rotate2D(_st,PI*-.5);
    }
    else if(index==3.)
    {
      _st=rotate2D(_st,PI);
    }
    return _st;
  }

  vec3 truchet(vec2 st)
  {
    //st=tile(st,3.0);
    //st=rotateTilePattern(st);

    st=tile(st,2.);
    st=rotate2D(st,-PI*cc_time.x*.25);
    st=rotateTilePattern(st*2.);
    st=rotate2D(st,PI*cc_time.x*.25);

    //step(st.x,st.y);

    return vec3(step(st.x,st.y));
  }

  void main () {
    vec4 o = vec4(1, 1, 1, 1);

    #if USE_TEXTURE
      CCTexture(texture, v_uv0, o);
    #endif
    o *= v_color;
    ALPHA_TEST(o);


    vec3 _color=vec3(0.);
    vec2 st=v_uv0;
    if(patternType==1.)
    {
      st*=3.;
      st=fract(st);
      _color=vec3(st,0.); 
    }
    else if(patternType==2.)
    {
      st=tile(st,4.);
      st=rotate2D(st,PI*.25);
      float boxval=box(st,vec2(.7),.01);
      _color=vec3(boxval);
    }
    else if(patternType==3.)
    {
      _color=truchet(st);
    }

    gl_FragColor = vec4(_color,1.);
  }
}%


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Cocos Creator是一款面向游戏开发者的跨平台游戏开发工具,它集成了Cocos2d-x游戏引擎和Cocos Studio编辑器,支持多种平台上的游戏开发,如iOS、Android、Windows等。 消灭星星是一款基于Cocos Creator开发的游戏。在游戏中,玩家需要消除屏幕上的星星,以获得分数。游戏开始时,屏幕上会随机生成一些星星,玩家可以通过点击相连的星星来消除它们。消除的星星越多,得到的分数就越高。玩家可以通过不断消除星星来刷新高分记录,挑战自己的极限。 在消灭星星游戏中,Cocos Creator提供了丰富的功能和工具,为游戏开发者提供了便利。开发者可以使用Cocos Creator的图形界面编辑器来创建游戏场景、导入资源和设置游戏规则等。同时,Cocos Creator还提供了强大的脚本编写功能,开发者可以使用JavaScript或TypeScript编写游戏逻辑,实现游戏中的各种功能。 除了基本的消除星星玩法,Cocos Creator还支持添加特殊道具、关卡设计、人物角色等功能。开发者可以根据自己的需求,自定义游戏的玩法和功能,使游戏更加有趣和有挑战性。 总而言之,Cocos Creator游戏开发工具提供了强大的功能和便捷的开发环境,使开发者可以轻松地开发出各种各样的游戏,包括消灭星星这样的小而精致的休闲游戏。无论是想要学习游戏开发还是实现自己的游戏创意,Cocos Creator都是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值