OpenGL 法线贴图 基础

来源:互联网 发布:java判断字符串不相等 编辑:程序博客网 时间:2024/04/30 10:53

法线贴图

http://learnopengl-cn.readthedocs.io/zh/latest/05%20Advanced%20Lighting/04%20Normal%20Mapping/

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>#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")#pragma comment (lib, "assimp.lib")const GLuint SCR_WIDTH = 800, SCR_HEIGHT = 600;void key_callback(GLFWwindow* pWnd, int key, int scancode, int action, int mode);void scroll_callback(GLFWwindow* pWnd, double xoffset, double yoffset);void mouse_callback(GLFWwindow* pWnd, double xpos, double ypos);void Do_Movement();GLuint loadTexture(GLchar* path);void RenderQuad();Camera camera(glm::vec3(0.0f, 0.0f, 3.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(SCR_WIDTH, SCR_HEIGHT, "OGL Mapping", 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, SCR_WIDTH, SCR_HEIGHT);    glEnable(GL_DEPTH_TEST);    Shader shader("./Shader/normal_mapping.vs", "./Shader/normal_mapping.frag");    GLuint diffuseMap = loadTexture("./resource/brickwall.jpg");    // 漫反射贴图    GLuint normalMap = loadTexture("./resource/brickwall_normal.jpg");  // 法线贴图    shader.useShaderPrograme();    glUniform1i(glGetUniformLocation(shader.getPrograme(), "diffuseMap"), 0);    glUniform1i(glGetUniformLocation(shader.getPrograme(), "normalMap"), 1);    glm::vec3 lightPos(0.5f, 1.0f, 0.3f);    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);        shader.useShaderPrograme();        glm::mat4 view = camera.GetViewMatrix();        glm::mat4 projection = glm::perspective(camera.Zoom, (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);        glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "view"), 1, GL_FALSE, glm::value_ptr(view));        glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));        glm::mat4 model;        model = glm::rotate(model, (GLfloat)glfwGetTime() * 1, glm::normalize(glm::vec3(1.0, 0.0, 1.0)));   // 旋转动画        glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "model"), 1, GL_FALSE, glm::value_ptr(model));        glUniform3fv(glGetUniformLocation(shader.getPrograme(), "lightPos"), 1, &lightPos[0]);        glUniform3fv(glGetUniformLocation(shader.getPrograme(), "viewPos"), 1, &camera.Position[0]);        // 砖墙纹理        glActiveTexture(GL_TEXTURE0);        glBindTexture(GL_TEXTURE_2D, diffuseMap);        // 法线贴图反射光        glActiveTexture(GL_TEXTURE1);        glBindTexture(GL_TEXTURE_2D, normalMap);        RenderQuad();   // 绘制砖墙        model = glm::mat4();        model = glm::translate(model, lightPos);        model = glm::scale(model, glm::vec3(0.1f));        glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "model"), 1, GL_FALSE, glm::value_ptr(model));        //RenderQuad(); // 立方体 当作灯泡        glfwSwapBuffers(pWnd);    }    glfwTerminate();    return 0;}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////GLuint quadVAO = 0;GLuint quadVBO;void RenderQuad(){    if (quadVAO == 0)    {        // 位置        glm::vec3 pos1(-1.0, 1.0, 0.0);     glm::vec3 pos2(-1.0, -1.0, 0.0);        glm::vec3 pos3(1.0, -1.0, 0.0);     glm::vec3 pos4(1.0, 1.0, 0.0);        // 纹理坐标        glm::vec2 uv1(0.0, 1.0);        glm::vec2 uv2(0.0, 0.0);        glm::vec2 uv3(1.0, 0.0);        glm::vec2 uv4(1.0, 1.0);        // 向量 normal vector        glm::vec3 nm(0.0, 0.0, 1.0);        // calculate tangent/bitangent vectors of both triangles        // 切线        glm::vec3 tangent1, bitangent1;        glm::vec3 tangent2, bitangent2;        // 先计算第一个三角形的边和deltaUV坐标   - triangle 1         glm::vec3 edge1 = pos2 - pos1;        glm::vec3 edge2 = pos3 - pos1;        glm::vec2 deltaUV1 = uv2 - uv1;        glm::vec2 deltaUV2 = uv3 - uv1;        // 根据公式进行计算        GLfloat f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);        tangent1.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);        tangent1.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);        tangent1.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);        tangent1 = glm::normalize(tangent1);    // 进行标准化        bitangent1.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);        bitangent1.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);        bitangent1.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);        bitangent1 = glm::normalize(bitangent1);        // - triangle 2        edge1 = pos3 - pos1;        edge2 = pos4 - pos1;        deltaUV1 = uv3 - uv1;        deltaUV2 = uv4 - uv1;        f = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV2.x * deltaUV1.y);        tangent2.x = f * (deltaUV2.y * edge1.x - deltaUV1.y * edge2.x);        tangent2.y = f * (deltaUV2.y * edge1.y - deltaUV1.y * edge2.y);        tangent2.z = f * (deltaUV2.y * edge1.z - deltaUV1.y * edge2.z);        tangent2 = glm::normalize(tangent2);        bitangent2.x = f * (-deltaUV2.x * edge1.x + deltaUV1.x * edge2.x);        bitangent2.y = f * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y);        bitangent2.z = f * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z);        bitangent2 = glm::normalize(bitangent2);        GLfloat quadVertices[] = {            // Positions            // normal         // TexCoords  // Tangent                          // Bitangent            pos1.x, pos1.y, pos1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,            pos2.x, pos2.y, pos2.z, nm.x, nm.y, nm.z, uv2.x, uv2.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,            pos3.x, pos3.y, pos3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, tangent1.x, tangent1.y, tangent1.z, bitangent1.x, bitangent1.y, bitangent1.z,            pos1.x, pos1.y, pos1.z, nm.x, nm.y, nm.z, uv1.x, uv1.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z,            pos3.x, pos3.y, pos3.z, nm.x, nm.y, nm.z, uv3.x, uv3.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z,            pos4.x, pos4.y, pos4.z, nm.x, nm.y, nm.z, uv4.x, uv4.y, tangent2.x, tangent2.y, tangent2.z, bitangent2.x, bitangent2.y, bitangent2.z        };        // 平面        glGenVertexArrays(1, &quadVAO);        glBindVertexArray(quadVAO);        {            glGenBuffers(1, &quadVBO);            glBindBuffer(GL_ARRAY_BUFFER, quadVBO);            {                glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW);                glEnableVertexAttribArray(0);       // 对应vs的 position                glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)0);                glEnableVertexAttribArray(1);       // 对应vs的 normal                glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));                glEnableVertexAttribArray(2);       // 对应vs的 texCoords                glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat)));                glEnableVertexAttribArray(3);       // 对应vs的 tangent                glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(8 * sizeof(GLfloat)));                glEnableVertexAttribArray(4);       // 对应vs的 bitangent                glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(11 * sizeof(GLfloat)));            }            glBindBuffer(GL_ARRAY_BUFFER, 0);        }        glBindVertexArray(0);    }    glBindVertexArray(quadVAO);    glDrawArrays(GL_TRIANGLES, 0, 6);    glBindVertexArray(0);}GLuint loadTexture(GLchar* path){    GLuint textureID;    glGenTextures(1, &textureID);    int width, height;    unsigned char* image = SOIL_load_image(path, &width, &height, 0, SOIL_LOAD_RGB);    glBindTexture(GL_TEXTURE_2D, textureID);    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);    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_LINEAR);    glBindTexture(GL_TEXTURE_2D, 0);    SOIL_free_image_data(image);    return textureID;}bool keys[1024];bool keysPressed[1024];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);}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;            keysPressed[key] = false;        }    }}GLfloat lastX = 400, lastY = 300;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 valuesconst 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

