首页 > 系统相关 >Linux OpenGL(3) —— 一个三角形

Linux OpenGL(3) —— 一个三角形

时间:2023-12-26 13:34:34浏览次数:52  
标签:fragmentShader OpenGL 对象 vertexShader Linux 顶点 三角形 GL 着色器

绘制图形的大致流程

image
图中,浅蓝色方格是整个过程中的重要对象。

准备顶点坐标,创建VAO,并将坐标存入VBO

GLfloat vertices[] = {                                                      // 顶点位置
	-0.5, -0.5, 0,
	0.5, -0.5, 0,
	0, 0.5, 0
	};

unsigned int VAO;                                                           // 用以储存当前VBO和顶点属性
glGenVertexArrays(1, &VAO);                                                 // 创建一个顶点数组对象
glBindVertexArray(VAO);                                                     // 绑定顶点数组对象,这样后面的VBO才会被记录

unsigned int VBO;
glGenBuffers(1, &VBO);                                                      // 生成一个缓冲对象
glBindBuffer(GL_ARRAY_BUFFER, VBO);                                         // 将缓冲对象与顶点缓冲区VAO绑定
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);  // 将数据写入顶点缓冲区,第四个参数描述了数据在未来是否会发生剧烈改变, GL_STATIC_DRAW 代表几乎不会改变

创建顶点着色器对象

const char* vertexShaderSource = "#version 330 core\n"                      // 顶点着色器的源码
	"layout (location = 0) in vec3 aPos;\n"
	"void main(){\n"
	"   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
	"}\0"; 

unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);                            // 创建一个顶点着色器对象

glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);                 // 将着色器对象与源码进行装配。第二个参数为着色器源码的数量。
glCompileShader(vertexShader);                                              // 编译着色器

GLint issuccess;
GLchar infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &issuccess);                 // 检查编译是否成功
if(!issuccess){
	glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);               // 如果编译失败则获得错误信息
	std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
	abort();
}

创建片段着色器对象

const char* fragmentShaderSource = "#version 330 core\n"                    // 片段着色器源码
	"out vec4 FragColor;\n"
	"void main(){\n"
	"   FragColor = vec4(1.0, 0.5, 0.2, 1.0);\n"
	"}\0";

unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);                        // 创建一个片段着色器对象
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);             // 将片段着色器与源码进行装配
glCompileShader(fragmentShader);                                            // 编译片段着色器

glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &issuccess);               // 检查编译是否成功
if(!issuccess){
	glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);             // 如果编译失败则获得错误信息
	std::cout << "ERROR::SHADER::FRAGEMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
	abort();
}

创建程序对象

unsigned int shaderProgram;
shaderProgram = glCreateProgram();                                          // 创建一个程序对象
glAttachShader(shaderProgram, vertexShader);                                // 让程序对象包含的那个点着色器
glAttachShader(shaderProgram, fragmentShader);                              // 让程序对象包含片段着色器
glLinkProgram(shaderProgram);                                               // 链接程序

glGetProgramiv(shaderProgram, GL_LINK_STATUS, &issuccess);                  // 检查链接是否成功
if(!issuccess){
	glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);             // 失败时获得报错信息
	std::cout << "ERROR::SHADER::PROGRAM::LINK_FAILED\n" << infoLog << std::endl;
	abort();
}

声明顶点的内存排列形式

glDeleteShader(vertexShader);glDeleteShader(fragmentShader);                    // 删除不再需要的着色器对象
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (void*)0);   // 告诉 openGL 我们的顶点数据的内存排列形式。参数:起始位置、每组数据个数、数据类型、是否归一化、每一组数据的大小、起始位置序号的指针。
glEnableVertexAttribArray(0);                                                   // 启用顶点属性

这里的起始位置是 0 是因为我们在顶点着色器中声明了 location = 0

绘制三角形

// 主循环
while(!glfwWindowShouldClose(window)){
	// 检查输入
	...
	// 渲染
	glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);
	glUseProgram(shaderProgram);                                            // 激活程序对象
	glBindVertexArray(VAO);                                                 // 指定使用的顶点数组对象
	glDrawArrays(GL_TRIANGLES, 0, 3);                                       // 绘制三角形。参数:图形模式、数据起点、点个数
	// 更新
	glfwSwapBuffers(window);
	glfwPollEvents();
}

整体代码

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

void frameBufferSizeCallback(GLFWwindow* window, int width, int height);
void checkInput(GLFWwindow* window);

