opengl 学习(二)-----你好,三角形

你好,三角形

  • 分类
  • demo
  • 效果
  • 解析

分类

opengl c++

demo

#include "glad/glad.h"
#include "glfw3.h"
#include <iostream>
#include <cmath>
#include <vector>using namespace std;/**
* 在学习此节之前,建议将这三个单词先记下来:
- 顶点数组对象:Vertex Array Object,VAO
- 顶点缓冲对象:Vertex Buffer Object,VBO
- 元素缓冲对象:Element Buffer Object,EBO 或 索引缓冲对象 Index Buffer Object,IBO
*//**
* 在OpenGL中,任何事物都在3D空间中,而屏幕和窗口却是2D像素数组,
这导致OpenGL的大部分工作都是关于把3D坐标转变为适应你屏幕的2D像素。
3D坐标转为2D坐标的处理过程是
由OpenGL的图形渲染管线(Graphics Pipeline,大多译为管线,
实际上指的是一堆原始图形数据途经一个输送管道,
期间经过各种变化处理最终出现在屏幕的过程)管理的。
图形渲染管线可以被划分为两个主要部分:
第一部分把你的3D坐标转换为2D坐标,
第二部分是把2D坐标转变为实际的有颜色的像素。
这个教程里,我们会简单地讨论一下图形渲染管线,以及如何利用它创建一些漂亮的像素。
*//**
* 当今大多数显卡都有成千上万的小处理核心,
它们在GPU上为每一个(渲染管线)阶段运行各自的小程序,
从而在图形渲染管线中快速处理你的数据。这些小程序叫做着色器(Shader)。
*//**
* 首先,我们以数组的形式传递3个3D坐标作为图形渲染管线的输入,
用来表示一个三角形,这个数组叫做顶点数据(Vertex Data);
顶点数据是一系列顶点的集合。
一个顶点(Vertex)是一个3D坐标的数据的集合。
而顶点数据是用顶点属性(Vertex Attribute)表示的,
它可以包含任何我们想用的数据,
但是简单起见,
我们还是假定
每个顶点只由一个3D位置 和一些颜色值组成的吧。
*//**
* 顶点着色器->图元装配->几何着色器->光栅化阶段->裁切
* OpenGL中的一个片段是OpenGL渲染一个像素所需的所有数据。
*//**
* 片段着色器的主要目的是计算一个像素的最终颜色,这也是所有OpenGL高级效果产生的地方。
在现代OpenGL中,
我们必须定义至少一个顶点着色器
和
一个片段着色器(因为GPU中没有默认的顶点/片段着色器)。
出于这个原因,刚开始学习现代OpenGL的时候可能会非常困难,
因为在你能够渲染自己的第一个三角形之前已经需要了解一大堆知识了。
在本节结束你最终渲染出你的三角形的时候,
你也会了解到非常多的图形编程知识。
*//**
* 开始绘制图形之前,我们需要先给OpenGL输入一些顶点数据。
OpenGL是一个3D图形库,
所以在OpenGL中我们指定的所有坐标都是3D坐标(x、y和z)。
OpenGL不是简单地把所有的3D坐标变换为屏幕上的2D像素;
OpenGL仅当3D坐标在3个轴(x、y和z)上-1.0到1.0的范围内时才处理它。
所有在这个范围内的坐标叫做标准化设备坐标(Normalized Device Coordinates),
此范围内的坐标最终显示在屏幕上(在这个范围以外的坐标则不会显示)。
由于我们希望渲染一个三角形,
我们一共要指定三个顶点,
每个顶点都有一个3D位置。
我们会将它们以标准化设备坐标的形式(OpenGL的可见区域)定义为一个float数组。
*/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";const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
"   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow* window)
{if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)glfwSetWindowShouldClose(window, true);
}// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{// make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays.glViewport(0, 0, width, height);
}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, "LearnOpenGL", NULL, NULL);if (window == NULL){std::cout << "Failed to create GLFW window" << std::endl;glfwTerminate();return -1;}glfwMakeContextCurrent(window);glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);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);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;}// fragment shaderunsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);glCompileShader(fragmentShader);// check for shader compile errorsglGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);if (!success){glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;}// link shadersunsigned int shaderProgram = glCreateProgram();glAttachShader(shaderProgram, vertexShader);glAttachShader(shaderProgram, fragmentShader);glLinkProgram(shaderProgram);// check for linking errorsglGetProgramiv(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);float vertices[] = {-0.5f, -0.5f, 0.0f,0.5f, -0.5f, 0.0f,0.0f,  0.5f, 0.0f};unsigned int VBO, VAO;glGenVertexArrays(1, &VAO);glGenBuffers(1, &VBO);// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).glBindVertexArray(VAO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbindglBindBuffer(GL_ARRAY_BUFFER, 0);// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.glBindVertexArray(0);// uncomment this call to draw in wireframe polygons.//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);// render loop// -----------while (!glfwWindowShouldClose(window)){// input// -----processInput(window);// render// ------glClearColor(0.2f, 0.3f, 0.3f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);// draw our first triangleglUseProgram(shaderProgram);glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organizedglDrawArrays(GL_TRIANGLES, 0, 3);// glBindVertexArray(0); // no need to unbind it every time // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)// -------------------------------------------------------------------------------glfwSwapBuffers(window);glfwPollEvents();}// optional: de-allocate all resources once they've outlived their purpose:// ------------------------------------------------------------------------glDeleteVertexArrays(1, &VAO);glDeleteBuffers(1, &VBO);glDeleteProgram(shaderProgram);// glfw: terminate, clearing all previously allocated GLFW resources.// ------------------------------------------------------------------glfwTerminate();return 0;
}

