zoukankan      html  css  js  c++  java
  • 着色器详解

    在顶点着色器中,每个输入变量叫做顶点属性

    着色器语言之变量类型
    1>uniform:

    其实就是统一(全局)变量,统一变量通常保存在所谓的“常量存储”中,uniform变量是外部(cpu)application程序传递给(顶点和片元)(GPU)着色器的变量,该变量不会随着顶点或片元的变化而变化,除非应用程序对它进行了更新。在GLSL语言中,其类似于C语言中的常量const,它不能被shader程序修改,也就是个只读变量,只能读,不能更改。

    uniform 的空间被顶点和片元着色器共享,因此若在一个顶点着色器中声明了uniform,相当于在片元着色器中也声明过了。

    uniform变量一般用来表示:变换矩阵,材质,光照参数和颜色等信息。

    uniform变量在所有可用的着色阶段之间都是共享的。

    例如:

    我们设置一个给图元着色的颜色值,此时可以声明一个uniform变量,将颜色值信息传递到着色器中。而着色器中会进行如下声明:

    uniform vec4 color;

    在片元着色器中设置:

    1 #version 330 core
    2 out vec4 FragColor;
    3 
    4 uniform vec4 ourColor; // 在OpenGL程序代码中设定这个变量
    5 
    6 void main()
    7 {
    8     FragColor = ourColor;
    9 }

    我们在片段着色器中声明了一个uniform vec4ourColor,并把片段着色器的输出颜色设置为uniform值的内容。因为uniform是全局变量,我们可以在任何着色器中定义它们,而无需通过顶点着色器作为中介。顶点着色器中不需要这个uniform,所以我们不用在顶点着色器中定义颜色。

    这个uniform现在还是空的;我们还没有给它添加任何数据,所以下面我们就做这件事。我们首先需要找到着色器中uniform属性的索引/位置值。当我们得到uniform的索引/位置值后,我们就可以更新它的值了。这次我们不去给像素传递单独一个颜色,而是让它随着时间改变颜色:

    1 float timeValue = glfwGetTime();
    2 float greenValue = (sin(timeValue) / 2.0f) + 0.5f;
    3 int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");
    4 glUseProgram(shaderProgram);
    5 glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);

    首先我们通过glfwGetTime()获取运行的秒数。然后我们使用sin函数让颜色在0.0到1.0之间改变,最后将结果储存到greenValue里。

    接着,我们用glGetUniformLocation查询uniform ourColor的位置值。我们为查询函数提供着色器程序和uniform的名字(这是我们希望获得的位置值的来源)。如果glGetUniformLocation返回-1就代表没有找到这个位置值。

    最后,我们可以通过glUniform4f函数设置uniform值。注意,查询uniform地址不要求你之前使用过着色器程序,但是更新一个uniform之前你必须先使用程序(调用glUseProgram),因为它是在当前激活的着色器程序中设置uniform的。

    如果我们打算让颜色慢慢变化,我们就要在游戏循环的每一次迭代中(所以他会逐帧改变)更新这个uniform,否则三角形就不会改变颜色。所以我们把这5行代码放在渲染循环中。

    glUniform的功能:为当前程序对象指定Uniform变量的值
    void glUniform4f(GLint location,  GLfloat v0,  GLfloat v1,  GLfloat v2,  GLfloat v3); 

    location指明要更改的uniform变量的位置,

    v0,v1,v2,v3指明在指定的uniform变量中要使用的新值

    1、为什么是greenValue?

    只因为放在了RGB中第二个位置,如果放在第一个位置,则为红色。

    2、为什么是变成了黑色?

    因为用了sin让值在0-1中渐变,当为0的时候,就变成了黑色。同理,如果设置了另外的RGB中的值,视情况而定。

    2>attribute变量

    attribute变量是只能在vertex shader中使用的变量。(它不能在fragment shader中声明attribute变量,也不能被fragment shader中使用)

    一般用attribute变量来表示一些顶点的数据,如:顶点坐标,法线,纹理坐标,顶点颜色等。

    例如:

    1 uniform mat4 u_matViewProjection;
    2 attribute vec4 a_position;
    3 attribute vec2 a_texCoord0;
    4 varying vec2 v_texCoord;
    5 void main(void)
    6 {
    7 gl_Position = u_matViewProjection * a_position;
    8 v_texCoord = a_texCoord0;
    9 }

    3>varying变量

    varying变量是vertex和fragment shader之间做数据传递用的。一般vertex shader修改varying变量的值,然后fragment shader使用该varying变量的值。因此varying变量在vertex和fragment shader二者之间的声明必须是一致的。

    例如:

     1 // Vertex shader
     2 uniform mat4 u_matViewProjection;
     3 attribute vec4 a_position;
     4 attribute vec2 a_texCoord0;
     5 varying vec2 v_texCoord; // Varying in vertex shader
     6 void main(void)
     7 {
     8 gl_Position = u_matViewProjection * a_position;
     9 v_texCoord = a_texCoord0;//被修改
    10 }
    11 
    12 
    13 // Fragment shader
    14 precision mediump float;
    15 varying vec2 v_texCoord; // Varying in fragment shader
    16 uniform sampler2D s_baseMap;
    17 uniform sampler2D s_lightMap;
    18 void main()
    19 {
    20 vec4 baseColor;
    21 vec4 lightColor;
    22 baseColor = texture2D(s_baseMap, v_texCoord);
    23 lightColor = texture2D(s_lightMap, v_texCoord);//被使用
    24 gl_FragColor = baseColor * (lightColor + 0.25);
    25 }

    4>in/out

    in --输入

    out--输出

    在顶点着色器中的out变量在片元着色器中就是对应的in变量,因为片元着色器的输入就是顶点着色器的输出

    in out定义的变量的值会在openGL每次执行着色器的时候更新(如果处理的是顶点,那么这里会为每个顶点传递新的值;如果处理的是片元,那么会为每个片元传递新的值)

  • 相关阅读:
    关于Update语句在不同数据库中的差别
    MSIL指令速查表
    一个对于博客园的建议
    代码风格关于if语句
    关于Page.cs文件中注释的一点补充
    在Java、C#和C++中遍历集合
    BPEL4WS的开源Java实现
    【Linux】linux固定ip
    【Linux】【MySQL】MySQL主从数据库
    wpf 写个简单的控件吧
  • 原文地址:https://www.cnblogs.com/keguniang/p/9873052.html
Copyright © 2011-2022 走看看