[OpenGL] 着色器语言GLSL

本文介绍了GLSL的基本概念,包括其在OpenGL中的作用,以及数据类型(如向量、矩阵)的使用。重点讲解了向量操作、输入输出、顶点着色器和片段着色器的接口,以及Uniform的作用。后续还涉及了顶点数据的扩展和练习实例。
摘要由CSDN通过智能技术生成

目录

一 简介

二 数据类型

2.1 向量

2.1.1 向量重组

2.2 输入与输出

2.2.1 顶点着色器

2.2.2 片段着色器

2.2.3 Uniform

三 更多属性

四 练习


本章节源码请点击此处

一 简介

GLSL(Graphics Library Shader Language))是一种类C语言,它是一种为OpenGL设计的编程语言,用于编写图形着色器程序。着色器是运行在图形处理器(GPU)上的小型程序,它们允许开发者对图形管线的各个阶段进行编程控制,以实现复杂的视觉效果和实时渲染功能。

这里主要借鉴的openGL中文手册,唯一不同的是,测试示例和代码改成了Qt+OpenGL,而并非采用原生的C++版本的测试调用

参考此处GLSL原生C++版本GLSL使用请点击此处

在学习这部分之前要对OpenGL的基础先有所了解

二 数据类型

GLSL中包含C等其它语言大部分的默认基础数据类型:intfloatdoubleuintbool。GLSL也有两种容器类型,它们会在这个教程中使用很多,分别是向量(Vector)和矩阵(Matrix)。

2.1 向量

GLSL中的向量是一个可以包含有2、3或者4个分量的容器,分量的类型可以是前面默认基础类型的任意一个。它们可以是下面的形式(n代表分量的数量):

类型含义
vecn包含n个float分量的默认向量
bvecn包含n个bool分量的向量
ivecn包含n个int分量的向量
uvecn包含n个unsigned int分量的向量
dvecn包含n个double分量的向量
  • 向量跟结构体类似,是有自己的分量的,对于一个拥有四个分量的向量(vec4),我们可以这样访问:vec.x vec.y vec.z vec.w  注意vec.w分量不是用作表达空间中的位置的(我们处理的是3D不是4D),而是用在所谓透视除法(Perspective Division)上。

2.1.1 向量重组

  • 向量的分量是允许灵活重组的,但你不能在一个vec2的向量中去获取一个z元素
  • 一个向量可以作为参数传递给不同的向量构造函数,以减少需求参数的数量
vec2 someVec;
vec4 differentVec = someVec.xyxx;
vec3 anotherVec = differentVec.zyw;
vec4 otherVec = someVec.xxxx + anotherVec.yxzy;

vec2 vect = vec2(0.5, 0.7);
vec4 result = vec4(vect, 0.0, 0.0);
vec4 otherResult = vec4(result.xyz, 1.0);

2.2 输入与输出

GLSL关键字 :个着色器都有输入和输出,这样才能进行数据交流和传递。GLSL定义了inout关键字专门来实现这个目的。

  • in:  着色器接收输入
  • out:着色器输出

只要一个输出变量与下一个着色器的输入相匹配,它就会传递下去。

但在顶点有所不同,需要使用loaction中指定输入变量.

  • location:layout (location = n)

2.2.1 顶点着色器

#version 330 core
layout (location = 0) in vec3 aPos; // 位置变量的属性位置值为0

out vec4 vertexColor; // 为片段着色器指定一个颜色输出

void main()
{
    gl_Position = vec4(aPos, 1.0); // 注意我们如何把一个vec3作为vec4的构造器的参数
    vertexColor = vec4(0.5, 0.0, 0.0, 1.0); // 把输出变量设置为暗红色
}

2.2.2 片段着色器

注意: 只有上一个阶段的输出和下一个阶段的输入变量类型命令都相同时,才会被传递

#version 330 core
out vec4 FragColor;

in vec4 vertexColor; // 从顶点着色器传来的输入变量(名称相同、类型相同)

void main()
{
    FragColor = vertexColor;
}

2.2.3 Uniform

  • uniform:Uniform是一种从CPU中的应用向GPU中的着色器发送数据的方式,可以被任何着色器在任意阶段访问,因为他是全局的。
// 顶点着色器
#version 330 core
layout(location = 0) in vec3 aPos;
uniform vec4 ourColor;   // 从CPU 也就是程序接收一个vec4的变量
out vec4 vertexColor;    // 输出一个vec4变量的数据

void main(){
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f);
    vertexColor = ourColor;
}

// 片段着色器
#version 330 core
in  vec4 vertexColor;    // 接收命名为vertexColor的vec4的变量,并输出给下一个阶段
out vec4 FragColor;
void main(){
     FragColor = vertexColor;
}

解释: 定义了uniform变量 等待程序输入一个vec4变量类型的值,然后将这个值作为输出传递给片段着色器

CPU传值部分代码:这样就可以实现整体的

  makeCurrent(); // 拿到当前的上下文 这是很关键的
    int timeValue = QTime::currentTime().second();
    float greenValue = (sin(timeValue)/2.0f) + 0.5f;
    shaderProgramObject.bind();
    QVector4D colorVec(0.0f, greenValue, 0.0f, 1.0f);
// 设置Uniform变量的值
    shaderProgramObject.setUniformValue("ourColor",colorVec);
    shaderProgramObject.release();
    update();
    doneCurrent();

三 更多属性

对于顶点数据是可以把颜色也存放进去的,

    float vertices_data[24] = {
        // 所有的值是在[-1, 1]之间的
        0.25f,  0.0f,  0.0f,1.0f, 0.0f, 0.0f,
        0.0f,  0.5f,  0.0f,0.0f, 1.0f, 0.0f,
        -0.25f, -0.0f,  0.0f,0.0f, 0.0f, 1.0f
    };

这时候对于顶点着色器就需要修改了,与上面的唯一不同是不再用uniform传递颜色

// 顶点着色器
#version 330 core
layout(location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor; // 颜色变量的属性位置值为 1
out vec4 vertexColor;                 // 输出一个vec4变量的数据

void main(){
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0f);
    vertexColor = vec4(aColor,1.0f);
}

// 片段着色器
#version 330 core
in  vec4 vertexColor;    // 接收命名为vertexColor的vec4的变量,并输出给下一个阶段
out vec4 FragColor;
void main(){
     FragColor = vertexColor;
}

这时候就需要更新顶点数据的格式

// 位置属性
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 颜色属性
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3* sizeof(float)));
glEnableVertexAttribArray(1);

四 练习

对应练习的QT版本源码在附录中已经做了具体实现

  1. 修改顶点着色器让三角形上下颠倒: 修改顶点着色器中的y左边为相反数
  2. 使用uniform定义一个水平偏移量,在顶点着色器中使用这个偏移量把三角形移动到屏幕右侧:
  • shaderProgramObject.setUniformValue("xOffset",0.5f);

使用out关键字把顶点位置输出到片段着色器,并将片段的颜色设置为与顶点位置相等(来看看连顶点位置值都在三角形中被插值的结果):

  • 因为把顶点位置输出给了片段着色器中,所以片段着色器中的左下角位置使用的是-0.5f,-0.5f,0.0f,但是颜色取值是0-1f的所有就会被转换成0.0f,0.0f,0.0f--->黑色
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值