GLSL Shader 部分

normal_mapping.vs

#version 330 core// 先将前面计算出来的切线和副切线向量传给顶点着色器layout (location = 0) in vec3 position;layout (location = 1) in vec3 normal;layout (location = 2) in vec2 texCoords;layout (location = 3) in vec3 tangent;layout (location = 4) in vec3 bitangent;out VS_OUT {    vec3 FragPos;    vec2 TexCoords;    vec3 TangentLightPos;    vec3 TangentViewPos;    vec3 TangentFragPos;} vs_out;uniform mat4 projection;uniform mat4 view;uniform mat4 model;uniform vec3 lightPos;uniform vec3 viewPos;void main(){    gl_Position = projection * view * model * vec4(position, 1.0f);    vs_out.FragPos = vec3(model * vec4(position, 1.0));       vs_out.TexCoords = texCoords;    // 创建TBN矩阵    mat3 normalMatrix = transpose(inverse(mat3(model)));    vec3 T = normalize(normalMatrix * tangent);    vec3 B = normalize(normalMatrix * bitangent);    vec3 N = normalize(normalMatrix * normal);        mat3 TBN = transpose(mat3(T, B, N));      vs_out.TangentLightPos = TBN * lightPos;    vs_out.TangentViewPos  = TBN * viewPos;    vs_out.TangentFragPos  = TBN * vs_out.FragPos;}

normal_mapping.frag

#version 330 coreout vec4 FragColor;in VS_OUT {    vec3 FragPos;    vec2 TexCoords;    vec3 TangentLightPos;    vec3 TangentViewPos;    vec3 TangentFragPos;} fs_in;uniform sampler2D diffuseMap;uniform sampler2D normalMap;uniform bool normalMapping;void main(){               // Obtain normal from normal map in range [0,1]    vec3 normal = texture(normalMap, fs_in.TexCoords).rgb;    // Transform normal vector to range [-1,1]    normal = normalize(normal * 2.0 - 1.0);  // this normal is in tangent space    // Get diffuse color    vec3 color = texture(diffuseMap, fs_in.TexCoords).rgb;    // Ambient    vec3 ambient = 0.1 * color;    // Diffuse    vec3 lightDir = normalize(fs_in.TangentLightPos - fs_in.TangentFragPos);    float diff = max(dot(lightDir, normal), 0.0);    vec3 diffuse = diff * color;    // Specular    vec3 viewDir = normalize(fs_in.TangentViewPos - fs_in.TangentFragPos);    vec3 reflectDir = reflect(-lightDir, normal);    vec3 halfwayDir = normalize(lightDir + viewDir);      float spec = pow(max(dot(normal, halfwayDir), 0.0), 32.0);    vec3 specular = vec3(0.2) * spec;    FragColor = vec4(ambient + diffuse + specular, 1.0f);}

这里写图片描述

这里写图片描述

这里写图片描述

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

0 0
原创粉丝点击