OpenGL-- Shader 颜色 光照 4 光照贴图 柔光射灯

这里写图片描述

光照越远,衰减越厉害
衰减算法:
这里写图片描述

常数项通常是1.0,它的作用是保证分母永远不会比1小,因为它可以利用一定的距离增加亮度,这个结果不会影响到我们所寻找的。
一次项用于与距离值相乘,这会以线性的方式减少亮度。
二次项用于与距离的平方相乘,为光源设置一个亮度的二次递减。二次项在距离比较近的时候相比一次项会比一次项更小,但是当距离更远的时候比一次项更大。

柔光算法:
内圆亮度都是一样
内圆到外圆,逐渐变暗,即形成了柔和的光照边缘

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, "LightBase", 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", "./obj_fragement");
    Shader lampShader("./lamp_vertex", "./lamp_fragement");

    // 点数据
    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) };

    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 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); // 绑定灯泡的顶点数据进行操作
        {
            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);
}




Shader.h Camera.h 以及Shader等参照 http://blog.csdn.net/yulinxx/article/details/72720944

obj_fragement 稍有修改:


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

struct Material {
    sampler2D diffuse;
    sampler2D specular;
    float     shininess;
};  

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

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;  

uniform vec3 viewPos;
uniform Material material;
uniform Light light;

void main()
{

    // 环境光
    vec3 ambient = light.ambient * vec3(texture(material.diffuse, IN_TexCoords));

    // 漫反射 
    vec3 norm = normalize(IN_Normal);   // 标准化 只关心方向
    vec3 lightDir = normalize(light.position - IN_ObjPos); // 光源和片段位置之间的方向向量

    //vec3 lightDir = normalize(-light.direction);
    float diff = max(dot(norm, lightDir), 0.0); // 点乘, 来计算光对当前片段的实际的散射影响  大于90度, 点乘的结果就会变成负数, max 函数返回两个参数之间较大的参数, 从而保证散射因子不会变成负数。
    vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, IN_TexCoords));

    // 镜面光
    vec3 reflectDir = reflect(-lightDir, norm);  // 计算反射向量和视线方向的角度, 如果之间的角度越小, 那么镜面光的作用就会越大
    vec3 viewDir = normalize(viewPos - IN_ObjPos);  // 观察者世界空间位置(Viewer’s WorldSpace Position) 到片段的位置 的向量
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    vec3 specular = light.specular * spec * vec3(texture(material.specular, IN_TexCoords));

    // 柔边缘算法 Spotlight (soft edges)

    float theta = dot(lightDir, normalize(-light.direction));
    float epsilon = (light.cutOff - light.outerCutOff);     // 内外角之差 相差越大,
    float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);       // 把第一个参数固定在0.0和1.0之间

    diffuse  *= intensity;
    specular *= intensity;


    //vec3 specular = vec3(0.0, 0.0, 0.0);

    // Attenuation 衰减
    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;

    color = vec4(ambient + diffuse + specular, 1.0f);   // 最后的输出颜色。
}


源码下载:http://download.csdn.net/detail/yulinxx/9851470

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值