OpenGL-- Shader 颜色 光照 5 多光源

版权声明:----------------------------未经博主允许, 随意转载---------------------------- https://blog.csdn.net/yulinxx/article/details/72838217

http://learnopengl-cn.readthedocs.io/zh/latest/02%20Lighting/06%20Multiple%20lights/

main.cpp

//main.cpp 
#include <string>

#define GLEW_STATIC
#include <GL/glew.h>

#include <GLFW/glfw3.h>

#include "Shader.h"
#include "Camera.h"

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include <SOIL/SOIL.h>

#include <iostream>

#include "Shader.h"

#pragma comment(lib, "./SOIL.lib")

#pragma comment (lib, "opengl32.lib")
#pragma comment (lib, "glew32s.lib")
#pragma comment (lib, "glfw3.lib") 
#pragma comment (lib, "glfw3dll.lib") 
#pragma comment (lib, "glew32mxs.lib")


void key_callback(GLFWwindow* pWnd, int key, int scancode, int action, int mode);
void mouse_callback(GLFWwindow* pWnd, double xpos, double ypos);
void scroll_callback(GLFWwindow* pWnd, double xoffset, double yoffset);
void do_movement();

const GLuint WIDTH = 800, HEIGHT = 600;

Camera  camera(glm::vec3(0.0f, 0.0f, 3.0f));
GLfloat lastX = WIDTH / 2.0;
GLfloat lastY = HEIGHT / 2.0;
bool    keys[1024];

glm::vec3 lightPos(1.2f, 1.0f, 2.0f);

GLfloat deltaTime = 0.0f;
GLfloat lastFrame = 0.0f;

/////////////////////////////////////////////////////////////////////////
int main()
{
    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);

    GLFWwindow* pWnd = glfwCreateWindow(WIDTH, HEIGHT, "MultipleLight", nullptr, nullptr);
    glfwMakeContextCurrent(pWnd);

    glfwSetKeyCallback(pWnd, key_callback);
    glfwSetCursorPosCallback(pWnd, mouse_callback);
    glfwSetScrollCallback(pWnd, scroll_callback);

    // 鼠标指针隐藏
    //glfwSetInputMode(pWnd, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

    glewExperimental = GL_TRUE;

    glewInit();
    glViewport(0, 0, WIDTH, HEIGHT);
    glEnable(GL_DEPTH_TEST);

    // Shader 处理 箱子  以及  灯光  
    Shader lightingObjShader("./obj_vertex.vs", "./obj_fragement.fs");
    Shader lampShader("./lamp_vertex.vs", "./lamp_fragement.fs");

    // 点数据
    GLfloat vertices[] = {  // 位置3  向量3  纹理2
        // 背面
        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  0.0f,
        0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  0.0f,
        0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  1.0f,

        0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  1.0f,  1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,  0.0f,  0.0f,
        //  前面
        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,
        0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  0.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  1.0f,

        0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  1.0f,  1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f,  0.0f,  1.0f,  0.0f,  0.0f,
        // 左面
        -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
        -0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  1.0f,
        -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
        -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
        -0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  0.0f,  0.0f,
        -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
        // 右面
        0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
        0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  1.0f,
        0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
        0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  1.0f,
        0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  0.0f,  0.0f,
        0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,  1.0f,  0.0f,
        // 下面
        -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  1.0f,
        0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  1.0f,
        0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  0.0f,
        0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  1.0f,  0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,  0.0f,  1.0f,
        // 上面
        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f,  1.0f,
        0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  1.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  0.0f,
        0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  1.0f,  0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,  0.0f,  0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,  0.0f,  1.0f
    };

    // 箱子位置
    glm::vec3 objPos[] = {
        glm::vec3(-3.0f,  -1.0f,  -5.0f),       glm::vec3(2.0f,  5.0f, -1.0f),
        glm::vec3(-1.5f, -2.2f, -2.5f),         glm::vec3(0.0f, -2.0f, -5.3f),
        glm::vec3(2.4f, -0.4f, -3.5f),          glm::vec3(-1.7f,  0.0f, -7.5f),
        glm::vec3(1.3f, -2.0f, -2.5f),          glm::vec3(1.5f,  2.0f, -2.5f),
        glm::vec3(1.5f,  0.2f, -1.5f),          glm::vec3(-1.3f,  1.0f, -1.5f) };

    glm::vec3 pointLightPositions[] = {
        glm::vec3(0.7f,  0.2f,  2.0f),
        glm::vec3(2.3f, -3.3f, -4.0f),
        glm::vec3(-4.0f,  2.0f, -12.0f),
        glm::vec3(0.0f,  0.0f, -3.0f)
    };

    GLuint objVAO, VBO;

    glGenVertexArrays(1, &objVAO);

    // 光照物体
    glBindVertexArray(objVAO); // --- Begin
    {
        // 顶点数据复至GPU中
        glGenBuffers(1, &VBO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        {
            glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

            // 位置索引 传至Shader的
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
            glEnableVertexAttribArray(0);
            // 向量索引
            glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
            glEnableVertexAttribArray(1);
            // 纹理索引
            glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));
            glEnableVertexAttribArray(2);
        }
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
    glBindVertexArray(0); // --- End

     // 灯泡 (只需要用到一部分坐标点数据,用于绘制一个立方体即可)
    GLuint lampVAO, lampVBO;
    glGenVertexArrays(1, &lampVAO);
    glBindVertexArray(lampVAO);
    {
        //glGenBuffers(1, &lampVBO);
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        {
            glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (GLvoid*)0);
            glEnableVertexAttribArray(0);
        }
        glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
    glBindVertexArray(0);

    // 纹理1 木箱纹理贴图 -- 
    //  1. 加载图片 木箱图片
    int nTextureW = 0, nTextureH = 0;
    unsigned char* pChImg = nullptr;
    pChImg = SOIL_load_image("texture.png", &nTextureW, &nTextureH, 0, SOIL_LOAD_RGB);

    // 2. 纹理设置
    GLuint diffuseMap;
    glGenTextures(1, &diffuseMap);
    {
        glBindTexture(GL_TEXTURE_2D, diffuseMap);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nTextureW, nTextureH, 0, GL_RGB, GL_UNSIGNED_BYTE, pChImg);
        glGenerateMipmap(GL_TEXTURE_2D);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);
    }
    glBindTexture(GL_TEXTURE_2D, 0);

    SOIL_free_image_data(pChImg);   // 释放内存

    // 纹理2 木箱边框反射贴图 -- 
    //  1. 加载图片 木箱边框图片
    pChImg = SOIL_load_image("texture_specular.png", &nTextureW, &nTextureH, 0, SOIL_LOAD_RGB);

    // 2. 纹理设置
    GLuint specularMap;
    glGenTextures(1, &specularMap);
    glBindTexture(GL_TEXTURE_2D, specularMap);
    {
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nTextureW, nTextureH, 0, GL_RGB, GL_UNSIGNED_BYTE, pChImg);
        glGenerateMipmap(GL_TEXTURE_2D);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST_MIPMAP_NEAREST);
    }
    glBindTexture(GL_TEXTURE_2D, 0);
    SOIL_free_image_data(pChImg);

    // 设置Shader中的材质属性
    lightingObjShader.useShaderPrograme();
    glUniform1i(glGetUniformLocation(lightingObjShader.getPrograme(), "material.diffuse"), 0);
    glUniform1i(glGetUniformLocation(lightingObjShader.getPrograme(), "material.specular"), 1);

    GLuint  nCurrentTime = glfwGetTime();
    GLuint nLastTime = glfwGetTime();
    GLuint nFPS = 0;
    glm::mat4 view;
    glm::mat4 model;

    //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);  // 只绘边框
    while (!glfwWindowShouldClose(pWnd))
    {
        GLfloat currentFrame = glfwGetTime();
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        glfwPollEvents();

        do_movement();

        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        lightingObjShader.useShaderPrograme();


        GLint viewPosLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "viewPos");
        glUniform3f(viewPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);

        // 设置Shader中的材质属性
        glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "material.shininess"), 4.0f);

        // Directional light
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "dirLight.direction"), -0.2f, -1.0f, -0.3f);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "dirLight.ambient"), 0.05f, 0.05f, 0.05f);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "dirLight.diffuse"), 0.4f, 0.4f, 0.4f);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "dirLight.specular"), 0.5f, 0.5f, 0.5f);
        // Point light 1
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[0].position"), pointLightPositions[0].x, pointLightPositions[0].y, pointLightPositions[0].z);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[0].ambient"), 0.05f, 0.05f, 0.05f);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[0].diffuse"), 0.8f, 0.8f, 0.8f);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[0].specular"), 1.0f, 1.0f, 1.0f);
        glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[0].constant"), 1.0f);
        glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[0].linear"), 0.09);
        glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[0].quadratic"), 0.032);
        // Point light 2
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[1].position"), pointLightPositions[1].x, pointLightPositions[1].y, pointLightPositions[1].z);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[1].ambient"), 0.05f, 0.05f, 0.05f);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[1].diffuse"), 0.8f, 0.8f, 0.8f);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[1].specular"), 1.0f, 1.0f, 1.0f);
        glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[1].constant"), 1.0f);
        glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[1].linear"), 0.09);
        glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[1].quadratic"), 0.032);
        // Point light 3
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[2].position"), pointLightPositions[2].x, pointLightPositions[2].y, pointLightPositions[2].z);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[2].ambient"), 0.05f, 0.05f, 0.05f);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[2].diffuse"), 0.8f, 0.8f, 0.8f);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[2].specular"), 1.0f, 1.0f, 1.0f);
        glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[2].constant"), 1.0f);
        glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[2].linear"), 0.09);
        glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[2].quadratic"), 0.032);
        // Point light 4
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[3].position"), pointLightPositions[3].x, pointLightPositions[3].y, pointLightPositions[3].z);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[3].ambient"), 0.05f, 0.05f, 0.05f);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[3].diffuse"), 0.8f, 0.8f, 0.8f);
        glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[3].specular"), 1.0f, 1.0f, 1.0f);
        glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[3].constant"), 1.0f);
        glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[3].linear"), 0.09);
        glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "lights[3].quadratic"), 0.032);


        GLint modelLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "model");
        GLint viewLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "view");
        GLint projLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "projection");

        view = camera.GetViewMatrix();
        glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);
        glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
        glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));




        //// 设置光源参数
        //GLint lightPosLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "light.position");
        //GLint lightDirLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "light.direction");
        //GLint lightPosCutoffLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "light.cutOff");
        //GLint lightSpotOuterCutOffLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "light.outerCutOff");       // add 外圆
        //GLint viewPosLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "viewPos");

        //glUniform3f(lightPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);
        //glUniform3f(lightDirLoc, camera.Front.x, camera.Front.y, camera.Front.z);
        //glUniform1f(lightPosCutoffLoc, glm::cos(glm::radians(12.5)));         // 聚光灯半径         内圆
        //glUniform1f(lightSpotOuterCutOffLoc, glm::cos(glm::radians(17.5f)));          // add 聚光灯 外圆  内圆至外圆逐渐变暗
        //glUniform3f(viewPosLoc, camera.Position.x, camera.Position.y, camera.Position.z);

        //// 设置Shader中的灯光属性
        //glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "light.ambient"), 0.1f, 0.1f, 0.1f);
        //glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "light.diffuse"), 0.8f, 0.8f, 0.8f);
        //glUniform3f(glGetUniformLocation(lightingObjShader.getPrograme(), "light.specular"), 1.0f, 1.0f, 1.0f);

        //glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "light.constant"), 1.0f);
        //glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "light.linear"), 0.09f);
        //glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "light.quadratic"), 0.032f);
        //
        //// 设置Shader中的材质属性
        //glUniform1f(glGetUniformLocation(lightingObjShader.getPrograme(), "material.shininess"), 4.0f);

        //// 摄像机设置
        //view = camera.GetViewMatrix();
        //glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)WIDTH / (GLfloat)HEIGHT, 0.1f, 100.0f);

        //GLint modelLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "model");
        //GLint viewLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "view");
        //GLint projLoc = glGetUniformLocation(lightingObjShader.getPrograme(), "projection");
        //glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
        //glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));

        // 绑定漫反射贴图
        glActiveTexture(GL_TEXTURE0);   // 箱子纹理
        glBindTexture(GL_TEXTURE_2D, diffuseMap);

        glActiveTexture(GL_TEXTURE1);   // 箱子边框的镜面反射纹理
        glBindTexture(GL_TEXTURE_2D, specularMap);

        // 绘制箱子 -------------------
        glBindVertexArray(objVAO); // 绑定箱子的顶点数据进行操作
        for (GLuint i = 0; i < 10; i++)
        {
            model = glm::mat4();

            model = glm::translate(model, objPos[i]);
            GLfloat angle = glfwGetTime();
            model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
            glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

            glDrawArrays(GL_TRIANGLES, 0, 36);
        }

        for (GLuint i = 0; i < 10; i++)
        {
            model = glm::mat4();

            model = glm::translate(model, objPos[i] + objPos[i]);
            GLfloat angle = glfwGetTime();
            model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
            glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

            glDrawArrays(GL_TRIANGLES, 0, 36);
        }

        for (GLuint i = 0; i < 10; i++)
        {
            model = glm::mat4();

            model = glm::translate(model, objPos[i] + objPos[i] + objPos[i]);
            GLfloat angle = glfwGetTime();
            model = glm::rotate(model, angle, glm::vec3(1.0f, 0.3f, 0.5f));
            glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

            glDrawArrays(GL_TRIANGLES, 0, 36);
        }
        glBindVertexArray(0);       // 解绑


        // 绘制灯泡 -------------------
        lampShader.useShaderPrograme();
        modelLoc = glGetUniformLocation(lampShader.getPrograme(), "model");
        viewLoc = glGetUniformLocation(lampShader.getPrograme(), "view");
        projLoc = glGetUniformLocation(lampShader.getPrograme(), "projection");
        glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
        glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection));
        //model = glm::mat4();
        //model = glm::translate(model, lightPos);
        //model = glm::scale(model, glm::vec3(0.2f)); // 缩小
        //glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

        glBindVertexArray(lampVAO); // 绑定灯泡的顶点数据进行操作
        {
            for (GLuint i = 0; i<4; i++)
            {
                model = glm::mat4();
                model = glm::translate(model, pointLightPositions[i]);
                model = glm::scale(model, glm::vec3(0.2f));
                glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
                glDrawArrays(GL_TRIANGLES, 0, 36);
            }
        }
        glBindVertexArray(0);       // 解绑

        glfwSwapBuffers(pWnd);

        // -----------------------------------------------  
        nLastTime = glfwGetTime();
        nFPS++;
        if (nLastTime - nCurrentTime > 1)
        {
            std::cout << "当前帧率:" << nFPS << std::endl;
            nFPS = 0;
            nCurrentTime = nLastTime;
        }
    }

    glfwTerminate();
    return 0;
}


