zoukankan      html  css  js  c++  java
  • love2d--glsl02变量和语句

     

    Shader分为顶点着色器和片段着色器,GPU先处理顶点再处理片段,大概可以这么理解,

    顶点着色器处理模型里的点,输出处理后的数据,这些数据经过GPU其它模块处理后传入

    片段着色器,经片段着色器综合后渲染。片段处理器的名字也很恰当,表明了它处理的数

    据是一些顶点集合的数据片段。(以上理解仅供参考,如有错误,欢迎指正)

    love2d里片段着色器被称作像素着色器pixelcode,下文也使用像素着色器。

    以上过程如下图,来自此文

     

     

    另外在泡泡网上找到了这两幅图,仅供参考

     

    使用shader时需要先检测显卡是否支持,可以用love.graphics.isSupported("shader")来检测,love.graphics.isSupported可以检测某个特性是否被支持,更多功能检测请参照wiki

     下面介绍一下love2d shader里的变量和函数。

    变量

    基本类型

    名称

    注释

    number

    glsl里的float

    bool

    true false

    int

    整型

     

    复合类型

    名称

    注释

    Image

    glsl里的sample2d

    Texel(tex纹理,uv二维向量)

    glsl里的texture2d

    mat2、mat3、mat4 矩阵

    投影矩阵、变换矩阵等

    vec2、vec3、vec4 向量

    位置、颜色

     

    变量修饰符

    名称

    注释

    extern

    glsl里的uniform,用来和外部程序通信,在shader里只读

    const 

    常量,只读

    varying 

    顶点和像素着色器通信用,必须在两个着色器里都用varying修饰,且在像素着色器里只读

     更多解释请参照wiki

    还可以使用宏#define,即文本替换

    #define A 2,即遇到A就用2替换,关于宏以后遇到再细说。

     

    可以像lua那样使用变量,在shader里变量都有类型,变量名前要加上类型名,即:

    number a=2;

    Image  b;

    矩阵(二维的)和向量(一维的)的初始化如下:

    vec2 a = vec2(1.0,2.0);//直接赋值

    vec2 b = vec2(3.0,4.0);

    vec4 c = vec4(a,b)  

    mat4 m = mat4(1.0)   // 用1.0初始化矩阵对角线

    mat2 n = mat2(a,b); //用向量赋值,行主序

    mat2 k = mat2(1.0,0.0,1.0,0.0); // 直接赋值

     

    还可以使用结构体(类似lua里的table)

    struct myobject //定义一个结构体

    {

    vec2 pos;

    vec4 color;

    };

    myobject mo=myobject(vec2(0.1,0.2),vec4(0.1,0.2,0.3,0));

    向量成员可以使用x,y,z,w来访问位置类型的,或者r,g,b,a访问颜色类型的,或者s,t,p,q访问纹理坐标类型的,或者使用数组下标[i]。

    矩阵成员可以用数组下标,如m是一个矩阵,m[0]取第一列,m[2][3]取具体值。

    注意shader里的数组下标是从0开始的。

    结构体可以直接用.访问,如上文的mo.pos。

     

    语句 

    shader里的控制语句和C语言类似,

    if(exp)

    ...;

    else

    ...;

     

    for (initialization; bool expression; loop expression)  

    ...;

     

    while(exp)

    ...;

     

    do

    ...;

    while(exp);

    跳转语句有continue,break,discard,其中discard只在像素shader中使用,它将在不写入帧缓存或者深度缓存的情况下,终止当前的shader。

     

    函数

    像素着色器至少包含名为effect的函数,该函数用来处理所绘制对象的颜色变换。

    顶点着色器至少包含名为position的函数,该函数用来处理所绘制对象的顶点位置变换。

    这两个函数可以理解为shader的入口函数即main。

    像素着色器的定义如下:

    vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords )

    参数详解

    vec4 color 和love.graphics.setColor类似,不过它的取值范围是0--1.0,

          或者是逐像素的Mesh color(以后再介绍)

    Image texture 正在绘制的Image或canvas

    vec2 texture_coords 像素相对于纹理的坐标,取值范围是0--1.0,y轴朝上,(1,1)是右上角

    vec2 screen_coords 像素相对于屏幕的坐标,没有归一化,和love2d里的类似

    返回值

    vec4 返回一个rgba类型的颜色向量

    注意

      如果同时绘制多个canvas(如用love.graphics.setCanvas),可以使用effects替代effect,

    单独处理每个canva,effects的原型如下:

    void effects( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords )
    {
        // love_Canvases是一个可写的vec4 colors数组, 每个索引匹配一个canvas。

      //如果你没有对所有激活的canvas赋值,将会出错。
        love_Canvases[0] = color;
    }

      

     顶点着色器定义如下:

     vec4 position( mat4 transform_projection, vec4 vertex_position )

    参数

    mat4 transform_projection 变换矩阵受love.graphics.translate以及投影矩阵影响

    vec4 vertex_position 当前向量的原始坐标

    返回值

    vec4 返回一个vec4向量类型的转换后的坐标

     

    注意 

    像素着色器在每次绘制像素到屏幕事都会调用,顶点着色器在每次顶点绘制到屏幕都会调用。

    可以在一段着色器代码里使用两者,使用宏区分,即

    #ifdef VERTEX

    ...顶点代码

    #endif 

    #ifdef PIXEL

    ...像素代码

    #endif

     

    下面是一段简单的示例:(注意shader是类C的语言,if else和lua不同

    function love.load()
        
        if not love.graphics.isSupported("shader") then
          print("your gpu not support shader")
          return
        end
    
        local shadercode=[[
        
        extern number time; //time变量用来和外部交换,外部程序可以给这个time传值
    
        vec4 test(number x)
        {
            vec4 color;
            if( x>-1 && x<-0.5 )
               color = vec4(0.8,0.8,0.8,1.0);
            else if(x>-0.5 && x<0 )
               color = vec4(0.4,0.4,0.8,1.0);
            else if(x>0 && x<0.5)
               color = vec4(0.2,0.2,0.4,1.0);
            else
               color = vec4(0.1,0.1,0.1,1.0); 
          return color;
        }
        
        
            
            vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords)
            {   
                
                //(r,g,b,a)颜色,取值0-1,这里对time变量进行操作保证结果在0-1范围内
               return test(cos(time));
            }
        ]]
        --1 创建shader
        myeffect = love.graphics.newShader(shadercode) 
    
    end
    
    function love.draw()
        -- 2 关闭shader,矩形为默认效果
        love.graphics.setShader()
        love.graphics.rectangle('fill', 10,10,790,285)
    
        -- 2 加载effect shader,矩形效果绚丽
        love.graphics.setShader(myeffect)
        love.graphics.rectangle('fill', 10,305,790,285)
    end
    
    local t = 0
    function love.update(dt)
        t = t + dt
        myeffect:send("time", t) --3 更新
    end

     附:

    参考文章:http://blog.csdn.net/racehorse/article/details/6634830

  • 相关阅读:
    yocto/bitbake 学习资源
    QEMU/KVM学习资源
    ubuntu 中创建和删除用户
    git 重命名本地和远程分支
    Ubuntu 上搭建 FTP 服务器
    gdb 常见用法
    git log 显示与特定文件相关的 commit 信息
    基于 qemu system mode 运行 arm 程序
    基于 qemu user mode 运行 aarch64 程序
    checking in(airport)
  • 原文地址:https://www.cnblogs.com/xdao/p/love2d_shader02.html
Copyright © 2011-2022 走看看