终于把三角形绘制出来了,首先一些关键概念、操作。
Vertex Data 顶点数据
VBO Vertex Buffer Objects 顶点缓冲对象
VAO Vertex Array Objects 顶点数组对象
顶点属性指针
Vertex Shader Objects 顶点着色器对象
GLSL OpenGL Shading Language 着色器语言
顶点数组位置声明
顶点着色器 in 关键字声明输入
预定义关键字 gl_Position 顶点着色器输出
Fragment Shader Objects 片段着色器对象
片段着色器 out 关键字声明输出
Shader Program 着色器程序
着色器程序链接顶点着色器与片段着色器
在绘制循环里使用着色器程序、绑定顶点数组对象、告知绘制图元类型、解绑顶点数组对象。
就这些吧,上图、上源码:
主函数 main.cpp
// GLEW #define GLEW_STATIC #include <GL/glew.h> // GLFW #include <GLFW/glfw3.h> #include <iostream> #include "Triangles.h" int main(){ // glfw init 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); //create a glfw window GLFWwindow *window = glfwCreateWindow(640, 360, "opengl-triangles", nullptr, nullptr); if (window == nullptr){ std::cout << "create glfw window failed..." << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window);//set current window // glew init glewExperimental = GL_TRUE; if (glewInit() != GLEW_OK){ std::cout << "glew init failed..." << std::endl; return -1; } //get width and height from glfw window int width, height; glfwGetFramebufferSize(window, &width, &height); //define the glViewport glViewport(0, 0, width, height); Triangles triangles; triangles.init(); //add the game loop while (!glfwWindowShouldClose(window)){ //check event glfwPollEvents(); //now clear window glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT);//the gl color buffer bit //your OpenGL code logical triangles.draw(); //swap buffer glfwSwapBuffers(window); } //the end, glfw window has been closed glfwTerminate(); return 0; }
三角形头文件Triangles.h:
// GLEW #define GLEW_STATIC #include <GL/glew.h> // GLFW #include <GLFW/glfw3.h> #include <iostream> #include <sstream> class Triangles{ public: Triangles(); ~Triangles(); 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; };
三角形实现类Triangles.cpp:
#include "Triangles.h" Triangles::Triangles(){ } Triangles::~Triangles(){ } void Triangles::init(){ // x,y,z opengl coordinates, the vertex data, three 3d point in normalized device coordinates GLfloat vertexs[] = { -0.4f, -0.5f, 0.0f, 0.4f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, }; //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 //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 Triangles::draw(){ //use shader programs glUseProgram(shaderProgram); //draw the triangles glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLES, 0, 3); glBindVertexArray(0); } void Triangles::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 Triangles::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 Triangles::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); //return shaderProgram; } std::string Triangles::getVertexShaderSrc(){ std::stringstream ss; ss << "#version 330 core \n"; ss << "layout (location = 0) in vec3 position;"; ss << "void main()"; ss << "{"; ss << " gl_Position = vec4(position.x, position.y, position.z, 1.0);"; ss << "}"; //return ss.str(); 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 Triangles::getFragmentShaderSrc(){ std::stringstream ss; ss << " #version 330 core \n"; ss << " out vec4 color; \n"; ss << " void main(){ \n"; ss << " color = vec4(1.0f, 0.1f, 0.1f, 1.0f); \n"; ss << " } \n"; //return ss.str(); std::string fragmentShaderStr = "#version 330 core\n" "out vec4 color; " "void main () {" " color = vec4(1.0f, 0.1f, 0.1f, 1.0f);" "}"; return fragmentShaderStr; }