GL_TRIANGLE_STRIP绘制三角形方式很多时候令人疑惑,在这里对其运作机理进行解释。
一般情况下有三种绘制一系列三角形的方式,分别是GL_TRIANGLES、GL_TRIANGLE_STRIP和GL_TRIANGLE_FAN。
如下图所示:
它的渲染根据顶点数据组成方式不同分为两种方式:
一、它的渲染可以通过glGenBuffers,glBindBuffer,glBufferData个来完成。当需要动态修改顶点数据时,通过调用glBufferSubData来完成。
#include "glew.h" #include <glfw3.h> #include "common/loadShader.h" #include "glm.hpp" #include "ext.hpp" int main(void) { GLFWwindow* window; /* Initialize the library */ if (!glfwInit()) return -1; /* Create a windowed mode window and its OpenGL context */ window = glfwCreateWindow(480, 480, "Hello World", NULL, NULL); if (!window) { glfwTerminate(); return -1; } /* Make the window's context current */ glfwMakeContextCurrent(window); // Needed in core profile if( glewInit() != GLEW_OK) { glfwTerminate(); return -1; } float g_vertex_buffer_data[] = { -1, 1, 1, -1, -1, 1, 1, 1, 1, 1, -1, 1 }; float g_uv_buffer_data[] = { 0, 1, 0, 0, 1, 1, 1, 0 }; float g_color_buffer_data[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; GLuint Texture = loadBMP_custom("./resource/uvtemplate.bmp"); //This will identify our vertex buffer GLuint vertexbuffer; //Generate 1 buffer,put the resulting identifier in vertexbuffer glGenBuffers(1,&vertexbuffer); //The following commands will talk about our 'vertexbuffer' buffer glBindBuffer(GL_ARRAY_BUFFER,vertexbuffer); //Give our vertices to OpenGL. glBufferData(GL_ARRAY_BUFFER,sizeof(g_vertex_buffer_data),g_vertex_buffer_data,GL_STATIC_DRAW); GLuint uvbuffer; glGenBuffers(1,&uvbuffer); glBindBuffer(GL_ARRAY_BUFFER,uvbuffer); glBufferData(GL_ARRAY_BUFFER,sizeof(g_uv_buffer_data),g_uv_buffer_data,GL_STATIC_DRAW); GLuint colorbuffer; glGenBuffers(1,&colorbuffer); glBindBuffer(GL_ARRAY_BUFFER,colorbuffer); glBufferData(GL_ARRAY_BUFFER,sizeof(g_color_buffer_data),g_color_buffer_data,GL_STATIC_DRAW); GLuint programID = LoadShaders("./shader/vertex.shader","./shader/fragment.shader"); glUseProgram(programID); glClearColor(0.0f, 0.0f, 0.4f, 0.0f); /* Loop until the user closes the window */ // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit 100 units glm::mat4 Projection = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 0.1f, 100.0f); glm::mat4 View = glm::lookAt( glm::vec3(0,0,100), // Camera is at (4,3,3), in World Space glm::vec3(0,0,0), // and looks at the origin glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down) ); glm::mat4 Model = glm::mat4(1.0f); // Our ModelViewProjection : multiplication of our 3 matrices glm::mat4 MVP = Projection * View * Model;// Remember, matrix multiplication is the other way around // Get a handle for our "MVP" uniform. // Only at initialisation time. GLuint MatrixID = glGetUniformLocation(programID,"MVP"); // Send our transformation to the currently bound shader, // in the "MVP" uniform // For each model you render, since the MVP will be different (at least the M part) glUniformMatrix4fv(MatrixID,1,GL_FALSE,&MVP[0][0]); GLuint TextureID = glGetUniformLocation(programID,"myTextureSampler"); while (!glfwWindowShouldClose(window)) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glActiveTexture(GL_TEXTURE5); glBindTexture(GL_TEXTURE_2D,Texture); glUniform1i(TextureID, 5); glEnableVertexAttribArray(0); glBindBuffer(GL_ARRAY_BUFFER,vertexbuffer); //glBufferSubData(GL_ARRAY_BUFFER,0,sizeof(g_vertex_buffer_data),g_vertex_buffer_data); glVertexAttribPointer( 0, // attribute 0. No particular reason for 0, but must match the layout in the shader. 3, // size GL_FLOAT, // type GL_FALSE, // normalized? 0, // stride (void*)0 // array buffer offset ); glEnableVertexAttribArray(1); glBindBuffer(GL_ARRAY_BUFFER,uvbuffer); //glBufferSubData(GL_ARRAY_BUFFER,0,sizeof(g_uv_buffer_data),g_uv_buffer_data); glVertexAttribPointer( 1, // attribute 0. No particular reason for 0, but must match the layout in the shader. 2, // size GL_FLOAT, // type GL_FALSE, // normalized? 0, // stride (void*)0 // array buffer offset ); glEnableVertexAttribArray(2); glBindBuffer(GL_ARRAY_BUFFER,colorbuffer); //glBufferSubData(GL_ARRAY_BUFFER,0,sizeof(g_color_buffer_data),g_color_buffer_data); glVertexAttribPointer( 2, // attribute 0. No particular reason for 0, but must match the layout in the shader. 4, // size GL_FLOAT, // type GL_FALSE, // normalized? 0, // stride (void*)0 // array buffer offset ); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glDrawArrays(GL_TRIANGLE_STRIP,0,4);// Starting from vertex 0; 3 vertices total -> 1 triangle glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glDisableVertexAttribArray(2); /* Swap front and back buffers */ glfwSwapBuffers(window); /* Poll for and process events */ glfwPollEvents(); } glfwTerminate(); return 0; }
// glfwTest.cpp : 定义控制台应用程序的入口点。 // #include "glew.h" #include <glfw3.h> #include "common/loadShader.h" #include "glm.hpp" #include "ext.hpp" typedef struct { float Position[3]; float Colors[4]; float TexCoord[2]; } Vertex; int main(void) { GLFWwindow* window; /* Initialize the library */ if (!glfwInit()) return -1; /* Create a windowed mode window and its OpenGL context */ window = glfwCreateWindow(320, 320, "Hello World", NULL, NULL); if (!window) { glfwTerminate(); return -1; } /* Make the window's context current */ glfwMakeContextCurrent(window); // Needed in core profile if( glewInit() != GLEW_OK) { glfwTerminate(); return -1; } Vertex Vertices[] = { {{-1, 1, 1}, {1, 1, 1, 1}, {0, 1}}, {{-1, -1, 1}, {1, 1, 1, 1}, {0, 0}}, {{ 1, 1, 1}, {1, 1, 1, 1}, {1, 1}}, {{ 1, -1, 1}, {1, 1, 1, 1}, {1, 0}} }; GLuint Texture = loadBMP_custom("./resource/uvtemplate.bmp"); GLuint programID = LoadShaders("./shader/vertex.shader","./shader/fragment.shader"); glUseProgram(programID); glClearColor(0.0f, 0.0f, 0.4f, 0.0f); /* Loop until the user closes the window */ // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit 100 units glm::mat4 Projection = glm::ortho(-2.0f, 2.0f, -2.0f, 2.0f, 0.1f, 100.0f); //glm::mat4 Projection = glm::perspective(45.0f,4.0f/3.0f,0.1f,100.f); glm::mat4 View = glm::lookAt( glm::vec3(0,0,100), // Camera is at (4,3,3), in World Space glm::vec3(0,0,0), // and looks at the origin glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down) ); glm::mat4 Model = glm::mat4(1.0f); // Our ModelViewProjection : multiplication of our 3 matrices glm::mat4 MVP = Projection * View * Model;// Remember, matrix multiplication is the other way around // Get a handle for our "MVP" uniform. // Only at initialisation time. GLuint MatrixID = glGetUniformLocation(programID,"MVP"); // Send our transformation to the currently bound shader, // in the "MVP" uniform // For each model you render, since the MVP will be different (at least the M part) glUniformMatrix4fv(MatrixID,1,GL_FALSE,&MVP[0][0]); GLuint TextureID = glGetUniformLocation(programID,"myTextureSampler"); while (!glfwWindowShouldClose(window)) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glActiveTexture(GL_TEXTURE5); glBindTexture(GL_TEXTURE_2D,Texture); glUniform1i(TextureID, 5); #define kQuadSize sizeof(Vertex) long offset = (long)Vertices; int diff = offsetof( Vertex, Position); glEnableVertexAttribArray(0); glVertexAttribPointer( 0, // attribute 0. No particular reason for 0, but must match the layout in the shader. 3, // size GL_FLOAT, // type GL_FALSE, // normalized? kQuadSize, // stride (void*)(offset + diff) // array buffer offset ); diff = offsetof( Vertex, TexCoord); glEnableVertexAttribArray(1); glVertexAttribPointer( 1, // attribute 0. No particular reason for 0, but must match the layout in the shader. 2, // size GL_FLOAT, // type GL_FALSE, // normalized? kQuadSize, // stride (void*)(offset + diff) // array buffer offset ); diff = offsetof( Vertex, Colors); glEnableVertexAttribArray(2); glVertexAttribPointer( 2, // attribute 0. No particular reason for 0, but must match the layout in the shader. 4, // size GL_FLOAT, // type GL_FALSE, // normalized? kQuadSize, // stride (void*)(offset + diff) // array buffer offset ); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glDrawArrays(GL_TRIANGLE_STRIP,0,4);// Starting from vertex 0; 3 vertices total -> 1 triangle glDisableVertexAttribArray(0); glDisableVertexAttribArray(1); glDisableVertexAttribArray(2); /* Swap front and back buffers */ glfwSwapBuffers(window); /* Poll for and process events */ glfwPollEvents(); } glfwTerminate(); return 0; }