效果

请添加图片描述

解析

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

请添加图片描述
在这里插入图片描述

混合决定透明效果
测试决定前后次序

渲染管线的顺序:
顶->三->图->剪->光栅->片元->混测

图元转配是指:把变换后的顶点,根据顺序,组成三角形,直线等图元的过程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/729689.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Alveo 概念拓扑结构

在 Alveo 加速卡中,涉及到的概念拓扑结构主要包括 Alveo 卡上的各个关键组件以及与主机系统之间的通信结构。以下是对这些概念拓扑结构的简要介绍: 1.DDR 即双数据率内存(Double Data Rate memory),是一种常见的计算机内存类型,用于存储和提供处理器所需的数据和指令。…

macos m1 arm芯片 使用jpype报错 FileNotFoundError: [Errno 2] JVM DLL not found

startJVM(jpype.getDefaultJVMPath()) 报错 Traceback (most recent call last):File "/Users/thomas990p/PycharmProjects/tuya/volcano-biz-scripts/WenKongFa/FinalCode/java2python/CallJavaAPI.py", line 12, in <module>startJVM(jpype.getDefaultJVMPa…

基于springboot实现大学生兼职网站系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现大学生兼职系统演示 摘要 现代化的市场中&#xff0c;人们日常的工作、生活都在不断的提速&#xff0c;而人们在工作与生活中与互联网的结合也越来越紧密&#xff0c;通过与互联网紧密的结合可以更好地实现日常工作的线上化、信息化、便捷化。现如今的各行各…

ebpf入门---监听所有新进程

什么是ebpf eBPF 全称 extended Berkeley Packet Filter&#xff0c;中文意思是 扩展的伯克利包过滤器。一般来说&#xff0c;要向内核添加新功能&#xff0c;需要修改内核源代码或者编写 内核模块 来实现。而 eBPF 允许程序在不修改内核源代码&#xff0c;或添加额外的内核模…

私域流量怎样运营?建议你使用“5步推进法”!

私域“五步推进法”是一种确保客户添加上线工作有效进行的策略。 第一步&#xff0c;树标杆。我们需要在企业内部筛选出客户添加数量较多的区域和员工&#xff0c;将其塑造为榜样&#xff0c;并发挥其示范作用。如果企业在全国范围内拥有多家门店&#xff0c;可从不同的省份或…

鸿蒙App基础

像素单位 .1、基础单位 为开发者提供4种像素单位&#xff0c;框架采用vp为基准数据单位。 PS&#xff1a;个人建议使用lpx&#xff0c;配置好配置文件&#xff0c;这里就可以按照UI设计稿实际的来&#xff0c;可以更好的实现设计效果 名称描述px屏幕物理像素单位vp屏幕密度相…

一拖二快充线独特优势

在现代社会&#xff0c;手机已成为我们生活中不可或缺的一部分。随着科技的不断进步&#xff0c;手机的功能越来越强大&#xff0c;从通讯工具逐渐转变为工作、学习和娱乐的得力助手。然而&#xff0c;手机的电量问题一直是困扰着我们的难题。为了解决这个问题&#xff0c;市场…

在Linux/Ubuntu/Debian上将富文本Markdown (`.md`) 文件转换为HTML

你可以使用Pandoc将 Markdown (.md) 文件转换为 HTML。如果你没有安装 Pandoc&#xff0c;可以使用以下步骤安装&#xff1a; 打开终端。 运行以下命令安装 Pandoc&#xff1a; sudo apt-get update sudo apt-get install pandoc安装 Pandoc 后&#xff0c;你可以使用它将 Mar…

Lua调用c++函数的两种办法

使用Lua5.1.5进行的操作 方法一: lua调用应用程序中的函数 lua脚本,调用应用程序中的计算平均值的函数 script.lua number,sum,avg = average(10,20,30,40,50); print("The number is ", number

LLDB-调试

远程调试Android Device Android端启动lldb server 在此之前将lldb server push到设备&#xff0c;如/data/loca/tmp lldb-server platform \ --server --listen unix-abstract:///data/local/tmp/debug.sock后台运行&#xff1a; lldb-server platform \ --server --listen …

【树】-Lc617-合并二叉树(同时递归2棵树)

写在前面 最近想复习一下数据结构与算法相关的内容&#xff0c;找一些题来做一做。如有更好思路&#xff0c;欢迎指正。 目录 写在前面一、场景描述二、具体步骤1.环境说明2.代码 写在后面 一、场景描述 合并二叉树。将它们中的一个覆盖到另一个上时&#xff0c;两个二叉树的一…

3•8向女同胞致敬|营销枢纽SaaS厂商乐通达(ltd.com)正式更名枢纽云

为了向女同胞致敬&#xff0c;我们特地选择3月8日女神节变更公司名称&#xff0c;因为《如果SaaS有性别&#xff0c;那 TA一定是女性 》。 2024年3月8日&#xff0c;“杭州乐通达网络有限公司”名称正式变更为“杭州枢纽云计算有限公司”&#xff08;简称&#xff1a;营销枢纽&…

Vue教学18:Element UI进阶组件探索,提升Vue应用的专业性

大家好,欢迎回到我们的Vue教学系列博客!在前十七篇博客中,我们学习了Vue.js的基础知识、安装Node.js与npm、使用Vue Devtools进行调试、Vue实例与生命周期钩子、数据绑定(单向与双向)、计算属性与侦听器、条件渲染和列表渲染、事件处理、组件之间的传值(props和$emit)、…

测试常用的Linux命令

前言 直接操作硬件 将把操作硬件的代码封装成系统调用&#xff0c;供程序员使用 虚拟机软件 可以模拟的具有完整硬件系统的功能 可以在虚拟机上安装不同的操作系统 Linux内核只有一个&#xff0c;发行版有很多种 内核来运行程序和管理像磁盘和打印机等硬件设备的核心程序 终端…

积鼎科技两款国产流体仿真软件入选《上海市工业软件推广目录》!

为落实《上海市促进工业软件高质量发展行动计划(2021-2023年)》&#xff0c;聚焦重点行业和领域痛点问题&#xff0c;提升关键软件技术创新和供给能力&#xff0c;推动工业软件产品应用和产业生态建设更好支撑全市制造业数字化转型&#xff0c;《2023年上海市工业软件推荐目录》…

YOLOv8改进 | 独家创新篇 | 利用DCNv3集合DLKA形成全新的注意力机制(全网独家创新)

一、本文介绍 本文给大家带来的机制是由我独家创新结合Deformable Large Kernel Attention (D-LKA) 注意力机制和DCNv3可变形卷积的全新注意力机制模块(算是二次创新),D-LKA的基本原理是结合了大卷积核和可变形卷积的注意力机制,通过采用大卷积核来模拟类似自我关注的感受…

ERP物资采购策略解决方案

ERP物资采购策略解决方案 企业在不断探索物资采购的最优管理模式中&#xff0c;针对采购性质、对象、价值等方面&#xff0c;其使用的策略是不同的。如何最大限度地满足企业的各种需要是对ERP软件适应性提出的挑战。 一、 物资采购的对象 首先我们要明确企业物…

Python中排序函数sorted的用法

Python中排序函数sorted的用法 列表对象提供了sort()方法支持原地排序&#xff0c;而内置函数sorted()返回新列表&#xff0c;并不对原列表进行任何修改。 sorted()方法可以对列表、元组、字典、range对象等进行排序。 列表的sort()方法和内置函数sorted()都支持key参数实现复…

Linux安全--为Nginx加上PHP解析功能

yum install php-fpm -y安装php进程管理器 找到Nginx安装的路径 编辑Nginx配置文件

数学建模【主成分分析】

一、主成分分析简介 主成分分析&#xff08;Principal Component Analysis&#xff0c;PCA&#xff09;是一种降维算法&#xff0c;它能将多个指标转换为少数几个主成分&#xff0c;这些主成分是原始变量的线性组合&#xff0c;且彼此之间互不相关&#xff0c;其能反映出原始数…