OpenGL已經(jīng)學(xué)習(xí)了一段時間遇绞,現(xiàn)在進行一下綜合整理工作键袱。
繪制地板
以下是詳細代碼及注釋,這里不再做一一解釋,這里只摘錄了changeSize摹闽、SetupRC蹄咖、RenderScene這幾個方法中的代碼,其他代碼及他們的執(zhí)行流程付鹿,可以參照之前文章:
GLShaderManager shaderManager; // 著色器管理器
GLMatrixStack? ? ? ? modelViewMatrix;? ? ? ? // 模型視圖矩陣
GLMatrixStack? ? ? ? projectionMatrix;? ? ? ? // 投影矩陣
GLFrustum? ? ? ? ? ? viewFrustum;? ? ? ? ? ? // 視景體
GLGeometryTransform? ? transformPipeline;? ? ? ? // 幾何圖形變換管道
GLTriangleBatch? ? ? ? torusBatch;? ? ? ? ? ? //大球
GLTriangleBatch? ? sphereBatch;? ? ? ? ? ? //小球
GLBatch? ? ? ? ? ? ? ? floorBatch;? ? ? ? ? //地板
//角色幀 照相機角色幀
GLFrame? ? ? ? ? ? cameraFrame;
//**4澜汤、添加附加隨機球
#define NUM_SPHERES 50
GLFrame spheres[NUM_SPHERES];
//屏幕更改大小或已初始化
void changeSize(int w,int h)
{
? ? //設(shè)置視口大小
? ? glViewport(0, 0, w, h);
? ? //創(chuàng)建投影矩陣 并將它載入到投影矩陣堆棧中
? ? viewFrustum.SetPerspective(35.0f, (float)w/(float)h, 1.0f, 100.0f);
? ? //viewFrustum.GetProjectionMatrix()用來獲取投影矩陣
? ? projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
? ? //3.設(shè)置變換管道以使用兩個矩陣堆棧(變換矩陣modelViewMatrix ,投影矩陣projectionMatrix)
? ? transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}
//初始化操作
void setupRC()
{
? ? //進行初始化操作
? ? //1.清理顏色
? ? glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
? ? //初始化著色器
? ? shaderManager.InitializeStockShaders();
? ? //開啟深度測試
? ? glEnable(GL_DEPTH_TEST);
? ? //3. 使用批次類設(shè)置地板頂點數(shù)據(jù)
? ? floorBatch.Begin(GL_LINES, 324);
? ? for(GLfloat x = -20.0; x <= 20.0f; x+= 0.5) {
? ? ? ? floorBatch.Vertex3f(x, -0.55f, 20.0f);
? ? ? ? floorBatch.Vertex3f(x, -0.55f, -20.0f);
? ? ? ? floorBatch.Vertex3f(20.0f, -0.55f, x);
? ? ? ? floorBatch.Vertex3f(-20.0f, -0.55f, x);
? ? }
? ? floorBatch.End();
}
//進行調(diào)用以繪制場景
void RenderScene(void)
{
? ? //設(shè)置地板顏色值
? ? static GLfloat vFloorColor[] = {0.0f,1.0f,0.0f,1.0f};
? ? //2.清除顏色緩存區(qū)和深度緩沖區(qū)
? ? glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
? ? //3.繪制地面 GLT_SHADER_FLAT平面著色器
? ? shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vFloorColor);
? ? //進行繪制
? ? floorBatch.Draw();
? ? //交換緩沖區(qū)
? ? glutSwapBuffers();
}
執(zhí)行后結(jié)果:
繪制大球
代碼及注釋:
//以上面的代碼為基礎(chǔ)舵匾,changeSize中不需要更改俊抵,在setupRC設(shè)置大球模型
//設(shè)置大球模型? 因為OpenGL中自帶球類模型,不需要自己畫頂點坐梯,直接調(diào)用gltMakeSphere方法徽诲,使用批次類,傳對應(yīng)的參數(shù)及可吵血。
? ? gltMakeSphere(torusBatch, 0.4f, 40, 80);
//RenderScene中改動較大谎替,詳細代碼如下:
void RenderScene(void)
{
? ? //設(shè)置地板顏色值
? ? static GLfloat vFloorColor[] = {0.0f,1.0f,0.0f,1.0f};
? ? //設(shè)置大球顏色
? ? static GLfloat vTorusColor[] = { 1.0f, 0.0f, 0.0f, 1.0f };
? ? //創(chuàng)建定時器,用于控制大球轉(zhuǎn)動
? ? static CStopWatch rotTimer;
? ? //得到大球每秒轉(zhuǎn)動的角度
? ? float yRot = rotTimer.GetElapsedSeconds() *60.0;
? ? //2.清除顏色緩存區(qū)和深度緩沖區(qū)
? ? glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
? ? //進行壓棧蹋辅,為了確保每次操作獨立钱贯,不影響其他操作? 每一次壓棧PushMatrix都要對應(yīng)一次出棧PopMatrix
? ? modelViewMatrix.PushMatrix();
? ? //3.繪制地面 GLT_SHADER_FLAT平面著色器
? ? shaderManager.UseStockShader(GLT_SHADER_FLAT,transformPipeline.GetModelViewProjectionMatrix(),vFloorColor);
? ? //進行繪制
? ? floorBatch.Draw();
? ? //用矩陣設(shè)置一處光源
? ? M3DVector4f vLightPos = {0.0f,10.0f,5.0f,1.0f};
? ? //為了獲得更好的觀察效果,讓大球想屏幕里移動3.0
? ? modelViewMatrix.Translate(0.0f, 0.0f, -3.0f);
? ? //再次壓棧晕翠,為了下面的旋轉(zhuǎn)操作
? ? modelViewMatrix.PushMatrix();
? ? //大球繞y軸旋轉(zhuǎn)
? ? modelViewMatrix.Rotate(0.0f, 1.0f, 0.0f, 1.0f);
? ? //設(shè)置著色器(點光源著色器) 模型視圖變換矩陣? 投影矩陣 點光源位置 顏色值
? ? shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vTorusColor);
? ? //繪制
? ? torusBatch.Draw();
? ? //進行出棧 2次
? ? modelViewMatrix.PopMatrix();
? ? modelViewMatrix.PopMatrix();
? ? //交換緩沖區(qū)
? ? glutSwapBuffers();
? ? //重新提交渲染
? ? glutPostRedisplay();
}
執(zhí)行結(jié)果:
繪制多個小球
代碼如下:
//如添加大球時的操作喷舀,同樣SetupRC中添加小球模型,并隨機放置50個
//設(shè)置小球模型
? ? gltMakeSphere(sphereBatch, 0.2f, 13, 26);
? ? //隨機放置 NUM_SPHERES上面定義過的宏
? ? for (int i = 0; i < NUM_SPHERES; i++) {
? ? ? ? //y軸不變淋肾,X,Z產(chǎn)生隨機值 讓小球處于同一平面
? ? ? ? GLfloat x = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
? ? ? ? GLfloat z = ((GLfloat)((rand() % 400) - 200 ) * 0.1f);
? ? ? ? //在y方向硫麻,將球體設(shè)置為0.0的位置,這使得它們看起來是飄浮在眼睛的高度
? ? ? ? //對spheres數(shù)組中的每一個頂點樊卓,設(shè)置頂點數(shù)據(jù)
? ? ? ? spheres[i].SetOrigin(x, 0.0f, z);
? ? }
//同樣在RenderScene中去繪制這50個小球
//畫小球拿愧,for循環(huán)畫50個,單個小球畫法和大球差不多碌尔,不同的是通過壓棧來保持每一次小球的獨立
? ? for (int i = 0; i < NUM_SPHERES; i++) {
? ? ? ? modelViewMatrix.PushMatrix();
? ? ? ? modelViewMatrix.MultMatrix(spheres[i]);
? ? ? ? shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF, transformPipeline.GetModelViewMatrix(),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? transformPipeline.GetProjectionMatrix(), vLightPos, vSphereColor);
? ? ? ? sphereBatch.Draw();
? ? ? ? modelViewMatrix.PopMatrix();
? ? }
生成小球
小球圍繞大球轉(zhuǎn)動
代碼:
//在RenderScene方法中加入
//讓一個小籃球圍繞大球公眾自轉(zhuǎn)
? ? modelViewMatrix.Rotate(yRot * -2.0f, 0.0f, 1.0f, 0.0f);
? ? modelViewMatrix.Translate(0.8f, 0.0f, 0.0f);
? ? shaderManager.UseStockShader(GLT_SHADER_POINT_LIGHT_DIFF,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vLightPos,vSphereColor);
? ? sphereBatch.Draw();
鍵位控制
代碼:
//mian函數(shù)中注冊鍵位控制函數(shù)
glutSpecialFunc(SpeacialKeys);
//通過相應(yīng)的操作控制移動旋轉(zhuǎn)
void SpeacialKeys(int key,int x,int y){
? ? //移動步長
? ? float linear = 0.1f;
? ? //旋轉(zhuǎn)度數(shù)
? ? float angular = float(m3dDegToRad(5.0f));
? ? //上
? ? if (key == GLUT_KEY_UP) {
? ? ? ? //MoveForward 平移
? ? ? ? cameraFrame.MoveForward(linear);
? ? }
? ? //下
? ? if (key == GLUT_KEY_DOWN) {
? ? ? ? cameraFrame.MoveForward(-linear);
? ? }
? ? //左
? ? if (key == GLUT_KEY_LEFT) {
? ? ? ? //RotateWorld 旋轉(zhuǎn)
? ? ? ? cameraFrame.RotateWorld(angular, 0.0f, 1.0f, 0.0f);
? ? }
? ? //右
? ? if (key == GLUT_KEY_RIGHT) {
? ? ? ? cameraFrame.RotateWorld(-angular, 0.0f, 1.0f, 0.0f);
? ? }
}
//然后在RenderScene中加入一個觀察者 平移10步(地板,大球,小球,小小球)浇辜,通過移動觀察者來達到目的
? ? M3DMatrix44f mCamera;
? ? cameraFrame.GetCameraMatrix(mCamera);
? ? modelViewMatrix.PushMatrix(mCamera);
這里大球自轉(zhuǎn)券敌,小球圍繞大球公轉(zhuǎn)的案例就完成了。