亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

OpenGL 視差貼圖 基礎 Parallax Mapping

2019-11-11 07:34:56
字體:
來源:轉載
供稿:網友

main.cpp

#include <string>#define GLEW_STATIC#include <GL/glew.h>#include <GLFW/glfw3.h>#include "shader.h"#include "Camera.h"#include "model.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();void RenderQuad();GLuint loadTexture(GLchar* path);Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));GLfloat deltaTime = 0.0f;GLfloat lastFrame = 0.0f;GLboolean parallax_mapping = true;GLfloat height_scale = 0.1;/*************************************************************************/int main(){ // Init GLFW 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, "OGLParallaxMapping", 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);#if 1 GLuint diffuseMap = loadTexture("./img/bricks2.jpg"); GLuint normalMap = loadTexture("./img/bricks2_normal.jpg"); GLuint heightMap = loadTexture("./img/bricks2_disp.jpg");#else GLuint diffuseMap = loadTexture("./img/toy_box_diffuse.png"); GLuint normalMap = loadTexture("./img/toy_box_normal.png"); GLuint heightMap = loadTexture("./img/toy_box_disp.png");#endif Shader shader("./Shader/parallax_mapping.vs", "./Shader/parallax_mapping.frag"); shader.useShaderPrograme(); glUniform1i(glGetUniformLocation(shader.getPrograme(), "diffuseMap"), 0); glUniform1i(glGetUniformLocation(shader.getPrograme(), "normalMap"), 1); glUniform1i(glGetUniformLocation(shader.getPrograme(), "depthMap"), 2); shader.useShaderPrograme(); glm::vec3 lightPos(0.5f, 1.0f, 0.3f); // 燈光位置 glm::mat4 view = camera.GetViewMatrix(); glm::mat4 projection = glm::perspective(camera.Zoom, (GLfloat)SCR_WIDTH / (GLfloat)SCR_HEIGHT, 0.1f, 100.0f); while (!glfwWindowShouldClose(pWnd)) { GLfloat currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; glfwPollEvents(); Do_Movement(); glClearColor(0.1f, 0.2f, 0.23f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "view"), 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "projection"), 1, GL_FALSE, glm::value_ptr(projection)); // 1 繪制旋轉中的物體 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]); glUniform1f(glGetUniformLocation(shader.getPrograme(), "height_scale"), height_scale); glUniform1i(glGetUniformLocation(shader.getPrograme(), "parallax"), parallax_mapping); glActiveTexture(GL_TEXTURE0); // 紋理0 glBindTexture(GL_TEXTURE_2D, diffuseMap); glActiveTexture(GL_TEXTURE1); // 紋理1 glBindTexture(GL_TEXTURE_2D, normalMap); glActiveTexture(GL_TEXTURE2); // 紋理2 glBindTexture(GL_TEXTURE_2D, heightMap); RenderQuad(); // 2 繪制小燈泡 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) { // positions 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); // texture coordinates 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; // - 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); // VAO { glGenBuffers(1, &quadVBO); // VBO glBindBuffer(GL_ARRAY_BUFFER, quadVBO); { glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(2); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(6 * sizeof(GLfloat))); glEnableVertexAttribArray(3); glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 14 * sizeof(GLfloat), (GLvoid*)(8 * sizeof(GLfloat))); glEnableVertexAttribArray(4); 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(){ 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); if (keys[GLFW_KEY_Q]) height_scale -= 0.001; else if (keys[GLFW_KEY_E]) height_scale += 0.001; if (keys[GLFW_KEY_SPACE] && !keysPressed[GLFW_KEY_SPACE]) { parallax_mapping = !parallax_mapping; keysPressed[GLFW_KEY_SPACE] = true; }}/*************************************************************************/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 +=0.5; if (direction == BACKWARD) this->Position -= 0.5; if (direction == LEFT) this->Position -= 0.5; if (direction == RIGHT) this->Position += 0.5; //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)); }};

mesh.h

#pragma once// 網格類:#include <string>#include <fstream>#include <sstream>#include <iostream>#include <vector>using namespace std;#include <GL/glew.h>#include <glm/glm.hpp>#include <glm/gtc/matrix_transform.hpp>#include "Shader.h"#pragma comment (lib, "assimp-vc140-mt.lib")// ********************************************************************//// 用來索引每個頂點屬性struct Vertex { glm::vec3 Position; glm::vec3 Normal; glm::vec2 TexCoords;};// ********************************************************************//// 儲存紋理的id和它的類型struct Texture { GLuint id; string type; aiString path;};// ********************************************************************//class Mesh {public: vector<Vertex> vertices; // 頂點 vector<GLuint> indices; // vector<Texture> textures; // 紋理 Mesh(vector<Vertex> vertices, vector<GLuint> indices, vector<Texture> textures) { this->vertices = vertices; this->indices = indices; this->textures = textures; this->setupMesh(); } void Draw(Shader shader) { // Bind appropriate textures GLuint diffuseNr = 1; GLuint specularNr = 1; for (GLuint i = 0; i < this->textures.size(); i++) { glActiveTexture(GL_TEXTURE0 + i); // 激活紋理 stringstream ss; string number; string name = this->textures[i].type; if (name == "texture_diffuse") ss << diffuseNr++; // Transfer GLuint to stream else if (name == "texture_specular") ss << specularNr++; // Transfer GLuint to stream number = ss.str(); // Now set the sampler to the correct texture unit glUniform1i(glGetUniformLocation(shader.getPrograme(), (name + number).c_str()), i); // And finally bind the texture glBindTexture(GL_TEXTURE_2D, this->textures[i].id); } // Also set each mesh's shininess property to a default value (if you want you could extend this to another mesh property and possibly change this value) glUniform1f(glGetUniformLocation(shader.getPrograme(), "material.shininess"), 16.0f); // Draw mesh glBindVertexArray(this->VAO); glDrawElements(GL_TRIANGLES, this->indices.size(), GL_UNSIGNED_INT, 0); glBindVertexArray(0); // Always good practice to set everything back to defaults once configured. for (GLuint i = 0; i < this->textures.size(); i++) { glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, 0); } }private: /* Render data */ GLuint VAO, VBO, EBO; // 初始化所有的頂點數據等 void setupMesh() { glGenVertexArrays(1, &this->VAO); glGenBuffers(1, &this->VBO); glGenBuffers(1, &this->EBO); glBindVertexArray(this->VAO); glBindBuffer(GL_ARRAY_BUFFER, this->VBO); // A great thing about structs is that their memory layout is sequential for all its items. // The effect is that we can simply pass a pointer to the struct and it translates perfectly to a glm::vec3/2 array which // again translates to 3/2 floats which translates to a byte array. glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(Vertex), &this->vertices[0], GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->indices.size() * sizeof(GLuint), &this->indices[0], GL_STATIC_DRAW); // 設置頂點坐標指針 glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)0); // 設置法線指針 glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Normal)); // 設置頂點的紋理坐標 glEnableVertexAttribArray(2); glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, TexCoords)); glBindVertexArray(0); }};// ********************************************************************//

Model.h

