Xcode+opengl學習(2)點線面環基本渲染過程

基礎繪製篇

  • 點GL_POINTS
  • 線GL_LINES
  • 線帶GL_LINE_STRIP
  • 線環GL_LINE_LOOP
  • 4個三角面組成的四面體GL_TRIANGLES
  • 6個三角面組成的面扇(中心點拔高)GL_TRIANGLE_FAN
  • 三角環體GL_TRIANGLE_STRIP

  • SpecialKeys函數(控制上下左右鍵旋轉)
  • KeyPressFunc函數(空格(ASCII=32)控制模型切換)

  • GLMatrixStack
  • GLFrame
  • GLFrustum
  • GLGeometryTransform

#include<GLTools.h>
#include<GLMatrixStack.h>
#include<GLFrame.h>
#include<GLFrustum.h>
#include<GLBatch.h>
#include<GLGeometryTransform.h>

#include<math.h>
#include<GLUT/GLUT.h>


GLShaderManager shaderManager;
GLMatrixStack  modelViewMatrix;//模型視圖矩陣
GLMatrixStack projectionMatrix;//投影矩陣
GLFrame cameraFrame;
GLFrame objectFrame;
GLFrustum viewFrustum;//視景體

GLBatch pointBatch;
GLBatch lineBatch;
GLBatch lineStripBatch;
GLBatch lineLoopBatch;
GLBatch triangleBatch;
GLBatch triangleStripBatch;
GLBatch triangleFanBatch;

GLGeometryTransform transformPipeline;//幾何變換管線
M3DMatrix44f shadowMatrix;

GLfloat vGreen[]={0.0f,1.0f,0.0f,1.0f};
GLfloat vBlack[]={0.0f,0.0f,0.0f,1.0f};

int nstep=0;

