小白入门opengl(二)画出三角形

在opengl中任何事物都在3D空间中,而屏幕与窗口确实2D的,由3D坐标转化为2D的处理过程是opengl的图形渲染管线管理的。可以被划分为两个主要部分,第一部分把你的3D坐标转化为2D坐标,第二部分则是把2D坐标转化为有颜色的像素。
在图形渲染管线上运行各自的小程序,从而图形渲染管线鲁艾苏处理你的数据,这样的小程序叫做着色器。
有些着色器允许开发者自己配置,可以让我们更加细致的控制渲染管线的特定部分。
图像渲染管线每个阶段的展示
在现代OpenGL中,我们必须至少定义一个顶点着色器和一个片段着色器,
1.顶点输入
float vertices[]={
-0.5f,-0.5f,0.0f,
0.5f,-0.5f,0.0f,
0.0f,0.5f,0.0f
};
由于我们渲染的是一个2d图形,所以我们将它顶点的z坐标设置为0.0。
定义了以上的顶点数据后,我们会把它作为输入发送给图形渲染管线的第一个处理阶段。
我们通过顶点缓冲对象来管理这个内存,会在GPU内存中存储大量的顶点,好处就是可以一次性的发送大量的数据至显卡的内存中。顶点着色器能够立即访问到顶点。
我们可以使用glGenBuffers函数和一个缓冲ID来生成一个VBO对象,顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER,然后调用glBufferData来将之前定义的顶点数据复制到缓冲的内存中:

unsigned int VBO;
glGenBuffers(1,&VBO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);

glBufferData的第四个参数由三种形式,用于告诉显卡如何去管理给定的数据

  • GL_STATIC_DRAW:数据不会或者几乎不会改变很多
  • GL_DYNAMIC_DRAW:数据会被改变很多
  • GL_STREAM_DRAW:数据每次绘制的时候都会改变
    现在我们已经把顶点的数据存储到了显卡中了。
    2顶点着色器和片段着色器
    首先,我们使用GLSL(OpenGL Shading Language)编写顶点着色器,,然后编译此着色器。
    每个着色器都起始于一个版本声明,例如(GLSL 420 对应OpenGL4.2)
    下一步使用in关键字,在顶点着色器中输入顶点属性,现在我们只关心Position数据,所以我们只需要一个顶点属性,GLSL有一个向量数据类型,包含1到4个float分量,通过layout(location =0)设定输入变量的位置值。
    编译着色器,但是为了能够让OpenGL使用它,我们必须在运行时动态的编译它的源码。
    首先我们要做的就是要创建一个对象,注意还是用id来引用的,所以我们存储这个顶点着色器为unsigned int,然后用glCreateShader来创建这个着色器,同样类似的还有片段着色器
//将其存储在vertexShaderSource 字符串中
#version 330 core
layout (location = 0) in vec3 aPos;

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

然后就是编译该着色器。

unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
//下面是检查文件是否编译成功,如果编译不成功就是输出一些相关信息
int  success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if(!success)
{
    glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
    std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}

片段着色器与之类似,不过参数改为了GL_FRAGMENT_SHADER
然后创建一个着色器程序,将其连接到用来渲染的着色器程序。

int shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, vertexShader);
	glAttachShader(shaderProgram, fragmentShader);
	glLinkProgram(shaderProgram);
	// check for linking errors
	glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
	}
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);

opengl解释顶点属性
这里写图片描述
位置数据被储存为32位(4字节)浮点值。
每个位置包含3个这样的值。
在这3个值之间没有空隙(或其他值)。这几个值在数组中紧密排列(Tightly Packed)。
数据中第一个值在缓冲开始的位置。
有了这些信息我们就可以使用glVertexAttribPointer函数告诉OpenGL如何解析顶点函数。

glVertexAttritPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void)*0);
glEnableVertexAttribArray(0);//以顶点属性位置值作为参数,启用顶点属性

在OpenGL中绘制一个物体,代码会像如下所示那样


// 0. 复制顶点数组到缓冲中供OpenGL使用
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 1. 设置顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// 2. 当我们渲染一个物体时要使用着色器程序
glUseProgram(shaderProgram);
// 3. 绘制物体
someOpenGLFunctionThatDrawsOurTriangle();


顶点数组对象(VAO)


OpenGL的核心模式要求我们使用VAO,所以它知道该如何处理我们的顶点输入。如果我们绑定VAO失败,OpenGL会拒绝绘制任何东西。


一个顶点数组对象会存储下面的东西,

  • glEnableVertexAttribArray和glDisableVertexAttribArray的调用。
  • 通过glVertexAttribPointer设置的顶点属性配置。
  • 通过glVertexAttribPointer调用与顶点属性关联的顶点缓冲对象。
    这里写图片描述
    创建一个VAO与VBO很类似的
unsigned int VAO;
glGenVertexArrays(1,&VAO);

要想使用VAO,要做的是使用glBindVertexArray绑定VAO。绑定之后起,绑定和配置对应的VBO和属性指针,之后解绑VAO供之使用,在绘制一个物体前,将VAO绑定到希望的设定上去。

// ..:: 初始化代码(只运行一次 (除非你的物体频繁改变)) :: ..
// 1. 绑定VAO
glBindVertexArray(VAO);
// 2. 把顶点数组复制到缓冲中供OpenGL使用
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 3. 设置顶点属性指针
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

[...]

// ..:: 绘制代码(渲染循环中) :: ..
// 4. 绘制物体
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
someOpenGLFunctionThatDrawsOurTriangle();
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在Qt中使用OpenGLES画一个三角形的步骤如下: 1. 创建一个新的Qt Quick项目。 2. 在项目文件夹中创建一个新的源文件,命名为“main.cpp”。 3. 在“main.cpp”文件中添加以下代码: ```c++ #include <QGuiApplication> #include <QOpenGLContext> #include <QOpenGLFunctions> #include <QQuickWindow> #include <QSurfaceFormat> class MyTriangleRenderer : public QObject, protected QOpenGLFunctions { Q_OBJECT public: explicit MyTriangleRenderer(QObject *parent = nullptr) : QObject(parent) { connect(window, &QQuickWindow::beforeRendering, this, &MyTriangleRenderer::paint, Qt::DirectConnection); } void setWindow(QQuickWindow *w) { window = w; } public slots: void paint() { initializeOpenGLFunctions(); // 设置OpenGL视口 glViewport(0, 0, window->width(), window->height()); // 设置OpenGL清除颜色 glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // 清除OpenGL缓存 glClear(GL_COLOR_BUFFER_BIT); // 绘制三角形 glBegin(GL_TRIANGLES); glColor3f(1.0f, 0.0f, 0.0f); glVertex3f(-0.5f, -0.5f, 0.0f); glColor3f(0.0f, 1.0f, 0.0f); glVertex3f(0.5f, -0.5f, 0.0f); glColor3f(0.0f, 0.0f, 1.0f); glVertex3f(0.0f, 0.5f, 0.0f); glEnd(); // 交换OpenGL缓存 window->resetOpenGLState(); } private: QQuickWindow *window; }; int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); // 创建OpenGL窗口 QSurfaceFormat format; format.setVersion(2, 0); format.setProfile(QSurfaceFormat::CoreProfile); QQuickWindow window; window.setFormat(format); // 设置OpenGL渲染器 MyTriangleRenderer renderer; renderer.setWindow(&window); window.show(); renderer.paint(); return app.exec(); } #include "main.moc" ``` 4. 编译并运行你的Qt项目,你应该能够看到一个红绿蓝三角形。 这样,你就成功地在Qt中使用OpenGLES画了一个三角形

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值