当前位置: 首页 > news >正文

OpenGL-ES 学习(6)---- 立方体绘制

目录

        • 立方体绘制基本原理
        • 立方体的顶点坐标和绘制顺序
        • 立方体颜色和着色器
        • 实现效果和参考代码

立方体绘制基本原理

一个立方体是由8个顶点组成,共6个面,所以绘制立方体本质上就是绘制这6个面共12个三角形
Cube

顶点的坐标体系如下图所示,三维坐标的中心原点位于立方体的中心,但是要特别注意的是,前后方向表示的是Z轴,上下方向表示的是Y轴
CubeCoord

立方体的顶点坐标和绘制顺序

立方体坐标定义如下:

static GLfloat vertices[] = {// 位置           // 颜色-0.5f, -0.5f, -0.5f,  1.0f, 0.0f, 0.0f,  // 左下后 红色0.5f, -0.5f, -0.5f,  0.0f, 1.0f, 0.0f,  // 右下后 绿色0.5f,  0.5f, -0.5f,  0.0f, 0.0f, 1.0f,  // 右上后 蓝色-0.5f,  0.5f, -0.5f,  1.0f, 1.0f, 0.0f,  // 左上后 黄色-0.5f, -0.5f,  0.5f,  0.0f, 1.0f, 1.0f,  // 左下前 青色0.5f, -0.5f,  0.5f,  1.0f, 0.0f, 1.0f,  // 右下前 品红0.5f,  0.5f,  0.5f,  0.5f, 0.5f, 0.5f,  // 右上前 灰色-0.5f,  0.5f,  0.5f,  1.0f, 1.0f, 1.0f   // 左上前 白色
};// 立方体索引数据
static GLuint indices[] = {// 后面0, 1, 2,2, 3, 0,// 前面4, 5, 6,6, 7, 4,// 左面0, 4, 7,7, 3, 0,// 右面1, 5, 6,6, 2, 1,// 底面0, 1, 5,5, 4, 0,// 顶面3, 2, 6,6, 7, 3
};

在这里vertices定义不同的顶点,indices数组中表示不同顶点的绘制顺序,每三个顶点构成一个三角形,最后由 glDrawElements(GL_TRIANGLES,36,GL_UNSIGNED_INT,0);每三个顶点为一组绘制共12个三角形,不同的面和顶点的绑定关系如下:
Front
Back
Bottom
Top
Left
Right

立方体颜色和着色器

这里为立方体的每个顶点定义不同的颜色,同时在VertexShader中将颜色传递给FragmentShader,这样 FragmentShader会得到经过插值后的每个片元的颜色,并将这个颜色设置为最终的显示,实现的是一个渐变色的效果,shader 程序如下:

static const char* vertexShaderSource ="#version 300 es                            \n""precision mediump float;\n""uniform mat4 u_mvpMatrix;                   \n""layout(location = 0) in vec3 a_position;   \n""layout(location = 1) in vec3 a_color;      \n""out vec3 v_color;                          \n""void main() {\n""    gl_Position = u_mvpMatrix*vec4(a_position,1.0);\n""    v_color = a_color;                     \n""}\n";// Fragment Shader source code
static const char* fragmentShaderSource ="#version 300 es                            \n""precision mediump float;\n""layout(location = 0) out vec4 outColor;             \n""in vec3 v_color;           \n""void main() {\n""   outColor = vec4(v_color, 1.0);\n""}\n";
实现效果和参考代码

最终实现效果:
CubeEffectct01
CubeEffect02

参考代码如下:

Note: 这里还使用了ModeViewProject Matrix实现了旋转的效果,同时使用VAO,VBO,EBO实现了对顶点内容和顶点Index的缓冲

