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

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

OpenGL 視差貼圖 基礎 Parallax Mapping

2019-11-11 05:36:29
字體:
來源:轉載
供稿:網友

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
亚洲综合一区二区不卡| 97在线日本国产| 亚洲成年网站在线观看| 中文字幕亚洲无线码a| 国产一区二区日韩精品欧美精品| 欧美色图在线视频| 久久久久国产精品免费| 欧美成人午夜剧场免费观看| 中文字幕欧美国内| 久久久久久久久久久久久久久久久久av| 国产在线视频欧美| 久久久av网站| 久久99精品国产99久久6尤物| 久99九色视频在线观看| 欧美大肥婆大肥bbbbb| 日韩精品高清视频| 色99之美女主播在线视频| 精品国产欧美一区二区五十路| 欧美香蕉大胸在线视频观看| 欧美日韩国产精品| 亚洲a中文字幕| 视频一区视频二区国产精品| 成人免费淫片aa视频免费| 日韩av在线最新| 久久久精品亚洲| 日韩av资源在线播放| 欧美xxxx14xxxxx性爽| 亚洲va码欧洲m码| 国产精品视频999| 久久久久久久一区二区三区| 日本老师69xxx| 亚洲成人亚洲激情| 成人免费自拍视频| 欧美成人午夜视频| 国产精品18久久久久久首页狼| 日韩在线观看免费| 欧美激情二区三区| 久久久亚洲国产天美传媒修理工| 亚洲国产天堂久久综合网| 黑人巨大精品欧美一区二区免费| 福利视频一区二区| 久久99亚洲热视| 91嫩草在线视频| 日韩电影免费观看中文字幕| 日韩av在线导航| 热门国产精品亚洲第一区在线| 亚洲国产天堂久久综合| 亚洲午夜av电影| 国产精品777| 色香阁99久久精品久久久| 91网站免费看| 国产精品久久久久9999| 97久久精品国产| 中文字幕在线观看日韩| 一区二区三区在线播放欧美| 午夜精品福利视频| 中文字幕一区二区精品| 亚洲天堂av在线播放| 国产精品99久久久久久www| 91在线无精精品一区二区| 亚洲一区制服诱惑| 大胆欧美人体视频| 国产精品第三页| 国产亚洲精品91在线| 国产成人一区二区三区电影| 都市激情亚洲色图| 国产精品视频久| 久久99青青精品免费观看| 日韩女优人人人人射在线视频| 久久精品成人动漫| 国产日韩在线看| 久久久av免费| 黑人巨大精品欧美一区二区免费| 国产精品www色诱视频| 亚洲欧洲在线播放| 国产一区二区欧美日韩| 亚洲一级片在线看| 国产精品日韩在线| 欧美中文在线观看国产| 久久亚洲影音av资源网| 欧美日韩精品在线观看| 亚洲欧洲日产国码av系列天堂| www.欧美精品| 国产91在线播放精品91| 亚洲一区美女视频在线观看免费| 亚洲成av人片在线观看香蕉| 国产精品欧美一区二区| 精品视频中文字幕| 久久久噜久噜久久综合| 国产精品美女999| 亚洲欧美成人在线| 日韩成人av在线播放| 国产精品吹潮在线观看| 欧美中文字幕第一页| 精品亚洲夜色av98在线观看| 国产91精品最新在线播放| 97在线精品国自产拍中文| 欧美猛交ⅹxxx乱大交视频| 国产在线98福利播放视频| 久久综合免费视频影院| 最近中文字幕mv在线一区二区三区四区| 热99久久精品| 国产精品视频久久久| 日韩免费高清在线观看| xxx欧美精品| 黑人巨大精品欧美一区二区三区| 亚洲日本中文字幕| 精品人伦一区二区三区蜜桃免费| 欧美色欧美亚洲高清在线视频| 亚洲欧美视频在线| 91网在线免费观看| 福利视频第一区| 成人免费视频a| 国产欧美久久久久久| 国产91精品不卡视频| 精品久久久一区| 成人xxxx视频| 91在线免费视频| 精品国产一区二区三区久久狼黑人| 亚洲第一区在线观看| 成人疯狂猛交xxx| 欧美日韩国产一区在线| 尤物九九久久国产精品的特点| 国产精品久久在线观看| 日本欧美一级片| 国产91久久婷婷一区二区| 日韩亚洲欧美中文在线| 热门国产精品亚洲第一区在线| 国产日韩欧美电影在线观看| 国产精品嫩草视频| 亚洲第一黄色网| 中文字幕日韩专区| 欧美日韩亚洲网| 国产97在线亚洲| 日韩av在线一区| 国产精品久久久久aaaa九色| 91大神在线播放精品| 国产日韩精品在线| 亚洲色图第三页| 91欧美日韩一区| 俺去啦;欧美日韩| 久久国产精品久久久久久| 国产精品久久久久久久app| 亚洲天堂免费观看| 这里只有精品丝袜| 欧美国产视频一区二区| 亲爱的老师9免费观看全集电视剧| 欧美电影在线播放| 久久久精品视频在线观看| 久久久久久尹人网香蕉| 成人网在线免费看| 久久99精品视频一区97| 欧美精品久久久久久久久| 久久91亚洲人成电影网站| 欧美日韩日本国产| 欧美激情视频播放| 欧美国产日本在线| 91亚洲精品久久久| 91国产美女在线观看| 国产丝袜一区二区| 91色在线视频| 精品视频在线导航| 日韩精品免费看| 亚洲综合大片69999|