学习了《OpenGL超级宝典》第二章后,编写了我们的第一个OpenGL程序,也真正开始了OpenGL之旅。

下面来让我们一起重新练习熟悉一下第二章的3个例子吧!

1.  "Triangle" 第一个三角形

通过这个例子我们熟悉了OpenGL的一些流程,如初始化、窗口的创建、窗口的标题、图形的渲染等。

具体的例子代码我就不复制贴出了哈~,下面我只贴出我对此例子做的一些学习扩展:

// +++++++++++++++++++++++++++++++++++++++
// 《OpenGL 超级宝典》 Chapter02 Triangle
// ---------------------------------------// 头文件引用
......// GLTools 封装的顶点批次处理类
GLBatch triangleBatch;
// GLTools 封装的着色器管理器
GLShaderManager shaderManager;// +++++++++++
// 自己扩展部分
GLBatch triangle2Batch;
GLBatch triangle3Batch;
GLBatch triangle4Batch;
// -----------// 初始化
void SetupRC()
{// 书本相同// 蓝色背景glClearColor(0.0f, 0.0f, 1.0f, 1.0f);// 初始化 GLTools  的着色器管理器shaderManager.InitializeStockShaders();// 创建一个三角形顶点数组GLfloat vVerts[] = {0.5f,  -0.5f, 0.0f,-0.5f, -0.5f, 0.0f,0.0f,  0.0f, 0.0f,};// 拷贝三角形顶点数组到 GLTools 的顶点批次中// GL_TRIANGLES 表示为三角形顶点triangleBatch.Begin(GL_TRIANGLES, 3);triangleBatch.CopyVertexData3f(vVerts);triangleBatch.End();// +++++++++++// 自己扩展部分// 绿色三角形顶点GLfloat vVerts2[] = {0.5f,  -0.5f, 0.0f,0.5f,  0.5f, 0.0f,0.0f,  0.0f, 0.0f,};triangle2Batch.Begin(GL_TRIANGLES, 3);triangle2Batch.CopyVertexData3f(vVerts2);triangle2Batch.End();// 黄色三角形顶点GLfloat vVerts3[] = {0.5f,  0.5f, 0.0f,-0.5f,  0.5f, 0.0f,0.0f,  0.0f, 0.0f,};triangle3Batch.Begin(GL_TRIANGLES, 3);triangle3Batch.CopyVertexData3f(vVerts3);triangle3Batch.End();// 洋红色三角形顶点GLfloat vVerts4[] = {-0.5f,  0.5f, 0.0f,-0.5f,  -0.5f, 0.0f,0.0f,  0.0f, 0.0f,};triangle4Batch.Begin(GL_TRIANGLES, 3);triangle4Batch.CopyVertexData3f(vVerts4);triangle4Batch.End();// -----------
}// 渲染场景
void RenderScene(void)
{// 书本相同// 清除 颜色 和 深度 和 模板 的缓冲区数据glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);// 红色GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };// 装载红色着色器shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);// 绘制三角形triangleBatch.Draw();// +++++++++++// 自己扩展部分// 绿色GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f };// 装载红色着色器shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vGreen);// 绘制三角形triangle2Batch.Draw();// 黄色GLfloat vYellow[] = { 1.0f, 1.0f, 0.0f, 1.0f };// 装载红色着色器shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vYellow);// 绘制三角形triangle3Batch.Draw();// 洋红色GLfloat vMagenta[] = { 1.0f, 0.0f, 1.0f, 1.0f };// 装载红色着色器shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vMagenta);// 绘制三角形triangle4Batch.Draw();// -----------// 将后台缓冲区内容切换到前台缓冲区glutSwapBuffers();
}int main(int argc, char * argv[])
{// 书本相同.....return 0;
}

首先贴出运行的截图:

也就是通过四个三角形进行拼出一个正方形

下面进行讲解上面的程序:

1. 定义其他3个新的三角形GLBatch用于存放绘制是三角形顶点数据。