void key_callback(GLFWwindow* pWnd, int key, int scancode, int action, int mode)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(pWnd, 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()
{
    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* pWnd, double xpos, double ypos)
{
    if (firstMouse)
    {
        lastX = xpos;
        lastY = ypos;
        firstMouse = false;
    }

    GLfloat xoffset = xpos - lastX;
    GLfloat yoffset = lastY - ypos;

    lastX = xpos;
    lastY = ypos;

    //camera.ProcessMouseMovement(xoffset, yoffset);
}

void scroll_callback(GLFWwindow* pWnd, double xoffset, double yoffset)
{
    camera.ProcessMouseScroll(yoffset);
}




Camera.h

//Camera.h 

#pragma once

// Std. Includes
#include <vector>

// GL Includes
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>


// 摄像机移动方向  程序中用WSAD控制
enum Camera_Movement {
    FORWARD,
    BACKWARD,
    LEFT,
    RIGHT
};

// Default camera values
const GLfloat YAW = -90.0f;
const GLfloat PITCH = 0.0f;
const GLfloat SPEED = 3.0f;
const GLfloat SENSITIVTY = 0.25f;
const GLfloat ZOOM = 45.0f;


class Camera
{
public:
    // Camera Attributes
    glm::vec3 Position;
    glm::vec3 Front;
    glm::vec3 Up;
    glm::vec3 Right;
    glm::vec3 WorldUp;
    // Eular Angles
    GLfloat Yaw;
    GLfloat Pitch;
    // Camera options
    GLfloat MovementSpeed;
    GLfloat MouseSensitivity;
    GLfloat Zoom;

    // Constructor with vectors
    Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f), 
        glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), GLfloat yaw = YAW, 
        GLfloat pitch = PITCH) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), 
        MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
    {
        this->Position = position;
        this->WorldUp = up;
        this->Yaw = yaw;
        this->Pitch = pitch;
        this->updateCameraVectors();
    }
    // Constructor with scalar values
    Camera(GLfloat posX, GLfloat posY, GLfloat posZ, GLfloat upX, GLfloat upY, 
        GLfloat upZ, GLfloat yaw, GLfloat pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)), 
        MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
    {
        this->Position = glm::vec3(posX, posY, posZ);
        this->WorldUp = glm::vec3(upX, upY, upZ);
        this->Yaw = yaw;
        this->Pitch = pitch;
        this->updateCameraVectors();
    }

    // Returns the view matrix calculated using Eular Angles and the LookAt Matrix
    glm::mat4 GetViewMatrix()
    {
        return glm::lookAt(this->Position, this->Position + this->Front, this->Up);
    }

    // 按键处理
    void ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime)
    {
        GLfloat velocity = this->MovementSpeed * deltaTime;
        if (direction == FORWARD)
            this->Position += this->Front * velocity;
        if (direction == BACKWARD)
            this->Position -= this->Front * velocity;
        if (direction == LEFT)
            this->Position -= this->Right * velocity;
        if (direction == RIGHT)
            this->Position += this->Right * velocity;
    }

    // 鼠标移动处理
    void ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset, 
        GLboolean constrainPitch = true)
    {
        xoffset *= this->MouseSensitivity;
        yoffset *= this->MouseSensitivity;

        this->Yaw += xoffset;
        this->Pitch += yoffset;

        // Make sure that when pitch is out of bounds, screen doesn't get flipped
        if (constrainPitch)
        {
            if (this->Pitch > 89.0f)
                this->Pitch = 89.0f;
            if (this->Pitch < -89.0f)
                this->Pitch = -89.0f;
        }

        // Update Front, Right and Up Vectors using the updated Eular angles
        this->updateCameraVectors();
    }

    // Processes input received from a mouse scroll-wheel event. 
    //      Only requires input on the vertical wheel-axis
    void ProcessMouseScroll(GLfloat yoffset)
    {
        if (this->Zoom >= 1.0f && this->Zoom <= 45.0f)
            this->Zoom -= yoffset;
        if (this->Zoom <= 1.0f)
            this->Zoom = 1.0f;
        if (this->Zoom >= 45.0f)
            this->Zoom = 45.0f;
    }

