OpenGL学习(一)绘制一个图形

本文使用Qt进行操作演示。

注意:

坐标原点位于屏幕中心

坐标参数:0.0f - 1.0f

颜色参数:0.0f - 1.0f

OpenGL提供了几种用于绘制几何图形的绘制模式。下面是一些常用的绘制模式:

  1. 点(GL_POINTS):绘制单个点。

  2. 线(GL_LINES):绘制一系列相互独立的线段。

  3. 线带(GL_LINE_STRIP):绘制一系列连接在一起的线段,其中每个线段的起点都是前一个线段的终点。

  4. 线环(GL_LINE_LOOP):与线带类似,但会在最后一个点和第一个点之间绘制一条线段,形成闭合的图形。

  5. 三角形(GL_TRIANGLES):绘制一系列相互独立的三角形。

  6. 三角形带(GL_TRIANGLE_STRIP):绘制一系列连接在一起的三角形,其中每个三角形的前两个顶点是前一个三角形的后两个顶点。

  7. 三角形扇形(GL_TRIANGLE_FAN):绘制一系列共享一个公共顶点的三角形。

除了上述绘制模式,还有其他一些高级的绘制模式,如四边形、多边形等。此外,还可以使用索引缓冲对象(Index Buffer Objects,简称IBO)来指定绘制的顺序,从而实现更复杂的绘制。

绘制模式可以通过以下方式设置:

glDrawArrays(GL_TRIANGLES, 0, numVertices);

其中,第一个参数指定绘制的模式,第二个参数指定要绘制的顶点的起始位置,第三个参数指定要绘制的顶点数量。

1.绘制三角形

代码如下:

myopenglwidget.h
// An highlighted block
#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLShaderProgram>class MyOpenGLWidget : public QOpenGLWidget,protected QOpenGLFunctions  // 可直接使用QOpenGLFunctions中的OpenGL函数
{Q_OBJECT
public:explicit MyOpenGLWidget (QWidget * parent = 0);protected:void initializeGL();void paintGL();void resizeGL(int width,int height);private:QOpenGLShaderProgram * program;     // 着色器程序
};#endif // MYOPENGLWIDGET_H
myopenglwidget.cpp
#include "myopenglwidget.h"MyOpenGLWidget::MyOpenGLWidget(QWidget *parent): QOpenGLWidget(parent)
{
}void MyOpenGLWidget::initializeGL()
{initializeOpenGLFunctions();    //调用该函数来初始化OpenGL函数,以便在后续使用OpenGL的函数。QSurfaceFormat format;format.setSamples(4); // 设置采样数为4(可根据需要进行调整)setFormat(format);glEnable(GL_MULTISAMPLE);   // 启用多重采样//创建一个顶点着色器对象,并将其指针赋值给vShader变量。第一个参数QOpenGLShader::Vertex表示创建的是一个顶点着色器对象,第二个参数this表示将当前窗口或部件作为父对象。QOpenGLShader *vShader = new QOpenGLShader(QOpenGLShader::Vertex, this);//定义了一个字符串变量vsrc,用于存储顶点着色器代码。const char* vsrc ="attribute vec4 vPosition;  \n"     //定义了一个属性变量vPosition,用于接收传入的顶点坐标。"void main(){\n"                    //定义了一个主函数,其功能是将传入的顶点坐标赋值给内置变量gl_Position,从而确定此顶点的屏幕位置。"   gl_Position = vPosition;\n""}\n";vShader->compileSourceCode(vsrc);       //将顶点着色器代码编译成可执行代码,并将结果存储在vShader对象中。如果编译失败,则会抛出异常。//创建一个片段着色器对象,并将其指针赋值给fShader变量。第一个参数QOpenGLShader::Fragment表示创建的是一个片段着色器对象,第二个参数this表示将当前窗口或部件作为父对象。QOpenGLShader *fShader = new QOpenGLShader(QOpenGLShader::Fragment, this);const char* fsrc ="void main(){\n""   gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);\n" // 将输出的颜色设置为黄色"}\n";fShader->compileSourceCode(fsrc);           //将片段着色器代码编译成可执行代码,并将结果存储在fShader对象中。如果编译失败,则会抛出异常。program = new QOpenGLShaderProgram;     //创建一个着色器程序对象,并将其指针赋值给program变量。program->addShader(vShader);            //将之前创建并编译好的顶点着色器对象添加到着色器程序中。program->addShader(fShader);            //将之前创建并编译好的片段着色器对象添加到着色器程序中。program->link();                        //链接着色器程序,将顶点着色器和片段着色器关联起来,并生成最终的可执行程序。program->bind();                        //绑定着色器程序,使其成为当前OpenGL上下文中的活动程序。
}
void MyOpenGLWidget::paintGL()
{glEnable(GL_MULTISAMPLE);glClearColor(0.0f, 0.0f, 1.0f, 1.0f);       //设置清除颜色缓冲区时使用的颜色,这里设置为白色。glClear(GL_COLOR_BUFFER_BIT);               //清除颜色缓冲区,将之前设定的清除颜色填充整个窗口。GLfloat vertices[] = {                      //定义了一个包含矩形顶点坐标的数组。-0.8f, -0.8f,0.8f, -0.8f,0.0f, 0.8f};GLuint vPosition = program->attributeLocation("vPosition");             //获取顶点着色器中属性变量vPosition的位置。//将顶点数据与属性变量关联起来。vPosition表示属性变量的位置,2表示每个顶点有两个分量,GL_FLOAT表示每个分量的数据类型为浮点型,GL_FALSE表示不需要进行归一化处理,0表示相邻顶点间的偏移量,vertices表示顶点数据数组。glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, vertices);glEnableVertexAttribArray(vPosition);   //启用顶点属性数组。glDrawArrays(GL_TRIANGLE_FAN, 0, 3);    //使用顶点数组绘制图元。GL_TRIANGLE_FAN表示绘制三角形扇,0表示从数组中的第一个顶点开始绘制,4表示绘制的顶点数量。
}void MyOpenGLWidget::resizeGL(int w, int h)
{glViewport(0, 0, w, h);
}

