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;或添加额外的内核模…

鸿蒙App基础

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

一拖二快充线独特优势

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

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

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

测试常用的Linux命令

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

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

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

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

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

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

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

数学建模【主成分分析】

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

基于springboot的家庭装修报价系统设计与实现

目 录 摘 要 I Abstract II 引 言 1 1 相关技术 3 1.1 SpringBoot框架 3 1.2 ECharts 3 1.3 Vue框架 3 1.4 Bootstrap框架 3 1.5 JQuery技术 4 1.6 Ajax技术 4 1.7 本章小结 4 2 系统分析 5 2.1 需求分析 5 2.2 非功能需求 7 2.3 本章小结 8 3 系统设计 9 3.1 系统总体设计 9 …

【能力素质模型建立】某大型国有能源公司能力素质模型项目纪实

【客户评价】 我们之前挑选过很多家做管理咨询的企业&#xff0c;经过多家企业的竞标&#xff0c;我们最终选择了北京华恒智信人力资源顾问有限公司&#xff0c;因为在竞标中我们看到了贵公司的专业性和敬业精神。 在项目合作中&#xff0c;贵公司的多位咨询老师也表现出了高…

LeetCode100 刷题记录

文章目录 矩阵相关1. 旋转矩阵2. 搜索二维矩阵 矩阵相关 1. 旋转矩阵 题目描述&#xff1a; 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵…

【C++杂货铺】详解string

目录 &#x1f308;前言&#x1f308; &#x1f4c1; 为什么学习string &#x1f4c1; 认识string&#xff08;了解&#xff09; &#x1f4c1; string的常用接口 &#x1f4c2; 构造函数 &#x1f4c2; string类对象的容量操作 &#x1f4c2; string类对象的访问以及遍历操…

js判断页面是否是在iframe里面

文章目录 一、前言1.1、_blank跳转1.2、_self跳转 二、方法2.1、判断子项目是否是在iframe内部2.2、实现_self跳转 三、最后 一、前言 上面是父前端项目里的iframe加载了子前端项目的页面。此时如果点击子项目的内容&#xff0c;如果要进行父项目浏览器页面跳转&#xff0c;可以…

C++初阶 类(上)

目录 1. 什么是类 2. 如何定义出一个类 3. 类的访问限定符 4. 类的作用域 5. 类的实例化 6. 类的大小 7. this指针 1.this指针的引出 2. this指针的特性 8. 面试题 1. 什么是类 在C语言中&#xff0c;不同类型的数据集合体是结构体。为了方便管理结构体&#xff0c;我…

HarmonyOS NEXT应用开发案例——自定义TabBar

介绍 本示例主要介绍了TabBar中间页面如何实现有一圈圆弧外轮廓以及TabBar页签被点击之后会改变图标显示&#xff0c;并有一小段动画效果。 效果图预览 使用说明&#xff1a; 依次点击tabBar页面&#xff0c;除了社区图标之外&#xff0c;其它图标往上移动一小段距离。 实现…

中霖教育:消防工程师报考条件汇总

消防工程师考试报名条件汇总&#xff0c;想要参加考试的考生可以根据自己的专业和学历判断自己是否符合条件。 1、大专学历&#xff0c;消防工程专业&#xff0c;工作年限满6年&#xff0c;从事消防安全技术工作满4年;消防工程相关专业&#xff0c;工作年限满7年&#xff0c;从…