OpenGL教程 | 2.了解着色器,并绘制彩色三角形

个人博客食用体验更佳:文章链接

本篇我们会更深入地了解着色器:

  1. 学会着色器如何输入输出
  2. 学会使用Uniform,绘制会随时间变化颜色的图形
  3. 绘制彩色三角形
  4. 定义自己的着色器类

本文参考LearnOpenGL教学网站

经验:建议打开源代码看着学习,光跟着文档的话思路会很乱

下面是我做的笔记

配合源码食用更佳🤫:OpenGL学习源码

向量

数据类型:一般使用vecn(包含n个float分量的默认向量)

重组(灵活的分量选择方式):

//重组的例子
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);

输入与输出

我们给着色器加上输入和输出,让顶点着色器为片段着色器决定颜色。

顶点着色器

#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); // 把输出变量设置为暗红色
}

片段着色器

#version 330 core
out vec4 FragColor;

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

void main()
{
    FragColor = vertexColor;
}

现在运行,就可以看到我们成功将颜色由顶点着色器输入到片段着色器中,将三角形的颜色设置成了深红色。

Uniform

Uniform是一种从CPU中的应用向GPU中的着色器发送数据的方式

我们在片段着色器中声明Uniform

#version 330 core
out vec4 FragColor;

uniform vec4 ourColor; // 在OpenGL程序代码中设定这个变量

void main()
{
    FragColor = ourColor;
}

现在,我们就可以在渲染循环中去改变三角形颜色了。这里我们用让它随时间变化颜色。

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

源代码:Uniform源码

你好,彩色三角形

现在,我们将把颜色数据添加为3个值至vertices数组。我们将把三角形的三个角分别指定为红色、绿色和蓝色。

//顶点数据
float vertices[] = {
    // 位置              // 颜色
     0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f,   // 右下
    -0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f,   // 左下
     0.0f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f    // 顶部
};

我们让顶点着色器接收颜色值,并输出到片段着色器。

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

out vec3 ourColor; // 向片段着色器输出一个颜色

void main()
{
    gl_Position = vec4(aPos, 1.0);
    ourColor = aColor; // 将ourColor设置为我们从顶点数据那里得到的输入颜色
}

再修改一下片段着色器,让他输入颜色。

#version 330 core
out vec4 FragColor;  
in vec3 ourColor;

void main()
{
    FragColor = vec4(ourColor, 1.0);
}

现在我们修改着色器的顶点格式。

// 位置属性
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);

然后我们就可以看到一个彩色的三角形😍

三角形会自动将我们给的三个顶点颜色进行渐变,这是在片段着色器中进行的所谓片段插值(Fragment Interpolation)的结果。

源代码:彩色三角形源码

自己的着色器类

管理着色器类是很麻烦的事,所以我们要写一个类来让我们能更轻松的管理。

我们的着色器类用于:

  1. 打开着色器文件
  2. 编译和链接着色器
  3. use用来激活着色器程序
  4. set用于设置和查询uniform

使用方法

Shader ourShader("path/to/shaders/shader.vs", "path/to/shaders/shader.fs");
...
while(...)
{
    ourShader.use();
    ourShader.setFloat("someUniform", 1.0f);
    DrawStuff();
}

顶点和片段着色器的文件名可以任意取(推荐用shader.vs和shader.fs,很直观)

源代码:着色器类源码


