摘要:本篇3Dmax教程探讨了OpenGL Shader 加载3Dmax模型,希望阅读本篇文章以后大家有所收获,帮助大家对3Dmax的掌握更加熟练。
现在市面上有一个很流行的模型加载库,叫做Assimp,全称为Open Asset Import Library。Assimp可以导入几十种不同格式的模型文件(同样也可以导出部分模型格式)。只要Assimp加载完了模型文件,我们就可以从Assimp上获取所有我们需要的模型数据。Assimp把不同的模型文件都转换为一个统一的数据结构,所有无论我们导入何种格式的模型文件,都可以用同一个方式去访问我们需要的模型数据。
当导入一个模型文件时,即Assimp加载一整个包含所有模型和场景数据的模型文件到一个scene对象时,Assimp会为这个模型文件中的所有场景节点、模型节点都生成一个具有对应关系的数据结构,且将这些场景中的各种元素与模型数据对应起来。
Assimp:
下载,解压, 然后用CMake加载,指定输出路径后
Configure,再Generate,
然后用VS2015打开 H:\assimp-3.3.1\bin\Assimp.sln 编译
在 H:\assimp-3.3.1\bin\code\Debug 中,即可生成
assimp-vc140-mt.lib assimp-vc140-mt.dll
然后在项目中即可使用
VS2015 可用:
包含: lib , dll 以及头文件, 可以直接使用. .VS2015....assimp-3.3.1
//download.csdn.net/detail/yulinxx/9714936
代码:
main.cpp
[html] view plain copy
1. // Std. Includes
2. #include <string>
3.
4. // GLEW
5. #define GLEW_STATIC
6. #include <GL/glew.h>
7.
8. // GLFW
9. #include <GLFW/glfw3.h>
10.
11. // GL includes
12. #include "Shader.h"
13. #include "Camera.h"
14. #include "Model.h"
15.
16. // GLM Mathemtics
17. #include <glm/glm.hpp>
18. #include <glm/gtc/matrix_transform.hpp>
19. #include <glm/gtc/type_ptr.hpp>
20.
21. // Other Libs
22. #include <SOIL/SOIL.h>
23.
24.
25. #pragma comment(lib, "./SOIL.lib")
26.
27. #pragma comment (lib, "opengl32.lib")
28. #pragma comment (lib, "glew32s.lib")
29. #pragma comment (lib, "glfw3.lib")
30. #pragma comment (lib, "glfw3dll.lib")
31. #pragma comment (lib, "glew32mxs.lib")
32. #pragma comment (lib, "assimp.lib")
33.
34.
35. // Properties
36. GLuint screenWidth = 800, screenHeight = 600;
37.
38. // Function prototypes
39. void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);
40. void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
41. void mouse_callback(GLFWwindow* window, double xpos, double ypos);
42. void Do_Movement();
43.
44. // Camera
45. Camera camera(glm::vec3(0.0f, 0.0f, 3.0f));
46. bool keys[1024];
47. GLfloat lastX = 400, lastY = 300;
48. bool firstMouse = true;
49.
50. GLfloat deltaTime = 0.0f;
51. GLfloat lastFrame = 0.0f;
52.
53. // The MAIN function, from here we start our application and run the Game loop
54. int main()
55. {
56. // Init GLFW
57. glfwInit();
58. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
59. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
60. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
61. glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
62.
63. GLFWwindow* window = glfwCreateWindow(screenWidth, screenHeight, "LearnOpenGL", nullptr, nullptr); // Windowed
64. glfwMakeContextCurrent(window);
65.
66. // Set the required callback functions
67. glfwSetKeyCallback(window, key_callback);
68. glfwSetCursorPosCallback(window, mouse_callback);
69. glfwSetScrollCallback(window, scroll_callback);
70.
71. // Options
72. //glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
73.
74. // Initialize GLEW to setup the OpenGL Function pointers
75. glewExperimental = GL_TRUE;
76. glewInit();
77.
78. // Define the viewport dimensions
79. glViewport(0, 0, screenWidth, screenHeight);
80.
81. // Setup some OpenGL options
82. glEnable(GL_DEPTH_TEST);
83.
84. // Setup and compile our shaders
85. Shader shader("./Shader/obj_vertex", "./Shader/obj_fragement");
86. Shader lampShader("./Shader/lamp_vertex", "./Shader/lamp_fragement");
87.
88. // Load models
89. Model ourModel("./nanosuit.obj");
90. // Used a lamp object here. Find one yourself on the internet, or create your own one ;) (or be oldschool and set the VBO and VAO yourselves)
91. //Model lightBulb("./Bulb.obj");
92. Model lightBulb("./nanosuit.obj");
93.
94. // Draw in wireframe
95. //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
96.
97. // Point light positions
98. glm::vec3 pointLightPositions[] = {
99. glm::vec3(2.3f, -1.6f, -3.0f),
100. glm::vec3(-1.7f, 0.9f, 1.0f)
101. };
102.
103. // Game loop
104. while (!glfwWindowShouldClose(window))
105. {
106. // Set frame time
107. GLfloat currentFrame = glfwGetTime();
108. deltaTime = currentFrame - lastFrame;
109. lastFrame = currentFrame;
110.
111. // Check and call events
112. glfwPollEvents();
113. Do_Movement();
114.
115. // Clear the colorbuffer
116. glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
117. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
118.
119. shader.useShaderPrograme(); // <-- Don't forget this one!
120. // Transformation matrices
121. glm::mat4 projection = glm::perspective(camera.Zoom, (float)screenWidth / (float)screenHeight, 0.1f, 100.0f);
122. glm::mat4 view = camera.GetViewMatrix();
123. glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));
124. glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "view"), 1, GL_FALSE, glm::value_ptr(view));
125.
126. // Set the lighting uniforms
127. glUniform3f(glGetUniformLocation(shader.getPrograme(), "viewPos"), camera.Position.x, camera.Position.y, camera.Position.z);
128. // Point light 1
129. glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].position"), pointLightPositions[0].x, pointLightPositions[0].y, pointLightPositions[0].z);
130. //glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].ambient"), 0.5f, 0.5f, 0.05f);
131. //glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].diffuse"), 1.0f, 1.0f, 1.0f);
132. //glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].specular"), 1.0f, 1.0f, 1.0f);
133. //glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].constant"), 1.0f);
134. //glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].linear"), 0.9);
135. //glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].quadratic"), 0.32);
136. glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].ambient"), 0.05f, 0.05f, 0.05f);
137. glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].diffuse"), 1.0f, 1.0f, 1.0f);
138. glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].specular"), 1.0f, 1.0f, 1.0f);
139. glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].constant"), 1.0f);
140. glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].linear"), 0.009);
141. glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[0].quadratic"), 0.0032);
142. // Point light 2
143. //glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].position"), pointLightPositions[1].x, pointLightPositions[1].y, pointLightPositions[1].z);
144. //glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].ambient"), 0.5f, 0.5f, 0.5f);
145. //glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].diffuse"), 1.0f, 1.0f, 1.0f);
146. //glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].specular"), 1.0f, 1.0f, 1.0f);
147. //glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].constant"), 1.0f);
148. //glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].linear"), 0.9);
149. //glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].quadratic"), 0.32);
150. glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].ambient"), 0.05f, 0.05f, 0.05f);
151. glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].diffuse"), 1.0f, 1.0f, 1.0f);
152. glUniform3f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].specular"), 1.0f, 1.0f, 1.0f);
153. glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].constant"), 1.0f);
154. glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].linear"), 0.009);
155. glUniform1f(glGetUniformLocation(shader.getPrograme(), "pointLights[1].quadratic"), 0.0032);
156.
157. // Draw the loaded model
158. glm::mat4 model;
159. model = glm::translate(model, glm::vec3(0.0f, -1.75f, 0.0f)); // Translate it down a bit so it's at the center of the scene
160. model = glm::scale(model, glm::vec3(0.2f, 0.2f, 0.2f)); // It's a bit too big for our scene, so scale it down
161. glUniformMatrix4fv(glGetUniformLocation(shader.getPrograme(), "model"), 1, GL_FALSE, glm::value_ptr(model));
162. ourModel.Draw(shader);
163.
164. // Draw the lamps
165. lampShader.useShaderPrograme();
166. glUniformMatrix4fv(glGetUniformLocation(lampShader.getPrograme(), "projection"), 1, GL_FALSE, glm::value_ptr(projection));
167. glUniformMatrix4fv(glGetUniformLocation(lampShader.getPrograme(), "view"), 1, GL_FALSE, glm::value_ptr(view));
168. for (GLuint i = 0; i < 2; i++)
169. {
170. model = glm::mat4();
171. model = glm::translate(model, pointLightPositions[i]);
172. model = glm::scale(model, glm::vec3(0.3f, 0.3f, 0.3f)); // Downscale lamp object (a bit too large)
173. glUniformMatrix4fv(glGetUniformLocation(lampShader.getPrograme(), "model"), 1, GL_FALSE, glm::value_ptr(model));
174. lightBulb.Draw(lampShader);
175. }
176.
177. // Swap the buffers
178. glfwSwapBuffers(window);
179. }
180.
181. glfwTerminate();
182. return 0;
183. }
184.
185. #pragma region "User input"
186.
187. // Moves/alters the camera positions based on user input
188. void Do_Movement()
189. {
190. // Camera controls
191. if (keys[GLFW_KEY_W])
192. camera.ProcessKeyboard(FORWARD, deltaTime);
193. if (keys[GLFW_KEY_S])
194. camera.ProcessKeyboard(BACKWARD, deltaTime);
195. if (keys[GLFW_KEY_A])
196. camera.ProcessKeyboard(LEFT, deltaTime);
197. if (keys[GLFW_KEY_D])
198. camera.ProcessKeyboard(RIGHT, deltaTime);
199. }
200.
201. // Is called whenever a key is pressed/released via GLFW
202. void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
203. {
204. if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
205. glfwSetWindowShouldClose(window, GL_TRUE);
206.
207. if (action == GLFW_PRESS)
208. keys[key] = true;
209. else if (action == GLFW_RELEASE)
210. keys[key] = false;
211. }
212.
213. void mouse_callback(GLFWwindow* window, double xpos, double ypos)
214. {
215. if (firstMouse)
216. {
217. lastX = xpos;
218. lastY = ypos;
219. firstMouse = false;
220. }
221.
222. GLfloat xoffset = xpos - lastX;
223. GLfloat yoffset = lastY - ypos;
224.
225. lastX = xpos;
226. lastY = ypos;
227.
228. camera.ProcessMouseMovement(xoffset, yoffset);
229. }
230.
231. void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
232. {
233. camera.ProcessMouseScroll(yoffset);
234. }
235.
236. #pragma endregion
mesh.h
[html] view plain copy
1. #pragma once
2. // Std. Includes
3. #include <string>
4. #include <fstream>
5. #include <sstream>
6. #include <iostream>
7. #include <vector>
8. using namespace std;
9. // GL Includes
10. #include <GL/glew.h> // Contains all the necessery OpenGL includes
11. #include <glm/glm.hpp>
12. #include <glm/gtc/matrix_transform.hpp>
13.
14.
15. struct Vertex {
16. // Position
17. glm::vec3 Position;
18. // Normal
19. glm::vec3 Normal;
20. // TexCoords
21. glm::vec2 TexCoords;
22. };
23.
24. struct Texture {
25. GLuint id;
26. string type;
27. aiString path;
28. };
29.
30. class Mesh {
31. public:
32. /* Mesh Data */
33. vector<Vertex> vertices;
34. vector<GLuint> indices;
35. vector<Texture> textures;
36.
37. /* Functions */
38. // Constructor
39. Mesh(vector<Vertex> vertices, vector<GLuint> indices, vector<Texture> textures)
40. {
41. this->vertices = vertices;
42. this->indices = indices;
43. this->textures = textures;
44.
45. // Now that we have all the required data, set the vertex buffers and its attribute pointers.
46. this->setupMesh();
47. }
48.
49. // Render the mesh
50. void Draw(Shader shader)
51. {
52. // Bind appropriate textures
53. GLuint diffuseNr = 1;
54. GLuint specularNr = 1;
55. for (GLuint i = 0; i < this->textures.size(); i++)
56. {
57. glActiveTexture(GL_TEXTURE0 + i); // Active proper texture unit before binding
58. // Retrieve texture number (the N in diffuse_textureN)
59. stringstream ss;
60. string number;
61. string name = this->textures[i].type;
62. if (name == "texture_diffuse")
63. ss << diffuseNr++; // Transfer GLuint to stream
64. else if (name == "texture_specular")
65. ss << specularNr++; // Transfer GLuint to stream
66. number = ss.str();
67. // Now set the sampler to the correct texture unit
68. glUniform1i(glGetUniformLocation(shader.getPrograme(), (name + number).c_str()), i);
69. // And finally bind the texture
70. glBindTexture(GL_TEXTURE_2D, this->textures[i].id);
71. }
72.
73. // 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)
74. glUniform1f(glGetUniformLocation(shader.getPrograme(), "material.shininess"), 16.0f);
75.
76. // Draw mesh
77. glBindVertexArray(this->VAO);
78. glDrawElements(GL_TRIANGLES, this->indices.size(), GL_UNSIGNED_INT, 0);
79. glBindVertexArray(0);
80.
81. // Always good practice to set everything back to defaults once configured.
82. for (GLuint i = 0; i < this->textures.size(); i++)
83. {
84. glActiveTexture(GL_TEXTURE0 + i);
85. glBindTexture(GL_TEXTURE_2D, 0);
86. }
87. }
88.
89. private:
90. /* Render data */
91. GLuint VAO, VBO, EBO;
92.
93. /* Functions */
94. // Initializes all the buffer objects/arrays
95. void setupMesh()
96. {
97. // Create buffers/arrays
98. glGenVertexArrays(1, &this->VAO);
99. glGenBuffers(1, &this->VBO);
100. glGenBuffers(1, &this->EBO);
101.
102. glBindVertexArray(this->VAO);
103. // Load data into vertex buffers
104. glBindBuffer(GL_ARRAY_BUFFER, this->VBO);
105. // A great thing about structs is that their memory layout is sequential for all its items.
106. // The effect is that we can simply pass a pointer to the struct and it translates perfectly to a glm::vec3/2 array which
107. // again translates to 3/2 floats which translates to a byte array.
108. glBufferData(GL_ARRAY_BUFFER, this->vertices.size() * sizeof(Vertex), &this->vertices[0], GL_STATIC_DRAW);
109.
110. glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->EBO);
111. glBufferData(GL_ELEMENT_ARRAY_BUFFER, this->indices.size() * sizeof(GLuint), &this->indices[0], GL_STATIC_DRAW);
112.
113. // Set the vertex attribute pointers
114. // Vertex Positions
115. glEnableVertexAttribArray(0);
116. glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)0);
117. // Vertex Normals
118. glEnableVertexAttribArray(1);
119. glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, Normal));
120. // Vertex Texture Coords
121. glEnableVertexAttribArray(2);
122. glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (GLvoid*)offsetof(Vertex, TexCoords));
123.
124. glBindVertexArray(0);
125. }
126. };
model.h
[html] view plain copy
1. #pragma once
2. // Std. Includes
3. #include <string>
4. #include <fstream>
5. #include <sstream>
6. #include <iostream>
7. #include <map>
8. #include <vector>
9. using namespace std;
10. // GL Includes
11. #include <GL/glew.h> // Contains all the necessery OpenGL includes
12. #include <glm/glm.hpp>
13. #include <glm/gtc/matrix_transform.hpp>
14. #include <SOIL/SOIL.h>
15. #include <assimp/Importer.hpp>
16. #include <assimp/scene.h>
17. #include <assimp/postprocess.h>
18.
19. #include "Mesh.h"
20.
21. GLint TextureFromFile(const char* path, string directory);
22.
23. class Model
24. {
25. public:
26. /* Functions */
27. // Constructor, expects a filepath to a 3D model.
28. Model(GLchar* path)
29. {
30. this->loadModel(path);
31. }
32.
33. // Draws the model, and thus all its meshes
34. void Draw(Shader shader)
35. {
36. for (GLuint i = 0; i < this->meshes.size(); i++)
37. this->meshes[i].Draw(shader);
38. }
39.
40. private:
41. /* Model Data */
42. vector<Mesh> meshes;
43. string directory;
44. vector<Texture> textures_loaded; // Stores all the textures loaded so far, optimization to make sure textures aren't loaded more than once.
45.
46. /* Functions */
47. // Loads a model with supported ASSIMP extensions from file and stores the resulting meshes in the meshes vector.
48. void loadModel(string path)
49. {
50. // Read file via ASSIMP
51. Assimp::Importer importer;
52. const aiScene* scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
53. // Check for errors
54. if (!scene || scene->mFlags == AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // if is Not Zero
55. {
56. cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << endl;
57. return;
58. }
59. // Retrieve the directory path of the filepath
60. this->directory = path.substr(0, path.find_last_of('/'));
61.
62. // Process ASSIMP's root node recursively
63. this->processNode(scene->mRootNode, scene);
64. }
65.
66. // 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).
67. void processNode(aiNode* node, const aiScene* scene)
68. {
69. // Process each mesh located at the current node
70. for (GLuint i = 0; i < node->mNumMeshes; i++)
71. {
72. // The node object only contains indices to index the actual objects in the scene.
73. // The scene contains all the data, node is just to keep stuff organized (like relations between nodes).
74. aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
75. this->meshes.push_back(this->processMesh(mesh, scene));
76. }
77. // After we've processed all of the meshes (if any) we then recursively process each of the children nodes
78. for (GLuint i = 0; i < node->mNumChildren; i++)
79. {
80. this->processNode(node->mChildren[i], scene);
81. }
82.
83. }
84.
85. Mesh processMesh(aiMesh* mesh, const aiScene* scene)
86. {
87. // Data to fill
88. vector<Vertex> vertices;
89. vector<GLuint> indices;
90. vector<Texture> textures;
91.
92. // Walk through each of the mesh's vertices
93. for (GLuint i = 0; i < mesh->mNumVertices; i++)
94. {
95. Vertex vertex;
96. 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.
97. // Positions
98. vector.x = mesh->mVertices[i].x;
99. vector.y = mesh->mVertices[i].y;
100. vector.z = mesh->mVertices[i].z;
101. vertex.Position = vector;
102. // Normals
103. vector.x = mesh->mNormals[i].x;
104. vector.y = mesh->mNormals[i].y;
105. vector.z = mesh->mNormals[i].z;
106. vertex.Normal = vector;
107. // Texture Coordinates
108. if (mesh->mTextureCoords[0]) // Does the mesh contain texture coordinates?
109. {
110. glm::vec2 vec;
111. // A vertex can contain up to 8 different texture coordinates. We thus make the assumption that we won't
112. // use models where a vertex can have multiple texture coordinates so we always take the first set (0).
113. vec.x = mesh->mTextureCoords[0][i].x;
114. vec.y = mesh->mTextureCoords[0][i].y;
115. vertex.TexCoords = vec;
116. }
117. else
118. vertex.TexCoords = glm::vec2(0.0f, 0.0f);
119. vertices.push_back(vertex);
120. }
121. // Now wak through each of the mesh's faces (a face is a mesh its triangle) and retrieve the corresponding vertex indices.
122. for (GLuint i = 0; i < mesh->mNumFaces; i++)
123. {
124. aiFace face = mesh->mFaces[i];
125. // Retrieve all indices of the face and store them in the indices vector
126. for (GLuint j = 0; j < face.mNumIndices; j++)
127. indices.push_back(face.mIndices[j]);
128. }
129. // Process materials
130. if (mesh->mMaterialIndex >= 0)
131. {
132. aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
133. // We assume a convention for sampler names in the shaders. Each diffuse texture should be named
134. // as 'texture_diffuseN' where N is a sequential number ranging from 1 to MAX_SAMPLER_NUMBER.
135. // Same applies to other texture as the following list summarizes:
136. // Diffuse: texture_diffuseN
137. // Specular: texture_specularN
138. // Normal: texture_normalN
139.
140. // 1. Diffuse maps
141. vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse");
142. textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
143. // 2. Specular maps
144. vector<Texture> specularMaps = this->loadMaterialTextures(material, aiTextureType_SPECULAR, "texture_specular");
145. textures.insert(textures.end(), specularMaps.begin(), specularMaps.end());
146. }
147.
148. // Return a mesh object created from the extracted mesh data
149. return Mesh(vertices, indices, textures);
150. }
151.
152. // Checks all material textures of a given type and loads the textures if they're not loaded yet.
153. // The required info is returned as a Texture struct.
154. vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName)
155. {
156. vector<Texture> textures;
157. for (GLuint i = 0; i < mat->GetTextureCount(type); i++)
158. {
159. aiString str;
160. mat->GetTexture(type, i, &str);
161. // Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
162. GLboolean skip = false;
163. for (GLuint j = 0; j < textures_loaded.size(); j++)
164. {
165. if (textures_loaded[j].path == str)
166. {
167. textures.push_back(textures_loaded[j]);
168. skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
169. break;
170. }
171. }
172. if (!skip)
173. { // If texture hasn't been loaded already, load it
174. Texture texture;
175. texture.id = TextureFromFile(str.C_Str(), this->directory);
176. texture.type = typeName;
177. texture.path = str;
178. textures.push_back(texture);
179. this->textures_loaded.push_back(texture); // Store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.
180. }
181. }
182. return textures;
183. }
184. };
185.
186.
187.
188.
189. GLint TextureFromFile(const char* path, string directory)
190. {
191. //Generate texture ID and load texture data
192. string filename = string(path);
193. filename = directory + '/' + filename;
194. GLuint textureID;
195. glGenTextures(1, &textureID);
196. int width, height;
197. unsigned char* image = SOIL_load_image(filename.c_str(), &width, &height, 0, SOIL_LOAD_RGB);
198. // Assign texture to ID
199. glBindTexture(GL_TEXTURE_2D, textureID);
200. glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
201. glGenerateMipmap(GL_TEXTURE_2D);
202.
203. // Parameters
204. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
205. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
206. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
207. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
208. glBindTexture(GL_TEXTURE_2D, 0);
209. SOIL_free_image_data(image);
210. return textureID;
211. }
camera.h
[html] view plain copy
1. //Camera.h
2.
3. #pragma once
4.
5. // Std. Includes
6. #include <vector>
7.
8. // GL Includes
9. #include <GL/glew.h>
10. #include <glm/glm.hpp>
11. #include <glm/gtc/matrix_transform.hpp>
12.
13.
14. // 摄像机移动方向 程序中用WSAD控制
15. enum Camera_Movement {
16. FORWARD,
17. BACKWARD,
18. LEFT,
19. RIGHT
20. };
21.
22. // Default camera values
23. const GLfloat YAW = -90.0f;
24. const GLfloat PITCH = 0.0f;
25. const GLfloat SPEED = 3.0f;
26. const GLfloat SENSITIVTY = 0.25f;
27. const GLfloat ZOOM = 45.0f;
28.
29.
30. class Camera
31. {
32. public:
33. // Camera Attributes
34. glm::vec3 Position;
35. glm::vec3 Front;
36. glm::vec3 Up;
37. glm::vec3 Right;
38. glm::vec3 WorldUp;
39. // Eular Angles
40. GLfloat Yaw;
41. GLfloat Pitch;
42. // Camera options
43. GLfloat MovementSpeed;
44. GLfloat MouseSensitivity;
45. GLfloat Zoom;
46.
47. // Constructor with vectors
48. Camera(glm::vec3 position = glm::vec3(0.0f, 0.0f, 0.0f),
49. glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f), GLfloat yaw = YAW,
50. GLfloat pitch = PITCH) : Front(glm::vec3(0.0f, 0.0f, -1.0f)),
51. MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
52. {
53. this->Position = position;
54. this->WorldUp = up;
55. this->Yaw = yaw;
56. this->Pitch = pitch;
57. this->updateCameraVectors();
58. }
59. // Constructor with scalar values
60. Camera(GLfloat posX, GLfloat posY, GLfloat posZ, GLfloat upX, GLfloat upY,
61. GLfloat upZ, GLfloat yaw, GLfloat pitch) : Front(glm::vec3(0.0f, 0.0f, -1.0f)),
62. MovementSpeed(SPEED), MouseSensitivity(SENSITIVTY), Zoom(ZOOM)
63. {
64. this->Position = glm::vec3(posX, posY, posZ);
65. this->WorldUp = glm::vec3(upX, upY, upZ);
66. this->Yaw = yaw;
67. this->Pitch = pitch;
68. this->updateCameraVectors();
69. }
70.
71. // Returns the view matrix calculated using Eular Angles and the LookAt Matrix
72. glm::mat4 GetViewMatrix()
73. {
74. return glm::lookAt(this->Position, this->Position + this->Front, this->Up);
75. }
76.
77. // 按键处理
78. void ProcessKeyboard(Camera_Movement direction, GLfloat deltaTime)
79. {
80. GLfloat velocity = this->MovementSpeed * deltaTime;
81. if (direction == FORWARD)
82. this->Position += this->Front * velocity;
83. if (direction == BACKWARD)
84. this->Position -= this->Front * velocity;
85. if (direction == LEFT)
86. this->Position -= this->Right * velocity;
87. if (direction == RIGHT)
88. this->Position += this->Right * velocity;
89. }
90.
91. // 鼠标移动处理
92. void ProcessMouseMovement(GLfloat xoffset, GLfloat yoffset,
93. GLboolean constrainPitch = true)
94. {
95. xoffset *= this->MouseSensitivity;
96. yoffset *= this->MouseSensitivity;
97.
98. this->Yaw += xoffset;
99. this->Pitch += yoffset;
100.
101. // Make sure that when pitch is out of bounds, screen doesn't get flipped
102. if (constrainPitch)
103. {
104. if (this->Pitch > 89.0f)
105. this->Pitch = 89.0f;
106. if (this->Pitch < -89.0f)
107. this->Pitch = -89.0f;
108. }
109.
110. // Update Front, Right and Up Vectors using the updated Eular angles
111. this->updateCameraVectors();
112. }
113.
114. // Processes input received from a mouse scroll-wheel event.
115. // Only requires input on the vertical wheel-axis
116. void ProcessMouseScroll(GLfloat yoffset)
117. {
118. if (this->Zoom >= 1.0f && this->Zoom <= 45.0f)
119. this->Zoom -= yoffset;
120. if (this->Zoom <= 1.0f)
121. this->Zoom = 1.0f;
122. if (this->Zoom >= 45.0f)
123. this->Zoom = 45.0f;
124. }
125.
126. private:
127. // Calculates the front vector from the Camera's (updated) Eular Angles
128. void updateCameraVectors()
129. {
130. // Calculate the new Front vector
131. glm::vec3 front;
132. front.x = cos(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
133. front.y = sin(glm::radians(this->Pitch));
134. front.z = sin(glm::radians(this->Yaw)) * cos(glm::radians(this->Pitch));
135. this->Front = glm::normalize(front);
136. // Also re-calculate the Right and Up vector
137. // Normalize the vectors, because their length gets closer to 0 the more
138. // you look up or down which results in slower movement.
139. this->Right = glm::normalize(glm::cross(this->Front, this->WorldUp));
140. this->Up = glm::normalize(glm::cross(this->Right, this->Front));
141. }
142. };
shader.h
[html] view plain copy
1. //Shader.h
2. #pragma once
3.
4. #ifndef TEXTURE_SHADER_H_
5. #define TEXTURE_SHADER_H_
6.
7. #include <string>
8. #include <fstream>
9. #include <sstream>
10. #include <iostream>
11.
12. #include <gl/glew.h>
13.
14. #include <string>
15. #include <fstream>
16. #include <sstream>
17. #include <iostream>
18.
19. #include <GL/glew.h>
20.
21. class Shader
22. {
23. public:
24. Shader(const GLchar* vertexPath, const GLchar* fragmentPath);
25. ~Shader();
26.
27. public:
28. void useShaderPrograme();
29.
30. GLuint getPrograme() {
31. return this->m_nProgram;
32. }
33.
34. private:
35. GLuint m_nProgram;
36. };
37.
38. Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
39. {
40. std::string vertexCode;
41. std::string fragmentCode;
42. std::ifstream vertexShaderF;
43. std::ifstream fragementShaderF;
44.
45. vertexShaderF.exceptions(std::ifstream::badbit);
46. fragementShaderF.exceptions(std::ifstream::badbit);
47.
48. try
49. {
50. vertexShaderF.open(vertexPath); // 打开文件
51. fragementShaderF.open(fragmentPath);
52.
53. std::stringstream vertexShaderStream, fragementShaderStream;
54. vertexShaderStream << vertexShaderF.rdbuf(); // 读取文件至stringstream中
55. fragementShaderStream << fragementShaderF.rdbuf();
56.
57. vertexShaderF.close();
58. fragementShaderF.close();
59.
60. vertexCode = vertexShaderStream.str(); // 转换成string类型
61. fragmentCode = fragementShaderStream.str();
62. }
63. catch (std::ifstream::failure e)
64. {
65. std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ:" << std::endl;
66. }
67.
68. const GLchar* pVertexCode = vertexCode.c_str(); // string 转 char*
69. const GLchar* pFragementCode = fragmentCode.c_str();
70.
71. GLuint nVertexShader, nFragementShader;
72. GLint nRes = 0;
73. GLchar chLogInfo[512] = { '\0' };
74.
75. // 创建顶点着色器
76. nVertexShader = glCreateShader(GL_VERTEX_SHADER);
77. // 将顶点着色程序的源代码字符数组绑定到顶点着色器对象
78. glShaderSource(nVertexShader, 1, &pVertexCode, nullptr);
79. glCompileShader(nVertexShader); // compile shader 编译着色器
80.
81. // 获取编译结果
82. glGetShaderiv(nVertexShader, GL_COMPILE_STATUS, &nRes);
83. if (!nRes)
84. {
85. glGetShaderInfoLog(nVertexShader, 512, nullptr, chLogInfo);
86. std::cout << "ERROR::SHADEF::VERTEX::COMPILATION_FAILED:" << chLogInfo << std::endl;
87. }
88.
89. // 创建片断着色器
90. nFragementShader = glCreateShader(GL_FRAGMENT_SHADER);
91. // 将片段着色程序的源代码字符数组绑定到片段着色器对象
92. glShaderSource(nFragementShader, 1, &pFragementCode, nullptr);
93. glCompileShader(nFragementShader);
94. glGetShaderiv(nFragementShader, GL_COMPILE_STATUS, &nRes);
95. if (!nRes)
96. {
97. glGetShaderInfoLog(nFragementShader, 512, nullptr, chLogInfo);
98. std::cout << "ERROR::SHADEF::FRAGEMENT::COMPILATION_FAILED:" << chLogInfo << std::endl;
99. }
100.
101. this->m_nProgram = glCreateProgram(); // 创建GLSL程序
102. glAttachShader(this->m_nProgram, nVertexShader); // 绑定shader到program
103. glAttachShader(this->m_nProgram, nFragementShader);
104.
105. // glLinkProgram操作产生最后的可执行程序,它包含最后可以在硬件上执行的硬件指令
106. glLinkProgram(this->m_nProgram); // 链接
107. glGetProgramiv(this->m_nProgram, GL_LINK_STATUS, &nRes);
108. if (!nRes)
109. {
110. glGetProgramInfoLog(this->m_nProgram, 512, nullptr, chLogInfo);
111. std::cout << "ERROR::SHADEF::FRAGEMENT::LINK_FAILED:" << chLogInfo << std::endl;
112. }
113.
114. glDeleteShader(nVertexShader);
115. glDeleteShader(nFragementShader);
116. }
117.
118. Shader::~Shader()
119. {
120. }
121.
122. #include <glm/glm.hpp>
123. #include <glm/gtc/matrix_transform.hpp>
124. #include <glm/gtc/type_ptr.hpp>
125.
126. void Shader::useShaderPrograme()
127. {
128. glUseProgram(this->m_nProgram); // 使用porgram
129. }
130.
131. #endif
***********************************Shader 源码部分************************************
obj_vertex:
[html] view plain copy
1. // Vertex shader:
2. // ================
3. #version 330 core
4. layout (location = 0) in vec3 position;
5. layout (location = 1) in vec3 normal;
6. layout (location = 2) in vec2 texCoords;
7.
8. out vec2 TexCoords;
9. out vec3 fragPosition;
10. out vec3 Normal;
11.
12. uniform mat4 model;
13. uniform mat4 view;
14. uniform mat4 projection;
15.
16. void main()
17. {
18. gl_Position = projection * view * model * vec4(position, 1.0f);
19. fragPosition = vec3(model * vec4(position, 1.0f));
20. Normal = mat3(transpose(inverse(model))) * normal;
21. TexCoords = texCoords;
22. }
obj_fragement:
[html] view plain copy
1. // Fragment shader:
2. // ================
3. #version 330 core
4. struct Material {
5. sampler2D texture_diffuse1;
6. sampler2D texture_specular1;
7. float shininess;
8. };
9. /* Note: because we now use a material struct again you want to change your
10. mesh class to bind all the textures using material.texture_diffuseN instead of
11. texture_diffuseN. */
12.
13. struct PointLight {
14. vec3 position;
15.
16. float constant;
17. float linear;
18. float quadratic;
19.
20. vec3 ambient;
21. vec3 diffuse;
22. vec3 specular;
23. };
24.
25. #define NR_POINT_LIGHTS 2
26.
27. in vec3 fragPosition;
28. in vec3 Normal;
29. in vec2 TexCoords;
30.
31. out vec4 color;
32.
33. uniform vec3 viewPos;
34. uniform PointLight pointLights[NR_POINT_LIGHTS];
35. uniform Material material;
36.
37. // Function prototypes
38. vec3 CalcPointLight(PointLight light, Material mat, vec3 normal, vec3 fragPos, vec3 viewDir);
39.
40. void main()
41. {
42. vec3 result;
43. vec3 viewDir = normalize(viewPos - fragPosition);
44. vec3 norm = normalize(Normal);
45.
46. for(int i = 0; i < NR_POINT_LIGHTS; i++)
47. result += CalcPointLight(pointLights[i], material, norm, fragPosition, viewDir);
48.
49. color = vec4(result, 1.0f);
50. }
51.
52.
53. // Calculates the color when using a point light.
54. vec3 CalcPointLight(PointLight light, Material mat, vec3 normal, vec3 fragPos, vec3 viewDir)
55. {
56. vec3 lightDir = normalize(light.position - fragPos);
57. // Diffuse shading
58. float diff = max(dot(normal, lightDir), 0.0);
59. // Specular shading
60. vec3 reflectDir = reflect(-lightDir, normal);
61. float spec = pow(max(dot(viewDir, reflectDir), 0.0), mat.shininess);
62. // Attenuation
63. float distance = length(light.position - fragPos);
64. float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
65. // Combine results
66. vec3 ambient = light.ambient * vec3(texture(mat.texture_diffuse1, TexCoords));
67. vec3 diffuse = light.diffuse * diff * vec3(texture(mat.texture_diffuse1, TexCoords));
68. vec3 specular = light.specular * spec * vec3(texture(mat.texture_specular1, TexCoords));
69. ambient *= attenuation;
70. diffuse *= attenuation;
71. specular *= attenuation;
72. return (ambient + diffuse + specular);
73. }
lamp_vertex:
[html] view plain copy
1. #version 330 core
2. layout (location = 0) in vec3 position;
3. layout (location = 1) in vec3 normal;
4. layout (location = 2) in vec2 texCoords;
5.
6. out vec2 TexCoords;
7.
8. uniform mat4 model;
9. uniform mat4 view;
10. uniform mat4 projection;
11.
12. void main()
13. {
14. gl_Position = projection * view * model * vec4(position, 1.0f);
15. TexCoords = texCoords;
16. }
lamp_fragement:
[html] view plain copy
1. #version 330 core
2.
3. in vec2 TexCoords;
4.
5. out vec4 color;
6.
7. uniform sampler2D texture_diffuse1;
8.
9. void main()
10. {
11. color = vec4(texture(texture_diffuse1, TexCoords));
12. }
本文由职坐标整理发布,更多相关知识,请关注职坐标常用软件3Dmax频道!
您输入的评论内容中包含违禁敏感词
我知道了
请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号