#pragma once// Std. Includes#include <string>#include <fstream>#include <sstream>#include <iostream>#include <map>#include <vector>using namespace std;// GL Includes#include <GL/glew.h> // Contains all the necessery OpenGL includes#include <glm/glm.hpp>#include <glm/gtc/matrix_transform.hpp>#include <SOIL/SOIL.h>#include <assimp/Importer.hpp>#include <assimp/scene.h>#include <assimp/postprocess.h>#include "Mesh.h"GLint TextureFromFile(const char* path, string directory);class Model{public: Model(GLchar* path) { this->loadModel(path); } void Draw(Shader shader) { for (GLuint i = 0; i < this->meshes.size(); i++) this->meshes[i].Draw(shader); }private: vector<Mesh> meshes; // 一個模型包含多個Mesh string directory; /* Functions */ // Loads a model with supported ASSIMP extensions from file and stores the resulting meshes in the meshes vector. // 加載模型 void loadModel(string path) { // Read file via ASSIMP Assimp::Importer importer; const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs); // Check for errors if (!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // if is Not Zero { cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << endl; return; } // Retrieve the directory path of the filepath this->directory = path.substr(0, path.find_last_of('/')); // Process ASSIMP's root node recursively this->processNode(scene->mRootNode, scene); } // Processes a node in a recursive fashion. Processes each individual mesh located at the node and repeats this process on its children nodes (if any). void processNode(aiNode* node, const aiScene* scene) { // Process each mesh located at the current node for (GLuint i = 0; i < node->mNumMeshes; i++) { // The node object only contains indices to index the actual objects in the scene. // The scene contains all the data, node is just to keep stuff organized (like relations between nodes). aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; this->meshes.push_back(this->processMesh(mesh, scene)); // 存儲Mesh } // After we've processed all of the meshes (if any) we then recursively process each of the children nodes for (GLuint i = 0; i < node->mNumChildren; i++) { this->processNode(node->mChildren[i], scene); } } Mesh processMesh(aiMesh* mesh, const aiScene* scene) { // Data to fill vector<Vertex> vertices; vector<GLuint> indices; vector<Texture> textures; // Walk through each of the mesh's vertices for (GLuint i = 0; i < mesh->mNumVertices; i++) { Vertex vertex; glm::vec3 vector; // We declare a placeholder vector since assimp uses its own vector class that doesn't directly convert to glm's vec3 class so we transfer the data to this placeholder glm::vec3 first. // Positions vector.x = mesh->mVertices[i].x; vector.y = mesh->mVertices[i].y; vector.z = mesh->mVertices[i].z; vertex.Position = vector; // Normals vector.x = mesh->mNormals[i].x; vector.y = mesh->mNormals[i].y; vector.z = mesh->mNormals[i].z; vertex.Normal = vector; // Texture Coordinates if (mesh->mTextureCoords[0]) // Does the mesh contain texture coordinates? { glm::vec2 vec; // A vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't // use models where a vertex can have multiple texture coordinates so we always take the first set (0). vec.x = mesh->mTextureCoords[0][i].x; vec.y = mesh->mTextureCoords[0][i].y; vertex.TexCoords = vec; } else vertex.TexCoords = glm::vec2(0.0f, 0.0f); vertices.push_back(vertex); } // Now wak through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices. for (GLuint i = 0; i < mesh->mNumFaces; i++) { aiFace face = mesh->mFaces[i]; // Retrieve all indices of the face and store them in the indices vector for (GLuint j = 0; j < face.mNumIndices; j++) indices.push_back(face.mIndices[j]); } // Process materials if (mesh->mMaterialIndex >= 0) { aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex]; // We assume a convention for sampler names in the shaders. Each diffuse texture should be named // as 'texture_diffuseN' where N is a sequential number ranging from 1 to MAX_SAMPLER_NUMBER. // Same applies to other texture as the following list summarizes: // Diffuse: texture_diffuseN // Specular: texture_specularN // Normal: texture_normalN // 1. Diffuse maps vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse"); textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end()); // 2. Specular maps vector<Texture> specularMaps = this->loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular"); textures.insert(textures.end(), specularMaps.begin(), specularMaps.end()); } // Return a mesh object created from the extracted mesh data return Mesh(vertices, indices, textures); } // Checks all material textures of a given type and loads the textures if they're not loaded yet. // The required info is returned as a Texture struct. vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName) { vector<Texture> textures; for (GLuint i = 0; i < mat->GetTextureCount(type); i++) { aiString str; mat->GetTexture(type, i, &str); // Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture Texture texture; texture.id = TextureFromFile(str.C_Str(), this->directory); texture.type = typeName; texture.path = str; textures.push_back(texture); } return textures; }};GLint TextureFromFile(const char* path, string directory){ //Generate texture ID and load texture data string filename = string(path); filename = directory + '/' + filename; GLuint textureID; glGenTextures(1, &textureID); int width, height; unsigned char* image = SOIL_load_image(filename.c_str(), &width, &height, 0, SOIL_LOAD_RGB); // Assign texture to ID 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); // Parameters 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;}

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

OpenGL Shader 部分 GLSL

頂點著色器 parallax_mapping.vs

#version 330 corelayout (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; vec3 T = normalize(mat3(model) * tangent); vec3 B = normalize(mat3(model) * bitangent); vec3 N = normalize(mat3(model) * 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;}