private:
    // Calculates the front vector from the Camera's (updated) Eular Angles
    void updateCameraVectors()
    {
        // Calculate the new Front vector
        glm::vec3 front;
        front.x = cos(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
        front.y = sin(glm::radians(this->Pitch));
        front.z = sin(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
        this->Front = glm::normalize(front);
        // Also re-calculate the Right and Up vector
        // Normalize the vectors, because their length gets closer to 0 the more 
        //      you look up or down which results in slower movement.
        this->Right = glm::normalize(glm::cross(this->Front, this->WorldUp));  
        this->Up = glm::normalize(glm::cross(this->Right, this->Front));
    }
};


Shader.h

//Shader.h 
#pragma once

#ifndef TEXTURE_SHADER_H_
#define TEXTURE_SHADER_H_

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

#include <gl/glew.h>

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

#include <GL/glew.h>

class Shader
{
public:
    Shader(const GLchar* vertexPath, const GLchar* fragmentPath);
    ~Shader();

public:
    void useShaderPrograme();

    GLuint getPrograme() {
        return this->m_nProgram;
    }

private:
    GLuint  m_nProgram;
};

Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
{
    std::string vertexCode;
    std::string fragmentCode;
    std::ifstream vertexShaderF;
    std::ifstream fragementShaderF;

    vertexShaderF.exceptions(std::ifstream::badbit);
    fragementShaderF.exceptions(std::ifstream::badbit);

    try
    {
        vertexShaderF.open(vertexPath);     // 打开文件
        fragementShaderF.open(fragmentPath);

        std::stringstream vertexShaderStream, fragementShaderStream;
        vertexShaderStream << vertexShaderF.rdbuf();    // 读取文件至stringstream中
        fragementShaderStream << fragementShaderF.rdbuf();

        vertexShaderF.close();
        fragementShaderF.close();

        vertexCode = vertexShaderStream.str();      // 转换成string类型
        fragmentCode = fragementShaderStream.str();
    }
    catch (std::ifstream::failure e)
    {
        std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ:" << std::endl;
    }

    const GLchar* pVertexCode = vertexCode.c_str(); // string 转 char*
    const GLchar* pFragementCode = fragmentCode.c_str();

    GLuint nVertexShader, nFragementShader;
    GLint nRes = 0;
    GLchar chLogInfo[512] = { '\0' };

    // 创建顶点着色器
    nVertexShader = glCreateShader(GL_VERTEX_SHADER);
    // 将顶点着色程序的源代码字符数组绑定到顶点着色器对象
    glShaderSource(nVertexShader, 1, &pVertexCode, nullptr);
    glCompileShader(nVertexShader); // compile shader 编译着色器

    // 获取编译结果
    glGetShaderiv(nVertexShader, GL_COMPILE_STATUS, &nRes);
    if (!nRes)
    {
        glGetShaderInfoLog(nVertexShader, 512, nullptr, chLogInfo);
        std::cout << "ERROR::SHADEF::VERTEX::COMPILATION_FAILED:" << chLogInfo << std::endl;
    }

    // 创建片断着色器
    nFragementShader = glCreateShader(GL_FRAGMENT_SHADER);
    // 将片段着色程序的源代码字符数组绑定到片段着色器对象
    glShaderSource(nFragementShader, 1, &pFragementCode, nullptr);
    glCompileShader(nFragementShader);
    glGetShaderiv(nFragementShader, GL_COMPILE_STATUS, &nRes);
    if (!nRes)
    {
        glGetShaderInfoLog(nFragementShader, 512, nullptr, chLogInfo);
        std::cout << "ERROR::SHADEF::FRAGEMENT::COMPILATION_FAILED:" << chLogInfo << std::endl;
    }

    this->m_nProgram = glCreateProgram();   // 创建GLSL程序
    glAttachShader(this->m_nProgram, nVertexShader);    // 绑定shader到program
    glAttachShader(this->m_nProgram, nFragementShader);

    // glLinkProgram操作产生最后的可执行程序,它包含最后可以在硬件上执行的硬件指令
    glLinkProgram(this->m_nProgram);        // 链接
    glGetProgramiv(this->m_nProgram, GL_LINK_STATUS, &nRes);
    if (!nRes)
    {
        glGetProgramInfoLog(this->m_nProgram, 512, nullptr, chLogInfo);
        std::cout << "ERROR::SHADEF::FRAGEMENT::LINK_FAILED:" << chLogInfo << std::endl;
    }

    glDeleteShader(nVertexShader);
    glDeleteShader(nFragementShader);
}

Shader::~Shader()
{
}

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

void Shader::useShaderPrograme()
{
    glUseProgram(this->m_nProgram); // 使用porgram
}

#endif




lamp_vertex.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);

}