typedef struct {GLuint programObject;GLuint vboIds[2];GLuint vaoId;uint64_t timeInMiliSeconds;GLint   mvpLoc;GLfloat   angle;GLint  deltaTime;ESMatrix  mvpMatrix;
} UserData;static GLfloat vertices[] = {// 位置           // 颜色-0.5f, -0.5f, -0.5f,  1.0f, 0.0f, 0.0f,  // 左下后 红色0.5f, -0.5f, -0.5f,  0.0f, 1.0f, 0.0f,  // 右下后 绿色0.5f,  0.5f, -0.5f,  0.0f, 0.0f, 1.0f,  // 右上后 蓝色-0.5f,  0.5f, -0.5f,  1.0f, 1.0f, 0.0f,  // 左上后 黄色-0.5f, -0.5f,  0.5f,  0.0f, 1.0f, 1.0f,  // 左下前 青色0.5f, -0.5f,  0.5f,  1.0f, 0.0f, 1.0f,  // 右下前 品红0.5f,  0.5f,  0.5f,  0.5f, 0.5f, 0.5f,  // 右上前 灰色-0.5f,  0.5f,  0.5f,  1.0f, 1.0f, 1.0f   // 左上前 白色
};// 立方体索引数据
static GLuint indices[] = {// 后面0, 1, 2,2, 3, 0,// 前面4, 5, 6,6, 7, 4,// 左面0, 4, 7,7, 3, 0,// 右面1, 5, 6,6, 2, 1,// 底面0, 1, 5,5, 4, 0,// 顶面3, 2, 6,6, 7, 3
};static const char* vertexShaderSource ="#version 300 es                            \n""precision mediump float;\n""uniform mat4 u_mvpMatrix;                   \n""layout(location = 0) in vec3 a_position;   \n""layout(location = 1) in vec3 a_color;      \n""out vec3 v_color;                          \n""void main() {\n""    gl_Position = u_mvpMatrix*vec4(a_position,1.0);\n""    v_color = a_color;                     \n""}\n";// Fragment Shader source code
static const char* fragmentShaderSource ="#version 300 es                            \n""precision mediump float;\n""layout(location = 0) out vec4 outColor;             \n""in vec3 v_color;           \n""void main() {\n""   outColor = vec4(v_color, 1.0);\n""}\n";static int initInternal(ESContext* esContext) {UserData *userData = esContext->userData;// Vertex Shader source codeGLuint programObject = esLoadProgram(vertexShaderSource, fragmentShaderSource);if (programObject == 0) {return GL_FALSE;}// turn on depth testglEnable(GL_DEPTH_TEST);glDepthFunc(GL_LESS);glClearColor(0.0, 0.0, 0.0, 1.0);// Store the program objectuserData->programObject = programObject;userData->vboIds[0] =  userData->vboIds[1] = 0;userData->mvpLoc = glGetUniformLocation(userData->programObject, "u_mvpMatrix");userData->angle = 0.0f;return GL_TRUE;
}static void uMVPMatrixUpdateRotate(ESContext *esContext, GLuint deltaTime)
{UserData *userData = esContext->userData;ESMatrix perspective;ESMatrix modelview;float    aspect;userData->angle +=  1.0f;if (userData->angle >= 360.0f) {userData->angle -= 360.0f;}aspect = (GLfloat) esContext->width / (GLfloat) esContext->height;esMatrixLoadIdentity(&perspective);esMatrixLoadIdentity(&modelview);esPerspective(&perspective, 45.0f, aspect, 1.0f, 10.0f);esTranslate(&modelview, 0.0, 0.0, -4.0);esRotate(&modelview, userData->angle, 0.0, 1.0, 0.0);esMatrixMultiply(&userData->mvpMatrix, &modelview, &perspective);
}static void DrawPrimitiveWithVBOs(ESContext *esContext)
{UserData *userData = esContext->userData;GLuint   offset = 0;// vboIds[0] - used to store vertex attribute data// vboIds[l] - used to store element indicesif (userData->vboIds[0] == 0 && userData->vboIds[1] == 0) {// Only allocate on the first drawglGenBuffers(2, userData->vboIds);glGenVertexArrays(1, &userData->vaoId);printf("gen vbo id:%d %d vao id:%d.\n",userData->vboIds[0],userData->vboIds[1],userData->vaoId);glBindVertexArray(userData->vaoId);glBindBuffer(GL_ARRAY_BUFFER, userData->vboIds[0]);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);glVertexAttribPointer(0, 3,GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat) , NULL);glEnableVertexAttribArray(0);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat) ,(void*)(3*sizeof(GLfloat)));glEnableVertexAttribArray(1);// notice using GL_ARRAY_BUFFERglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, userData->vboIds[1]);glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(indices), indices, GL_STATIC_DRAW);glBindVertexArray(0);}glBindVertexArray(userData->vaoId);glUniformMatrix4fv(userData->mvpLoc, 1, GL_FALSE, (GLfloat *)&userData->mvpMatrix.m[0][0]);glDrawElements(GL_TRIANGLES,36,GL_UNSIGNED_INT,0);glBindVertexArray(0);
}static int drawLoopInternal(ESContext* esContext) {UserData *userData = esContext->userData;struct timespec currentts;clock_gettime(CLOCK_REALTIME, &currentts);uint64_t milliseconds = currentts.tv_sec * 1000LL + currentts.tv_nsec / 1000000;int periodInMs = milliseconds - userData->timeInMiliSeconds;userData->timeInMiliSeconds = milliseconds;userData->deltaTime++;//printf("current time in milliseconds %lld period:%d\n",milliseconds, (periodInMs > 0 ? periodInMs: -1));// Set the viewportglViewport(0, 0, 640, 480);glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glUseProgram(userData->programObject);uMVPMatrixUpdateRotate(esContext,userData->deltaTime);DrawPrimitiveWithVBOs(esContext);// Swap bufferseglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);
}static int cleanupInternal(ESContext* esContext) {printf("%s enter!.\n",__FUNCTION__);UserData *userData = esContext->userData;glDeleteProgram(userData->programObject);eglDestroySurface(esContext->eglDisplay, esContext->eglSurface);eglDestroyContext(esContext->eglDisplay, esContext->eglContext);eglTerminate(esContext->eglDisplay);XDestroyWindow(esContext->x_display, esContext->win);XCloseDisplay(esContext->x_display);return GL_TRUE;
}int testbasicDrawCube(ESContext* esContext) {printf("%s enter!.\n", __FUNCTION__);esContext->userData = (UserData*)malloc(sizeof(UserData));esCreateWindow(esContext, esContext->testcaseName,640, 480, ES_WINDOW_DEPTH);initInternal(esContext);while (1) {XEvent xev;while (XPending(esContext->x_display)) {XNextEvent(esContext->x_display, &xev);if (xev.type == KeyPress) {cleanupInternal(esContext);}}drawLoopInternal(esContext);}
}

