OpenGL学习——绘制矩形
接下来稍微扩展一步,绘制矩形,即两个拼在一起的三角形。
引入一个概念, EBO Element Buffer Object 元素缓冲对象,
EBO用于存放描述“顶点绘制顺序”的对象。
外注:创建VS工程配置:
project properties
*.h dir:
D:\code\OpenGL\glfw\prebuilt\include;D:\code\OpenGL\glew\prebuilt\include;
*.lib dir:
D:\code\OpenGL\glfw\prebuilt\lib;D:\code\OpenGL\glew\prebuilt\lib;
linked lib name:
opengl32.lib;libglew32d.lib;glfw3.lib;
加入SOIL后:
*.h dir:
D:\code\OpenGL\glfw\prebuilt\include;D:\code\OpenGL\glew\prebuilt\include;D:\code\OpenGL\soil\prebuilt\include;
*.lib dir:
D:\code\OpenGL\glfw\prebuilt\lib;D:\code\OpenGL\glew\prebuilt\lib;D:\code\OpenGL\soil\prebuilt\lib;
linked lib name:
opengl32.lib;libglew32d.lib;glfw3.lib;SOIL.lib;
顶点数组对象(VAO)绑定会存储元素缓冲对象(EBO)解绑,就是说在绘制循环里只关心VAO即可。
元素缓冲对象(EBO)的创建和绑定同顶点缓冲对象(VBO),只是绑定目标换成 GL_ELEMENT_ARRAY_BUFFER 。
Wireframe Mode 线框模式,在绘制循环里设置,可控制画线和添充。
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // GL_FILL set the wireframe mode
加入元素缓冲对象(EBO)后,绘制函数改用 glDrawElements
好了,上图上代码:
main.cpp同三角形绘制。
头文件 Rectangles.h
// GLEW #define GLEW_STATIC #include <GL/glew.h> // GLFW #include <GLFW/glfw3.h> #include <iostream> #include <sstream> class Rectangles{ public: Rectangles(); ~Rectangles(); public: void init(); void draw(); private: //create vertex shader void createVertexShader(); //create fragment shader void createFragmentShader(); //create shader program void createShaderProgram(); //get vertex shader source code std::string getVertexShaderSrc(); //get fragment shader source code std::string getFragmentShaderSrc(); private: GLuint VAO; //define VAO, vertex array object GLuint vertexShader; GLuint fragmentShader; GLuint shaderProgram; };
实现类 Rectangles.cpp
#include "Rectangles.h" Rectangles::Rectangles(){ } Rectangles::~Rectangles(){ } void Rectangles::init(){ // x,y,z opengl coordinates, the vertex data, three 3d point in normalized device coordinates GLfloat vertexs[] = { 0.5f, 0.5f, 0.0f, // 0-right up 0.5f, -0.5f, 0.0f, // 1-right down -0.5f, 0.5f, 0.0f, // 2-left up -0.5f, -0.5f, 0.0f, // 3-left down }; // vertex draw index array GLuint indexs[] = { 0, 1, 2, 1, 2, 3, }; //define VAO, vertex array object //GLuint VAO; glGenVertexArrays(1, &VAO); glBindVertexArray(VAO); // bind vertex array object //define VBO, vertex buffer object GLuint VBO; glGenBuffers(1, &VBO); // gen buffer object glBindBuffer(GL_ARRAY_BUFFER, VBO); // bind buffer to the target glBufferData(GL_ARRAY_BUFFER, sizeof(vertexs), vertexs, GL_STATIC_DRAW); // copy vertex data to VBO //define EBO, element buffer object GLuint EBO; glGenBuffers(1, &EBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexs), indexs, GL_STATIC_DRAW); //set vertex attribute point glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); glBindVertexArray(0);//unbind vertex array object //create shader program this->createShaderProgram(); } void Rectangles::draw(){ //use shader programs glUseProgram(shaderProgram); //draw the Rectangles glBindVertexArray(VAO); //glDrawArrays(GL_TRIANGLES, 0, 3); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // GL_LINE set the wireframe mode glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glBindVertexArray(0); } void Rectangles::createVertexShader(){ //compile vertex shader source std::string vertexShaderStr = this->getVertexShaderSrc(); const char *vertexShaderSrc = vertexShaderStr.c_str(); std::cout << "vertexShaderSrc:\n" << vertexShaderSrc; //GLuint vertexShader; // shader object vertexShader = glCreateShader(GL_VERTEX_SHADER); // create vertex shader object glShaderSource(vertexShader, 1, &vertexShaderSrc, NULL); // shader source attach to shader object glCompileShader(vertexShader); // compile shader //compile result check GLint success; GLchar infoLog[512]; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); if (!success){ glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); std::cout << "vertex shader source compile failed...\n" << infoLog << std::endl; std::cout << vertexShaderSrc; } } void Rectangles::createFragmentShader(){ //compile fragment shader source std::string fragmentShaderStr = this->getFragmentShaderSrc(); const char *fragmentShaderSrc = fragmentShaderStr.c_str(); std::cout << "\n\nfragmentShaderSrc:\n" << fragmentShaderSrc; //GLuint fragmentShader; fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentShaderSrc, NULL); glCompileShader(fragmentShader); } void Rectangles::createShaderProgram(){ this->createVertexShader(); this->createFragmentShader(); if (vertexShader == NULL || fragmentShader == NULL){ return; } //shader program, link vertex shader object and fragment shader object //GLuint shaderProgram; shaderProgram = glCreateProgram(); // create shader program glAttachShader(shaderProgram, vertexShader); // attach vertex shader glAttachShader(shaderProgram, fragmentShader); // attach fragment shader glLinkProgram(shaderProgram); // linking //check link result GLint success; GLchar infoLog[512]; glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); if (!success){ glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); std::cout << "shader program linking failed...\n" << infoLog << std::endl; return; } //delete vertex shader object and fragment shader object glDeleteShader(vertexShader); glDeleteShader(fragmentShader); } std::string Rectangles::getVertexShaderSrc(){ std::string vertexShaderStr = "#version 330 core\n" "layout (location = 0) in vec3 pos; " "void main () {" " gl_Position = vec4(pos, 1.0);" "}"; return vertexShaderStr; } std::string Rectangles::getFragmentShaderSrc(){ std::string fragmentShaderStr = "#version 330 core\n" "out vec4 color; " "void main () {" " color = vec4(1.0f, 0.1f, 0.1f, 1.0f);" "}"; return fragmentShaderStr; }
运行结果: