OpenGL 学习笔记(三)

一、OpenGL实现窗口图形的绘制

        OpenGL使用特有的API来实现窗口图形的绘制,下面我们先看使用OpenGL创建一个绘制窗口:

        OpenGL绘制窗口界面代码如下:

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>

using namespace std;

int main()

{

//glfw的初始化和设置

// -----------------------------------------------------

//调用glfwInit函数来初始化GLFW

glfwInit();

//配置GLFW,第一个参数代表选项的名称,第二个参数接受一个整型,用来设置这个选项的值

//此处设置表示使用的OpenGL版本号3.3

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);

//glfwWindowHint作为窗口创建的一种提示,可以设置窗口的多种属性,包括透明度等等,感兴趣的可以在glfw文档中查询

glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

//使用流水线配置模式

glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

//glfw窗口创建

// -----------------------------------------------------

//glfwCreateWindow函数需要窗口的宽和高作为它的前两个参数,第三个参数表示这个窗口的名称,最后两个参数我们暂时忽略,它返还一个GLFWwindow对象

GLFWwindow* window = glfwCreateWindow(800, 800, "OpenGL", NULL, NULL);

//创建完窗口,通知GLFW将我们窗口的上下文设置为当前线程的主上下文了

glfwMakeContextCurrent(window);

while (!glfwWindowShouldClose(window))

{

//OpenGL采用双缓冲来渲染窗口

glfwSwapBuffers(window);

//处理按键事件

glfwPollEvents();

}

return 0;

}

        glfwWindowHint的更多设置,可以在glfw窗口官方文档中具体了解,执行以上代码可以获得一个OpenGL绘制窗口,如图1-1所示:

                                                         图1-1 OpenGL绘制窗口

        上面流程我们通过glfwInit()、glfwWindowHint()、glfwCreateWindow()等等就创建了一个窗口对象。

        以上只是一个窗口,那么如何使用OpenGL绘制呢?这就需要了解一点背景知识,Khronos组织一直在维护opengl接口,如果Khronos定义了一个glDrawLIne的接口,那么支持OpenGL的GPU设备厂商会让自己的程序员在硬件产品上用图像逻辑去实现这个接口,而当前主流的GPU设备厂商都是支持OpenGL的。

        所以是Khronos和GPU设备厂商帮我们实现了具体逻辑,而我们要做的就是遵循这一系列接口的规范,去得到想要的内容,下面可以看下OpenGL和GPU的关系,如图1-2所示:

        通过以上,我们可以看出OpenGL的简单流程,首先调用OpenGL的接口,将Attributes、textturedata、uniform等数据输入到vetexshader等着色器中,如果是attributes数据,顶点着色器会处理它,并把结果流转到下一个primitive assembly中实现光栅化,紧接着配合textturedata通过片元着色器进行处理,最终渲染出结果,可以对照着OpenGL渲染管线图进行参考。

        OpenGL的常见名词:

 OpenGL的渲染实例,代码如下:

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
using namespace std;
//Shader创建
// -----------------------------------------------------
//GLSL编写的用于顶点着色器的shader
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
//用于片段着色器的shader,rgba格式
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(0.41f, 0.35f, 0.80f, 1.0f);\n"
"}\n\0";
//顶点数据
float vertices[] = {
0.5f,  0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
-0.5f,  0.5f, 0.0f,
0.5f,  0.4f, 0.0f,
-0.4f, -0.5f, 0.0f
};
//索引数据
unsigned int indices[] = {
0, 2, 3,
1, 4, 5
};
int main()
{
//glfw创建
// -----------------------------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(800, 800, "OpenGL", NULL, NULL);
glfwMakeContextCurrent(window);

//glad初始化
// -----------------------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
    std::cout << "Failed to initialize GLAD" << std::endl;
    return -1;
}
//着色器创建和链接
// -----------------------------------------------------
//顶点着色器创建
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
//片段着色器创建
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
//链接着色器
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);

//创建数据对象和绑定数据对象
// -----------------------------------------------------
//顶点数组对象:Vertex Array Object,VAO
//顶点缓冲对象:Vertex Buffer Object,VBO
//索引缓冲对象:Element Buffer Object,EBO或Index Buffer Object,IBO

unsigned int VBO, VAO, EBO;
//unsigned int VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
//绑定VAO数据对象
glBindVertexArray(VAO);
//复制顶点数组到缓冲中供OpenGL使用
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//复制索引数组到缓冲中供OpenGL使用
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

//解释顶点数据
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
//启用顶点属性
glEnableVertexAttribArray(0);
//解绑VAO
glBindVertexArray(0);

while (!glfwWindowShouldClose(window))
{
    //按照rgba格式设置窗口背景颜色
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    //将当前设置的color写入启用的缓冲区
    glClear(GL_COLOR_BUFFER_BIT);
    //加载shdaer
    glUseProgram(shaderProgram);
    //绑定VAO数据对象
    glBindVertexArray(VAO); 
    //获取索引,根据GL_TRIANGLES类型绘制图像
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    glfwSwapBuffers(window);
    glfwPollEvents();
}
return 0;
}

程序执行效果如下:

      以上实现的流程,简单的将OpenGL渲染过程进行了介绍,窗口的创建、shader的编写、着色器的创建及链接、VAO、VBO、EBO创建及绘图。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个简单的使用OpenGL进行绘图的Julia代码示例: ```julia using GLFW using GL using AbstractPlotting const WIDTH = 640 const HEIGHT = 480 function main() # 初始化 GLFW glfwInit() # 创建窗口 window = glfwCreateWindow(WIDTH, HEIGHT, "Julia OpenGL Demo", nothing, nothing) glfwMakeContextCurrent(window) # 初始化 OpenGL glViewport(0, 0, WIDTH, HEIGHT) glMatrixMode(GL_PROJECTION) glLoadIdentity() glOrtho(-2, 2, -2, 2, -1, 1) glMatrixMode(GL_MODELVIEW) # 设置绘图回调函数 plot = surface(rand(-2:0.01:2, 401), rand(-2:0.01:2, 401)) do x, y z = complex(x, y) c = -0.8 + 0.156im n = 0 while n < 100 && abs2(z) < 4 z = z^2 + c n += 1 end n end function draw() glClear(GL_COLOR_BUFFER_BIT) with_saved_context() do glScalef(1/2, 1/2, 1) glTranslatef(-1, -1, 0) draw(plot) end glfwSwapBuffers(window) end # 主循环 while !glfwWindowShouldClose(window) glfwPollEvents() draw() end # 清理资源 glfwTerminate() end main() ``` 这个例子使用GLFWOpenGL来创建一个窗口和渲染上下文,并使用AbstractPlotting绘制了一个Julia集的图像。其中,`surface`函数用来创建一个网格,并根据给定的函数计算每个网格点的高度,然后使用抗锯齿线框架绘制出来。在绘制回调函数中,我们首先使用OpenGL的变换函数将坐标系从(-2, -2)到(2, 2)映射到屏幕上,然后调用`draw`函数来实际绘制图像。最后,我们在主循环中不断调用绘制回调函数,直到窗口被关闭为止。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大王算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值