惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Secure Thoughts
云风的 BLOG
云风的 BLOG
Engineering at Meta
Engineering at Meta
A
About on SuperTechFans
Hugging Face - Blog
Hugging Face - Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
WordPress大学
WordPress大学
U
Unit 42
月光博客
月光博客
美团技术团队
S
Security Affairs
L
Lohrmann on Cybersecurity
Latest news
Latest news
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Recent Announcements
Recent Announcements
P
Palo Alto Networks Blog
The Last Watchdog
The Last Watchdog
T
Tor Project blog
Schneier on Security
Schneier on Security
Jina AI
Jina AI
MongoDB | Blog
MongoDB | Blog
Cloudbric
Cloudbric
B
Blog RSS Feed
Project Zero
Project Zero
Hacker News: Ask HN
Hacker News: Ask HN
Security Latest
Security Latest
C
Cybersecurity and Infrastructure Security Agency CISA
NISL@THU
NISL@THU
M
MIT News - Artificial intelligence
H
Help Net Security
Google DeepMind News
Google DeepMind News
L
LINUX DO - 热门话题
V
Visual Studio Blog
W
WeLiveSecurity
T
The Exploit Database - CXSecurity.com
Recent Commits to openclaw:main
Recent Commits to openclaw:main
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Threat Research - Cisco Blogs
Help Net Security
Help Net Security
F
Fortinet All Blogs
IT之家
IT之家
A
Arctic Wolf
Apple Machine Learning Research
Apple Machine Learning Research
I
Intezer
D
DataBreaches.Net
C
Cyber Attacks, Cyber Crime and Cyber Security
Stack Overflow Blog
Stack Overflow Blog
SecWiki News
SecWiki News
Last Week in AI
Last Week in AI

音视频开发进阶

