openGl超级宝典学习笔记 (2) 7个主要的几何图元-LMLPHP

点(GL_POINTS):

openGl超级宝典学习笔记 (2) 7个主要的几何图元-LMLPHP

点总是正方形的像素,默认情况下,点的大小不受透视除法影响。

即无论与视点的距离怎样,它的大小都不改变。为了获得圆点。必须在抗锯齿模式下绘制点。

能够用glPointSize改变点的大小。

//点
//建立批次
GLBatch pointBatch; 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 }}; // Load point batch
pointBatch.Begin(GL_POINTS, 24);
pointBatch.CopyVertexData3f(vCoast);
pointBatch.End(); //改变点的大小。提交图形到着色器 下面代码在渲染函数中
glPointSize(4.0f);
pointBatch.Draw();

线段(GL_LINES):

一条线段是在两个顶点之间绘制的,每批线段都应该包括偶数个顶点()。默认情况下宽度为1,唯一改变线段宽度的方法是glLineWidth(Gl float);

openGl超级宝典学习笔记 (2) 7个主要的几何图元-LMLPHP

GLBatch	lineBatch;

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 }}; // Load as a bunch of line segments
lineBatch.Begin(GL_LINES, 24);
lineBatch.CopyVertexData3f(vCoast);
lineBatch.End();
<pre name="code" class="cpp">//改变线段的大小,提交图形到着色器 下面代码在渲染函数中

glLineWidth(2.0f);lineBatch.Draw();

线带(GL_LINE_STRIP):

连续从一个顶点到下一个顶点绘制线段。

openGl超级宝典学习笔记 (2) 7个主要的几何图元-LMLPHP

GLBatch	lineStripBatch;

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 }}; // Load as a single line segment
lineStripBatch.Begin(GL_LINE_STRIP, 24);
lineStripBatch.CopyVertexData3f(vCoast);
lineStripBatch.End();
<pre name="code" class="cpp">//改变线段的大小。提交图形到着色器 下面代码在渲染函数中

glLineWidth(2.0f);lineStripBatch.Draw();

线环(GL_LINE_LOOP):

线带的扩展,把一个批次中最后一个点和第一个点连接起来。

openGl超级宝典学习笔记 (2) 7个主要的几何图元-LMLPHP

三角形(GL_TRIANGLES):

三角形是OpenGl唯一支持的一种多边图形。

每三个顶点定义一个新三角形。不像线段组成的环,它是实心的,能够填充颜色的。

上一篇我们已经创建了一个三角形。这里我们用四个三角形组成一个金字塔。用方向键能够调整三角形。

openGl超级宝典学习笔记 (2) 7个主要的几何图元-LMLPHP

GLBatch    triangleBatch;
<p class="p1"><span class="s1">GLfloat</span><span class="s2"> vGreen[] = { </span><span class="s3">0.0f</span><span class="s2">, </span><span class="s3">1.0f</span><span class="s2">, </span><span class="s3">0.0f</span><span class="s2">, </span><span class="s3">1.0f</span><span class="s2"> };</span></p><p class="p1"><span class="s1">GLfloat</span><span class="s2"> vBlack[] = { </span><span class="s3">0.0f</span><span class="s2">, </span><span class="s3">0.0f</span><span class="s2">, </span><span class="s3">0.0f</span><span class="s2">, </span><span class="s3">1.0f</span><span class="s2"> };</span></p>
// For Triangles, we'll make a Pyramid 四个三角形,组成一个金字塔
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(); //渲染运行
DrawWireFramedBatch(&triangleBatch); void DrawWireFramedBatch(GLBatch* pBatch)
{
// Draw the batch solid green
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
pBatch->Draw(); //下面部分是为了给图形加入黑色边框
// Draw black outline
glPolygonOffset(-1.0f, -1.0f); // Shift depth values 偏移深度,在同一位置要绘制填充和边线,会产生z冲突,所以要偏移
glEnable(GL_POLYGON_OFFSET_LINE); // Draw lines antialiased 反锯齿,让黑边好看些
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Draw black wireframe version of geometry
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);//三种模式。实心,边框,点。能够作用在正面,背面。或者两面
glLineWidth(2.5f);
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
pBatch->Draw(); // Put everything back the way we found it //复原原本的设置
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_POLYGON_OFFSET_LINE);
glLineWidth(1.0f);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
}

多边模式:

多边形不一定是实心的,我们能够通过glPolygoMode指定将多边形显示为实习。轮廓,点。

glPolygoMode(Glenum face,Glenum mode)

face:GL_FRONT,GL_BACK,GL_FRONT_AND_BACK(默认逆时针的方向为正面)

mode:GL_FILL,GL_LINE,GL_POINT

多边形偏移:

深度模式下,有意将两个几何图形绘制到同一位置。会发生z-fighting(z冲突)。

glPolygonOffset(GLfloat factor,GLfloat units)能够在不实际改变3d空间中的物理绘制,实现深度值偏移。

Depth Offset = (DZ*factor) + (r*units)

DZ是深度值。r是使深度缓冲区值产生变化的最小值。

还必须启动多边形单独偏移:GL_POLYGON_OFFSET_FILL,GL_POLYGON_OFFSET_LINE,GL_POLYGON_OFFSET_POINT

三角形带(GL_TRIANGLE_STRIP):

绘制一连串的三角形。

长处:

1)指定第一个三角形后,下一个三角形仅仅要再指定一个点。

2)提高运算性能,节省宽带。

openGl超级宝典学习笔记 (2) 7个主要的几何图元-LMLPHP

