OpenGL学习——绘制第一个三角形

终于把三角形绘制出来了,首先一些关键概念、操作。

Vertex Data                       顶点数据

VBO Vertex Buffer Objects  顶点缓冲对象

VAO Vertex Array Objects   顶点数组对象

Vertex Attribute Pointer      顶点属性指针

NDC Normalized Device Coordinates 标准化设备坐标

Vertex Shader Objects        顶点着色器对象

GLSL   OpenGL Shading Language 着色器语言

顶点数组位置声明

顶点着色器 in 关键字声明输入

预定义关键字 gl_Position 顶点着色器输出

Fragment Shader Objects    片段着色器对象

片段着色器 out 关键字声明输出

Shader Program                 着色器程序

着色器程序链接顶点着色器与片段着色器

在绘制循环里使用着色器程序、绑定顶点数组对象、告知绘制图元类型、解绑顶点数组对象。

Graphics Pipeline:

Vertex Data => Vertex Shader => Primitive Assembly => Geometry Shader

                                                                                       ⇩

         Alpha Test And Blending <= Fragment Shader   <= Rasterization

就这些吧,上图、上源码:

主函数 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:
" << 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...
" << 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 << "

fragmentShaderSrc:
" << 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...
"<< 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 
";
    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
"
    "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  
";
    ss << " out vec4 color;  
";
    ss << " void main(){  
";
    ss << "        color = vec4(1.0f, 0.1f, 0.1f, 1.0f);  
";
    ss << " }  
";
    //return ss.str();
    
    
    std::string  fragmentShaderStr =
        "#version 330 core
"
        "out vec4 color; "
        "void main () {"
        " color = vec4(1.0f, 0.1f, 0.1f, 1.0f);"
        "}";
    return fragmentShaderStr;
}

运行结果:

 参照:https://learnopengl-cn.readthedocs.io/zh/latest/01%20Getting%20started/04%20Hello%20Triangle/

 
原文地址:https://www.cnblogs.com/xingchong/p/12068333.html