int main(){
    // 窗口初始化
    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, 600, "opengl test window", NULL, NULL);
    if(window==NULL){
        std::cout<< "Failed to create window with glfw.\n";
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);
    if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){
        std::cout<< "Failed to initalize glad.\n";
        return -1;
    }
    glViewport(0, 0, 800, 600);
    glfwSetFramebufferSizeCallback(window, frameBufferSizeCallback);
    
    // 绘制

    GLfloat vertices[] = {                                                      // 顶点位置
        -0.5, -0.5, 0,
        0.5, -0.5, 0,
        0, 0.5, 0
    };

    unsigned int VAO;                                                           // 用以储存当前VBO和顶点属性
    glGenVertexArrays(1, &VAO);                                                 // 创建一个顶点数组对象
    glBindVertexArray(VAO);                                                     // 绑定顶点数组对象,这样后面的VBO才会被记录

    unsigned int VBO;
    glGenBuffers(1, &VBO);                                                      // 生成一个缓冲对象
    glBindBuffer(GL_ARRAY_BUFFER, VBO);                                         // 将缓冲对象与顶点缓冲区VAO绑定
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);  // 将数据写入顶点缓冲区,第四个参数描述了数据在未来是否会发生剧烈改变, GL_STATIC_DRAW 代表几乎不会改变

    const char* vertexShaderSource = "#version 330 core\n"                      // 顶点着色器的源码
    "layout (location = 0) in vec3 aPos;\n"
    "void main(){\n"
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
    "}\0"; 

    unsigned int vertexShader;
    vertexShader = glCreateShader(GL_VERTEX_SHADER);                            // 创建一个顶点着色器对象

    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);                 // 将着色器对象与源码进行装配。第二个参数为着色器源码的数量。
    glCompileShader(vertexShader);                                              // 编译着色器

    GLint issuccess;
    GLchar infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &issuccess);                 // 检查编译是否成功
    if(!issuccess){
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);                   // 如果编译失败则获得错误信息
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
        abort();
    }

    const char* fragmentShaderSource = "#version 330 core\n"                    // 片段着色器源码
    "out vec4 FragColor;\n"
    "void main(){\n"
    "   FragColor = vec4(1.0, 0.5, 0.2, 1.0);\n"
    "}\0";

    unsigned int fragmentShader;
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);                        // 创建一个片段着色器对象
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);             // 将片段着色器与源码进行装配
    glCompileShader(fragmentShader);                                            // 编译片段着色器

    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &issuccess);               // 检查编译是否成功
    if(!issuccess){
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);                 // 如果编译失败则获得错误信息
        std::cout << "ERROR::SHADER::FRAGEMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
        abort();
    }
    
    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();                                          // 创建一个程序对象
    glAttachShader(shaderProgram, vertexShader);                                // 让程序对象包含的那个点着色器
    glAttachShader(shaderProgram, fragmentShader);                              // 让程序对象包含片段着色器
    glLinkProgram(shaderProgram);                                               // 链接程序

    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &issuccess);                  // 检查链接是否成功
    if(!issuccess){
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);                 // 失败时获得报错信息
        std::cout << "ERROR::SHADER::PROGRAM::LINK_FAILED\n" << infoLog << std::endl;
        abort();
    }

    glDeleteShader(vertexShader);glDeleteShader(fragmentShader);                    // 删除不再需要的着色器对象
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (void*)0);   // 告诉 openGL 我们的顶点数据的内存排列形式。参数:起始位置、每组数据个数、数据类型、是否归一化、每一组数据的大小、起始位置序号的指针。
    glEnableVertexAttribArray(0);                                                   // 启用顶点属性

    // 主循环
    while(!glfwWindowShouldClose(window)){
        // 检查输入
        checkInput(window);
        // 渲染
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        glUseProgram(shaderProgram);                                            // 激活程序对象
        glBindVertexArray(VAO);                                                 // 指定使用的顶点数组对象
        glDrawArrays(GL_TRIANGLES, 0, 3);                                       // 绘制三角形。参数:图形模式、数据起点、点个数
        // 更新
        glfwSwapBuffers(window);
        glfwPollEvents();
    }
    glfwTerminate();
    return 0;
}
// g++ -o out main.cpp lib/glad.c -lglfw -lGL -lm -lXrandr -lXi -lX11 -lXxf86vm -lpthread -ldl -lXinerama -lXcursor