音视频教程-第三节 音视频教程-第二节 真的,AI 可能就是新时代的信息差 充值 Cursor 之后,工作有了哪些变化?🤔 个人'蒸馏'大模型能做哪些有意思的事情 DeepSeek 大模型在 Mac 上的部署和运行 音视频教程-第一节 【WebRTC 专栏】-- Android 开发集成 WebRTC 库的几种方式 【WebRTC 专栏】-- 在 Mac M1 等系列芯片编译和开发 WebRTC-Android 库 Meta Llama3 大模型在 Mac 上的部署和运行 iOS VideoToolBox 解码 HEVC Open-GOP 视频的问题排查 Flutter 状态管理之 InheritedWidget 使用和分析 用 ChatGPT 回答技术问题怎么样 ? 音视频开发系统入门大致路线 UE 4.27 添加自定义 ShadingModel 用 UE4 虚幻引擎做个捏脸小功能~~ UE4 材质练习 之 凹凸贴图偏移的使用 UE4 材质练习系列基础 OpenGL上下文创建以及共享机制 007 | 播放器系列专栏-解析 MP4 文件读取信息 006 | 播放器系列专栏-在 Mac 上查看 MP4 格式信息 干货 | 快速抽取缩略图是怎么练成的? 关于直播、WebRTC、FFmpeg 的那些事 005 | 播放器系列专栏-在 Windows 上查看 MP4 格式信息 将音视频中的花屏、绿屏、黑屏问题一网打尽 关于音视频里面的解码帧率和渲染帧率 004 | 播放器系列专栏-认识MP4视频(下) 003 | 播放器系列专栏-认识MP4视频(上) 入门或者转行音视频,应该要怎么做? H264视频文件如何缩放分辨率 002 | 播放器系列专栏-FFmpeg依赖库的配置 001 | 播放器系列专栏-关于播放器项目的一个小实践 Seek策略以及在有B帧情况下的处理 目前流媒体开发工程师工作内容主要是什么? 一个音视频领域专业问答的小圈子 干货收藏 || Vulkan Game Engine 视频教程 音视频春节假期内卷指南(实操) Vulkan 在 FFmpeg 中的支持 Windows 下 FFmpeg 和 LibX264 的编译和配置 Metal 开发 | 使用 C++ 进行接口调用 音视频开发工作经验分享 || 视频版 FFmpeg 调用 MediaCodec 硬解码到 Surface 上 代码吸猫 | 用 OpenGL 图像渲染的养猫计划 百倍变速--解码到底能不能丢 非参考帧 ?FFmpeg 有话说!!! 老生常谈-FFmpeg 的编译问题轻松搞定 FFmpeg 调用 Android MediaCodec 进行硬解码(附源码) 【WebRTC 专栏】--创建相机预览 Unity Shader 光照基础之 Half Lambert 光照模型 Unity Shader 光照基础之Lambert光照模型 Unity Shader 光照基础内容 Unity Shader 显示一张图片纹理 UnityShader 的基本概念 Unity 物体的基本操作 C++ 模板系列小结07-尾置返回类型 C++ 模板系列小结06-可变参数模板特性 C++ 中的多线程的使用和线程池建设 C++ 模板系列小结05-模板类型作为模板参数 C++ 模板系列小结04-类模板中的成员模板 C++ 模板系列小结03-在模板中指定变量类型 C++ 模板系列小结02-非类型模板参数 C++ 模板系列小结01-函数模板和类模板 从零打造渲染引擎系列01-什么是渲染引擎 iOS开发 - 在 Swift 中去调用 C/C++ 代码 2021 技术新番 - 从零打造渲染引擎系列 iOS 音视频开发的一些基础准备工作 音视频交流群又来啦~~~ 【WebRTC 专栏】WebRTC & Android 开发学习环境搭建~ 【喜大普奔】域名终于备案通过啦 Shader 优化 | OpenGL 绘制网格效果 【音视频连载-011】第二季 FFmpeg 一层一层获取文件信息 KodeLife | Shader 实时编辑预览的强大工具使用实践 推荐几个堪称教科书级别的 Android 音视频入门项目 【音视频连载-010】第二季 FFmpeg 日志打印 【音视频连载-008】基础学习篇-SDL 播放 PCM 音频文件(下) 【音视频连载-007】基础学习篇-SDL 播放 PCM 音频文件(上) 【音视频连载-006】基础学习篇-SDL 播放 YUV 视频文件 【音视频连载-005】基础学习篇-SDL 加载 YUV 文件并显示 【音视频连载-004】基础学习篇-SDL 加载图片并显示 【音视频连载-003】基础学习篇-SDL 消息循环和事件响应 【音视频连载-002】基础学习篇-SDL 创建窗口并显示颜色 【音视频连载-001】基础学习篇- SDL 介绍以及工程配置 LearnOpenGL 源码在 MAC 上的编译与调试 2019 年终总结与回顾 Android NDK 开发的免费技术视频来啦~~ OpenGL 实现视频编辑中的转场效果 OpenGL 实践之贝塞尔曲线绘制 图像库 libjpeg-turbo 编译与实践 图像库 libpng 编译与实践 rust 开发编译 Android 动态库实践 Android NDK 开发 —— 从 Assets 文件夹加载图片并上传纹理 简单易用的图像解码库介绍 —— stb_image 博客图床迁移记 进击的 Vulkan 移动开发之 SwapChain 进击的 Vulkan 移动开发之 Command Buffer 进击的 Vulkan 移动开发之 Instance & Device & Queue 进击的 Vulkan 移动开发(一)之今生前世 Java 显式锁 Lock 与条件队列 C++ 标准容器库小结 一文读懂 YUV 的采样与格式 《OpenGL ES 3.x 游戏开发》碰撞检测之 AABB 包围盒
OpenGL 学习系列---基本形状的绘制
音视频开发进阶 · 2017-12-22 · via 音视频开发进阶

一个专注音视频领域的小圈子

在之前的一篇博客中,讲述了 OpenGL 绘制一个点的流程及相关的代码,其中关于 OpenGL 程序编译部分都是可以在其他项目中接着复用的,接下来会讲到如何去绘制其他的基本图元。

绘制直线

两点确定一条直线,显然绘制一条直线是需要两个顶点数据的。

