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

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

OpenGL 視差貼圖 基礎 Parallax Mapping

2019-11-11 06:13:55
字體:
來源:轉載
供稿:網友

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久久精品人人澡人人爽缅北| 国产欧美日韩最新| 91社区国产高清| 亚洲深夜福利网站| 欧美黑人xxxⅹ高潮交| 国产美女久久精品| 国产美女直播视频一区| 欧美一级在线播放| 国产精品扒开腿做爽爽爽的视频| 亚洲97在线观看| 亚洲伊人成综合成人网| 欧美中文在线免费| 亚洲欧美激情视频| 一本大道香蕉久在线播放29| 精品久久久久久久久久| 欧美精品成人在线| 色视频www在线播放国产成人| 国产日韩在线看片| 国语自产精品视频在线看| 最好看的2019的中文字幕视频| 日韩欧美a级成人黄色| 色噜噜狠狠狠综合曰曰曰| 亚洲自拍偷拍色图| 97精品视频在线| 欧美亚洲国产成人精品| 在线观看欧美视频| 日本精品视频在线播放| 在线视频免费一区二区| 法国裸体一区二区| 亚洲伊人久久大香线蕉av| 538国产精品一区二区免费视频| 国产一区二区三区在线观看网站| 国产日韩av在线| 91色琪琪电影亚洲精品久久| 国产日韩精品视频| 国产自摸综合网| 亚洲欧美三级伦理| 国产精品免费一区二区三区都可以| 亚洲欧美第一页| 国产精品扒开腿做爽爽爽的视频| 最好看的2019年中文视频| 黑人巨大精品欧美一区二区三区| 久久久综合免费视频| 久久久久久久香蕉网| 欧美日韩亚洲系列| 国产精品久久久久久久久久尿| 狠狠躁夜夜躁人人爽超碰91| 欧美激情精品久久久久| 中文字幕精品av| 日韩精品高清视频| 久久久国产一区二区| 国产成人av在线播放| 亚洲午夜性刺激影院| 精品日韩美女的视频高清| 久久成人在线视频| 久久亚洲精品国产亚洲老地址| 国产精品福利小视频| 性视频1819p久久| 国产啪精品视频| 久久香蕉国产线看观看av| 欧美激情精品久久久久| 久久九九精品99国产精品| 中文字幕久热精品视频在线| 亚洲精选在线观看| 免费av在线一区| 久久99国产精品久久久久久久久| 日韩av高清不卡| 亚洲国产精品小视频| 国产极品jizzhd欧美| 成人h视频在线观看播放| 国产美女91呻吟求| 久久全国免费视频| 精品中文字幕久久久久久| 亚洲男人的天堂网站| 国内精久久久久久久久久人| 欧美日韩亚洲高清| 欧美主播福利视频| 国产亚洲欧洲黄色| 久久免费观看视频| 国产91对白在线播放| 91网站在线看| 97碰在线观看| 日韩国产欧美精品在线| 久久综合国产精品台湾中文娱乐网| 日韩中文在线不卡| 国产精品丝袜久久久久久高清| 欧美激情欧美狂野欧美精品| 91超碰caoporn97人人| 国产精品欧美日韩久久| 国产精品香蕉国产| 日韩欧美中文字幕在线观看| 97视频在线观看网址| 欧美性20hd另类| 2020久久国产精品| 亚洲天堂一区二区三区| 欧美视频免费在线观看| 98视频在线噜噜噜国产| 国产精品入口免费视| 亚洲精品国产拍免费91在线| 日本成人黄色片| 4p变态网欧美系列| 色午夜这里只有精品| 欧美性生交xxxxx久久久| 97免费视频在线播放| 国产成人av在线播放| 黄网站色欧美视频| 欧美午夜精品久久久久久人妖| 97香蕉久久超级碰碰高清版| 久久全球大尺度高清视频| 8x海外华人永久免费日韩内陆视频| 97在线观看免费高清| 奇米成人av国产一区二区三区| 九九热最新视频//这里只有精品| 色妞久久福利网| 国产精品久久久久久久久久久久久| 国产精品成人播放| 欧美大片va欧美在线播放| 久久成人这里只有精品| 久久精品色欧美aⅴ一区二区| 色av中文字幕一区| 久久久久久亚洲精品| 久久亚洲精品国产亚洲老地址| 欧美怡红院视频一区二区三区| 欧美大奶子在线| 久久精品电影网| 韩国三级电影久久久久久| 精品久久久久久中文字幕大豆网| 午夜精品三级视频福利| 久久精品最新地址| 久久资源免费视频| 国产精品一区二区久久国产| 国产精品视频大全| 欧美精品中文字幕一区| 成人av在线天堂| 色综合久久精品亚洲国产| 成人精品一区二区三区电影免费| 疯狂蹂躏欧美一区二区精品| 91在线视频免费| 日韩在线视频免费观看| 国产精品白丝av嫩草影院| 久久精品久久精品亚洲人| 日韩成人xxxx| 国产69久久精品成人看| 国产精品入口免费视| 国产视频福利一区| 国产精品自产拍在线观看| 日韩欧美国产黄色| 亚洲女同性videos| 97在线免费观看视频| 97超级碰碰人国产在线观看| 国产一区二区三区在线看| 性欧美长视频免费观看不卡| 国产精品草莓在线免费观看| 91伊人影院在线播放| 日韩一二三在线视频播| 中文字幕精品一区二区精品| 中文字幕一区二区精品| 久久精品国产成人| 日韩在线一区二区三区免费视频| 亚洲毛片在线免费观看| 91精品国产免费久久久久久| 国产一区二区三区在线播放免费观看| 久久久久久这里只有精品| 国产精品日韩欧美综合|