OpenGL绘制三维彩色立方体并实现自动旋转


北京航空航天大学计算机学院 2020春季计算机图形学课程第二次作业,使用OpenGL绘制三维彩色立方体并实现自动旋转,目标结果如下图:


本次任务重点主要有两个,一是绘制立方体,二是使之自动旋转。绘制立方体涉及到三维物体的呈现,包括了坐标的设定,观察位置和角度的设定。立方体的自动旋转涉及到动画,使用双缓冲,需要设置定时器回调函数。


1. 绘制立方体

有关绘制立方体,本次代码实现了两种绘制彩色立方体的方式。两种方法均将立方体放置在三维空间的第一卦限中,八个顶点分别位于(0, 0, 0), (0, 1, 0), (0, 1, 1), (0, 0, 1), (1, 0, 0), (1, 1, 0), (1, 1, 1), (1, 0, 1)。由于立方体放置在三维空间的第一卦限,平面上每一个像素点的颜色都恰好是该像素点三维坐标的RGB值。因此整个立方体,包括其内部的所有点,代表了整个RGB色彩空间。但本次代码仅仅绘制立方体的外表六个平面,内部的色彩是没有呈现出来的。

1.1 逐个像素点绘制小正方形

第一种方式是逐个绘制“像素”,实际是绘制很多个小的空间正方形,每个像素使用不同的颜色。这种方法的优点在于可以灵活控制像素点的尺寸,来绘制出不同效果的彩色立方体。但这种方法最明显的缺点在于其消耗的算力很大,在配合旋转的动画效果后,“分辨率”过高的彩色立方体会因为占据过多算力而卡住不动。在这种方法中,函数get_pix()来获取单个像素点(小正方形)四个顶点的坐标值,其输入是像素点所在平面,以及像素点在平面上的相对位置。输出的像素点正方形的四个顶点中,第一个顶点三维坐标值直接作为该像素点的颜色进行绘制,相关代码如下:

// 绘制一个色彩像素点(实际是小正方形)
// 返回值二维数组pix[4][3],分别存储正方形四个顶点坐标,同时第一个顶点坐标就是颜色值
// 参数direction表示像素点所在平面是正面还是背面,0表示背面,1表示正面
// 参数main_color表示像素点所在平面的基调颜色,0表示红色,1表示绿色,2表示蓝色
//      同时main_color也决定了像素点所在的平面法向,红色平面与x轴垂直,绿色y轴,蓝色z轴
// 参数relative_x和relative_y表示像素点在立方体平面上的相对位置
//      同时相对位置也和基调颜色共同决定了像素点的颜色RGB值
GLfloat** get_pix(unsigned int front_back, unsigned int direction, GLfloat relative_x, GLfloat relative_y)
{// 申请存储像素正方形四个顶点的二维数组pix[4][3]GLfloat** pix = (GLfloat**)malloc(sizeof(GLfloat*) * 4);if (pix == NULL) return NULL;for (unsigned int i = 0; i < 4; i++) {pix[i] = (GLfloat*)malloc(sizeof(GLfloat) * 3);if (pix[i] == NULL) return NULL;}  if (front_back == 0) {// 像素点位于朝向背面的三个面,正方形的顶点顺时针顺序排列if (direction == 0) {// 像素点位于YOZ平面(右后侧面)pix[0][0] = 0.0f; pix[0][1] = relative_x;        pix[0][2] = relative_y;pix[1][0] = 0.0f; pix[1][1] = relative_x;     pix[1][2] = relative_y + PIX;pix[2][0] = 0.0f; pix[2][1] = relative_x + PIX; pix[2][2] = relative_y + PIX;pix[3][0] = 0.0f; pix[3][1] = relative_x + PIX; pix[3][2] = relative_y;}else if (direction == 1) {// 像素点位于ZOX平面(左后侧面)pix[0][0] = relative_y;        pix[0][1] = 0.0f;    pix[0][2] = relative_x;pix[1][0] = relative_y + PIX; pix[1][1] = 0.0f;  pix[1][2] = relative_x;pix[2][0] = relative_y + PIX; pix[2][1] = 0.0f; pix[2][2] = relative_x + PIX;pix[3][0] = relative_y;        pix[3][1] = 0.0f; pix[3][2] = relative_x + PIX;}else if (direction == 2) {// 像素点位于XOY平面(底面)pix[0][0] = relative_x;          pix[0][1] = relative_y;      pix[0][2] = 0.0f;pix[1][0] = relative_x;        pix[1][1] = relative_y + PIX;   pix[1][2] = 0.0f;pix[2][0] = relative_x + PIX; pix[2][1] = relative_y + PIX; pix[2][2] = 0.0f;pix[3][0] = relative_x + PIX; pix[3][1] = relative_y;        pix[3][2] = 0.0f;}}else if (front_back == 1) {// 像素点位于朝向正面的三个面,正方形的顶点逆时针顺序排列if (direction == 0) {// 像素点位于垂直于X轴向前的平面(左前侧面)pix[0][0] = 1.0f; pix[0][1] = relative_x;      pix[0][2] = relative_y;pix[1][0] = 1.0f; pix[1][1] = relative_x + PIX;  pix[1][2] = relative_y;pix[2][0] = 1.0f; pix[2][1] = relative_x + PIX; pix[2][2] = relative_y + PIX;pix[3][0] = 1.0f; pix[3][1] = relative_x;       pix[3][2] = relative_y + PIX;}else if (direction == 1) {// 像素点位于垂直于Y轴向前的平面(右前侧面)pix[0][0] = relative_y;        pix[0][1] = 1.0f;    pix[0][2] = relative_x;pix[1][0] = relative_y;          pix[1][1] = 1.0f;    pix[1][2] = relative_x + PIX;pix[2][0] = relative_y + PIX; pix[2][1] = 1.0f; pix[2][2] = relative_x + PIX;pix[3][0] = relative_y + PIX; pix[3][1] = 1.0f; pix[3][2] = relative_x;}else if (direction == 2) {// 像素点位于垂直于Z轴向上的平面(顶面)pix[0][0] = relative_x;         pix[0][1] = relative_y;      pix[0][2] = 1.0f;pix[1][0] = relative_x + PIX; pix[1][1] = relative_y;      pix[1][2] = 1.0f;pix[2][0] = relative_x + PIX; pix[2][1] = relative_y + PIX; pix[2][2] = 1.0f;pix[3][0] = relative_x;          pix[3][1] = relative_y + PIX;   pix[3][2] = 1.0f;}}return pix;
}

在display函数中,依次绘制六个平面,每个平面依次绘制每个像素点,相关代码如下:

// 逐个像素点绘制小正方形for (unsigned int front_back = 0; front_back < 2; front_back++) {for (unsigned int direction = 0; direction < 3; direction++) {for (unsigned int i = 0; i < COLOR; i++) {for (unsigned int j = 0; j < COLOR; j++) {GLfloat** pix = get_pix(front_back, direction,(GLfloat)(i / COLOR), (GLfloat)(j / COLOR));glColor3fv(pix[0]);glBegin(GL_QUADS);for (unsigned int v = 0; v < 4; v++)glVertex3fv(pix[v]);glEnd();}}}}

1.2 直接绘制渐变平面

第二种方式是直接绘制立方体的六个平面,通过在glBegin()与glEnd()之间,在设定平面的四个顶点之间直接变换glColor3fv(),来绘制颜色渐变效果的立方体。这种方法的优点在于简单直观,并且节省算力,缺点在于不能灵活控制像素色彩“分辨率”。

如图,立方体的八个顶点依次编号,首先将八个顶点的三维坐标存储好,这样在绘制的时候省去了手动设定坐标的麻烦。其次,即使是每次调用一个点的坐标使用glVertex3fv(),也需要手动调用24次之多,可以进一步将六个平面顶点调用的顺序也存储下来,通过循环直接调用即可。同样的,顶点的坐标就是顶点位置颜色的RGB值,在glBegin()与glEnd()之间,在设定平面的四个顶点之间直接变换glColor3fv()即可得到渐变效果的正方形平面。相关代码如下:

// 设置立方体的八个顶点坐标static const GLfloat vertex[][3] = {0.0f, 0.0f, 0.0f,1.0f, 0.0f, 0.0f,0.0f, 1.0f, 0.0f,1.0f, 1.0f, 0.0f,0.0f, 0.0f, 1.0f,1.0f, 0.0f, 1.0f,0.0f, 1.0f, 1.0f,1.0f, 1.0f, 1.0f};// 设置绘制六个面时顶点的顺序static const GLint index[][4] = {0, 2, 3, 1,0, 4, 6, 2,0, 1, 5, 4, 4, 5, 7, 6, 1, 3, 7, 5, 2, 6, 7, 3};// 绘制六个面glBegin(GL_QUADS);for (unsigned int i = 0; i < 6; i++)for (unsigned int j = 0; j < 4; j++) {// 每个顶点的RGB颜色值和其顶点位置坐标一致glColor3fv(vertex[index[i][j]]);glVertex3fv(vertex[index[i][j]]);}glEnd();

1.3 设置平面方向及只绘制正面

经过实践可以发现,三维平面的绘制过程中,后绘制的平面会覆盖在先绘制的平面之上,比如如果先绘制三个正对着相机的面,后绘制三个背对着相机的面,则会出现背面覆盖正面的现象。如果绘制静止的立方体,则调整平面的绘制顺序即可,但考虑到立方体的旋转,这一问题就必须通过区分平面方向来解决。

OpenGL设定了平面方向机制可供选择,我们可以根据右手系,设定正方形四个顶点逆时针顺序排布时平面是正面(右手四指按四个顶点排列顺序方向弯曲,拇指指向为平面方向),然后在绘制开始时设定不绘制背朝观察点的面。这样一来,即使是旋转过程中,从任意角度都可以看到正常的立方体平面。相关代码如下:

// 设置逆时针排列的点围成的平面为正面
glFrontFace(GL_CCW);
// 设置不绘制背面,节省算力同时不会出现背面覆盖正面的情况
glCullFace(GL_BACK);
glEnable(GL_CULL_FACE);

2. 使立方体旋转

绘制好静止的立方体后,需要考虑的就是如何观察立方体,以及如何使立方体旋转。OpenGL提供了可以设置观察者位置和方向的函数,同时也提供了可以使绘制对象变换的矩阵操作函数,因此使立方体旋转总体上有两种思路:让观察者旋转或让绘制对象旋转。本次代码直接采用了固定观察者,让绘制的立方体旋转的思路。

首先gluLookAt()函数提供了设定观察者位置的接口,该函数的九个参数,每三个一组分别设置了观察者的位置,观察者朝向的点以及观察者头顶指向的方向(因为你可以歪着头看)。该函数在display函数中只调用一次,固定观察者。其次glTranslatef()和glRotatef()配合实现绘制对象绕任意轴旋转。glTranslatef()有三个参数,分别是将坐标系从原点平移到的目标点;glRotatef()有四个参数,分别是旋转的角度,以及旋转轴的向量。单纯的glRotatef()只能实现旋转轴过原点的旋转,若要实现任意旋转轴有以下思路:给定旋转轴上的两点A和B,首先将坐标系从原点平移到A点,然后根据A到B的方向旋转,最后再返还平移到原点。相关代码如下:

// 旋转初始的角度
GLfloat angle = 0.0f;
// 设置旋转轴:两个三维的点确定的旋转轴
GLfloat axis[][3] = {0.0f, 0.5f, 0.5f,1.0f, 0.5f, 0.5f
};// 加载单位阵
glLoadIdentity();
// 设置相机的位置和视角
// 有关gluLookAt:https://blog.csdn.net/Augusdi/article/details/20470813
gluLookAt(2, 2, 2, 0.0, 0.0, 0.0, -1, -1, 1);
// 设置绕给定的轴旋转
glTranslatef(axis[0][0], axis[0][1], axis[0][2]);
glRotatef(angle, axis[1][0] - axis[0][0], axis[1][1] - axis[0][1], axis[1][2] - axis[0][2]);
glTranslatef(-axis[0][0], -axis[0][1], -axis[0][2]);

若要产生连续的动画效果,需要设置定时器回调函数,来实现间隔一定的时间刷新一次。当间隔时间足够小时,在人眼视觉感官上就呈现了连续的动画效果。有关定时器回调函数和其在main函数中的调用代码如下:

// 动画所需的定时器回调函数
// 有关定时器回调函数:https://blog.csdn.net/shimazhuge/article/details/17894883
void timer_function(GLint value)
{// 旋转角度增加angle += STEP;// 若角度大于360转完一圈则清零if (angle > 360.0) angle -= 360.0;glutPostRedisplay();glutTimerFunc(50, timer_function, value);
}int main(int argc, char** argv)
{glutInit(&argc, argv);// 设置双缓冲和RGB颜色模式glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);// 设置窗口大小、位置和名称glutInitWindowSize(500, 500);glutInitWindowPosition(100, 100);glutCreateWindow("color_cube");// 设置绘制函数、窗口大小自适应函数和定时器回调函数glutDisplayFunc(display_1);glutReshapeFunc(reshape);glutTimerFunc(500, timer_function, 1);// 进入主循环glutMainLoop();return 0;
}

3. 运行效果

使用连续的渐变平面,以垂直于XOZ平面的旋转轴旋转的效果:

使用逐个像素点,像素点尺寸为1/8单位,以垂直于YOZ平面的旋转轴旋转的效果:


附录:完整代码

#include<GL/glut.h>
#include<math.h>
#include<iostream>
#define COLOR 8.0
#define PIX ((GLfloat)(1.0 / COLOR))
#define STEP 1.0f
using namespace std;// 旋转初始的角度
GLfloat angle = 0.0f;
// 设置旋转轴:两个三维的点确定的旋转轴
GLfloat axis[][3] = {0.0f, 0.5f, 0.5f,1.0f, 0.5f, 0.5f
};// 绘制一个色彩像素点(实际是小正方形)
// 返回值二维数组pix[4][3],分别存储正方形四个顶点坐标,同时第一个顶点坐标就是颜色值
// 参数direction表示像素点所在平面是正面还是背面,0表示背面,1表示正面
// 参数main_color表示像素点所在平面的基调颜色,0表示红色,1表示绿色,2表示蓝色
//      同时main_color也决定了像素点所在的平面法向,红色平面与x轴垂直,绿色y轴,蓝色z轴
// 参数relative_x和relative_y表示像素点在立方体平面上的相对位置
//      同时相对位置也和基调颜色共同决定了像素点的颜色RGB值
GLfloat** get_pix(unsigned int front_back, unsigned int direction, GLfloat relative_x, GLfloat relative_y)
{// 申请存储像素正方形四个顶点的二维数组pix[4][3]GLfloat** pix = (GLfloat**)malloc(sizeof(GLfloat*) * 4);if (pix == NULL) return NULL;for (unsigned int i = 0; i < 4; i++) {pix[i] = (GLfloat*)malloc(sizeof(GLfloat) * 3);if (pix[i] == NULL) return NULL;}  if (front_back == 0) {// 像素点位于朝向背面的三个面,正方形的顶点顺时针顺序排列if (direction == 0) {// 像素点位于YOZ平面(右后侧面)pix[0][0] = 0.0f; pix[0][1] = relative_x;        pix[0][2] = relative_y;pix[1][0] = 0.0f; pix[1][1] = relative_x;     pix[1][2] = relative_y + PIX;pix[2][0] = 0.0f; pix[2][1] = relative_x + PIX; pix[2][2] = relative_y + PIX;pix[3][0] = 0.0f; pix[3][1] = relative_x + PIX; pix[3][2] = relative_y;}else if (direction == 1) {// 像素点位于ZOX平面(左后侧面)pix[0][0] = relative_y;        pix[0][1] = 0.0f;    pix[0][2] = relative_x;pix[1][0] = relative_y + PIX; pix[1][1] = 0.0f;  pix[1][2] = relative_x;pix[2][0] = relative_y + PIX; pix[2][1] = 0.0f; pix[2][2] = relative_x + PIX;pix[3][0] = relative_y;        pix[3][1] = 0.0f; pix[3][2] = relative_x + PIX;}else if (direction == 2) {// 像素点位于XOY平面(底面)pix[0][0] = relative_x;          pix[0][1] = relative_y;      pix[0][2] = 0.0f;pix[1][0] = relative_x;        pix[1][1] = relative_y + PIX;   pix[1][2] = 0.0f;pix[2][0] = relative_x + PIX; pix[2][1] = relative_y + PIX; pix[2][2] = 0.0f;pix[3][0] = relative_x + PIX; pix[3][1] = relative_y;        pix[3][2] = 0.0f;}}else if (front_back == 1) {// 像素点位于朝向正面的三个面,正方形的顶点逆时针顺序排列if (direction == 0) {// 像素点位于垂直于X轴向前的平面(左前侧面)pix[0][0] = 1.0f; pix[0][1] = relative_x;      pix[0][2] = relative_y;pix[1][0] = 1.0f; pix[1][1] = relative_x + PIX;  pix[1][2] = relative_y;pix[2][0] = 1.0f; pix[2][1] = relative_x + PIX; pix[2][2] = relative_y + PIX;pix[3][0] = 1.0f; pix[3][1] = relative_x;       pix[3][2] = relative_y + PIX;}else if (direction == 1) {// 像素点位于垂直于Y轴向前的平面(右前侧面)pix[0][0] = relative_y;        pix[0][1] = 1.0f;    pix[0][2] = relative_x;pix[1][0] = relative_y;          pix[1][1] = 1.0f;    pix[1][2] = relative_x + PIX;pix[2][0] = relative_y + PIX; pix[2][1] = 1.0f; pix[2][2] = relative_x + PIX;pix[3][0] = relative_y + PIX; pix[3][1] = 1.0f; pix[3][2] = relative_x;}else if (direction == 2) {// 像素点位于垂直于Z轴向上的平面(顶面)pix[0][0] = relative_x;         pix[0][1] = relative_y;      pix[0][2] = 1.0f;pix[1][0] = relative_x + PIX; pix[1][1] = relative_y;      pix[1][2] = 1.0f;pix[2][0] = relative_x + PIX; pix[2][1] = relative_y + PIX; pix[2][2] = 1.0f;pix[3][0] = relative_x;          pix[3][1] = relative_y + PIX;   pix[3][2] = 1.0f;}}return pix;
}void display_1(void)
{// 设置逆时针排列的点围成的平面为正面glFrontFace(GL_CCW);// 设置不绘制背面,节省算力同时不会出现背面覆盖正面的情况glCullFace(GL_BACK);glEnable(GL_CULL_FACE);// 设置背景为白色glClearColor(1.0, 1.0, 1.0, 1.0);glClear(GL_COLOR_BUFFER_BIT);// 加载单位阵glLoadIdentity();// 设置相机的位置和视角// 有关gluLookAt:https://blog.csdn.net/Augusdi/article/details/20470813gluLookAt(2, 2, 2, 0.0, 0.0, 0.0, -1, -1, 1);// 设置绕给定的轴旋转glTranslatef(axis[0][0], axis[0][1], axis[0][2]);glRotatef(angle, axis[1][0] - axis[0][0], axis[1][1] - axis[0][1], axis[1][2] - axis[0][2]);glTranslatef(-axis[0][0], -axis[0][1], -axis[0][2]);// 逐个像素点绘制小正方形for (unsigned int front_back = 0; front_back < 2; front_back++) {for (unsigned int direction = 0; direction < 3; direction++) {for (unsigned int i = 0; i < COLOR; i++) {for (unsigned int j = 0; j < COLOR; j++) {GLfloat** pix = get_pix(front_back, direction,(GLfloat)(i / COLOR), (GLfloat)(j / COLOR));glColor3fv(pix[0]);glBegin(GL_QUADS);for (unsigned int v = 0; v < 4; v++)glVertex3fv(pix[v]);glEnd();}}}}// 双缓冲下的刷新帧缓存glutSwapBuffers();
}void display_2()
{// 设置逆时针排列的点围成的平面为正面glFrontFace(GL_CCW);// 设置不绘制背面,节省算力同时不会出现背面覆盖正面的情况glCullFace(GL_BACK);glEnable(GL_CULL_FACE);// 设置背景为白色glClearColor(1.0, 1.0, 1.0, 1.0);glClear(GL_COLOR_BUFFER_BIT);// 加载单位阵glLoadIdentity();// 设置相机的位置和视角// 有关gluLookAt:https://blog.csdn.net/Augusdi/article/details/20470813gluLookAt(2, 2, 2, 0.0, 0.0, 0.0, -1, -1, 1);// 设置绕给定的轴旋转glTranslatef(axis[0][0], axis[0][1], axis[0][2]);glRotatef(angle, axis[1][0] - axis[0][0], axis[1][1] - axis[0][1], axis[1][2] - axis[0][2]);glTranslatef(-axis[0][0], -axis[0][1], -axis[0][2]);// 设置立方体的八个顶点坐标static const GLfloat vertex[][3] = {0.0f, 0.0f, 0.0f,1.0f, 0.0f, 0.0f,0.0f, 1.0f, 0.0f,1.0f, 1.0f, 0.0f,0.0f, 0.0f, 1.0f,1.0f, 0.0f, 1.0f,0.0f, 1.0f, 1.0f,1.0f, 1.0f, 1.0f};// 设置绘制六个面时顶点的顺序static const GLint index[][4] = {0, 2, 3, 1,0, 4, 6, 2,0, 1, 5, 4, 4, 5, 7, 6, 1, 3, 7, 5, 2, 6, 7, 3};// 绘制六个面glBegin(GL_QUADS);for (unsigned int i = 0; i < 6; i++)for (unsigned int j = 0; j < 4; j++) {// 每个顶点的RGB颜色值和其顶点位置坐标一致glColor3fv(vertex[index[i][j]]);glVertex3fv(vertex[index[i][j]]);}glEnd();// 双缓冲下的刷新帧缓存glutSwapBuffers();
}// 动画所需的定时器回调函数
// 有关定时器回调函数:https://blog.csdn.net/shimazhuge/article/details/17894883
void timer_function(GLint value)
{// 旋转角度增加angle += STEP;// 若角度大于360转完一圈则清零if (angle > 360.0) angle -= 360.0;glutPostRedisplay();glutTimerFunc(50, timer_function, value);
}// 窗口大小自适应函数,使得窗口大小改变时仍保持图形的比例不变
// 有关窗口自适应函数:http://blog.sina.com.cn/s/blog_5497dc110102w8qh.html
void reshape(int w, int h)
{glViewport(0, 0, (GLsizei)w, (GLsizei)h);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(2, 2, 2, 0.0, 0.0, 0.0, -1, -1, 1);
}int main(int argc, char** argv)
{glutInit(&argc, argv);// 设置双缓冲和RGB颜色模式glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);// 设置窗口大小、位置和名称glutInitWindowSize(500, 500);glutInitWindowPosition(100, 100);glutCreateWindow("color_cube");// 设置绘制函数、窗口大小自适应函数和定时器回调函数glutDisplayFunc(display_1);glutReshapeFunc(reshape);glutTimerFunc(500, timer_function, 1);// 进入主循环glutMainLoop();return 0;
}