定义如下顶点数据,绘制一条屏幕对角线的直线:

    float[] lineVertex = {
            -0.5f, 0.5f,
            0.5f, -0.5f
    };

而我们的顶点着色器和片段着色器也会发生一些变化,最终还是绘制一条单一颜色的直线。

顶点着色器代码:

attribute vec4 a_Position;
void main(){
    gl_Position = a_Position;
}

由于是绘制的直线,相比于绘制点,就没有了 gl_PointSize变量来确定大小了。

片段着色器代码:

precision mediump float;
uniform vec4 u_Color;
void main()
{
    gl_FragColor = u_Color;
}

依旧是纯色,目前还没有涉及到颜色的变化。

而在我们给着色器变量绑定数据时,依旧是通过glGetUniformLocationglGetAttribLocation方法给uniformattribute类型的u_Colora_Position变量赋值。

最后还是通过glDrawArrays方法执行绘制。

glDrawArrays(GL_LINES, 0, 2);

GL_LINES代表绘制的类型是直线,而0,2则是绘制的顶点范围。

绘制三角形

绘制三角形和绘制直线基本差不多,从两个点的直线变成了三个点的三角形。

顶点数据也发生了相应的改动,假设如下的数据,注意要以逆时针定义数据。

    float[] triangleVertex = {
            -0.5f, 0.5f,
            -0.5f, -0.5f,
            0.5f, -0.5f
    };

那么最后绘制时,绘制类型也会发生变化了,顶点个数范围也会变化。

 glDrawArrays(GL_TRIANGLES, 0, 3);

绘制三角形结果如图:

绘制矩形

显然,OpenGL 是没有提供矩形这一基本图元的,但是我们可以用两个三角形来拼接成一个矩形。

OpenGL 中提供了一个绘制类型叫做三角形扇,如下图所示:

在上图中,矩形的每一条边上的顶点都被两个三角形使用了,而且中心的顶点被所有四个三角形使用了。

我们不必输入四个三角形的顶点数据来绘制四个三角形从而组成矩形,可以告诉 OpenGL 重用那些顶点数据,把这些顶点作为一个三角形扇绘制。

一个三角形扇以一个中心顶点作为起始,使用相邻的两个顶点创建第一个三角形,接下来的每个顶点都会创建一个三角形,围绕起始的中心点按扇形展开,为了使扇形闭合,我们需要在最后重复第二个点。

所以,以三角形扇的形式绘制一个矩形,我们可以重新定义矩形的顶点数据:

   float[] rectangleVertex = {
		   // 第一个点就是三角形扇的中心点
            0f,    0f, 
            -0.5f, -0.8f,   
            0.5f, -0.8f,   
            0.5f,  0.8f,   
            -0.5f,  0.8f,   
            -0.5f, -0.8f
          // 重复第二个点,使三角形扇闭合
    };

而着色器代码依旧不变,绘制一个纯色的矩形,绘制代码如下:

  glDrawArrays(GL_TRIANGLE_FAN, 0, 6);

绘制类型为GL_TRIANGLE_FAN,顶点数量也变成了 6 个。

那么问题来了,OpenGL 到底为我们提供哪些绘制方式呢?如下表所示:

绘制类型 绘制方式
GL_POINTS 将传入的顶点坐标作为单独的点绘制
GL_LINES 将传入的坐标作为单独线条绘制,ABCDEFG六个顶点,绘制AB、CD、EF三条线
GL_LINE_STRIP 将传入的顶点作为折线绘制,ABCD四个顶点,绘制AB、BC、CD三条线
GL_LINE_LOOP 将传入的顶点作为闭合折线绘制,ABCD四个顶点,绘制AB、BC、CD、DA四条线。
GL_TRIANGLES 将传入的顶点作为单独的三角形绘制,ABCDEF绘制ABC,DEF两个三角形
GL_TRIANGLE_STRIP 将传入的顶点作为三角条带绘制,ABCDEF绘制ABC,BCD,CDE,DEF四个三角形
GL_TRIANGLE_FAN 将传入的顶点作为扇面绘制,ABCDEF绘制ABC、ACD、ADE、AEF四个三角形

