zoukankan      html  css  js  c++  java
  • OpenGL — GLFW — 颜色

    OpenGL — GLFW — 颜色

    参考教程:https://learnopengl-cn.readthedocs.io/zh/latest/02%20Lighting/01%20Colors/

    既然,网络上已经有现成的教程了,我为什么还有在写一遍教程呢?
    这个教程不是给大家写的,而是给我自己写的,算是我的学习笔记吧。我将编程序的重点提起出来,并将我的经验和遇到的问题记下来,为日后的我做参考用的。知识会随着时间的流过,而慢慢的被遗忘,当日后有一个项目要用到OpenGL的知识时,那个时候的我可能已经将当初学到的OpenGL忘记的擦不多了,这个时候,我就需要过去的我来帮助我,可以这样理解,跨越时空的两个我在完成一个项目!不错,这就是记笔记的作用。

    给模型上颜色,两个步骤:

    1. 编写片段着色器
    2. 在主程序中给片段着色器赋值
    3. 在主主函数中,使用片段着色器

    你可能会问,颜色有什么好讲的?我想说:你问对了,真的没有什么好讲的。就是定义一个变量:

    glm::vec3 color(1.0f, 0.5f, 0.31f);   // 珊瑚红(Coral)

    编写程序步骤

    第1步:

    程序

    先顶点着色器程序,就用个精简版的程序:(顶点着色器(Vertex Shader)文件名为:color.vs

    #version 330 core
    layout (location = 0) in vec3 position;
    
    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;
    
    void main()
    {
        gl_Position = projection * view * model * vec4(position, 1.0f);
    }

    解释

    layout (location = 0) in vec3 position;

    得到CPP程序中是ID是0的数据,将ID为0的数据的物理意义定义为顶点位置

    uniform mat4 model;
    uniform mat4 view;
    uniform mat4 projection;

    这些变量是需要在CPP程序中等待赋值的。
    归根结底,这三个变量都是4*4的矩阵,都是作用于模型的每一个顶点的。
    但是他们代表着不同的物理意义:

    model 模型自身的姿态矩阵。姿态旋转平移组成。
    view 摄像机姿态矩阵。
    projection 透视矩阵。
    void main()
    {
        gl_Position = projection * view * model * vec4(position, 1.0f);
    }

    gl_PositionGLSL(OpenGL Shading Language)着色语言中的一个内置变量,即输出的顶点位置。

    总结:这个顶点着色器的作用就是:更新顶点的位置

    第2步:

    程序

    编写片段着色器:(片段着色器(Fragment shader)文件命名为:color.frag

    #version 330 core
    out vec4 color;
    
    uniform vec3 objectColor;
    uniform vec3 lightColor;
    
    void main()
    {
        color = vec4(lightColor * objectColor, 1.0f);
    }

    讲解

    out vec4 color;

    输出的color变量。

    uniform vec3 objectColor;
    uniform vec3 lightColor;

    这两个值在CPP程序中被赋值,分别表示物体色光源颜色

    void main()
    {
        color = vec4(lightColor * objectColor, 1.0f);
    }

    将光源颜色与物体颜色相乘,即两个向量相乘,得到最终的颜色。因为定义的color4维向量,objectColorlightColor3维向量。所以这里给color赋值的时候要这样做color = vec4(vec3, 1.0f);

    总结: 这个片段着色器做的事情:更新物体颜色。

    第3步

    编写CPP程序模板

    #include <iostream>
    #include <cmath>
    
    // GLEW
    #define GLEW_STATIC
    #include <GL/glew.h>
    
    // GLFW
    #include <GLFW/glfw3.h>
    
    // Other Libs
    #include <SOIL.h>
    // GLM Mathematics
    #include <glm/glm.hpp>
    #include <glm/gtc/matrix_transform.hpp>
    #include <glm/gtc/type_ptr.hpp>
    
    // Other includes
    #include <learnopenglshader.h>
    #include <learnopenglcamera.h>
    #include <learnopenglmodel.h>
    
    // Function prototypes
    void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
    void mouse_callback(GLFWwindow* window, double xpos, double ypos);
    void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
    void do_movement();
    
    // Window dimensions
    const GLuint WIDTH = 800, HEIGHT = 800;
    
    // Camera
    Camera  camera(glm::vec3(0.0f, 0.0f, 3.0f));
    GLfloat lastX  =  WIDTH  / 2.0;
    GLfloat lastY  =  HEIGHT / 2.0;
    bool    keys[1024];
    
    // Deltatime
    GLfloat deltaTime = 0.0f;   // Time between current frame and last frame
    GLfloat lastFrame = 0.0f;   // Time of last frame
    
    // The MAIN function, from here we start the application and run the game loop
    int main()
    {
        // Init GLFW
        glfwInit();
        // Set all the required options for GLFW
        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 GLFWwindow object that we can use for GLFW's functions
        GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "AoboSir OpenGL", nullptr, nullptr);
        glfwMakeContextCurrent(window);
    
        // Set the required callback functions
        glfwSetKeyCallback(window, key_callback);
        glfwSetCursorPosCallback(window, mouse_callback);
        glfwSetScrollCallback(window, scroll_callback);
    
        // GLFW Options
        glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
    
        // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
        glewExperimental = GL_TRUE;
        // Initialize GLEW to setup the OpenGL Function pointers
        glewInit();
    
        // Define the viewport dimensions
        glViewport(0, 0, WIDTH, HEIGHT);
    
        // OpenGL options
        glEnable(GL_DEPTH_TEST);
    
        //定义着色器类对象
    
        //定义模型类对象
    
        // Game loop
        while (!glfwWindowShouldClose(window))
        {
            // Calculate deltatime of current frame
            GLfloat currentFrame = glfwGetTime();
            deltaTime = currentFrame - lastFrame;
            lastFrame = currentFrame;
    
            // Check if any events have been activiated (key pressed, mouse moved etc.) and call corresponding response functions
            glfwPollEvents();
            do_movement();
    
            // Clear the colorbuffer
            //glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
            glClearColor(0.41f, 0.41f, 0.41f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
            //给着色器进行赋值
    
            //让模型使用这个着色器对象,显示模型
    
            // Swap the screen buffers
            glfwSwapBuffers(window);
        }
    
        // Terminate GLFW, clearing any resources allocated by GLFW.
        glfwTerminate();
        return 0;
    }
    
    // Is called whenever a key is pressed/released via GLFW
    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);
        if (key >= 0 && key < 1024)
        {
            if (action == GLFW_PRESS)
                keys[key] = true;
            else if (action == GLFW_RELEASE)
                keys[key] = false;
        }
    }
    
    void do_movement()
    {
        // Camera controls
        if (keys[GLFW_KEY_W])
            camera.ProcessKeyboard(FORWARD, deltaTime);
        if (keys[GLFW_KEY_S])
            camera.ProcessKeyboard(BACKWARD, deltaTime);
        if (keys[GLFW_KEY_A])
            camera.ProcessKeyboard(LEFT, deltaTime);
        if (keys[GLFW_KEY_D])
            camera.ProcessKeyboard(RIGHT, deltaTime);
    }
    
    bool firstMouse = true;
    void mouse_callback(GLFWwindow* window, double xpos, double ypos)
    {
        if(glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT )){
            if (firstMouse)
            {
                lastX = xpos;
                lastY = ypos;
                firstMouse = false;
            }
    
            GLfloat xoffset = xpos - lastX;
            GLfloat yoffset = ypos - lastY;  // Reversed since y-coordinates go from bottom to left
    
            lastX = xpos;
            lastY = ypos;
    
            camera.ProcessMouseMovement(glm::radians(xoffset), glm::radians(yoffset));
        } else {
            firstMouse = true;
        }
    }
    
    void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
    {
        camera.ProcessMouseScroll(glm::radians(yoffset) );
    }

    注意:
    1. glm::radians(angle)这个函数是将输入的角度转换为弧度。
    2. glfwGetMouseButton(window,GLFW_MOUSE_BUTTON_LEFT ) 函数,如果鼠标左键按下,函数会返回非零数据;如果鼠标左键没有被按下,函数会返回0.

    第4步

    定义着色器对象和模型对象,给着色器对象赋值,并让模型对象使用着色器对象,显示模型。

    定义着色器对象和模型对象

        //定义着色器类对象
        // Build and compile our shader program
        Shader lightingShader("shader/color.vs", "shader/color.frag");
        Shader lampShader("shader/lamp.vs", "shader/lamp.frag");
    
        //定义模型类对象
        Model ourModel("meshes/TexMesh.obj");
        Model lampModel("meshes/Light_Bulb.obj");

    给着色器进行赋值

            //给着色器进行赋值
            // Use cooresponding shader when setting uniforms/drawing objects
            lightingShader.Use();
            GLint objectColorLoc = glGetUniformLocation(lightingShader.Program, "objectColor");
            GLint lightColorLoc  = glGetUniformLocation(lightingShader.Program, "lightColor");
            glUniform3f(objectColorLoc, 1.0f, 0.5f, 0.31f);
            glUniform3f(lightColorLoc,  1.0f, 1.0f, 1.0f);
    
            // Create camera transformations
            glm::mat4 view;
            view = camera.GetViewMatrix();
            glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
            // Get the uniform locations
            GLint modelLoc = glGetUniformLocation(lightingShader.Program, "model");
            GLint viewLoc  = glGetUniformLocation(lightingShader.Program,  "view");
            GLint projLoc  = glGetUniformLocation(lightingShader.Program,  "projection");
            // Pass the matrices to the shader
            glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
            glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
    
            // Draw the loaded model
            glm::mat4 model;
            model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f)); // It's a bit too big for our scene, so scale it down
            glUniformMatrix4fv(glGetUniformLocation(lightingShader.Program, "model"), 1, GL_FALSE, glm::value_ptr(model));

    让模型使用这个着色器对象,显示模型

            //让模型使用这个着色器对象,显示模型
            ourModel.Draw(lightingShader);

    大功告成,第6步,运行程序

    Alt text
    (这其实是以一张倒人脸的背面,你现在看到的是一片珊瑚红色,是因为在我们的这个着色器是最简单的着色器,并且我们没有使用模型的点的法线向量,所以没有阴影的效果。)

    我们继续学习下一课。


    参考网站:
    http://www.cnblogs.com/zhanglitong/p/3209282.html
    http://www.glfw.org/docs/latest/group__input.html#gac1473feacb5996c01a7a5a33b5066704
    http://learnopengl.com/code_viewer.php?code=model_loading/model_diffuse
    下载一个灯泡模型:http://tf3dm.com/3d-model/light-bulb-simple-studio-9032.html

  • 相关阅读:
    IP地址分类整理
    PHP
    [转载]数组的全排列问题
    使用 Homebrew 安装 Git
    Homebrew简介及安装
    iOS开发~CocoaPods使用详细说明
    关于目前自己iOS项目使用的第三方开源库
    IOS 时间格式 时间转换 大总结
    Xcode磁盘空间大清理
    Swift百万线程攻破单例(Singleton)模式
  • 原文地址:https://www.cnblogs.com/aobosir/p/5928662.html
Copyright © 2011-2022 走看看