2. 定义其他3个新的三角形顶点数组,然后放入对应GLBatch中。

3. 渲染中进行渲染其他3个新的三角形。

2.  "Move" 通过按键输入让图形变得有活力

同样也只贴出扩展的内容部分:

 +++++++++++++++++++++++++++++++++++++++《OpenGL 超级宝典》 Chapter02 Move---------------------------------------.......+++++++++++自己扩展部分
GLBatch triangleBatch;GLfloat fPi = 3.1415926f;
GLfloat fRad = fPi / 180.0f;
GLfloat fTriangleX = 0.0f, fTriangleY = 0.0f;
GLfloat fCurAngle = 0.0f;
// 创建一个三角形顶点数组
GLfloat fScale = 0.8f;
GLfloat vTriangleVerts[] = {-blockSize * fScale, 0.0f, 0.0f,blockSize * fScale,  0.0f, 0.0f,0.0f,  blockSize * fScale, 0.0f,
};void Rotate(GLfloat angle, GLfloat *pX, GLfloat *pY)
{*pX = fTriangleX + (blockSize * fScale) * cos(angle * fRad);*pY = fTriangleY + (blockSize * fScale) * sin(angle * fRad);
}void RotateTriangleArrow(GLfloat angle)
{Rotate(angle, &vTriangleVerts[0], &vTriangleVerts[1]);Rotate(angle + 90.0f, &vTriangleVerts[3], &vTriangleVerts[4]);Rotate(angle + 180.0f, &vTriangleVerts[6], &vTriangleVerts[7]);
}
// -----------void SetupRC()
{.......triangleBatch.Begin(GL_TRIANGLES, 3);triangleBatch.CopyVertexData3f(vTriangleVerts);triangleBatch.End();
}void SpecialKeys(int key, int x, int y)
{.......if (key == GLUT_KEY_UP) {fCurAngle = 0.0f;blockY += stepSize;}if (key == GLUT_KEY_DOWN) {fCurAngle = 180.0f;blockY -= stepSize;}if (key == GLUT_KEY_LEFT) {fCurAngle = 90.0f;blockX -= stepSize;}if (key == GLUT_KEY_RIGHT) {fCurAngle = 270.0f;blockX += stepSize;}.......RotateTriangleArrow(fCurAngle);triangleBatch.CopyVertexData3f(vTriangleVerts);glutPostRedisplay();
}void RenderScene(void)
{......// 南瓜橙色GLfloat vPumpkinOrange[] = { 0.98f, 0.625f, 0.12f, 1.0f };shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vPumpkinOrange);triangleBatch.Draw();glutSwapBuffers();
}int main(int argc, char * argv[])
{......return 0;
}

首先贴出运行的截图:

分别对应按下了 ↑←↓→按键后箭头的变化

下面进行讲解上面的程序:

1. 首先是定义一个三角形的GLBatch。

2. 定义一个三角形的顶点数组,用于存放三角形的顶点数据。

3. fTriangleX 和 fTriangleY 表示为 三角形底边的中心点的坐标,当按键发生变化后,通过这个原点进行旋转。

4. fPi 和 fRad 为圆周率和弧度,同样为旋转用到的参数。

5. fCurAngle 表示为旋转的角度,分别对于按键改变后进行旋转的角度。

6. fScale 为对三角形的一个缩放比例。

7. Rotate 函数用于对顶点坐标进行旋转(详细旋转的部分,在以前的有讲过,如需单独详细讲解请给我留言吧,此处就略过了)。

8. RotateTriangleArrow函数用于旋转三角形的三个顶点。

9. 在SetupRC是时候将我们的三角形顶点数据进行放入我们定义的GLBatch中,然后在RenderScene的时候同样进行渲染。

10. 在SpecialKeys的时候,进行改变我们的fCurAngle(三角形旋转的角度)。

3. "Bounce" 简单的动画片,通过不断刷新进行更新渲染

通过参照 "Bounce" 和 "Triangle" 来进行做一些有意思的事情吧。