恭喜你又学完了一篇教程🎉,你正在向目标一步一步地进发。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,你可以按照以下步骤创建着色器绘制不同颜色的点: 1. 导入必要的库:`OpenGL.GL`和`OpenGL.GLUT` ```python from OpenGL.GL import * from OpenGL.GLUT import * ``` 2. 创建顶点着色器和片段着色器的源代码字符串: ```python vertex_shader_source = """ #version 330 in vec4 position; void main() { gl_Position = position; } """ fragment_shader_source = """ #version 330 out vec4 fragColor; void main() { fragColor = vec4(1.0, 0.0, 0.0, 1.0); } """ ``` 3. 创建着色器程序并编译着色器源代码: ```python def create_shader_program(): # 创建顶点着色器 vertex_shader = glCreateShader(GL_VERTEX_SHADER) glShaderSource(vertex_shader, vertex_shader_source) glCompileShader(vertex_shader) # 创建片段着色器 fragment_shader = glCreateShader(GL_FRAGMENT_SHADER) glShaderSource(fragment_shader, fragment_shader_source) glCompileShader(fragment_shader) # 创建着色器程序 shader_program = glCreateProgram() glAttachShader(shader_program, vertex_shader) glAttachShader(shader_program, fragment_shader) glLinkProgram(shader_program) return shader_program shader_program = create_shader_program() ``` 4. 创建绘制函数: ```python def draw(): glClear(GL_COLOR_BUFFER_BIT) # 使用着色器程序 glUseProgram(shader_program) # 创建顶点数据 vertices = [ -0.5, -0.5, 0.0, 0.5, -0.5, 0.0, 0.0, 0.5, 0.0 ] # 创建顶点缓冲区对象 vbo = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, vbo) glBufferData(GL_ARRAY_BUFFER, len(vertices) * 4, (GLfloat * len(vertices))(*vertices), GL_STATIC_DRAW) # 指定顶点属性 position_attribute = glGetAttribLocation(shader_program, "position") glEnableVertexAttribArray(position_attribute) glVertexAttribPointer(position_attribute, 3, GL_FLOAT, GL_FALSE, 0, None) # 绘制三个点 glDrawArrays(GL_POINTS, 0, 3) # 关闭顶点属性 glDisableVertexAttribArray(position_attribute) glutSwapBuffers() ``` 5. 设置OpenGL窗口和运行循环: ```python glutInit() glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB) glutInitWindowSize(800, 800) glutCreateWindow(b"OpenGL Window") glutDisplayFunc(draw) glutMainLoop() ``` 完整代码如下: ```python from OpenGL.GL import * from OpenGL.GLUT import * vertex_shader_source = """ #version 330 in vec4 position; void main() { gl_Position = position; } """ fragment_shader_source = """ #version 330 out vec4 fragColor; void main() { fragColor = vec4(1.0, 0.0, 0.0, 1.0); } """ def create_shader_program(): # 创建顶点着色器 vertex_shader = glCreateShader(GL_VERTEX_SHADER) glShaderSource(vertex_shader, vertex_shader_source) glCompileShader(vertex_shader) # 创建片段着色器 fragment_shader = glCreateShader(GL_FRAGMENT_SHADER) glShaderSource(fragment_shader, fragment_shader_source) glCompileShader(fragment_shader) # 创建着色器程序 shader_program = glCreateProgram() glAttachShader(shader_program, vertex_shader) glAttachShader(shader_program, fragment_shader) glLinkProgram(shader_program) return shader_program shader_program = create_shader_program() def draw(): glClear(GL_COLOR_BUFFER_BIT) # 使用着色器程序 glUseProgram(shader_program) # 创建顶点数据 vertices = [ -0.5, -0.5, 0.0, 0.5, -0.5, 0.0, 0.0, 0.5, 0.0 ] # 创建顶点缓冲区对象 vbo = glGenBuffers(1) glBindBuffer(GL_ARRAY_BUFFER, vbo) glBufferData(GL_ARRAY_BUFFER, len(vertices) * 4, (GLfloat * len(vertices))(*vertices), GL_STATIC_DRAW) # 指定顶点属性 position_attribute = glGetAttribLocation(shader_program, "position") glEnableVertexAttribArray(position_attribute) glVertexAttribPointer(position_attribute, 3, GL_FLOAT, GL_FALSE, 0, None) # 绘制三个点 glDrawArrays(GL_POINTS, 0, 3) # 关闭顶点属性 glDisableVertexAttribArray(position_attribute) glutSwapBuffers() glutInit() glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB) glutInitWindowSize(800, 800) glutCreateWindow(b"OpenGL Window") glutDisplayFunc(draw) glutMainLoop() ``` 运行程序后,应该会看到一个红色的三角形,每个顶点的颜色都是相同的。如果想要绘制不同颜色的点,可以修改片段着色器来输出不同的颜色。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值