每个三角形都是逆时针顺序。

openGl超级宝典学习笔记 (2) 7个主要的几何图元-LMLPHP

GLBatch       triangleStripBatch;
GLfloat vPoints[100][3]; // Scratch array, more than we need // For triangle strips, a little ring or cylinder segment
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); // Specify the point and move the Z value up a little
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++;
} // Close up the loop
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++; // Load the triangle strip
triangleStripBatch.Begin(GL_TRIANGLE_STRIP, iCounter);
triangleStripBatch.CopyVertexData3f(vPoints);
triangleStripBatch.End();

三角形扇(GL_TRIANGLE_FAN):

创建一组环绕中心点的相邻三角形。前三个点构成第一个三角形。兴许的每一个点都和原点以及vn-1行成一个三角形

openGl超级宝典学习笔记 (2) 7个主要的几何图元-LMLPHP

openGl超级宝典学习笔记 (2) 7个主要的几何图元-LMLPHP

GLBatch             triangleFanBatch;
// For a Triangle fan, just a 6 sided hex. Raise the center up a bit
GLfloat vPoints[100][3]; // Scratch array, more than we need
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;
} // Close the fan
nVerts++;
vPoints[nVerts][0] = r;
vPoints[nVerts][1] = 0;
vPoints[nVerts][2] = 0.0f; // Load it up
triangleFanBatch.Begin(GL_TRIANGLE_FAN, 8);
triangleFanBatch.CopyVertexData3f(vPoints);
triangleFanBatch.End();

完整范例代码:

// Primitieves.cpp
// OpenGL SuperBible, Chapter 2
// Demonstrates the 7 Geometric Primitives
// Program by Richard S. Wright Jr. #include <GLTools.h> // OpenGL toolkit
#include <GLMatrixStack.h>
#include <GLFrame.h>
#include <GLFrustum.h>
#include <GLBatch.h>
#include <GLGeometryTransform.h> #include <math.h>
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif /////////////////////////////////////////////////////////////////////////////////
// An assortment of needed classes
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 }; // Keep track of effects step
int nStep = 0; ///////////////////////////////////////////////////////////////////////////////
// This function does any needed initialization on the rendering context.
// This is the first opportunity to do any OpenGL related tasks.
void SetupRC()
{
// Black background
glClearColor(0.7f, 0.7f, 0.7f, 1.0f ); shaderManager.InitializeStockShaders(); glEnable(GL_DEPTH_TEST); transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix); cameraFrame.MoveForward(-15.0f); //////////////////////////////////////////////////////////////////////
// Some points, more or less in the shape of Florida
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 }}; // Load point batch
pointBatch.Begin(GL_POINTS, 24);
pointBatch.CopyVertexData3f(vCoast);
pointBatch.End(); // Load as a bunch of line segments
lineBatch.Begin(GL_LINES, 24);
lineBatch.CopyVertexData3f(vCoast);
lineBatch.End(); // Load as a single line segment
lineStripBatch.Begin(GL_LINE_STRIP, 24);
lineStripBatch.CopyVertexData3f(vCoast);
lineStripBatch.End(); // Single line, connect first and last points
lineLoopBatch.Begin(GL_LINE_LOOP, 24);
lineLoopBatch.CopyVertexData3f(vCoast);
lineLoopBatch.End(); // For Triangles, we'll make a Pyramid
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(); // For a Triangle fan, just a 6 sided hex. Raise the center up a bit
GLfloat vPoints[100][3]; // Scratch array, more than we need
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;
} // Close the fan
nVerts++;
vPoints[nVerts][0] = r;
vPoints[nVerts][1] = 0;
vPoints[nVerts][2] = 0.0f; // Load it up
triangleFanBatch.Begin(GL_TRIANGLE_FAN, 8);
triangleFanBatch.CopyVertexData3f(vPoints);
triangleFanBatch.End(); // For triangle strips, a little ring or cylinder segment
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); // Specify the point and move the Z value up a little
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++;
} // Close up the loop
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++; // Load the triangle strip
triangleStripBatch.Begin(GL_TRIANGLE_STRIP, iCounter);
triangleStripBatch.CopyVertexData3f(vPoints);
triangleStripBatch.End();
} /////////////////////////////////////////////////////////////////////////
void DrawWireFramedBatch(GLBatch* pBatch)
{
// Draw the batch solid green
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vGreen);
pBatch->Draw(); // Draw black outline
glPolygonOffset(-1.0f, -1.0f); // Shift depth values
glEnable(GL_POLYGON_OFFSET_LINE); // Draw lines antialiased
glEnable(GL_LINE_SMOOTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Draw black wireframe version of geometry
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glLineWidth(2.5f);
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformPipeline.GetModelViewProjectionMatrix(), vBlack);
pBatch->Draw(); // Put everything back the way we found it
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_POLYGON_OFFSET_LINE);
glLineWidth(1.0f);
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
} ///////////////////////////////////////////////////////////////////////////////
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
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(); // Flush drawing commands
glutSwapBuffers();
} // Respond to arrow keys by moving the camera frame of reference
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();
} ///////////////////////////////////////////////////////////////////////////////
// A normal ASCII key has been pressed.
// In this case, advance the scene when the space bar is pressed
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();
} ///////////////////////////////////////////////////////////////////////////////
// Window has changed size, or has just been created. In either case, we need
// to use the window dimensions to set the viewport and the projection matrix.
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();
} ///////////////////////////////////////////////////////////////////////////////
// Main entry point for GLUT based programs
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;
}
05-11 14:59