下面贴出扩展部分:

 +++++++++++++++++++++++++++++++++++++++《OpenGL 超级宝典》 Chapter02 Bounce---------------------------------------.......GLShaderManager shaderManager;GLBatch leftFootTriangleBatch;
GLBatch leftShankTriangleBatch;
GLBatch leftThighTriangleBatch;
GLBatch leftUpperArmTriangleBatch;
GLBatch leftForeArmTriangleBatch;
GLBatch leftFinger1TriangleBatch;
GLBatch leftFinger2TriangleBatch;GLBatch rightFootTriangleBatch;
GLBatch rightShankTriangleBatch;
GLBatch rightThighTriangleBatch;
GLBatch rightUpperArmTriangleBatch;
GLBatch rightForeArmTriangleBatch;
GLBatch rightFinger1TriangleBatch;
GLBatch rightFinger2TriangleBatch;GLBatch neckTriangleBatch;GLBatch bodySquareBatch;
GLBatch headSquareBatch;GLfloat fStartX = 0.0f, fStartY = 0.0f;// Left-Foot
GLfloat vLeftFootVerts[] = {fStartX - 0.02f - 0.1f, fStartY, 0.0f,fStartX - 0.02f, fStartY, 0.0f,fStartX - 0.07f, fStartY + 0.05f, 0.0f
};// Left-Shank
GLfloat vLeftShankVerts[] = {fStartX - 0.07f, fStartY + 0.05f, 0.0f,fStartX - 0.02f - 0.02f, fStartY + 0.05f + 0.1f, 0.0f,fStartX - 0.02f - 0.08f, fStartY + 0.05f + 0.1f, 0.0f,
};// Left-Thigh
GLfloat vLeftThightVerts[] = {fStartX - 0.02f - 0.08f, fStartY + 0.05f + 0.1f, 0.0f,fStartX - 0.02f - 0.02f, fStartY + 0.05f + 0.1f, 0.0f,fStartX - 0.07f, fStartY + 0.05f + 0.1f + 0.08f, 0.0f,
};// Right-Foot
GLfloat vRightFootVerts[] = {fStartX + 0.02f + 0.1f, fStartY, 0.0f,fStartX + 0.02f, fStartY, 0.0f,fStartX + 0.07f, fStartY + 0.05f, 0.0f
};// Right-Shank
GLfloat vRightShankVerts[] = {fStartX + 0.07f, fStartY + 0.05f, 0.0f,fStartX + 0.02f + 0.02f, fStartY + 0.05f + 0.1f, 0.0f,fStartX + 0.02f + 0.08f, fStartY + 0.05f + 0.1f, 0.0f,
};// Right-Thigh
GLfloat vRightThightVerts[] = {fStartX + 0.02f + 0.08f, fStartY + 0.05f + 0.1f, 0.0f,fStartX + 0.02f + 0.02f, fStartY + 0.05f + 0.1f, 0.0f,fStartX + 0.07f, fStartY + 0.05f + 0.1f + 0.08f, 0.0f,
};// Body
GLfloat vBodyVerts[] = {fStartX - 0.1f, fStartY + 0.05f + 0.1f + 0.08f, 0.0f,fStartX + 0.1f, fStartY + 0.05f + 0.1f + 0.08f, 0.0f,fStartX + 0.1f, fStartY + 0.05f + 0.1f + 0.08f + 0.15f, 0.0f,fStartX - 0.1f, fStartY + 0.05f + 0.1f + 0.08f + 0.15f, 0.0f,
};// Neck
GLfloat vNeckVerts[] = {fStartX - 0.07f, fStartY + 0.05f + 0.1f + 0.08f + 0.15f, 0.0f,fStartX + 0.07f, fStartY + 0.05f + 0.1f + 0.08f + 0.15f, 0.0f,fStartX, fStartY + 0.05f + 0.1f + 0.08f + 0.15f + 0.05f, 0.0f,};// Head
GLfloat vHeadVerts[] = {fStartX, fStartY + 0.05f + 0.1f + 0.08f + 0.15f + 0.05f, 0.0f,fStartX + 0.05f, fStartY + 0.05f + 0.1f + 0.08f + 0.15f + 0.05f + 0.05f, 0.0f,fStartX, fStartY + 0.05f + 0.1f + 0.08f + 0.15f + 0.05f + 0.05f + 0.1f, 0.0f,fStartX - 0.05f, fStartY + 0.05f + 0.1f + 0.08f + 0.15f + 0.05f + 0.05f, 0.0f,};// Left-UpperArm
GLfloat vLeftUpperArmVerts[] = {fStartX - 0.1f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f - 0.03f, 0.0f,fStartX - 0.1f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f, 0.0f,fStartX - 0.1f - 0.05f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f, 0.0f,};// Right-UpperArm
GLfloat vRightUpperArmVerts[] = {fStartX + 0.1f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f - 0.03f, 0.0f,fStartX + 0.1f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f, 0.0f,fStartX + 0.1f + 0.05f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f, 0.0f,};// Left-ForeArm
GLfloat vLeftForeArmVerts[] = {fStartX - 0.1f - 0.05f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f, 0.0f,fStartX - 0.1f - 0.05f - 0.07f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f, 0.0f,fStartX - 0.1f - 0.05f - 0.07f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f - 0.03f, 0.0f,
};// Right-ForeArm
GLfloat vRightForeArmVerts[] = {fStartX + 0.1f + 0.05f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f, 0.0f,fStartX + 0.1f + 0.05f + 0.07f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f, 0.0f,fStartX + 0.1f + 0.05f + 0.07f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f - 0.03f, 0.0f,
};// Left-Finger-1
GLfloat vLeftFinger1Verts[] = {fStartX - 0.1f - 0.05f - 0.07f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f, 0.0f,fStartX - 0.1f - 0.05f - 0.07f - 0.02f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f - 0.015f, 0.0f,fStartX - 0.1f - 0.05f - 0.07f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f - 0.03f, 0.0f,
};// Left-Finger-2
GLfloat vLeftFinger2Verts[] = {fStartX - 0.1f - 0.05f - 0.07f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f - 0.03f, 0.0f,fStartX - 0.1f - 0.05f - 0.07f - 0.02f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f - 0.015f - 0.03f, 0.0f,fStartX - 0.1f - 0.05f - 0.07f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f - 0.03f - 0.03f, 0.0f,
};// Right-Finger-1
GLfloat vRightFinger1Verts[] = {fStartX + 0.1f + 0.05f + 0.07f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f, 0.0f,fStartX + 0.1f + 0.05f + 0.07f + 0.02f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f - 0.015f, 0.0f,fStartX + 0.1f + 0.05f + 0.07f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f - 0.03f, 0.0f,
};// Right-Finger-2
GLfloat vRightFinger2Verts[] = {fStartX + 0.1f + 0.05f + 0.07f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f - 0.03f, 0.0f,fStartX + 0.1f + 0.05f + 0.07f + 0.02f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f - 0.015f - 0.03f, 0.0f,fStartX + 0.1f + 0.05f + 0.07f, fStartY + 0.05f + 0.1f + 0.08f + 0.075f + 0.03f - 0.03f - 0.03f, 0.0f,
};void Rotate(GLfloat fOriginX, GLfloat fOriginY, GLfloat fRadius, GLfloat angle, GLfloat *pX, GLfloat *pY)
{static GLfloat fPi = 3.1415926f, fRad = fPi / 180.0f;*pX = fOriginX + fRadius * cos(angle * fRad);*pY = fOriginY + fRadius * sin(angle * fRad);
}// 获取两点之间的距离
GLfloat GetDistanceBetweenTwoPoint(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
{// 根据勾股定理计算两点距离GLfloat a = x1 - x2;GLfloat b = y1 - y2;return sqrt(a * a + b * b);
}// 挥舞手臂
void WaringArm()
{static GLint counter = 1;static GLfloat fMinAngle = 180.0f - 30.0f, fMaxAngle = 180.0f + 30.0f, fAngle = fMinAngle, fAngleInc = 1.0f;if (++counter > 30)counter = 0;elsereturn;fAngle += fAngleInc;if (fAngle <= fMinAngle) {fAngle = fMinAngle;fAngleInc = 1;}else if (fAngle >= fMaxAngle) {fAngle = fMaxAngle;fAngleInc = -1;}// 肘关节的坐标点(x, y)GLfloat fLeftElbowX = vLeftForeArmVerts[0], fLeftElbowY = vLeftForeArmVerts[1];// 旋转点1Rotate(fLeftElbowX, fLeftElbowY,GetDistanceBetweenTwoPoint(fLeftElbowX, fLeftElbowY, vLeftForeArmVerts[3], vLeftForeArmVerts[4]),fAngle - 20, &vLeftForeArmVerts[3], &vLeftForeArmVerts[4]);// 旋转点2Rotate(fLeftElbowX, fLeftElbowY,GetDistanceBetweenTwoPoint(fLeftElbowX, fLeftElbowY, vLeftForeArmVerts[6], vLeftForeArmVerts[7]),fAngle + 20, &vLeftForeArmVerts[6], &vLeftForeArmVerts[7]);leftForeArmTriangleBatch.CopyVertexData3f(vLeftForeArmVerts);vRightForeArmVerts[3] = -vLeftForeArmVerts[3];vRightForeArmVerts[4] = vLeftForeArmVerts[4];vRightForeArmVerts[6] = -vLeftForeArmVerts[6];vRightForeArmVerts[7] = vLeftForeArmVerts[7];rightForeArmTriangleBatch.CopyVertexData3f(vRightForeArmVerts);// 旋转 Finger1 点1Rotate(fLeftElbowX, fLeftElbowY,GetDistanceBetweenTwoPoint(fLeftElbowX, fLeftElbowY, vLeftFinger1Verts[0], vLeftFinger1Verts[1]),fAngle - 6 - 11, &vLeftFinger1Verts[0], &vLeftFinger1Verts[1]);// 旋转 Finger1 点2Rotate(fLeftElbowX, fLeftElbowY,GetDistanceBetweenTwoPoint(fLeftElbowX, fLeftElbowY, vLeftFinger1Verts[3], vLeftFinger1Verts[4]),fAngle - 6, &vLeftFinger1Verts[3], &vLeftFinger1Verts[4]);// 旋转 Finger1 点3Rotate(fLeftElbowX, fLeftElbowY,GetDistanceBetweenTwoPoint(fLeftElbowX, fLeftElbowY, vLeftFinger1Verts[6], vLeftFinger1Verts[7]),fAngle - 6 + 11, &vLeftFinger1Verts[6], &vLeftFinger1Verts[7]);leftFinger1TriangleBatch.CopyVertexData3f(vLeftFinger1Verts);vRightFinger1Verts[0] = -vLeftFinger1Verts[0];vRightFinger1Verts[1] = vLeftFinger1Verts[1];vRightFinger1Verts[3] = -vLeftFinger1Verts[3];vRightFinger1Verts[4] = vLeftFinger1Verts[4];vRightFinger1Verts[6] = -vLeftFinger1Verts[6];vRightFinger1Verts[7] = vLeftFinger1Verts[7];rightFinger1TriangleBatch.CopyVertexData3f(vRightFinger1Verts);// 旋转 Finger2 点1Rotate(fLeftElbowX, fLeftElbowY,GetDistanceBetweenTwoPoint(fLeftElbowX, fLeftElbowY, vLeftFinger2Verts[0], vLeftFinger2Verts[1]),fAngle + 6 - 11, &vLeftFinger2Verts[0], &vLeftFinger2Verts[1]);// 旋转 Finger2 点2Rotate(fLeftElbowX, fLeftElbowY,GetDistanceBetweenTwoPoint(fLeftElbowX, fLeftElbowY, vLeftFinger2Verts[3], vLeftFinger2Verts[4]),fAngle + 6, &vLeftFinger2Verts[3], &vLeftFinger2Verts[4]);// 旋转 Finger2 点3Rotate(fLeftElbowX, fLeftElbowY,GetDistanceBetweenTwoPoint(fLeftElbowX, fLeftElbowY, vLeftFinger2Verts[6], vLeftFinger2Verts[7]),fAngle + 6 + 11, &vLeftFinger2Verts[6], &vLeftFinger2Verts[7]);leftFinger2TriangleBatch.CopyVertexData3f(vLeftFinger2Verts);vRightFinger2Verts[0] = -vLeftFinger2Verts[0];vRightFinger2Verts[1] = vLeftFinger2Verts[1];vRightFinger2Verts[3] = -vLeftFinger2Verts[3];vRightFinger2Verts[4] = vLeftFinger2Verts[4];vRightFinger2Verts[6] = -vLeftFinger2Verts[6];vRightFinger2Verts[7] = vLeftFinger2Verts[7];rightFinger2TriangleBatch.CopyVertexData3f(vRightFinger2Verts);
}void AutoTriangleCopyVertexData3f(GLBatch *pTriangleBatch, GLfloat *vVerts)
{pTriangleBatch->Begin(GL_TRIANGLES, 3);pTriangleBatch->CopyVertexData3f(vVerts);pTriangleBatch->End();
}void SetupRC()
{......AutoTriangleCopyVertexData3f(&leftFootTriangleBatch, vLeftFootVerts);AutoTriangleCopyVertexData3f(&leftShankTriangleBatch, vLeftShankVerts);AutoTriangleCopyVertexData3f(&leftThighTriangleBatch, vLeftThightVerts);AutoTriangleCopyVertexData3f(&rightFootTriangleBatch, vRightFootVerts);AutoTriangleCopyVertexData3f(&rightShankTriangleBatch, vRightShankVerts);AutoTriangleCopyVertexData3f(&rightThighTriangleBatch, vRightThightVerts);bodySquareBatch.Begin(GL_TRIANGLE_FAN, 4);bodySquareBatch.CopyVertexData3f(vBodyVerts);bodySquareBatch.End();AutoTriangleCopyVertexData3f(&neckTriangleBatch, vNeckVerts);headSquareBatch.Begin(GL_TRIANGLE_FAN, 4);headSquareBatch.CopyVertexData3f(vHeadVerts);headSquareBatch.End();AutoTriangleCopyVertexData3f(&leftUpperArmTriangleBatch, vLeftUpperArmVerts);AutoTriangleCopyVertexData3f(&leftForeArmTriangleBatch, vLeftForeArmVerts);AutoTriangleCopyVertexData3f(&leftFinger1TriangleBatch, vLeftFinger1Verts);AutoTriangleCopyVertexData3f(&leftFinger2TriangleBatch, vLeftFinger2Verts);AutoTriangleCopyVertexData3f(&rightUpperArmTriangleBatch, vRightUpperArmVerts);AutoTriangleCopyVertexData3f(&rightForeArmTriangleBatch, vRightForeArmVerts);AutoTriangleCopyVertexData3f(&rightFinger1TriangleBatch, vRightFinger1Verts);AutoTriangleCopyVertexData3f(&rightFinger2TriangleBatch, vRightFinger2Verts);
}void RenderScene(void)
{......GLfloat vRed[] = { 1.0f, 0.0f, 0.0f, 1.0f };shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);leftFootTriangleBatch.Draw();rightFootTriangleBatch.Draw();GLfloat vGreen[] = { 0.0f, 1.0f, 0.0f, 1.0f };shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vGreen);leftShankTriangleBatch.Draw();rightShankTriangleBatch.Draw();GLfloat vYellow[] = { 1.0f, 1.0f, 0.0f, 1.0f };shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vYellow);leftThighTriangleBatch.Draw();rightThighTriangleBatch.Draw();GLfloat vMagenta[] = { 1.0f, 0.0f, 1.0f, 1.0f };shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vMagenta);bodySquareBatch.Draw();GLfloat vCyan[] = { 1.0f, 1.0f, 1.0f, 1.0f };shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vCyan);neckTriangleBatch.Draw();GLfloat vPumpkinOrange[] = { 0.98f, 0.625f, 0.12f, 1.0f };shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vPumpkinOrange);headSquareBatch.Draw();GLfloat vPastelPink[] = { 0.98f, 0.04f, 0.70f, 1.0f };shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vPastelPink);leftUpperArmTriangleBatch.Draw();rightUpperArmTriangleBatch.Draw();GLfloat vPlum1[] = {  0.67f, 0.50f, 1.0f, 1.0f };shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vPlum1);leftForeArmTriangleBatch.Draw();rightForeArmTriangleBatch.Draw();GLfloat vOrchid1[] = { 1.0f, 0.51f, 0.98f, 1.0f };shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vOrchid1);leftFinger1TriangleBatch.Draw();leftFinger2TriangleBatch.Draw();rightFinger1TriangleBatch.Draw();rightFinger2TriangleBatch.Draw();WaringArm();glutSwapBuffers();glutPostRedisplay();
}int main(int argc, char* argv[])
{.......return 0;
}