片斷著色器 parallax_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 sampler2D depthMap;uniform bool parallax;uniform float height_scale;vec2 ParallaxMapping(vec2 texCoords, vec3 viewDir){ float height = texture(depthMap, texCoords).r; return texCoords - viewDir.xy / viewDir.z * (height * height_scale); }void main(){ // Offset texture coordinates with Parallax Mapping vec3 viewDir = normalize(fs_in.TangentViewPos - fs_in.TangentFragPos); vec2 texCoords = fs_in.TexCoords; if(parallax) texCoords = ParallaxMapping(fs_in.TexCoords, viewDir); // Obtain normal from normal map vec3 normal = texture(normalMap, texCoords).rgb; normal = normalize(normal * 2.0 - 1.0); // Get diffuse color vec3 color = texture(diffuseMap, 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 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/9747841


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产69精品99久久久久久宅男| 欧美色道久久88综合亚洲精品| 亚洲第一视频网| 欧美高跟鞋交xxxxxhd| 91久久综合亚洲鲁鲁五月天| 97国产精品免费视频| 欧美精品18videos性欧美| 日本中文字幕久久看| 亚洲天堂av网| 91极品女神在线| 久久资源免费视频| 日韩av在线免费播放| 欧美激情一区二区三级高清视频| 岛国av一区二区在线在线观看| 亚洲高清免费观看高清完整版| 亚洲欧美日本另类| 不卡毛片在线看| 久久精品视频中文字幕| 国产香蕉精品视频一区二区三区| 亚洲一区www| 欧美日韩国产一区在线| 国产精品福利在线观看| 日韩精品免费在线观看| 成人观看高清在线观看免费| 国产精品久久久久久亚洲影视| 韩国一区二区电影| 福利视频导航一区| 久热在线中文字幕色999舞| 91色精品视频在线| 日韩风俗一区 二区| 国产福利视频一区二区| 最新国产精品拍自在线播放| 久久久久久久激情视频| 日韩视频永久免费观看| 欧美成人午夜影院| 成人a在线视频| 国产精品入口夜色视频大尺度| 日韩精品极品视频| 91在线精品播放| 日韩欧美999| 欧美在线视频免费观看| 一区二区三区天堂av| 久久久av网站| 国产91精品在线播放| 国产精品v片在线观看不卡| 亚洲国产成人在线视频| 亚洲视频第一页| 亚洲男人天堂手机在线| 亚洲在线观看视频| 国产精品极品美女粉嫩高清在线| 欧美精品九九久久| 成人h片在线播放免费网站| 亚州成人av在线| 亚洲天堂网在线观看| 性欧美暴力猛交69hd| 91亚洲精品在线观看| 国产精品中文久久久久久久| 久久久在线免费观看| 欧美一区二区大胆人体摄影专业网站| 亚洲激情在线视频| 国产成人一区二区三区电影| 九九精品在线播放| 欧美精品久久久久久久免费观看| 国产精品自产拍在线观看中文| 久久免费福利视频| 国产精品久久久久久婷婷天堂| 国产精品a久久久久久| 亚洲成人精品久久| 国内外成人免费激情在线视频| 国产在线观看精品一区二区三区| 国产免费一区二区三区在线观看| 91精品久久久久| 欧美日韩另类字幕中文| 性视频1819p久久| 亚洲免费电影在线观看| 91精品国产综合久久香蕉的用户体验| 精品视频9999| 精品国产乱码久久久久酒店| 久久久久国色av免费观看性色| 日韩在线免费视频观看| 欧美中文字幕视频| 色播久久人人爽人人爽人人片视av| 久久免费精品视频| 亚洲国产天堂久久综合网| 国产丝袜精品第一页| 久久久国产精品一区| 亚洲成人网久久久| 久久国产天堂福利天堂| 日韩经典一区二区三区| 久久资源免费视频| 亚洲精品视频网上网址在线观看| 5278欧美一区二区三区| 欧美自拍大量在线观看| 国产精品爽爽爽爽爽爽在线观看| 91精品成人久久| 亚洲大胆人体av| 中文字幕亚洲色图| 成人免费视频a| 日韩在线视频二区| 国产精品一区=区| 性欧美办公室18xxxxhd| 久久精品成人欧美大片古装| 久久久久久噜噜噜久久久精品| 国产精品丝袜久久久久久高清| 国产一区视频在线| 国产精品久久97| 亚洲第一网中文字幕| 欧美丰满少妇xxxxx| 国产一区二区激情| 日韩精品视频在线播放| 91在线|亚洲| 国产精品久久久久久av福利| 久久不射热爱视频精品| 精品一区电影国产| 亚洲www永久成人夜色| 日本一区二区在线播放| 亚州欧美日韩中文视频| 欧美激情在线一区| 97精品一区二区视频在线观看| 亚洲精品午夜精品| 米奇精品一区二区三区在线观看| 三级精品视频久久久久| 欧美激情第一页xxx| 日本不卡高字幕在线2019| 欧美成人免费va影院高清| 久久国产精品99国产精| 欧美成人免费在线观看| 九九久久综合网站| 国产精品精品久久久| 日韩中文字幕在线免费观看| 日韩精品极品视频| 欧美体内谢she精2性欧美| 国精产品一区一区三区有限在线| 欧日韩不卡在线视频| 日韩av电影免费观看高清| 国产91精品高潮白浆喷水| yw.139尤物在线精品视频| 亚洲精品456在线播放狼人| 国产日韩在线免费| 6080yy精品一区二区三区| 中文字幕最新精品| 欧美中文字幕第一页| www.欧美免费| 国产精欧美一区二区三区| 国产精品人人做人人爽| 中文字幕av一区二区三区谷原希美| 91久久久久久久久| 精品丝袜一区二区三区| 欧美日韩免费在线观看| 国产精品1区2区在线观看| 欧美激情喷水视频| 国产精品入口福利| 欧美日韩在线第一页| 97在线观看视频| 欧美性猛交xxxx免费看漫画| 欧美一区二区影院| 日韩欧美国产黄色| 亚洲国模精品私拍| 国产精品扒开腿做爽爽爽视频| 亚洲国产成人爱av在线播放| 国产精品日韩专区| 欧美日韩成人在线播放| 九九久久精品一区| 国产一区二区香蕉|