对代码进行修改,绘制点(将paintGL函数中代码替换如下):

     // 定义顶点数据GLfloat points[] = {0.0f, 0.0f, 0.0f,  // 第一个点的位置0.5f, 0.5f, 0.0f,  // 第二个点的位置-0.5f, -0.5f, 0.0f  // 第三个点的位置};// 创建顶点缓冲对象(VBO)并将顶点数据传入GLuint vbo;     //定义一个无符号整数变量vbo,用于存储VBO的标识符。glGenBuffers(1, &vbo);      //生成一个新的VBO,并将其标识符存储在vbo变量中。glBindBuffer(GL_ARRAY_BUFFER, vbo);     //绑定(激活)VBO,告诉OpenGL后续的操作都是针对这个VBO的。这里使用GL_ARRAY_BUFFER作为目标,表示这个VBO中存储的是顶点数据。//将数据复制到VBO中。sizeof(points)表示点数组占用的字节数,points是指向点数组的指针。GL_STATIC_DRAW表示这个VBO中的数据将被修改很少,并且会被频繁地用于渲染操作。glBufferData(GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW);// 启用顶点属性数组glEnableClientState(GL_VERTEX_ARRAY);glVertexPointer(3, GL_FLOAT, 0, 0);// 绘制独立的点glDrawArrays(GL_POINTS, 0, 3);// 禁用顶点属性数组glDisableClientState(GL_VERTEX_ARRAY);

绘制线段:(只需修改绘制模式)

    // 绘制一条直线glDrawArrays(GL_LINES, 0, 2);//绘制多条直线//首先顶点数要够GLfloat lines[] = {0.0f, 0.0f, 0.0f,  // 第一条线起点0.5f, 0.5f, 0.0f,  // 第一条线终点-0.5f, -0.5f, 0.0f,  // 第二条线起点-1.0f,1.0f,0.0f // 第二条线终点 };//其余不动glDrawArrays(GL_LINES, 0, sizeof(points)/sizeof(GLfloat)*3); //*3因为每个点有三个坐标x,y,z

main.cpp
#include "myopenglwidget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MyOpenGLWidget w;w.resize(400,300);w.show();return a.exec();
}