void frameBufferSizeCallback(GLFWwindow* window, int width, int height){glViewport(0, 0, width, height);}// 设置回调函数
void checkInput(GLFWwindow* window){
	if(glfwGetKey(window, GLFW_KEY_ESCAPE)==GLFW_PRESS){
        glfwSetWindowShouldClose(window, 1);
    }
}

参考链接你好,三角形

标签:fragmentShader,OpenGL,对象,vertexShader,Linux,顶点,三角形,GL,着色器
From: https://www.cnblogs.com/torch-hxm/p/17927927.html

相关文章

  • 如何应对Linux 内核崩溃
    如何应对Linux内核崩溃kdump是一种用于获取Linux内核崩溃转储的方法,而要找到关于其使用和内部结构的解释性文档可能有一些挑战。在这篇文章中,我将深入探讨kdump的基本用法以及kdump/kexec在内核中的实现。首先,让我们了解kexec。kexec是一个Linux内核到内核的引导加载程......
  • linux常用命令(笔记)
    1、telnet进去后怎么退出:telnet10.102.5.11922查看ip,端口通讯状况退出的话:Ctrl+]然后输入q退出,如下图:2、linux下查看tomcat版本curl172.16.45.231:8080|grep"ApacheTomcat"curlIP:端口|grep"ApacheTomcat"3、关于CPU命令——查看CPU型号cat/......
  • linux下服务器ping不通公网域名(不定时更新)
    1、服务器开通的公网访问,但是ping不通域名,可配置hosts重试保存后,重试,OK2、服务器公网IP也ping不通,修改网卡配置,配置DNS重启网卡后,问题解决......
  • Linux系统CPU状态信息详解:解读us, sy, ni, id, wa, hi, si, st的含义
    Cpu(s):0.0%us,0.5%sy,0.0%ni,99.5%id,0.0%wa,0.0%hi,0.0%si,0.0%st上面一组字符,有何含义?今天我们一起来解读。在计算机系统中,CPU是核心组件,负责执行程序中的指令。为了更好地理解系统的运行状况,我们需要关注CPU的各种状态信息。本文将详细介绍这些状态信息,并以具体示例进行解释。......
  • 分享一些linux云计算开发面试题
    近年来,随着云计算的快速发展,对于中高级Linux云计算开发人才的需求也越来越大。在面试过程中,面试官通常会提出一系列与Linux云计算开发相关的问题,以评估面试者的技术实力和解决问题的能力。本文将围绕中高级Linux云计算开发面试题展开讨论,并给出相关问答。 一、虚拟化技术 1.什么......
  • Linux openEuler(欧拉系统)无公网实现ssh远程连接(高效运维!)
    欧拉操作系统(openEuler,简称“欧拉”)是面向数字基础设施的操作系统,支持服务器、云计算、边缘openEuler是面向数字基础设施的操作系统,支持服务器、云计算、边缘计算、嵌入式等应用场景,支持多样性计算,致力于提供安全、稳定、易用的操作系统Cpolar是一种安全的内网穿透云服务,......
  • GScan v0.1 被攻击入侵后 溯源 安全应急响应 Linux主机排查 实现主机侧Checklist的自
    GScanv0.1本程序旨在为安全应急响应人员对Linux主机排查时提供便利,实现主机侧Checklist的自动全面化检测,根据检测结果自动数据聚合,进行黑客攻击路径溯源。CheckList检测项自动化程序的CheckList项如下:1、主机信息获取2、系统初始化alias检查3、文件类安全扫描3.1、系统重要文......
  • 在linux中查看运行指定进程资源占用(cpu+gpu)
    在运行程序时有时候会需要查看资源占用,以方便部署在其他服务器上时进行参考。以下是总结了我在linux上查找程序进程资源的两种方法(cpu和gpu都有)。CPU1.查找进程号如果进程较多,输入ps-ef|grep+指令关键词进行搜索。如果运行的是python程序,可以输入ps-ef|greppytho......
  • linux经典电灯驱动(古老版,参考用)
    驱动程序#include<linux/types.h>#include<linux/kernel.h>#include<linux/delay.h>#include<linux/ide.h>#include<linux/init.h>#include<linux/module.h>#include<linux/errno.h>#include<linux/gpio.h>#inc......
  • linux声音处理 alsa & jack 是什么
    alsa(AdvancedLinuxSoundArchitecture)是什么:简单的说,linux之前的内核里处理声音使用oss,后来大家觉得不好用,重写了声音部分,改名叫alsa(更高级的),并且提供了用户空间库(alsa-lib),供应用程序方便调用。官方说明:高级Linux声音架构(ALSA)为Linux操作系统提供音频和MIDI......