首先贴出运行的截图:

通过三角形和正方形进行绘制一个"简单的机器人"并且挥舞着双手向我们 "打招呼"

下面进行讲解上面的程序:

1. 三角形图形的绘制部分,是通过绘制多个三角形和四边形进行实现的,后面会贴出图片。(详细见机器人绘制图片)

2. 挥舞手臂的动作实现,通过旋转三角形,例如像 "Move" 的方向箭头通过旋转实现。(详细见挥舞手臂图片)

PS: 因为三角形的角度部分为大概计算的,所以旋转后的手臂并不完美,不过也算达到目的了。

机器人绘制图片:

挥舞手臂:

模仿我们摆动手臂的动作,进行做旋转操作。

好的,本章扩展学习内容部分就到此结束了,如有不懂的可评论留言,后续在进行补充。

最后祝大家七夕快乐~

本章源码:已上传到Github-learn-extension-Chapter02了哦,有兴趣的读者可以看下~

OpenGL 游戏开发: 熟悉练习【《OpenGL超级宝典》第二章】相关推荐

  1. DirectX12 3D游戏开发实践(龙书)第二章_矩阵代数

    矩阵 第二章矩阵代数 矩阵代数 定义 矩阵运算 简单代数运算 矩阵乘法 定义 向量与矩阵的乘法 结合律 转置矩阵 单位矩阵 矩阵的行列式 余子阵 行列式的定义 伴随矩阵 逆矩阵 用DirectXMat ...

  2. 穷查理宝典-----第二章 (芒格的生活、学习决策方法)

    穷查理宝典-----第二章 (芒格的生活.学习决策方法) 穷查理宝典-----第二章 (芒格的生活.学习决策方法) 芒格进行商业分析和评估的"多元思维模型" 芒格的投资评估过程 穷 ...

  3. 【OpenGL游戏开发之二】OpenGL常用API

    OpenGL常用API 开发基于OpenGL的应用程序,必须先了解OpenGL的库函数.它采用C语言风格,提供大量的函数来进行图形的处理和显示.OpenGL库函数的命名方式非常有规律.所有OpenGL ...

  4. SRPG游戏开发(六十三)第十一章 地图动作与地图事件 - 十二 完善地图信息与测试(Perfect MapEventInfo and Testing)

    返回<SRPG游戏开发>导航 第十一章 地图动作与地图事件(Map Action and Map Event) 我们已经有了剧本,而且可以运行剧本,但我们还缺少对地图的操作控制. 我们这一 ...

  5. SRPG游戏开发(六十)第十一章 地图动作与地图事件 - 九 触发事件与切换回合(Trigger Events and Change Turn)

    返回<SRPG游戏开发>导航 第十一章 地图动作与地图事件(Map Action and Map Event) 我们已经有了剧本,而且可以运行剧本,但我们还缺少对地图的操作控制. 我们这一 ...

  6. SRPG游戏开发(六十一)第十一章 地图动作与地图事件 - 十 NPC操作(NPC Control)

    返回<SRPG游戏开发>导航 第十一章 地图动作与地图事件(Map Action and Map Event) 我们已经有了剧本,而且可以运行剧本,但我们还缺少对地图的操作控制. 我们这一 ...

  7. SRPG游戏开发(六十四)间章 第十一点五章 总结(Summary)

    返回<SRPG游戏开发>导航 间章 第十一点五章 总结(Summary) 这一章,是对第十章与第十一章的一个补充性质的文章. 文章目录 间章 第十一点五章 总结(Summary) 一 说明 ...

  8. [游戏开发]Python打表工具系列 [第二篇] [打表流程描简述]

    [上一篇链接] [游戏开发]Python打表工具系列 [第一篇][IDE开发环境部署] VSCode Python环境调试_Little丶Seven的博客-CSDN博客 [前言] 第二篇文章是对流程的 ...

  9. [OpenGL - 游戏开发] 仿制《Minecraft/我的世界》 - 总结及演示程序

    [更新]我的新博客:www.ryuzhihao.cc,当然这个csdn博客也会更新               本文在新博客中的链接:点击打开链接 首先上一下效果图:尝试用C++以及OpenGL做的一 ...