相关文章:

OpenGL-ES 学习(6)---- 立方体绘制

目录 立方体绘制基本原理立方体的顶点坐标和绘制顺序立方体颜色和着色器实现效果和参考代码 立方体绘制基本原理 一个立方体是由8个顶点组成,共6个面,所以绘制立方体本质上就是绘制这6个面共12个三角形 顶点的坐标体系如下图所示,三维坐标…...

《数据结构与算法基础 by王卓老师》学习笔记——类C语言有关操作补充

1.元素类型说明 2.数组定义 3.C语言的内存动态分配 4..C中的参数传递 5.传值方式 6.传地址方式 例子...

高频面试题基本总结回顾2(含笔试高频算法整理)

干货分享,感谢您的阅读! (暂存篇---后续会删除,完整版和持续更新见高频面试题基本总结回顾(含笔试高频算法整理)) 备注:引用请标注出处,同时存在的问题请在相关博客留言…...

《深入浅出MySQL:数据库开发、优化与管理维护(第3版)》

深入浅出MySQL sql执行流程第一步:通过连接器进行连接第二步:解析器解析 SQL第三步:执行SQL 行记录存储格式行溢出日志数据库三大范式第一范式第二范式第三范式 索引索引分类B树索引BTree vs Hash需要索引1、字段需要频繁的查询操作2、字段用…...

VBA技术资料MF171:创建指定工作表数的工作簿

我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套,分为初级、中级、高级三大部分,教程是对VBA的系统讲解&#…...

【效率提升】新一代效率工具平台utools

下载地址:utools uTools这款软件,是一款功能强大且高度可定制的效率神器,使用快捷键alt space(空格) 随时调用,支持调用系统应用、用户安装应用和市场插件等。 utools可以调用系统设置和内置应用,这样可以方便快捷的…...

Jmeter插件管理器,websocket协议,Jmeter连接数据库,测试报告的查看

目录 1、Jmeter插件管理器 1、Jmeter插件管理器用处:Jmeter发展并产生大量优秀的插件,比如取样器、性能监控的插件工具等。但要安装这些优秀的插件,需要先安装插件管理器。 2、插件的下载,从Availabale Plugins中选择&#xff…...

Android中ViewModel+LiveData+DataBinding的配合使用(kotlin)