void SetupRC()
{
   glClearColor(0.7f,0.7f,0.7f,1.0f);//黑色背景
   shaderManager.InitializeStockShaders();
   glEnable(GL_DEPTH_TEST);//深度測試,高效消除隱藏表面
   transformPipeline.SetMatrixStacks(modelViewMatrix,projectionMatrix);//設置變換管線以使用兩個矩陣堆棧
   cameraFrame.MoveForward(-15.0f);
   
   GLfloat vCoast[24][3] = {{2.80, 1.20, 0.0 }, {2.0,  1.20, 0.0 },
                           {2.0,  1.08, 0.0 },  {2.0,  1.08, 0.0 },
                           {0.0,  0.80, 0.0 },  {-.32, 0.40, 0.0 },
                           {-.48, 0.2, 0.0 },   {-.40, 0.0, 0.0 },
                           {-.60, -.40, 0.0 },  {-.80, -.80, 0.0 },
                           {-.80, -1.4, 0.0 },  {-.40, -1.60, 0.0 },
                           {0.0, -1.20, 0.0 },  { .2, -.80, 0.0 },
                           {.48, -.40, 0.0 },   {.52, -.20, 0.0 },
                           {.48,  .20, 0.0 },   {.80,  .40, 0.0 },
                           {1.20, .80, 0.0 },   {1.60, .60, 0.0 },
                           {2.0, .60, 0.0 },    {2.2, .80, 0.0 },
                           {2.40, 1.0, 0.0 },   {2.80, 1.0, 0.0 }};
   //創建一個點批次,
   pointBatch.Begin(GL_POINTS,24);
   pointBatch.CopyVertexData3f(vCoast);
   pointBatch.End();
   
   //線
   lineBatch.Begin(GL_LINES,24);
   lineBatch.CopyVertexData3f(vCoast);
   lineBatch.End();
   
   //線帶
   lineStripBatch.Begin(GL_LINE_STRIP,24);
   lineStripBatch.CopyVertexData3f(vCoast);
   lineStripBatch.End();
   
   //線環
   lineLoopBatch.Begin(GL_LINE_LOOP,24);
   lineLoopBatch.CopyVertexData3f(vCoast);
   lineLoopBatch.End();
   
   //三角形
   GLfloat vPyramid[12][3] = { -2.0f, 0.0f, -2.0f,
                                2.0f, 0.0f, -2.0f,
                                0.0f, 4.0f, 0.0f,
       
                                2.0f, 0.0f, -2.0f,
                                2.0f, 0.0f, 2.0f,
                                0.0f, 4.0f, 0.0f,
       
                                2.0f, 0.0f, 2.0f,
                               -2.0f, 0.0f, 2.0f,
                                0.0f, 4.0f, 0.0f,
       
                               -2.0f, 0.0f, 2.0f,
                               -2.0f, 0.0f, -2.0f,
                                0.0f, 4.0f, 0.0f};
   triangleBatch.Begin(GL_TRIANGLES,12);
   triangleBatch.CopyVertexData3f(vPyramid);
   triangleBatch.End();
   
   //六個三角形面組成的扇,頂點拔高
   GLfloat vPoints[100][3];
   int nVerts = 0;
   GLfloat r = 3.0f;
   vPoints[nVerts][0] = 0.0f;
   vPoints[nVerts][1] = 0.0f;
   vPoints[nVerts][2] = 0.0f;
   
   for(GLfloat angle = 0; angle < M3D_2PI; angle += M3D_2PI / 6.0f)
   {
       nVerts++;
       vPoints[nVerts][0] = float(cos(angle)) * r;
       vPoints[nVerts][1] = float(sin(angle)) * r;
       vPoints[nVerts][2] = -0.5f;
   }

   nVerts++;
   vPoints[nVerts][0] = r;
   vPoints[nVerts][1] = 0;
   vPoints[nVerts][2] = 0.0f;
   
   triangleFanBatch.Begin(GL_TRIANGLE_FAN, 8);
   triangleFanBatch.CopyVertexData3f(vPoints);
   triangleFanBatch.End();
   
   //三角形環
   int iCounter = 0;
   GLfloat radius = 3.0f;
   for(GLfloat angle = 0.0f; angle <= (2.0f*M3D_PI); angle += 0.3f)
   {
       GLfloat x = radius * sin(angle);
       GLfloat y = radius * cos(angle);
       
       vPoints[iCounter][0] = x;
       vPoints[iCounter][1] = y;
       vPoints[iCounter][2] = -0.5;
       iCounter++;
       
       vPoints[iCounter][0] = x;
       vPoints[iCounter][1] = y;
       vPoints[iCounter][2] = 0.5;
       iCounter++;
   }
   
   vPoints[iCounter][0] = vPoints[0][0];
   vPoints[iCounter][1] = vPoints[0][1];
   vPoints[iCounter][2] = -0.5;
   iCounter++;
   
   vPoints[iCounter][0] = vPoints[1][0];
   vPoints[iCounter][1] = vPoints[1][1];
   vPoints[iCounter][2] = 0.5;
   iCounter++;
   
   triangleStripBatch.Begin(GL_TRIANGLE_STRIP, iCounter);
   triangleStripBatch.CopyVertexData3f(vPoints);
   triangleStripBatch.End();

}

void DrawWireFramedBatch(GLBatch* pBatch)
{
   shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
   pBatch->Draw();
   
       //關於gPolygonOffset深度偏移函數,爲了防止深度測試時出現z-fighting,第二次繪製是在z方向進行一點偏移
       //void glPolygonOffset(GLfloat factor,GLfloat units)
       //應用到片段上的總偏移Depth Offset=(DZ✖️factor)+(r✖️units)
       //DZ爲深度值相對於多邊形屏幕區域的變化量,r是使深度緩衝區值發生變化的最小值
       //除了使用gPolygonOffset設置偏移值外,必須啓用多邊形單獨偏移來填充
       //幾何圖形(GL_POLYGON_OFFSET_FILL),線(GL_POLYGON_OFFSET_LINE),點(GL_POLYGON_OFFSET_POINT)
   glPolygonOffset(-1.0f, -1.0f);
   glEnable(GL_POLYGON_OFFSET_LINE);
   
       //以下三步爲抗鋸齒操作
   glEnable(GL_LINE_SMOOTH);//線抗鋸齒
   glEnable(GL_BLEND);//開啓混合
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//配置混合
   
       //關於glPolygonMode函數,可以多邊形渲染成實體,輪廓,或只有點,其原型void glPolygonMode(GLenum face,GLenum mode)
       //face參數可以有GL_FRONT,GL_BACK,GL_FRONT_AND_BACK
       //mode參數可以有GL_FILL(默認值),GL_POINT,GL_LINE
   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
   glLineWidth(2.5f);//線寬
   shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
   pBatch->Draw();
   
   //把所有操作函數恢復默認
   glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
   glDisable(GL_POLYGON_OFFSET_LINE);
   glLineWidth(1.0f);
   glDisable(GL_BLEND);
   glDisable(GL_LINE_SMOOTH);
}