最新文章

  1. Android pms权限管理,Android权限机制
  2. linux期末脚本作业,linux – 使用R Markdown将bash脚本作为Cron作业运行
  3. [ACM] hdu 1754 I Hate It (线段树,单点更新)
  4. 解决“chrome正受到自动测试软件的控制”信息栏显示问题(转)
  5. Python3系列__01Python安装
  6. 登录显示离线_使用emoji加密文本;nali—终端离线查询 IP 地理信息
  7. python项目开发实例-Python小项目:快速开发出一个简单的学生管理系统
  8. Android的Gallery3D模块介绍
  9. 马哥linux高端班视频,马哥Linux高端运维云计算就业班
  10. 【SAM】bzoj5084: hashit
  11. 从各行业的实际运用中,窥见华为云虚拟专用网络VPN的强大性能
  12. 运营进阶:产品运营画布九要素
  13. ballerina 学习 三十 扩展开发(一)
  14. Spring Boot使用宝兰德BES进行改造和部署
  15. 普渡大学统计与计算机科学,普渡大学西拉法叶校区计算机科学与工程世界排名2017年最新排名第47(ARWU世界排名)...
  16. 微信小程序实现下拉刷新功能
  17. 无法访问您试图使用的功能所在的网络位置 无法找到vcredist.msi的解决办法
  18. ZAP日志框架lumberjack日志归档库的分析使用
  19. 方舟服务器参数文件夹,方舟生存进化私人服务器怎么设置 私人服务器参数调整攻略...
  20. 从截图里面识别数字_【答疑解惑】还没成功入驻数字工坊的同学看过来!!!

热门文章

  1. 运放脉冲宽度放大_下一代Ka波段雷达系统应用脉冲行波管放大器(twta),工作频率为34至36GHz,峰值功率为1000瓦,占空比为10%。...
  2. 杨辉三角形实现过程详解-C语言基础
  3. MySQL中定时任务的使用
  4. 新闻列表中,常用的文字超出后显示省略号..
  5. Java 提取PDF图片(pdfbox)Extract PDF document images
  6. Altium Designer导出Gerber文件的一般步骤
  7. Lecture6 逻辑斯蒂回归(Logistic Regression)
  8. Echarts3实例 map地图值渲染
  9. 数据人需要掌握的技能,从底层到应用
  10. 基于深度信念网络的硬件模拟器研究(Matlab代码实现)