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

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

OpenGL 視差貼圖 基礎 Parallax Mapping

2019-11-11 06:10:49
字體:
來源:轉載
供稿:網友

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
国产激情久久久| 日韩免费观看高清| 国内外成人免费激情在线视频| 亚洲mm色国产网站| 日韩国产高清污视频在线观看| 欧美精品在线第一页| 久久久免费精品视频| 久久久久久美女| 日韩国产高清视频在线| 国产成人精品免费久久久久| 久久久久久久激情视频| 国产日韩在线亚洲字幕中文| 欧美激情精品久久久久久黑人| 欧美午夜影院在线视频| 夜夜躁日日躁狠狠久久88av| 日韩中文字幕视频在线观看| 国产精品揄拍500视频| 国产在线视频2019最新视频| 亚洲视频专区在线| 欧美夫妻性生活xx| 欧美做受高潮电影o| 国内精品久久久久久久久| 精品国产一区二区三区四区在线观看| 国产亚洲欧美aaaa| 亚洲欧美精品一区二区| 欧美日韩国产色视频| 国产一区二区三区在线视频| 美女av一区二区三区| 欧美一区二区三区图| 欧美一级大片在线免费观看| 国产裸体写真av一区二区| 日韩欧美一区二区三区| 国产婷婷97碰碰久久人人蜜臀| 日韩精品免费在线| 最新国产精品亚洲| 国产日本欧美一区二区三区| 国产综合久久久久久| 日韩在线视频线视频免费网站| 亚洲电影免费观看高清完整版在线| 亚洲精品wwww| 久久久久久网站| 欧美性一区二区三区| 国产精品日本精品| 综合av色偷偷网| 久久影院中文字幕| 日韩va亚洲va欧洲va国产| 亚洲天堂成人在线视频| 欧美国产日韩在线| 国产精品视频午夜| 亚洲字幕在线观看| 91视频-88av| 亚洲成人动漫在线播放| 97在线看免费观看视频在线观看| 国产97在线亚洲| 欧美在线视频导航| 成人亚洲激情网| 亚洲人精品午夜在线观看| 日韩视频―中文字幕| 国产一区二区黄| 国产成人激情视频| 国产日韩av在线播放| 国产精品天天狠天天看| 在线观看国产精品91| 久久久久久久91| 精品成人在线视频| 欧美诱惑福利视频| 欧美激情亚洲激情| 久久精品国产一区二区三区| 亚洲精品福利视频| 国产日韩在线观看av| 国产精品久久久久久一区二区| 欧美黄网免费在线观看| 亚洲自拍小视频| 在线观看欧美日韩| 久久精品国产清自在天天线| 亚洲免费小视频| 91po在线观看91精品国产性色| 欧美丝袜一区二区三区| 欧美极品xxxx| 久久影视电视剧免费网站清宫辞电视| 国产一区二区三区18| 国产精品高潮呻吟久久av野狼| 亚洲一区二区三区香蕉| 国产精品av免费在线观看| 国产亚洲精品高潮| 国产一区二区日韩| 国产精品久久久久久av福利软件| 国产情人节一区| 亚洲一区二区三区四区视频| 中文字幕欧美日韩精品| 日韩欧美在线视频观看| 国产精品久久久精品| 亚洲春色另类小说| 国产精品人成电影在线观看| 久久久久久91香蕉国产| 国产精品丝袜一区二区三区| 日韩视频免费观看| 日韩电影大片中文字幕| 亚洲精品国产精品国产自| 亚洲欧美综合区自拍另类| 色悠悠国产精品| 日韩毛片中文字幕| 久久精品国产v日韩v亚洲| 国产一区二区三区欧美| 日韩欧美在线观看| 欧美丰满老妇厨房牲生活| 成人福利网站在线观看11| 日韩av影视综合网| 国产精品日韩av| 国产不卡视频在线| 亚洲精品电影在线| 国产精品美乳一区二区免费| 久久久久中文字幕| 国产精品综合不卡av| 成人性生交大片免费观看嘿嘿视频| 亚洲人成啪啪网站| 日韩激情视频在线播放| 亚洲区免费影片| 狠狠色狠狠色综合日日小说| 国产精品美女在线| 亚洲综合在线小说| 国产精品美女免费看| 国内精品一区二区三区四区| 久久久人成影片一区二区三区观看| 96精品久久久久中文字幕| 久久久成人精品视频| 人九九综合九九宗合| 国产手机视频精品| 欧美亚洲另类在线| 国产亚洲成av人片在线观看桃| 亚洲国产天堂久久综合| 欧美成人剧情片在线观看| 欧美一区二区大胆人体摄影专业网站| 欧美日韩国产一中文字不卡| 亚洲一区亚洲二区| 亚洲一区二区三区四区视频| 中文精品99久久国产香蕉| 国产精品99免视看9| 91国偷自产一区二区三区的观看方式| 国产精品白嫩美女在线观看| 国内免费精品永久在线视频| 欧美激情亚洲精品| 色阁综合伊人av| 98午夜经典影视| 91精品啪aⅴ在线观看国产| 欧美在线激情网| 欧美另类高清videos| 亚洲一区二区在线| 国产精品视频26uuu| 91精品国产九九九久久久亚洲| 欧美大成色www永久网站婷| 国产午夜精品理论片a级探花| 久久精品夜夜夜夜夜久久| 成人久久久久久久| 亚洲男人天堂视频| 久久久久久久久久久免费精品| 欧美小视频在线| 成人国内精品久久久久一区| 91久久在线视频| 国产亚洲精品久久久久动| 一区二区欧美在线| 国产精品第三页| 奇米4444一区二区三区| 亚洲欧美综合区自拍另类|