void RenderScene(void)
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
   
   modelViewMatrix.PushMatrix();
   M3DMatrix44f mCamera;
   cameraFrame.GetCameraMatrix(mCamera);
   modelViewMatrix.MultMatrix(mCamera);
   
   M3DMatrix44f mObjectFrame;
   objectFrame.GetMatrix(mObjectFrame);
   modelViewMatrix.MultMatrix(mObjectFrame);
   
   shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
   
   switch(nstep) {
       case 0:
           glPointSize(4.0f);
           pointBatch.Draw();
           glPointSize(1.0f);
           break;
       case 1:
           glLineWidth(2.0f);
           lineBatch.Draw();
           glLineWidth(1.0f);
           break;
       case 2:
           glLineWidth(2.0f);
           lineStripBatch.Draw();
           glLineWidth(1.0f);
           break;
       case 3:
           glLineWidth(2.0f);
           lineLoopBatch.Draw();
           glLineWidth(1.0f);
           break;
       case 4:
           DrawWireFramedBatch(&triangleBatch);
           break;
       case 5:
           DrawWireFramedBatch(&triangleStripBatch);
           break;
       case 6:
           DrawWireFramedBatch(&triangleFanBatch);
           break;
   }
   
   modelViewMatrix.PopMatrix();
   
   glutSwapBuffers();//刷新繪圖命令
}

   //該函數用於控制上下左右旋轉視角
void SpecialKeys(int key, int x, int y)
{
   if(key == GLUT_KEY_UP)
       objectFrame.RotateWorld(m3dDegToRad(-5.0f), 1.0f, 0.0f, 0.0f);
   
   if(key == GLUT_KEY_DOWN)
       objectFrame.RotateWorld(m3dDegToRad(5.0f), 1.0f, 0.0f, 0.0f);
   
   if(key == GLUT_KEY_LEFT)
       objectFrame.RotateWorld(m3dDegToRad(-5.0f), 0.0f, 1.0f, 0.0f);
   
   if(key == GLUT_KEY_RIGHT)
       objectFrame.RotateWorld(m3dDegToRad(5.0f), 0.0f, 1.0f, 0.0f);
   
   glutPostRedisplay();//通知glut進行一次相同的操作
}

   //該函數控制按空格鍵進行下一項,空格鍵的ascii碼爲32
void KeyPressFunc(unsigned char key, int x, int y)
{
   if(key == 32)
   {
       nstep++;
       
       if(nstep > 6)
           nstep = 0;
   }
   
   switch(nstep)
   {
       case 0:
           glutSetWindowTitle("GL_POINTS");
           break;
       case 1:
           glutSetWindowTitle("GL_LINES");
           break;
       case 2:
           glutSetWindowTitle("GL_LINE_STRIP");
           break;
       case 3:
           glutSetWindowTitle("GL_LINE_LOOP");
           break;
       case 4:
           glutSetWindowTitle("GL_TRIANGLES");
           break;
       case 5:
           glutSetWindowTitle("GL_TRIANGLE_STRIP");
           break;
       case 6:
           glutSetWindowTitle("GL_TRIANGLE_FAN");
           break;
   }
   
   glutPostRedisplay();
}

void ChangeSize(int w, int h)
{
   glViewport(0, 0, w, h);
   viewFrustum.SetPerspective(35.0f, float(w) / float(h), 1.0f, 500.0f);//創建投影矩陣,並將它載入投影矩陣堆棧中
   projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
   modelViewMatrix.LoadIdentity();
}

int main(int argc, char* argv[])
{
   gltSetWorkingDirectory(argv[0]);
   
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
   glutInitWindowSize(800, 600);
   glutCreateWindow("GL_POINTS");
   glutReshapeFunc(ChangeSize);
   glutKeyboardFunc(KeyPressFunc);
   glutSpecialFunc(SpecialKeys);
   glutDisplayFunc(RenderScene);
   
   GLenum err = glewInit();
   if (GLEW_OK != err) {
       fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
       return 1;
   }

   SetupRC();
   
   glutMainLoop();
   return 0;
}










發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章