lamp_fragement.fs

 // 灯泡片断着色器
#version 330 core
out vec4 color;

in vec3 IN_Normal;

void main()
{
    color = vec4(1.0f); // 灯泡为白色
}

obj_vertex.vs

// 箱子顶点着色器
#version 330 core

// 位置顶点 及 位置顶点的向量
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texCoords;        // 纹理坐标

out vec3 IN_ObjPos;     // 顶点位置
out vec3 IN_Normal;     // 法向量
out vec2 IN_TexCoords;  // 纹理

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
// 顶点变换到世界空间坐标 把顶点位置属性乘以模型矩阵
void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f); 

    IN_ObjPos = vec3(model * vec4(position, 1.0f));
    IN_Normal = mat3(transpose(inverse(model))) * normal;

    IN_TexCoords = texCoords;   // 纹理输出至片断着色器
}

obj_fragement.fs


// 箱子 片断着色器
#version 330 core

// 材质结构体  
struct Material  
{  
    sampler2D diffuse;   //  漫反射光照下物体的颜色  
    sampler2D specular;  // 物体受到的镜面光照的影响的颜色  
    float shininess;    // 高光的散射/半径  
}; 


struct DirLight {
    vec3 direction;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};


struct Light {
    vec3 position;      // 光源位置
    //vec3 direction;   

