LearnOpenGL(六):采用不同的片元shader渲染两个三角形

和前面使用不同的VBO和VAO缓存顶点数据一样,不同的片元Shader我们需要创建多个片元ShaderID,shader进程,并且对进程进行连接。代码如下:

/*引入OpneGL方法库头文件*/
#include <glad/glad.h>
#include <GLFW/glfw3.h>

/*引入文件里头文件,方便我们调用方法进行问题检查*/
#include <iostream>

/*视口变换回调函数*/
void framebuffer_size_callback(GLFWwindow *window, int width, int height)
{
    glViewport(0, 0, width, height);
}

/*输入设置,比如按下Esc键关闭窗口*/
void player_input(GLFWwindow *window)
{
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
        glfwSetWindowShouldClose(window, true);
}

/*顶点Shader源码*/
const char *vertexShaderSource = "#version 330 core\n"
                                 "layout (location=0) in vec3 aPos;\n"
                                 "void main()\n"
                                 "{\n"
                                 "gl_Position = vec4(aPos.x,aPos.y,aPos.z,1.0);\n"
                                 "}\0";
/*片元Shader源码*/
const char *fragmentShaderSource = "#version 330 core\n"
                                   "out vec4 finalColor;\n"
                                   "void main()\n"
                                   "{\n"
                                   "finalColor = vec4(1.0);\n"
                                   "}\0";

const char *fragmentShaderSource_Second = "#version 330 core\n"
                                          "out vec4 finalColor;\n"
                                          "void main()\n"
                                          "{\n"
                                          "finalColor = vec4(1.0,1.0,0.0,1.0);\n"
                                          "}\0";

/*声明屏幕的宽度和高度,分别为800和600*/
const unsigned int Screen_Width = 800;
const unsigned int Screen_Height = 600;

/*主函数*/
int main()
{
    /*初始化GLFW*/
    glfwInit();
    /*此函数基于OpenGL 3.3版本展开,需要告诉GLFW我们要使用的OpenGL版本是3.3,这样GLFW会在创建OpenGL上下文时做出适当的调整。
    这也可以确保用户在没有适当的OpenGL版本支持的情况下无法运行。将主版本号(Major)和次版本号(Minor)都设为3。同样你可以修改它们的版本*/
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);

    /*我们明确告诉GLFW我们使用的是核心模式(Core-profile)
    明确告诉GLFW我们需要使用核心模式意味着我们只能使用OpenGL功能的一个子集(没有我们已不再需要的向后兼容特性)。*/
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

/* 如果使用的是Mac OS X系统,还需要加下面这行代码到你的初始化代码中这些配置才能起作用*/
#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
#endif

    /*设置窗口对象 */
    GLFWwindow *window = glfwCreateWindow(Screen_Width, Screen_Height, "LearOpenGLWidnow", NULL, NULL);

    /*如果窗口对象创建失败,在终端输出日志,并且释放内存*/
    if (window == NULL)
    {
        std::cout << "Fail to create window !" << std::endl;
        glfwTerminate();
        return -1;
    }

    /*窗口对象创建成功,使用这个窗口 */
    glfwMakeContextCurrent(window);
    /*窗口大小变换回调*/
    glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

    /*检测是否加载所有glad方法库的函数 */
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Fail to initialize glad !" << std::endl;
        return -1;
    }

    /*构建编译顶点Shader*/
    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);
    /*检查是否构建编译成功*/
    int success;
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vertexShader, sizeof(infoLog), NULL, infoLog);
        std::cout << "Error:Shader:VertexShader:Compile_Status_Failure" << infoLog << std::endl;
        return -1;
    }

    /*构建编译片元Shader*/
    unsigned int fragmentShader[2];
    fragmentShader[0] = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader[0], 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader[0]);

    fragmentShader[1] = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader[1], 1, &fragmentShaderSource_Second, NULL);
    glCompileShader(fragmentShader[1]);

    /*链接顶点Shader和片元Shader组成Shader进程 */
    unsigned int shaderProgram[2];
    shaderProgram[0] = glCreateProgram();
    glAttachShader(shaderProgram[0], vertexShader);
    glAttachShader(shaderProgram[0], fragmentShader[0]);
    glLinkProgram(shaderProgram[0]);

    shaderProgram[1] = glCreateProgram();
    glAttachShader(shaderProgram[1], vertexShader);
    glAttachShader(shaderProgram[1], fragmentShader[1]);
    glLinkProgram(shaderProgram[1]);

    /*删除顶点Shader与片元Shader内存*/
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader[0]);
    glDeleteShader(fragmentShader[1]);

    /*设置三角形顶点数据 */
    float first_vertexts[]{
        -0.9, -0.5, 0.0,
        -0.4, -0.5, 0.0,
        -0.65, 0.5, 0.0};

    float second_vertexts[]{
        -0.4, -0.5, 0.0,
        0.1, -0.5, 0.0,
        -0.15, 0.5, 0.0};

    /*声明顶点缓冲物体(Vertex Buffer Object)id,顶点数组物体(Vertex Array Objet)id与元素缓冲物体(Element Buffer Object)id*/
    unsigned int VBO[2], VAO[2];
    /*生成顶点数组 */
    glGenVertexArrays(2, VAO);
    /*生成顶点缓冲区*/
    glGenBuffers(2, VBO);

    /*先绑定顶点数组,在绑定和设置缓冲区,然后绑定顶点属性*/
    /*绑定顶点数组*/
    glBindVertexArray(VAO[0]);
    /*绑定顶点缓冲区数据*/
    glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(first_vertexts), first_vertexts, GL_STATIC_DRAW);
    /*绑定顶点属性*/
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void *)0);
    /*以顶点属性位置值作为参数,启用顶点属性;顶点属性默认是禁用的*/
    glEnableVertexAttribArray(0);

    /*先绑定顶点数组,在绑定和设置缓冲区,然后绑定顶点属性*/
    /*绑定顶点数组*/
    glBindVertexArray(VAO[1]);
    /*绑定顶点缓冲区数据*/
    glBindBuffer(GL_ARRAY_BUFFER, VBO[1]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(second_vertexts), second_vertexts, GL_STATIC_DRAW);
    /*绑定顶点属性*/
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 3, (void *)0);
    /*以顶点属性位置值作为参数,启用顶点属性;顶点属性默认是禁用的*/
    glEnableVertexAttribArray(0);

    /*当窗口没有被关闭时,执行渲染循环 */
    while (!glfwWindowShouldClose(window))
    {
        /* code */
        /*按键输入以及对应操作事件*/
        player_input(window);

        /*渲染*/
        /*清除颜色缓冲区*/
        glClear(GL_COLOR_BUFFER_BIT);
        /*使用Shader进程*/
        glUseProgram(shaderProgram[0]);
        glBindVertexArray(VBO[0]);
        /*绘制顶点数据*/
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glUseProgram(shaderProgram[1]);
        glBindVertexArray(VBO[1]);
        /*绘制顶点数据*/
        glDrawArrays(GL_TRIANGLES, 0, 3);

        /*交换缓存区 */
        glfwSwapBuffers(window);
        /*执行事件 */
        glfwPollEvents();
    }

    /*删除对象,缓存,进程*/
    glDeleteVertexArrays(2, VAO);
    glDeleteBuffers(2, VBO);
    glDeleteProgram(shaderProgram[0]);
    glDeleteProgram(shaderProgram[1]);

    /*退出循环后释放内存*/
    glfwTerminate();
    return 0;
}