绘制圆形

现在我们要绘制一个圆形,显然 OpenGL 是没有提供圆形的绘制类型的,这就要用到上面提供的绘制方式了。

以绘制一个实心的圆形为例子:

有了上面三角形扇绘制矩形的例子,我们按照同样的思想,把一个圆形分成多个三角形组成,如下图所示:

我们分的三角形越多,三角形个数趋向于无限大的时候,整个图案也就越趋向于圆。

这样一来,顶点数据就不能再靠手写了。

    // 圆形分割的数量,分成 360 份,可由 360 个线段组成空心圆,也可以由 360 个三角形组成实心圆
    public static final int VERTEX_DATA_NUM = 360;
    // 360 个顶点的位置,因为有 x 和 y 坐标,所以 double 一下,再加上中心点 和 闭合的点
    float[] circleVertex = new float[VERTEX_DATA_NUM * 2 + 4];
    // 分成 360 份,每一份的弧度
    float radian = (float) (2 * Math.PI / VERTEX_DATA_NUM);
    // 绘制的半径
    float radius = 0.8f;
    
    // 初始化圆形的顶点数据
    private void initVertexData() {
        // 中心点
        circleVertex[0] = 0f;
        circleVertex[1] = 0f;
        // 圆的 360 份的顶点数据
        for (int i = 0; i < VERTEX_DATA_NUM; i++) {
            circleVertex[2 * i + 2] = (float) (radius * Math.cos(radian * i));
            circleVertex[2 * i + 1 + 2] = (float) (radius * Math.sin(radian * i));
        }
        // 闭合点
        circleVertex[VERTEX_DATA_NUM * 2 + 2] = (float) (radius * Math.cos(radian));
        circleVertex[VERTEX_DATA_NUM * 2 + 3] = (float) (radius * Math.sin(radian));
    }

把圆分成了 360 份。圆形的顶点数据也分为了三部分了,以原心作为我们的中心点,中间的 360 个点用来绘制三角形,最后一个点使得我们的图形闭合。

在绘制时依旧使用三角形扇的形式来绘制。

	// 要把顶点数据个数对应上
    glDrawArrays(GL_TRIANGLE_FAN, 0, VERTEX_DATA_NUM + 2);

当然,在绘制圆形时,我们也可以不单独定义原点和闭合点,直接使用圆形的 360 个顶点来绘制,最终的结果依旧会是一个圆形。

当然,我们也可以使用其他的绘制类型,比如直线,来绘制一个空心的圆形。

还是上面定义的顶点数据,但是我们只用其中分割成 360 份的那部分顶点数据就好了,也就是去掉首位两个点,然后把这个 360 个点依次连接绘制成圆形。

        glDrawArrays(GL_LINE_LOOP, 1, VERTEX_DATA_NUM );

这样就完成一个圆形的绘制。

正多边形的绘制

在绘制圆形的基础上,我们还可以进行拓展一下。

要知道,最后我们的圆形实际上是一个正多边形来趋近于圆形的,只是肉眼难以观察到了,毕竟它是一个正三百六十边形…

那么假设我们要绘制正五边形、正六边形、正七边形呢?

实际上也很简单,只要把圆分成五份、六份、七份就好了。

展示一些绘制图如下:

正五边形:

正六边形:

正七边形:

小结

到此,基本讲述了 OpenGL 的绘制流程以及基本图形的绘制。

根据图形和绘制类型来采用以何种方式进行绘制,以及定义顶点数据,最后直接绘制对应图形即可。

但显然,这还是不够的,还是有很多问题的。

想要绘制一个圆形,结果却成了椭圆;想要绘制一个正五边形,却成了歪的;这到底是道德的沦丧还是人性的泯灭,一切的揭晓就在下一篇博客中了。

具体代码详情,可以参考我的 Github 项目: https://github.com/glumes/AndroidOpenGLTutorial

参考

1、http://blog.csdn.net/junzia/article/details/52818488

原创文章,转载请注明来源:    OpenGL 学习系列---基本形状的绘制