OpenGL基础5:第一个正方形

绘制一个正方形真的很简单,很显然,两个三角形铺在一起就可以了

一、绘制正方形

其实如果完全理解了前面的知识, 那么理论上不需要任何参考就可以绘制正方形,就如上所说,两个三角形只有顶点的位置不同而已……

那么绘制一个正方形需要多少个顶点呢?按照如上的方法,应该是需要6个,然而很明显只需要4个即可,因为有两个顶点它们在同一个位置,如果重复绘制会多出50%额外的开销,所以我们的解决方法就是:定义4个顶点,然后再定义2个绘制索引,也就是顶点复用,因此对于上一份输出三角形的代码,添加改动如下:

GLfloat vertices[] = 
{
    -0.5f, -0.5f, 0.0f,
    0.5f, -0.5f, 0.0f,
    -0.5f, 0.5f, 0.0f,
    0.5f, 0.5f, 0.0f, 
};
GLuint indices[] = 
{
    0, 1, 2,        //用前3个顶点绘制第一个三角形
    1, 2, 3         //用后3个顶点绘制第二个三角形
};
GLuint EBO;
glGenBuffers(1, &EBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); 

while (!glfwWindowShouldClose(window))
{
    //......
    //glDrawArrays(GL_TRIANGLES, 0, 3);        --此行不要
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    //......
}
glDeleteBuffers(1, &EBO);

这样就可以输出我们想要的结果:

二、索引缓冲对象 EBO

上面的EBO(Element Buffer Object)即索引缓冲区对象,这个缓冲区主要用来存储顶点的索引信息,可以看出,它的用法和VBO非常的像,除此之外,它也可以被VAO所绑定

和VBO不同的是,我们传递GL_ELEMENT_ARRAY_BUFFER当作缓冲目标,并且在绘制时使用glDrawElements来替换glDrawArrays函数,表示我们使用当前绑定的索引缓冲对象中的索引进行绘制

glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0):第一个参数为绘制模式,第二个参数为绘制顶点个数,第三个参数为索引类型,第四个参数为EBO中的偏移量,一样填写0就好,当我们不再使用索引缓冲对象的时候,可以传递一个索引数组

三、线框模式

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)配置OpenGL如何绘制图元,第一个参数表示我们打算将其应用到所有的三角形的正面和背面(其实对于我们的例子没有什么区别,可以暂时无视),第二个参数表示用线来绘制,之后的绘制调用会一直以线框模式绘制三角形,直到第二个参数传入GL_FILL后回到默认模式

四、测试1

看可不可以在不参考任何文章和代码的情况下,仅通过修改之前生成的三角形的代码,生成如下图形:

参考代码:

#pragma comment(lib,"glew32.lib")
#include<iostream>
#include<opengl/glew.h>
#define GLEW_STATIC
#include<GLFW/glfw3.h>
#include<opengl/freeglut.h>

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
const GLuint WIDTH = 800, HEIGHT = 600;

// Shaders
const GLchar* VShader =
"#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
    "gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";

const GLchar* FShaderY =
"#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
    "color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";

const GLchar* FShaderB =
"#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
    "color = vec4(0.1f, 0.1f, 1.0f, 1.0f);\n"
"}\n\0";

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glfwSetKeyCallback(window, key_callback);
    glewExperimental = GL_TRUE;
    glewInit();

    int width, height;
    glfwGetFramebufferSize(window, &width, &height);
    glViewport(0, 0, width, height);

    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &VShader, NULL);
    glCompileShader(vertexShader);
    GLuint fShaderY = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fShaderY, 1, &FShaderY, NULL);
    glCompileShader(fShaderY);
    GLuint fShaderB = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fShaderB, 1, &FShaderB, NULL);
    glCompileShader(fShaderB);
   
    GLuint shaderYellow = glCreateProgram();
    GLuint shaderBlue = glCreateProgram();
    glAttachShader(shaderYellow, vertexShader);
    glAttachShader(shaderYellow, fShaderY);
    glLinkProgram(shaderYellow);
    glAttachShader(shaderBlue, vertexShader);
    glAttachShader(shaderBlue, fShaderB);
    glLinkProgram(shaderBlue);

    glDeleteShader(vertexShader);
    glDeleteShader(fShaderY);
    glDeleteShader(fShaderB);

    GLfloat trangleY[] =
    {
        -0.5f, -0.5f, 0.0f,
        -0.5f, 0.5f, 0.0f,
        0.0f, 0.0f, 0.0f
    };
    GLfloat trangleB[] =
    {
        0.5f, -0.5f, 0.0f,
        0.5f, 0.5f, 0.0f,
        0.0f, 0.0f, 0.0f
    };
    GLuint VBO[2], VAO[2];
    glGenVertexArrays(2, VAO);
    glGenBuffers(2, VBO);
    
    glBindVertexArray(VAO[0]);
    glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(trangleY), trangleY, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);

    glBindVertexArray(VAO[1]);
    glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(trangleB), trangleB, GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);

    while (!glfwWindowShouldClose(window))
    {
        glfwPollEvents();
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        glUseProgram(shaderYellow);
        glBindVertexArray(VAO[0]);
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glUseProgram(shaderBlue);
        glBindVertexArray(VAO[1]);
        glDrawArrays(GL_TRIANGLES, 0, 3);

        glBindVertexArray(0);
        glfwSwapBuffers(window);
    }
    glDeleteVertexArrays(2, VAO);
    glDeleteBuffers(2, VBO);
    glfwTerminate();
    return 0;
}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);
}

参考文献:https://learnopengl.com/#!Getting-started/OpenGL

原创文章 1134 获赞 1439 访问量 61万+

猜你喜欢

转载自blog.csdn.net/Jaihk662/article/details/105669044