显示效果
image
实现流程
image
重要函数功能分析
image
image
image
源码分析
#include "GLTools.h"
#include "GLShaderManager.h"
#include "GLFrustum.h"
#include "GLBatch.h"
#include "GLMatrixStack.h"
#include "GLGeometryTransform.h"
#include "StopWatch.h"
#include <math.h>
#include <stdio.h>
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif
//定义一个,着色管理器
GLShaderManager shaderManager;//着色器管理器
GLMatrixStack modelViewMatrix;//模型视图矩阵堆栈
GLMatrixStack projectionMatrix;//投影矩阵堆栈
GLFrustum viewFrustum; //视景体:设置和获取投影矩阵
GLGeometryTransform transformPipeline;// 几何图形变换管道
//简单的批次容器,是GLTools的一个简单的容器类。
GLBatch floorBatch;
GLTriangleBatch torusBatch;
GLTriangleBatch sphereBatch;
#define NUM_SPHERE 50
GLFrame sphere[NUM_SPHERE]; //GLFrame ->#include "GLFrustum.h"
//角色帧 照相机角色帧
GLFrame cameraFrame;
GLFrame objectFrame; //物体角色帧
/*
在窗口大小改变时,接收新的宽度&高度。
*/
void changeSize(int w,int h)
{
if(h ==0){
h = 1;
}
/*
设置视口
x,y 参数代表窗口中视图的左下角坐标,而宽度、高度是像素为表示,通常x,y 都是为0
*/
glViewport(0, 0, w, h);
//投影矩阵
viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0, 100.0f);
projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
//初始化变换管道
transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
//1. 颜色(地板,大球颜色,小球颜色)
static GLfloat vFloorColor[] = {0.0f,1.0f,0.0f,1.0f};
static GLfloat vTorusColor[] = {1.0f,0.0f,0.0f,1.0f};
static GLfloat vSpereColor[] = {0.0f,0.0f,1.0f,1.0f};
static GLfloat vBigSpereColor[] = {0.0f,0.6f,1.0f,0.8f};
//设置点光源位置
M3DVector4f vLightPos = {0,10,5,1};
//动画
static CStopWatch rotTimer;
float yRot = rotTimer.GetElapsedSeconds()*60.0f;
//单元矩阵
modelViewMatrix.PopMatrix();
//观察者角色帧矩阵入栈
M3DMatrix44f mCamera;
cameraFrame.GetCameraMatrix(mCamera);
modelViewMatrix.PushMatrix(mCamera);
//绘制地板
shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vFloorColor);
floorBatch.Draw();
//平移模型视图矩阵,往里平移3个单位
modelViewMatrix.Translate(0.0f, 0.0f, -3.0f);
//绘制大球 及自转
modelViewMatrix.PushMatrix();
modelViewMatrix.Rotate(yRot, 0, 1.0, 0);
//点光源着色器
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vTorusColor);
torusBatch.Draw();
modelViewMatrix.PopMatrix();
//绘制小球
for(int i = 0 ; i < NUM_SPHERE; i++){
modelViewMatrix.PushMatrix();
modelViewMatrix.MultMatrix(sphere[i]);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSpereColor);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
}
//小球围着大球公转;
modelViewMatrix.Rotate(yRot * -2.0f, 0, 1, 0);
modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vBigSpereColor);
sphereBatch.Draw();
modelViewMatrix.PopMatrix();
modelViewMatrix.PopMatrix();
glutSwapBuffers();
glutPostRedisplay();
}
void setupRC()
{
//设置清屏颜色(背景颜色)
glClearColor(0, 0, 0, 1);
//没有着色器,在OpenGL 核心框架中是无法进行任何渲染的。初始化一个渲染管理器。
shaderManager.InitializeStockShaders();
//开启深度测试
glEnable(GL_DEPTH_TEST);
// 地板数据
floorBatch.Begin(GL_LINES, 324); //[-20,20]以0.5的步进,横向和纵向每个方向81条线段,每条线段连个顶点 ;所有定点数是81*2*2=324
for(GLfloat x = -20.0; x <= 20.0f; x+= 0.5) {
//平行于x轴的线段
floorBatch.Vertex3f(x, -0.55f, 20.0f);
floorBatch.Vertex3f(x, -0.55f, -20.0f);
//平行于z轴的线段
floorBatch.Vertex3f(20.0f, -0.55f, x);
floorBatch.Vertex3f(-20.0f, -0.55f, x);
}
floorBatch.End();
//设置一个球体(基于gltools模型)
gltMakeSphere(torusBatch, 0.4f, 40, 80);
//绘制小球;
gltMakeSphere(sphereBatch, 0.1f, 20, 40);
//随机放置小球
for(int i = 0; i < NUM_SPHERE;i++){
//y轴不变,X,Z产生随机值
GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
//对spheres数组中的每一个顶点,设置顶点数据
sphere[i].SetOrigin(x,0.0,z);
}
}
void SpecialKeys(int key, int x, int y){
float linner = 0.2f;
float arg = float(m3dDegToRad(5.0)); //#include "math3d.h"
if(key == GLUT_KEY_UP){
cameraFrame.MoveForward(linner);
}
if(key == GLUT_KEY_DOWN){
cameraFrame.MoveForward(-linner);
}
if(key == GLUT_KEY_LEFT){
cameraFrame.RotateLocal(arg, 0, 1.0, 0);
}
if(key == GLUT_KEY_RIGHT){
cameraFrame.RotateLocal(-arg, 0, 1.0, 0);
}
}
int main(int argc,char *argv[])
{
//初始化GLUT库,这个函数只是传说命令参数并且初始化glut库
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH|GLUT_STENCIL);
//GLUT窗口大小、窗口标题
glutInitWindowSize(800, 600);
glutCreateWindow("Triangle");
//注册重塑函数
glutReshapeFunc(changeSize);
//注册显示函数
glutDisplayFunc(RenderScene);
//注册功能按键函数
glutSpecialFunc(SpecialKeys);
/*
初始化一个GLEW库,确保OpenGL API对程序完全可用。
在试图做任何渲染之前,要检查确定驱动程序的初始化过程中没有任何问题
*/
GLenum status = glewInit();
if (GLEW_OK != status) {
printf("GLEW Error:%s\n",glewGetErrorString(status));
return 1;
}
//设置我们的渲染环境
setupRC();
glutMainLoop();
return 0;
}
网友评论