你好,三角形
1.绘制两个彼此相连的三角形
画两个独立的三角形,给出两个三角形顶点,使用GL_TRIANGLES绘图即可。
关键代码
void MyOpenglWgt::initializeGL()
{
initializeOpenGLFunctions();
// 1. 创建ShaderProgram着色器:加载顶点着色器代码和片元着色器代码
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,
"#version 330 core\n"
"layout(location = 0) in vec2 aPos;\n"
"void main() { gl_Position = vec4(aPos, 0.0, 1.0); }"
);
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main() { FragColor = vec4(1.0, 0.5, 0.2, 1.0); }"
);
shaderProgram.link();
vao.create();
vao.bind();
vbo.create();
vbo.bind();
vbo.setUsagePattern(QOpenGLBuffer::DynamicDraw);
// 顶点数据
float vertices[] = {
// 第一个三角形
-1.0f, -0.5f, // 左下角
0.0f, -0.5f, // 右下角
-0.5f, 0.5f, // 顶点
// 第二个三角形
0.0f, -0.5f, // 左下角
1.0f, -0.5f, // 右下角
0.5f, 0.5f, // 顶点
};
vbo.allocate(vertices, sizeof(vertices));
// 配置顶点属性
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
vbo.release();
vao.release();
}
void MyOpenglWgt::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
shaderProgram.bind();
vao.bind();
glDrawArrays(GL_TRIANGLES, 0, 6); // GL_TRIANGLES:以每三个顶点绘制一个独立的三角形
vao.release();
shaderProgram.release();
}
效果图
2.创建相同的两个三角形,但对它们的数据使用不同的VAO和VBO
在初始化时候,直接用两个vao和vbo分别存储两个三角形。
在绘制时,先绑定第一个VAO,绘制第一个三角形,然后绑定第二个VAO,绘制第二个。
关键代码
void MyOpenglWgt::initializeGL()
{
initializeOpenGLFunctions();
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,
"#version 330 core\n"
"layout(location = 0) in vec2 aPos;\n"
"void main() { gl_Position = vec4(aPos, 0.0, 1.0); }"
);
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main() { FragColor = vec4(1.0, 0.5, 0.2, 1.0); }"
);
shaderProgram.link();
vao.create();
vao.bind();
vbo.create();
vbo.bind();
vbo.setUsagePattern(QOpenGLBuffer::DynamicDraw);
// 顶点数据
float vertices[] = {
// 第一个三角形
-1.0f, -0.5f, // 左下角
0.0f, -0.5f, // 右下角
-0.5f, 0.5f, // 顶点
};
vbo.allocate(vertices, sizeof(vertices));
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
vbo.release();
vao.release();
vao_2.create();
vao_2.bind();
vbo_2.create();
vbo_2.bind();
vbo_2.setUsagePattern(QOpenGLBuffer::DynamicDraw);
// 顶点数据
float vertices2[] = {
// 第二个三角形
0.0f, -0.5f, // 左下角
1.0f, -0.5f, // 右下角
0.5f, 0.5f, // 顶点
};
vbo_2.allocate(vertices2, sizeof(vertices2));
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
vbo_2.release();
vao_2.release();
}
void MyOpenglWgt::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
shaderProgram.bind();
vao.bind();
glDrawArrays(GL_TRIANGLES, 0, 3);//绘制第一个三角形
vao.release();
vao_2.bind();
glDrawArrays(GL_TRIANGLES, 0, 3);//绘制第二个三角形
vao_2.release();
shaderProgram.release();
}
效果图
3.创建两个着色器程序,第二个程序使用一个不同的片段着色器
在初始化时,再添加一个着色器,修改着色器代码中的FragColor值。
在绘制时,使用不同的着色器绘制三角形即可。
关键代码
void MyOpenglWgt::initializeGL()
{
initializeOpenGLFunctions();
// 第一个着色器
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,
"#version 330 core\n"
"layout(location = 0) in vec2 aPos;\n"
"void main() { gl_Position = vec4(aPos, 0.0, 1.0); }"
);
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main() { FragColor = vec4(1.0, 0.5, 0.2, 1.0); }"
);
shaderProgram.link();
vao.create();
vao.bind();
vbo.create();
vbo.bind();
vbo.setUsagePattern(QOpenGLBuffer::DynamicDraw);
// 上传第一个三角形的顶点数据并配置顶点属性
float vertices[] = {
// 第一个三角形
-1.0f, -0.5f, // 左下角
0.0f, -0.5f, // 右下角
-0.5f, 0.5f, // 顶点
};
vbo.allocate(vertices, sizeof(vertices));
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
vbo.release();
vao.release();
// 第二个着色器
shaderProgram_2.addShaderFromSourceCode(QOpenGLShader::Vertex,
"#version 330 core\n"
"layout(location = 0) in vec2 aPos;\n"
"void main() { gl_Position = vec4(aPos, 0.0, 1.0); }"
);
shaderProgram_2.addShaderFromSourceCode(QOpenGLShader::Fragment,
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main() { FragColor = vec4(0.9, 0.6, 0.8, 1.0); }"
);
shaderProgram_2.link();
vao_2.create();
vao_2.bind();
vbo_2.create();
vbo_2.bind();
vbo_2.setUsagePattern(QOpenGLBuffer::DynamicDraw);
// 上传第二个三角形的顶点数据并配置顶点属性
float vertices2[] = {
// 第二个三角形
0.0f, -0.5f, // 左下角
1.0f, -0.5f, // 右下角
0.5f, 0.5f, // 顶点
};
vbo_2.allocate(vertices2, sizeof(vertices2));
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
vbo_2.release();
vao_2.release();
}
void MyOpenglWgt::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
// 绘制第一个三角形
shaderProgram.bind();
vao.bind();
glDrawArrays(GL_TRIANGLES, 0, 3);
vao.release();
shaderProgram.release();
// 绘制第二个三角形
shaderProgram_2.bind();
vao_2.bind();
glDrawArrays(GL_TRIANGLES, 0, 3);
vao_2.release();
shaderProgram_2.release();
}
效果图
着色器
1.修改顶点着色器让三角形上下颠倒
使用两个相同的三角形顶点数据,在顶点着色器中将y轴的值改为负值即可。
关键代码
void MyOpenglWgt::initializeGL()
{
initializeOpenGLFunctions();
// 顶点数据
float vertices[] = {
-1.0f, -0.5f, // 左下角
0.0f, -0.5f, // 右下角
-0.5f, 0.0f, // 顶点
};
// 第一个着色器
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,
"#version 330 core\n"
"layout(location = 0) in vec2 aPos;\n"
"void main() { gl_Position = vec4(aPos, 0.0, 1.0); }"
);
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main() { FragColor = vec4(1.0, 0.5, 0.2, 1.0); }"
);
shaderProgram.link();
vao.create();
vao.bind();
vbo.create();
vbo.bind();
vbo.setUsagePattern(QOpenGLBuffer::DynamicDraw);
vbo.allocate(vertices, sizeof(vertices));
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
vbo.release();
vao.release();
// 第二个着色器
shaderProgram_2.addShaderFromSourceCode(QOpenGLShader::Vertex,
"#version 330 core\n"
"layout(location = 0) in vec2 aPos;\n"
"void main() { gl_Position = vec4(aPos.x, -aPos.y, 0.0, 1.0); }"
);
shaderProgram_2.addShaderFromSourceCode(QOpenGLShader::Fragment,
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main() { FragColor = vec4(0.9, 0.6, 0.8, 1.0); }"
);
shaderProgram_2.link();
vao_2.create();
vao_2.bind();
vbo_2.create();
vbo_2.bind();
vbo_2.setUsagePattern(QOpenGLBuffer::DynamicDraw);
vbo_2.allocate(vertices, sizeof(vertices));
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
vbo_2.release();
vao_2.release();
}
效果图
2.使用uniform定义一个水平偏移量,在顶点着色器中使用这个偏移量把三角形移动到屏幕右侧
在顶点着色器中,定义变量offset,并将该值加到x轴上。
uniform float offset;
void main() { gl_Position = vec4(aPos.x + offset, aPos.y, 0.0, 1.0);
Uniform的设置时机很重要: 在设置uniform之前,必须确保着色器程序已经绑定,否则setUniformValue可能不起作用。
shaderProgram_2.bind();
shaderProgram_2.setUniformValue("offset", 0.8f);
shaderProgram_2.release();
关键代码
void MyOpenglWgt::initializeGL()
{
initializeOpenGLFunctions();
// 顶点数据
float vertices[] = {
-1.0f, -0.5f, // 左下角
0.0f, -0.5f, // 右下角
-0.5f, 0.0f, // 顶点
};
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,
"#version 330 core\n"
"layout(location = 0) in vec2 aPos;\n"
"void main() { gl_Position = vec4(aPos, 0.0, 1.0); }"
);
shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main() { FragColor = vec4(1.0, 0.5, 0.2, 1.0); }"
);
shaderProgram.link();
vao.create();
vao.bind();
vbo.create();
vbo.bind();
vbo.setUsagePattern(QOpenGLBuffer::DynamicDraw);
vbo.allocate(vertices, sizeof(vertices));
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
vbo.release();
vao.release();
// 第二个着色器
shaderProgram_2.addShaderFromSourceCode(QOpenGLShader::Vertex,
"#version 330 core\n"
"layout(location = 0) in vec2 aPos;\n"
"uniform float offset;\n"
"void main() { gl_Position = vec4(aPos.x + offset, aPos.y, 0.0, 1.0); }"
);
shaderProgram_2.addShaderFromSourceCode(QOpenGLShader::Fragment,
"#version 330 core\n"
"out vec4 FragColor;\n"
"void main() { FragColor = vec4(0.9, 0.6, 0.8, 1.0); }"
);
shaderProgram_2.link();
vao_2.create();
vao_2.bind();
vbo_2.create();
vbo_2.bind();
vbo_2.setUsagePattern(QOpenGLBuffer::DynamicDraw);
vbo_2.allocate(vertices, sizeof(vertices));
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), nullptr);
glEnableVertexAttribArray(0);
vbo_2.release();
vao_2.release();
}
void MyOpenglWgt::paintGL()
{
glClear(GL_COLOR_BUFFER_BIT);
// 绘制第一个三角形
shaderProgram.bind();
vao.bind();
glDrawArrays(GL_TRIANGLES, 0, 3);
vao.release();
shaderProgram.release();
// 绘制第二个三角形
shaderProgram_2.bind();
vao_2.bind();
shaderProgram_2.setUniformValue("offset", 0.8f);// 在设置uniform之前,必须确保着色器程序已经绑定
glDrawArrays(GL_TRIANGLES, 0, 3);
vao_2.release();
shaderProgram_2.release();
}
效果图