projection 里的角度,角度越大,物体离摄像机越远;角度越小,物体离摄像机越近,这个角度表示视野(fov),视野越大,看到的物体就越小
头文件
1 #ifndef SHADER_H_INCLUDE 2 #define SHADER_H_INCLUDE 3 4 #include <iostream> 5 #include <string> 6 #include <sstream> 7 #include <fstream> 8 9 #include <GL/glew.h> 10 #include <GLFW/glfw3.h> 11 #include <glm/glm.hpp> 12 #include <glm/gtc/matrix_transform.hpp> 13 #include <glm/gtc/type_ptr.hpp> 14 #include <typeinfo> 15 class Shader { 16 public: 17 unsigned int ID; 18 19 Shader(const GLchar* vertexPath, const GLchar* fragmentPath) 20 { 21 std::string vertexCode; 22 std::string fragmentCode; 23 std::ifstream vShaderFile; 24 std::ifstream fShaderFile; 25 26 vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); 27 fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); 28 29 try { 30 //open files 31 vShaderFile.open(vertexPath); 32 fShaderFile.open(fragmentPath); 33 34 std::stringstream vShaderStream, fShaderStream; 35 36 //read file's buffer contents into streams 37 vShaderStream << vShaderFile.rdbuf(); 38 fShaderStream << fShaderFile.rdbuf(); 39 40 //close file handlers 41 vShaderFile.close(); 42 fShaderFile.close(); 43 44 //convert stream into string 45 vertexCode = vShaderStream.str(); 46 fragmentCode = fShaderStream.str(); 47 } 48 catch (std::ifstream::failure e) 49 { 50 std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ" << std::endl; 51 } 52 const char* vShaderCode = vertexCode.c_str(); 53 const char* fShaderCode = fragmentCode.c_str(); 54 55 //2.compile shaders 56 unsigned int vertex, fragment; 57 int success; 58 char infoLog[512]; 59 60 //vertex shader 61 vertex = glCreateShader(GL_VERTEX_SHADER); 62 glShaderSource(vertex, 1, &vShaderCode, NULL); 63 glCompileShader(vertex); 64 glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); 65 if (!success) 66 { 67 glGetShaderInfoLog(vertex, 512, NULL, infoLog); 68 std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED!" << std::endl; 69 } 70 71 fragment = glCreateShader(GL_FRAGMENT_SHADER); 72 glShaderSource(fragment, 1, &fShaderCode, NULL); 73 glCompileShader(fragment); 74 glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); 75 if (!success) 76 { 77 glGetShaderInfoLog(fragment, 512, NULL, infoLog); 78 std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED!" << std::endl; 79 } 80 81 ID = glCreateProgram(); 82 glAttachShader(ID, vertex); 83 glAttachShader(ID, fragment); 84 glLinkProgram(ID); 85 glGetProgramiv(ID, GL_LINK_STATUS, &success); 86 if (!success) 87 { 88 glGetProgramInfoLog(ID, 512, NULL, infoLog); 89 std::cout << "ERROR::SHADER::PROGRAM::LINKTING_FAILED!" << std::endl; 90 } 91 92 //delete the shaders sa they are linked into our program now and no long necessary 93 glDeleteShader(vertex); 94 glDeleteShader(fragment); 95 } 96 97 //activate the shader 98 void use() 99 { 100 glUseProgram(ID); 101 } 102 103 //utility uniform functions 104 void setBool(const std::string &name, bool value) const 105 { 106 glUniform1i(glGetUniformLocation(ID, name.c_str()), value); 107 } 108 109 void setInt(const std::string &name, int value) const 110 { 111 glUniform1i(glGetUniformLocation(ID, name.c_str()), value); 112 } 113 114 void setFloat(const std::string &name, float value) const 115 { 116 glUniform1f(glGetUniformLocation(ID, name.c_str()), value); 117 } 118 119 void setMat4(const std::string &name, glm::mat4 &trans) const 120 { 121 122 glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &trans[0][0]); 123 } 124 125 /*void setMat4(const std::string &name, glm::mat4 trans) const 126 { 127 128 //'trans': formal parameter with requested alignment of 16 won't be aligned,请求对齐的16的形式参数不会对齐 129 glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, glm::value_ptr(trans)); 130 }*/ 131 132 }; 133 134 #endif
.cpp源文件
1 //projection 里的角度,角度越大,物体离摄像机越远;角度越小,物体离摄像机越近,这个角度表示视野(fov) 2 //视野越大,看到的物体就越小 3 #include <iostream> 4 using namespace std; 5 #define GLEW_STATIC 6 #include <GL/glew.h> 7 #include <GLFW/glfw3.h> 8 #define STB_IMAGE_IMPLEMENTATION 9 #include "stb_image.h" 10 #include "Shader.h" 11 #include <glm/glm.hpp> 12 #include <glm/gtc/matrix_transform.hpp> 13 #include <glm/gtc/type_ptr.hpp> 14 15 16 void framebuffer_size_callback(GLFWwindow* window, int width, int height); 17 void mouse_callback(GLFWwindow* window, GLdouble xpos, GLdouble ypos); 18 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset); 19 //void scroll_callback(GLFWwindow* window, GLdouble xoffset, GLdouble yoffset); 20 void processInput(GLFWwindow *window); 21 22 glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f); 23 glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f); 24 glm::vec3 cameraUp = glm::vec3(0.0f, 1.0f, 0.0f); 25 26 float deltaTime = 0.0f; 27 float lastFrame = 0.0f; 28 float mixValue = 0.3f; 29 float SCR_WIDTH = 800; 30 float SCR_HEIGHT = 600; 31 float Left = 0.0f; 32 float Up = 0.0f; 33 float lastX = 400, lastY = 300; 34 float yaw = -90.0f, pitch = 0.0f;//yaw是偏航角,pitch是俯仰角 35 GLboolean firstMouse = true; 36 float fov = 45.0f; 37 38 39 40 int main() 41 { 42 glfwInit(); 43 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 44 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 45 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 46 GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL); 47 if (!window) 48 { 49 cout << "Failed to create window! " << endl; 50 glfwTerminate(); 51 return -1; 52 } 53 glfwMakeContextCurrent(window); 54 55 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); 56 glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); //隐藏并捕捉光标 57 glfwSetCursorPosCallback(window, mouse_callback); //回调鼠标事件 58 glfwSetScrollCallback(window, scroll_callback); //滚轮回调事件 59 60 glewExperimental = GL_TRUE; 61 if (glewInit() != GLEW_OK) 62 { 63 cout << "Failed to initialize GLEW!" << endl; 64 return -1; 65 } 66 67 68 //glfwSetCursorPosCallback(window, mouse_callback); 69 //glfwSetScrollCallback(window, scroll_callback); 70 71 //tell GLFW to capture our mouse 72 //glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED); 73 74 //configure global opengl state, z buffer 75 glEnable(GL_DEPTH_TEST);//Z缓冲,深度缓冲 76 77 //build and compile our shader program 78 Shader ourShader("E:\C++\3.txt", "E:\C++\4.txt"); 79 80 float vertices[] = { 81 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 82 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 83 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 84 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 85 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 86 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 87 88 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 89 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 90 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 91 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 92 -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 93 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 94 95 -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 96 -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 97 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 98 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 99 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 100 -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 101 102 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 103 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 104 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 105 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 106 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 107 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 108 109 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 110 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 111 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 112 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 113 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 114 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 115 116 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 117 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 118 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 119 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 120 -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 121 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f 122 }; 123 124 glm::vec3 cubePositions[] = { 125 glm::vec3(0.0f, 0.0f, 0.0f), 126 glm::vec3(2.0f, 5.0f, -15.0f), 127 glm::vec3(-1.5f, -2.2f, -2.5f), 128 glm::vec3(-3.8f, -2.0f, -12.3f), 129 glm::vec3(2.4f, -0.4f, -3.5f), 130 glm::vec3(-1.7f, 3.0f, -7.5f), 131 glm::vec3(1.3f, -2.0f, -2.5f), 132 glm::vec3(1.5f, 2.0f, -2.5f), 133 glm::vec3(1.5f, 0.2f, -1.5f), 134 glm::vec3(-1.3f, 1.0f, -1.5f) 135 }; 136 137 138 unsigned int indeices[] = { 139 0, 1, 2, 140 2, 3, 0 141 }; 142 unsigned int VBO, VAO, EBO; 143 glGenVertexArrays(1, &VAO); 144 glGenBuffers(1, &VBO); 145 glGenBuffers(1, &EBO); 146 147 glBindVertexArray(VAO); 148 glBindBuffer(GL_ARRAY_BUFFER, VBO); 149 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); 150 151 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 152 //glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indeices), indeices, GL_STATIC_DRAW); 153 154 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); 155 glEnableVertexAttribArray(0); 156 157 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); 158 glEnableVertexAttribArray(1); 159 160 //glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); 161 //glEnableVertexAttribArray(2); 162 163 unsigned int texture1, texture2; 164 glGenTextures(1, &texture1); 165 glBindTexture(GL_TEXTURE_2D, texture1); 166 167 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 168 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 169 170 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 171 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 172 173 int width, height, nrChannels;//Channels通道 174 stbi_set_flip_vertically_on_load(true); //tell stb_image.h to flip load texture's on the y-axis //flip翻转 175 unsigned char *data = stbi_load("wall.jpg", &width, &height, &nrChannels, 0); //加载图像 176 if (data) 177 { 178 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); //创建一个纹理 179 glGenerateMipmap(GL_TEXTURE_2D); //承担创建一个纹理后接下来的全部工作,为当前绑定的纹理自动生成所有需要的多级渐远纹理 180 } 181 else 182 { 183 cout << "Failed to load texture1!" << endl; 184 } 185 stbi_image_free(data); //为绑定的纹理生辰多级渐远纹理之后释放图像的内存 186 187 //texture2 188 glGenTextures(1, &texture2); 189 glBindTexture(GL_TEXTURE_2D, texture2); 190 191 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); 192 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); 193 194 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 195 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 196 197 data = stbi_load("timg.jpg", &width, &height, &nrChannels, 0); 198 if (data) 199 { 200 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); 201 glGenerateMipmap(GL_TEXTURE_2D); 202 } 203 else 204 { 205 cout << "Failed to load texture2!" << endl; 206 } 207 stbi_image_free(data); 208 209 ourShader.use(); 210 glUniform1i(glGetUniformLocation(ourShader.ID, "texture1"), 0); 211 glUniform1i(glGetUniformLocation(ourShader.ID, "texture2"), 1); 212 213 214 //trans = glm::rotate(trans, glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)); 215 //trans = glm::scale(trans, glm::vec3(0.5f, -0.5f, 1.0f)); 216 //第二个参数是传递的矩阵的数量,第三个是是否希望矩阵被置换(行与列交换),第四个是要传递的矩阵 217 218 219 float axis; 220 221 //render loop 222 while (!glfwWindowShouldClose(window)) 223 { 224 //per-frame time logic 每帧的时间增量 225 GLfloat currentFrame = glfwGetTime(); 226 deltaTime = currentFrame - lastFrame; 227 lastFrame = currentFrame; 228 229 processInput(window); 230 231 glClearColor(0.2f, 0.3f, 0.3f, 1.0f); 232 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 233 234 glActiveTexture(GL_TEXTURE0); 235 glBindTexture(GL_TEXTURE_2D, texture1); 236 glActiveTexture(GL_TEXTURE1); 237 glBindTexture(GL_TEXTURE_2D, texture2); 238 239 ourShader.setFloat("mixValue", mixValue); 240 241 glm::mat4 trans; 242 243 //trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f)); 244 //trans = glm::rotate(trans, glm::radians(15.0f), glm::vec3(1.0f, 0.0f, 0.0f)); 245 //trans = glm::rotate(trans, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f)); 246 glUniformMatrix4fv(glGetUniformLocation(ourShader.ID, "transform"), 1, GL_FALSE, glm::value_ptr(trans)); 247 248 glUseProgram(ourShader.ID); 249 glm::mat4 transform; 250 transform = glm::translate(trans, glm::vec3(Left, Up, 0.0f)); 251 ourShader.setMat4("transform", transform); 252 253 //glm::mat4 model; 254 glm::mat4 view; 255 glm::mat4 projection; 256 //model = glm::rotate(model, glm::radians(45.0f), glm::vec3(0.0f, 1.0f, 0.0f)); 257 //model = glm::rotate(model, (float)glfwGetTime() * glm::radians(50.0f), glm::vec3(0.5f, 1.0f, 0.0f)); 258 //view = glm::translate(view, glm::vec3(0.0f, 0.0f, -3.0f)); 259 view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp); 260 261 //摄像机的lookAt矩阵就是观察矩阵 262 //glm::mat4 view; 263 float radius = 10.0f; 264 float camX = sin(glfwGetTime()) * radius; 265 float camZ = cos(glfwGetTime()) * radius; 266 //view = glm::lookAt(glm::vec3(camX, 0.0f, camZ), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)); 267 268 269 //projection = glm::ortho(0.0f, 800.0f, 0.0f, 600.0f, 0.1f, 100.0f); 270 projection = glm::perspective(glm::radians(fov), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); // 271 //glUniformMatrix4fv(glGetUniformLocation(ourShader.ID, "model"), 1, GL_FALSE, glm::value_ptr(model)); 272 glUniformMatrix4fv(glGetUniformLocation(ourShader.ID, "view"), 1, GL_FALSE, glm::value_ptr(view)); 273 ourShader.setMat4("projection", projection); 274 275 glBindVertexArray(VAO); 276 277 278 for (unsigned int i = 0; i < 10; i++) 279 { 280 glm::mat4 model; 281 model = glm::translate(model, cubePositions[i]); 282 float angle = 20.0f * i; 283 284 angle = glfwGetTime() * 25.0f; 285 286 //axis = sin(glfwGetTime()); 287 model = glm::rotate(model, glm::radians(angle), glm::vec3(0.2f * i, 0.1* i, 0.3)); 288 ourShader.setMat4("model", model); 289 glDrawArrays(GL_TRIANGLES, 0, 36); 290 } 291 292 //glDrawArrays(GL_TRIANGLES, 0, 36); 293 //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 294 295 //trans = glm::mat4(); //trans必须是与上面的trans是同一个,一个uniform在同一个程序中只能被绑定一次 296 //trans = glm::translate(trans, glm::vec3(-0.5f, 0.5f, 0.0f)); 297 //trans = glm::scale(trans, glm::vec3(sin(glfwGetTime()), sin(glfwGetTime()), sin(glfwGetTime()))); 298 //glUniformMatrix4fv(glGetUniformLocation(ourShader.ID, "transform"), 1, GL_FALSE,glm::value_ptr(trans)); 299 ////glBindVertexArray(VAO); 300 //glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 301 302 303 glfwSwapBuffers(window); 304 glfwPollEvents(); 305 } 306 307 glDeleteVertexArrays(1, &VAO); 308 glDeleteBuffers(1, &VBO); 309 310 glfwTerminate(); 311 return 0; 312 313 314 return 0; 315 } 316 317 void framebuffer_size_callback(GLFWwindow* window, int width, int height) 318 { 319 glViewport(0, 0, width, height); 320 } 321 322 void processInput(GLFWwindow* window) 323 { 324 if (glfwGetKey(window, GLFW_KEY_ENTER) == GLFW_PRESS) 325 glfwSetWindowShouldClose(window, true); 326 if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) 327 { 328 mixValue += 0.001f; 329 if (mixValue >= 1.0f) 330 mixValue = 1.0f; 331 } 332 if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) 333 { 334 mixValue -= 0.001f; 335 if (mixValue <= 0.0f) 336 mixValue = 0.0f; 337 } 338 339 if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS) 340 { 341 Left -= 0.001; 342 } 343 344 if (glfwGetKey(window, GLFW_KEY_6) == GLFW_PRESS) 345 { 346 Left += 0.001f; 347 } 348 if (glfwGetKey(window, GLFW_KEY_8) == GLFW_PRESS) 349 { 350 Up += 0.001f; 351 } 352 353 if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS) 354 { 355 Up -= 0.001f; 356 } 357 358 float cameraSpeed = 2.5 * deltaTime; 359 if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) 360 cameraPos += cameraSpeed * cameraFront; 361 if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) 362 cameraPos -= cameraSpeed * cameraFront; 363 if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) 364 cameraPos -= glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed; 365 if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) 366 cameraPos += glm::normalize(glm::cross(cameraFront, cameraUp)) * cameraSpeed; 367 } 368 369 void mouse_callback(GLFWwindow* window, double xpos, double ypos) 370 { 371 if (firstMouse) 372 { 373 lastX = xpos; 374 lastY = ypos; 375 firstMouse = false; 376 } 377 378 float xoffset = xpos - lastX; 379 float yoffset = lastY - ypos; 380 381 lastX = xpos; 382 lastY = ypos; 383 float sensitivity = 0.0005f; 384 xoffset *= sensitivity; 385 yoffset *= sensitivity; 386 yaw += xoffset; 387 pitch += yoffset; 388 389 if (pitch > 89.0f) 390 pitch = 89.0f; 391 if (pitch < -89.0f) 392 pitch = -89.0f; 393 394 glm::vec3 front; 395 front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch)); 396 front.y = sin(glm::radians(pitch)); 397 front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch)); 398 cameraFront = glm::normalize(front); 399 400 } 401 402 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) 403 { 404 if (fov >= 1.0f && fov <= 45.0f) 405 fov -= yoffset; 406 if (fov <= 1.0f) 407 fov = 1.0f; 408 if (fov >= 45.0f) 409 fov = 45.0f; 410 }
timg.jpg文件
wall.jpg文件