Android 中 ViewModel、LiveData 和 Data Binding 的配合使用(Kotlin) 摘要 本文将介绍如何在 Android 开发中结合使用 ViewModel、LiveData 和 Data Binding 进行数据绑定和状态更新。我们将详细探讨这三者之间的关系,并展示如何在 Kotlin…...

Elasticsearch 避免常见查询错误和陷阱

Elasticsearch 作为一款强大的搜索引擎和分析工具,已经被广泛应用于各种场景中。然而,在使用 Elasticsearch 进行查询时,如果不注意一些常见的错误和陷阱,可能会导致查询效率低下、结果不准确甚至系统性能下降。本文旨在总结一些常…...

【PyQt】20-QTimer(动态显示时间、定时关闭)

QTimer 前言一、QTimer介绍二、动态时间展示2.1 代码2.2 运行结果 三、定时关闭3.1 介绍他的两种用法1、使用函数或Lambda表达式2、带有定时器类型(高级) 3.2 代码3.3 运行结果 总结 前言 好久没学习了。 一、QTimer介绍 pyqt里面的多线程可以有两种实…...

[深度学习] 自编码器Autoencoder

自编码器(Autoencoder)是一种无监督学习算法,主要用于数据的降维、特征提取和数据重建。自编码器由两个主要部分组成:编码器(Encoder)和解码器(Decoder)。其基本思想是将输入数据映射…...

模型微调、智能体、知识库之间的区别

使用开源模型微调和使用知识库与智能体(agent)的区别主要体现在工作原理、应用场景和实现目标上。以下是对这三者的详细对比: 开源模型微调 定义: 微调是对预训练模型(例如BERT、GPT等)进行额外训练&…...

七日世界Once Human跳ping、延迟高、丢包怎么办?

七日世界是一款开放世界为轴点的生存射击游戏,玩家将进入一个荒诞、荒芜的末日世界,在这里与好友一起对抗可怖的怪物和神秘物质星尘的入侵,给这个星球留下最后的希望,共筑一片安全的领地。不过有部分玩家在游玩七日世界的时候&…...

机器人控制系列教程之关节空间运动控制器搭建(1)

机器人位置控制类型 机器人位置控制分为两种类型: 关节空间运动控制—在这种情况下,机器人的位置输入被指定为一组关节角度或位置的向量,这被称为机器人的关节配置,记作q。控制器跟踪一个参考配置,记作 q r e f q_{re…...

[linux]sed命令基础入门详解

sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”,接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这…...

Charles抓包工具系列文章(一)-- Compose 拼接http请求

一、背景 众所周知,Charles是一款抓包工具,当然是http协议,不支持tcp。(如果你想要抓tcp包,请转而使用wireshark,在讲述websocket的相关技术有梳理过wireshark抓包) 话说回来,char…...

OLMo:真正完全开源的大模型

最近,又有一家机构AI2(Allen Institute for AI)开源了一个LLM:OLMo,它的英文全称就叫Open Language Model。相比之前开源的大模型,OLMo的独特之处是完全开源,除了训练的模型,OLMo还开…...

51单片机STC89C52RC——12.1 数据存储芯片AT24C02

目的/效果 利用存储芯片AT24C02存储数据,LCD1602显示存储的数据。 一,STC单片机模块 二,AT24C02存储芯片 2.1 介绍 AT24C02是一个2K位串行CMOS E2PROM,内部含有256个8位字节,采用先进CMOS技术实质上减少了器件的功…...

融入云端的心跳:在Spring Cloud应用中集成Eureka Client

融入云端的心跳:在Spring Cloud应用中集成Eureka Client 引言 在微服务架构中,服务发现是一个关键组件,它允许服务实例之间相互发现并通信。Netflix Eureka是Spring Cloud体系中广泛使用的服务发现框架。Eureka提供了一个服务注册中心&…...

CocosCreator构建IOS的wwise教程

CocosCreator构建IOS教程 添加wwise教程: 1.添加include 2.添加SoundEngine 3.添加Profile-iphoneos下面lib下面的.a 4.导入js调用C++的文件 5.导入这些文件 6.初始化ios绝对路径和TTS语音合成对象 6.获得根目录绝对路径,加载pck需要找到绝对路径。怎么找绝对路径? #impor…...

JavaSec-RCE

简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性&#xff0c…...

C++_核心编程_多态案例二-制作饮品

#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为&#xff1a;煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例&#xff0c;提供抽象制作饮品基类&#xff0c;提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...