OpenGL绘制三维彩色立方体并实现自动旋转相关推荐

  1. matlab rgb三维直方图,MATLAB小技巧之十:利用MATLAB绘制三维彩色柱状图[转载]

    MATLAB自带有绘制三维柱状图的函数bar3,有版友反映不好控制柱子的颜色,特别是bar3不能绘制渐变色的柱子,并且bar3不能根据用户指定的散点数据绘制柱状图.为此,我编写了一个函数(scatte ...

  2. matlab矩阵画柱状三维,[原创]利用MATLAB绘制三维彩色柱状图

    function scatterbar(x,y,z,scale) %   根据散点数据绘制3维彩色柱状图 %   scatterbar(x,y,z,scale)  x,y,z是实值数组,用来指定柱子顶 ...

  3. Android开发笔记(一百五十三)OpenGL绘制三维图形的流程

    从这篇文章开始,接下来会连载一系列的OpenGL相关博文,好好探讨如何在Android中进行OpenGL开发. OpenGL的全称是"Open Graphics Library", ...

  4. android绘制过程3d图形,Android开发之OpenGL绘制三维图形的流程

    从这篇文章开始,接下来会连载一系列的OpenGL相关博文,好好探讨如何在Android中进行OpenGL开发. OpenGL的全称是"Open Graphics Library", ...

  5. opengl绘制三维人物luweiqi

    素材中有四个.bmp格式的纹理文件和一个.txt的模型参数文件 文件格式说明: 纹理文件数量纹理文件1(字符串)//.bmp纹理文件2(字符串)纹理文件3(字符串)... 材质数量ambient(fl ...

  6. 使用OpenGL绘制三维场景

    计算机图形学(OpenGL版) (第3版) COMPUTER GRAPHICS USING OpenGL 清华大学出版社 三维变换:在三维场景中如何把物体变换到所需的位置和朝向.(OpenGL 提供所 ...

  7. D50.1.0 如何使用OpenGL绘制三维坐标系

    如何在屏幕左下角绘制直角坐标系? 第一步,指定屏幕绘制区域 第二步,设定投影效果.观察坐标及旋转缩放等 第三步,绘制坐标轴,绘制箭头 第四步,添加"xyz"字符 ​ ​ 第一,图中 ...

  8. 【Qt for Android】OpenGL ES 绘制彩色立方体

    Qt 内置对OpenGL ES的支持.选用Qt进行OpenGL ES的开发是很方便的,很多辅助类都已经具备.从Qt 5.0開始添加了一个QWindow类,该类既能够使用OpenGL绘制3D图形,也能够 ...

  9. 现代OpenGL教程(三):绘制彩色立方体(imgui+OpenGL3.3)

    前言:imgui 是一个开源的GUI框架,自带的例子里面直接集成了glfw+gl3w环境,本例使用的版本是imgui v1.61,下载地址:https://github.com/ocornut/img ...

  10. 基于OpenGL的三维曲面数据场动态显示 (转)

    基于OpenGL的三维曲面数据场动态显示 2007-08-20 08:53 作者: 白婷 赵军 朱双华等 出处: 计算机与信息技术 责任编辑:方舟 摘 要 在大数据量条件下,实时动态显示三维曲面较困难 ...

最新文章

  1. Github标星9k+,超赞的 PyTorch 资源大列表!
  2. android 语音自动播报,Android 语音播报实现
  3. elasticsearch 基础语句
  4. 中国农业科技领域最大一笔融资来了:极飞科技拿下12亿投资,百度&软银领投...
  5. 一文读懂Java 11的ZGC为何如此高效
  6. 用JS写的取存款功能
  7. ios企业应用发布流程
  8. 【英语学习】【医学】无机化学 - 化合物命名(2) - 非金属类二元化合物
  9. 简单工厂模式和策略模式结合使用php
  10. git项目初始上传服务器,快速架设一个使用 SSH 的 Git 服务
  11. python编写登录接口_使用python编写一个登录接口
  12. mysql实例备份和单库备份_史上最简单的MySQL数据备份与还原教程(上)(三十五)...
  13. FTP升级cisco2811 IOS 实战
  14. flink-metric原理与实战
  15. 第一章、Android基础入门 - Android移动开发基础笔记
  16. 计算机无法屏幕亮度,今天详解win10电脑屏幕亮度无法调节的具体解决手法
  17. 面试十五年经验程序员,面试官沦为听众
  18. 常用文本编辑器英文大小写切换
  19. 【蓝桥杯嵌入式备赛】10.拓展板数码管、ADC按键及光敏电阻
  20. OPPO和一点资讯牵手,手机厂商正式接管分发大权?

热门文章

  1. 【软件测试】BUG的管理
  2. Android bluetooth介绍(三): 蓝牙扫描(scan)设备分析
  3. 视频教程-NodeJs零基础到实战项目-Node.js
  4. docker容器-nginx conf文件使用环境变量值
  5. 【U8+】用友U8+16.1不自动删除历史的自动备份文件
  6. 蓝凌OA 漏洞学习——treexml.tmpl 远程命令执行漏洞
  7. 史上最全的Windows进程详解!
  8. 斗鱼爬虫,爬取颜值频道的主播图片和名字
  9. 麻瓜编程python爬虫微专业_网易微专业Python Web开发工程师课程下载
  10. Ubuntu下编译OpenHarmony