    vec3 ambient;       // 环境光
    vec3 diffuse;           // 漫反射光
    vec3 specular;      // 镜面光
                                // 计算衰减值
    float constant;     // 常数项Kc
    float linear;           // 一次项Kl
    float quadratic;        // 二次项KqKq

    //float cutOff;     //  内圆切光角
    //float outerCutOff;        // add 外圆切光角
};

in vec3 IN_ObjPos;      // 顶点位置
in vec3 IN_Normal;      // 法向量
in vec2 IN_TexCoords;   // 纹理

out vec4 color;  

#define NR_POINT_LIGHTS 4
uniform vec3 viewPos;
uniform DirLight dirLight;      // 
uniform Material material;
uniform Light lights[NR_POINT_LIGHTS];      // 光源数组


vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcPointLight(Light light, vec3 normal, vec3 fragPos, vec3 viewDir);

void main()
{
    vec3 normal = normalize(IN_Normal)  ;
    vec3 viewDir = normalize(viewPos - IN_ObjPos);

    vec3 result = CalcDirLight(dirLight, normal, viewDir);

    for(int i = 0; i< NR_POINT_LIGHTS; i++)
    {
        result += CalcPointLight(lights[i], normal, IN_ObjPos, viewDir);
    }

    color = vec4(result, 1.0);
}


vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
    vec3 lightDir = normalize(-light.direction);        // 光线方向

    float diff = max(dot(normal, lightDir), 0.0);
    vec3 reflectDir = reflect(-lightDir, normal);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);

    vec3 ambient = light.ambient * vec3(texture(material.diffuse, IN_TexCoords));// 环境光
    vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, IN_TexCoords));// 漫反射光
    vec3 specular = light.specular * spec * vec3(texture(material.specular, IN_TexCoords));// 镜面光

    return vec3(ambient + diffuse + specular);
}

vec3 CalcPointLight(Light light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
    vec3 lightDir = normalize(light.position - IN_ObjPos); // 光源和片段位置之间的方向向量
    float diff = max(dot(normal, lightDir), 0.0);   // 点乘, 来计算光对当前片段的实际的散射影响  大于90度, 点乘的结果就会变成负数, max 函数返回两个参数之间较大的参数, 从而保证散射因子不会变成负数。
    vec3 reflectDir = reflect(-lightDir, normal);  // 计算反射向量和视线方向的角度, 如果之间的角度越小, 那么镜面光的作用就会越大   
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);

    vec3 ambient = light.ambient * vec3(texture(material.diffuse, IN_TexCoords));// 环境光
    vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, IN_TexCoords));// 漫反射光
    vec3 specular = light.specular * spec * vec3(texture(material.specular, IN_TexCoords));// 镜面光

    float distance = length(light.position - IN_ObjPos);    // 光源到物体的距离
    float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * (distance * distance));    // 衰减因子

    ambient *= attenuation;     // 所有的光线都与衰减因子相乘
    diffuse *= attenuation;
    specular *= attenuation;

    return vec3(ambient + diffuse + specular);  // 最后的输出颜色。
}

这里写图片描述

源码下载: VS2015http://download.csdn.net/detail/yulinxx/9858107

猜你喜欢

转载自blog.csdn.net/yulinxx/article/details/72838217