控制绘制图形颜色代码:
QOpenGLShader *fShader = new QOpenGLShader(QOpenGLShader::Fragment, this);
const char* fsrc ="void main(){\n""   gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);\n" // 将输出的颜色设置为黄色"}\n";
fShader->compileSourceCode(fsrc); //将片段着色器代码编译成可执行代码,并将结果存储在fShader对象中。如果编译失败,则会抛出异常。
顶点数组:
GLfloat vertices[] = {                      //定义了一个包含矩形顶点坐标的数组。-0.8f, -0.8f,0.8f, -0.8f,0.0f, 0.8f
};
使用顶点数组绘制图元:
    glDrawArrays(GL_TRIANGLE_FAN, 0, 3);    //使用顶点数组绘制图元。GL_TRIANGLE_FAN表示绘制三角形扇,0表示从数组中的第一个顶点开始绘制,4表示绘制的顶点数量。

2.绘制两个三角形

其余不变:

void MyOpenGLWidget::paintGL()
{glEnable(GL_MULTISAMPLE);glClearColor(1.0f, 1.0f, 1.0f, 1.0f);       //设置清除颜色缓冲区时使用的颜色,这里设置为白色。glClear(GL_COLOR_BUFFER_BIT);               //清除颜色缓冲区,将之前设定的清除颜色填充整个窗口。GLfloat vertices[] = {                      //定义了一个包含矩形顶点坐标的数组。-0.9f, 0.9f,0.1f, 0.9f,-0.9f, 0.5f,0.0f,0.0f,-0.9f,0.0f,-0.9f,-0.5f,};GLuint vPosition = program->attributeLocation("vPosition");             //获取顶点着色器中属性变量vPosition的位置。//将顶点数据与属性变量关联起来。vPosition表示属性变量的位置,2表示每个顶点有两个分量,GL_FLOAT表示每个分量的数据类型为浮点型,GL_FALSE表示不需要进行归一化处理,0表示相邻顶点间的偏移量,vertices表示顶点数据数组。glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, vertices);glEnableVertexAttribArray(vPosition);   //启用顶点属性数组。glDrawArrays(GL_TRIANGLE_FAN, 0, 3);    //使用顶点数组绘制图元。GL_TRIANGLE_FAN表示绘制三角形扇,0表示从数组中的第一个顶点开始绘制,4表示绘制的顶点数量。glDrawArrays(GL_TRIANGLE_FAN, 3, 3);qDebug()<<sizeof(vertices)/(sizeof(GLfloat)*2);
//    glDrawArrays(GL_TRIANGLE_FAN, 3, sizeof(vertices)/sizeof(GLfloat)*3);
}

在 glDrawArrays函数中,第一个参数是绘制模式,第二个参数是顶点数组中起始下标,第三个参数是绘制使用的顶点个数.

绘制独立的三角形还是需要用特定模式:

  • 一步到位
 glDrawArrays(GL_TRIANGLES, 0, sizeof(vertices)/(sizeof(GLfloat)*2));

 

3.绘制两个不同颜色的三角形

其余不变:

void MyOpenGLWidget::initializeGL()
{initializeOpenGLFunctions();// 创建顶点着色器对象和片段着色器对象QOpenGLShader *vshader = new QOpenGLShader(QOpenGLShader::Vertex, this);const char *vsrc ="attribute vec4 vPosition;\n""void main() {\n""  gl_Position = vPosition;\n""}\n";vshader->compileSourceCode(vsrc);QOpenGLShader *fshader = new QOpenGLShader(QOpenGLShader::Fragment, this);const char *fsrc ="uniform vec4 uColor;\n""void main() {\n""  gl_FragColor = uColor;\n""}\n";fshader->compileSourceCode(fsrc);// 创建着色器程序,并链接顶点着色器和片段着色器program = new QOpenGLShaderProgram(this);program->addShader(vshader);program->addShader(fshader);program->link();
}
void MyOpenGLWidget::paintGL()
{glClearColor(1.0f, 1.0f, 1.0f, 1.0f);glClear(GL_COLOR_BUFFER_BIT);GLfloat vertices[] = {-0.9f, 0.9f,0.1f, 0.9f,-0.9f, 0.5f,0.0f, 0.0f,-0.9f, 0.0f,-0.9f,-0.5f};GLuint vPosition = program->attributeLocation("vPosition");//获取 attribute 变量 vPosition 的位置program->bind();//绑定着色器程序glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, vertices);glEnableVertexAttribArray(vPosition);program->setUniformValue("uColor", QVector4D(1.0f, 0.0f, 0.0f, 1.0f)); // 设置第一个三角形的颜色为红色glDrawArrays(GL_TRIANGLES, 0, 3);program->setUniformValue("uColor", QVector4D(0.0f, 0.0f, 1.0f, 1.0f)); // 设置第二个三角形的颜色为蓝色glDrawArrays(GL_TRIANGLES, 3, 3);

变化之处:

1.创建片段着色器时需要把颜色替换成一个变量

2.绘制图像之前对赵色器的颜色进行设置修改

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

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

相关文章

【云备份】服务端数据管理模块

21. 服务端工具类实现-文件实用工具类设计 不管是客户端还是服务端&#xff0c;文件的传输备份都涉及到文件的读写&#xff0c;包括数据管理信息的持久化也是如此&#xff0c;因此首先设计封装文件操作类&#xff0c;这个类封装完毕之后&#xff0c;则在任意模块中对文件进行操…

Tap虚拟网卡 (草稿)

1 概述 Tap设备通常用于虚拟化场景下&#xff0c;参考如下场景&#xff1a; 图中标注了关键函数&#xff0c;以及数据流向。 tun有两个数据接口&#xff0c; file&#xff0c;给用户态使用&#xff1b;socket&#xff0c;给内核态使用&#xff0c;例如vhost 2 异步处理 图…

IRS辅助的隐蔽通信 (IRS aided covert communication)

这里写自定义目录标题 系统模型与问题formulation系统模型Willie的检测优化问题构建 提出算法A IRS反射矩阵优化Willie的Detection Error Probability (DEP) 本文是论文 Covert Communication in Intelligent Reflecting Surface Assisted Networks With a Friendly Jammer 的阅…

常见算法

简单认识算法 什么是算法&#xff1f; 解决某个实际问题的过程和方法&#xff01; 排序算法 冒泡排序 选择排序 冒泡排序 每次从数组中找到最大值放在数组的后面去 import java.util.Arrays;public class Work1 {public static void main(String[] args) {//准备一个数组in…

浅谈对ASP.NET MVC(微软Web开发框架)的理解

今天来总结下y2扩展就业的课程使用asp.netmvc开发企业级应用自学成果。首先ASP.NET是Microsoft公司.NetFramwork框架的一个动态网页开发的核心技术集&#xff0c;他可以帮助.net方向的动态web开发人员快速高效制作动态网页交互&#xff0c;同样支持jquery&#xff0c;js和h5c3&…

vue计算排列布局

1、效果 2、html <div class"databubble"><div ref"content"><divv-for"(item, index) in databubble"ref"contentPage":key"index"class"contentPage"><div><span class"title&…

2023年全国硕士研究生入学统一考试管理类专业学位联考逻辑试题——解析版

文章目录 2023年全国硕士研究生入学统一考试管理类专业学位联考逻辑试题三、逻辑推理真题(2023-26)真题(2023-27)真题(2023-28)真题(2023-29)真题(2023-30)真题(2023-31-32)真题(2023-33)真题(2023-34)真题(2023-35)真题(2023-36)真题(2023-37-38

Vue2+echarts 实现图表的简单绘制

Echarts是一个基于JavaScript的开源可视化库&#xff0c;由百度开发和维护。它通过简单的配置方式&#xff0c;就可以实现各种复杂的数据可视化和图表展示。Echarts支持多种图表类型&#xff0c;包括柱状图、折线图、饼图、散点图、漏斗图等&#xff0c;同时还支持地图可视化和…

SQL自学通之表达式条件语句与运算

目录 一、目标 二、表达式条件语句 1、表达式&#xff1a; 2、条件 2.1、WHERE 子句 三、运算 1、数值型运算: 1.1、加法() 1.2、减法 (-) 1.3、除法&#xff08;/&#xff09; 1.4、乘法 &#xff08;*&#xff09; 1.5、取模 &#xff08;%&#xff09; 优先级别…

HTTP缓存

需求开发中不断的往项目中添加图片、字体等这些静态资源使得项目打包体积越来越大。 打包后这些静态资源占据了包体积的大部分。 基于此&#xff0c;我们准备将静态资源从项目中移出来放到 oss 云服务上&#xff0c;这样项目的体积会缩小很多&#xff0c;打包速度也会快很多 …

[论文笔记] tiktoken中的gpt4 tokenizer

亲测可用!!!!! 注意是bytelevel的BPE!! 只有vocab.json是不ok的,只能encode单字节的字符,对于中文这种会encode之后tokens,ids都是[]。 gpt-tokenizer - npm GitHub - openai/tiktoken: tiktoken is a fast BPE tokeniser for use with OpenAIs models. GitHub - …

Android studio版本对用的gradle版本和插件版本(注意事项)

简介 Android Studio 构建系统以 Gradle 为基础&#xff0c;并且 Android Gradle 插件添加了几项专用于构建 Android 应用的功能。虽然 Android 插件通常会与 Android Studio 的更新步调保持一致&#xff0c;但插件&#xff08;以及 Gradle 系统的其余部分&#xff09;可独立于…

接口测试很难?1分钟带你入门接口自动化测试

1、什么是接口&#xff1f; 接口是连接前台和后台的桥梁&#xff0c;前台通过接口调用后端已完成的功能&#xff0c;而无需关注内部的实现细节。借助于接口&#xff0c;可以实现前后台分离&#xff0c;各自完成开发工作后&#xff0c;进行联调&#xff0c;提高工作效率 2、接…

系列十三、SpringBoot的自动配置原理分析

一、概述 我们知道Java发展到现在功能十分的强大&#xff0c;生态异常的丰富&#xff0c;这里面离开不了Spring及其家族产品的支持&#xff0c;而作为Spring生态的明星产品Spring Boot可以说像王者一般的存在&#xff0c;那么的耀眼&#xff0c;那么的光彩夺目&#xff01;那么…

分享66个菜单导航JS特效,总有一款适合您

分享66个菜单导航JS特效&#xff0c;总有一款适合您 66个菜单导航JS特效下载链接&#xff1a;https://pan.baidu.com/s/1dpGGbptx6hEKcBnTMNLIdA?pwd6666 提取码&#xff1a;6666 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 学习知识费力气&#xff0c;…

聚焦工业生产安全,汉威科技推出最轻最小迷你便携式单气体检测仪

有毒有害气体、可燃气体等是工业生产中常见的危险因素。我国已经出台了多项法律法规、行业标准&#xff0c;在石油、化工、钢铁冶金、危化品、矿业等行业以及有限空间相关场所作业&#xff0c;应当佩戴便携式气体检测仪&#xff0c;以保障作业人员的安全。 然而&#xff0c;近年…

SSM项目实战-前端-将uid存放在pinia中

https://pinia.vuejs.org/zh/getting-started.html 1、安装pinia npm install pinia {"name": "pro20-schedule","private": true,"version": "0.0.0","type": "module","scripts": {"d…

什么是中间人攻击

中间人攻击 1. 定义2. 中间人攻击如何工作3. 常见中间人攻击类型4. 如何防止中间人攻击 1. 定义 中间人攻击&#xff08;Man-in-the-Middle Attack&#xff0c;简称MITM&#xff09;&#xff0c;是一种会话劫持攻击。攻击者作为中间人&#xff0c;劫持通信双方会话并操纵通信过…

全球与中国汽车电力电子市场:增长趋势、竞争格局与前景展望

目前&#xff0c;世界各国都致力于转向更环保、更永续的传统交通替代方案。 电动车满足所有要求&#xff0c;因为它们具有零废气排放、改善空气品质、减少温室气体排放并创造更清洁、更健康的环境。此外&#xff0c;电动车的运作成本比传统内燃机驱动的汽车低&#xff0c;因为…

企业微信群发助手:实现高效触达的关键利器

在当今的商业环境中&#xff0c;流量已经成为了每个企业争夺的宝贵资源&#xff0c;这也导致了获客成本的不断上升。为了解决这个问题&#xff0c;越来越多的企业开始转向私域流量的运营&#xff0c;通过私域来吸引和维护客户。以电商为例&#xff0c;商家通过客服引导用户添加…