OpenGL Shader 绘制天空盒_基础 2
参考:
http://learnopengl-cn.readthedocs.io/zh/latest/04%20Advanced%20OpenGL/06%20Cubemaps/
源码:
http://download.csdn.net/detail/yulinxx/9719755
main.cpp
#define GLEW_STATIC #include <GL/glew.h> #include <GLFW/glfw3.h> #include "Shader.h" #include "Camera.h" #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #include <SOIL/SOIL.h> #include <vector> #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") #pragma comment(lib, "SOIL.lib") GLuint WIDTH = 800, HEIGHT = 600; void key_callback(GLFWwindow* pWnd, int key, int scancode, int action, int mode); void mouse_callback(GLFWwindow* pWnd, double xpos, double ypos); void Do_Movement(); GLuint loadTexture(GLchar* path, GLboolean alpha = false); GLuint loadCubemapTexture(std::vector<const GLchar *> vecSkyfaces); Camera camera(glm::vec3(0.0f, 0.0f, 3.0f)); bool keys[1024]; GLfloat lastX = 400, lastY = 300; bool firstMouse = true; GLfloat deltaTime = 0.0f; GLfloat lastFrame = 0.0f; // ****************************************************** int main() { 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(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr); // Windowed glfwMakeContextCurrent(pWnd); glfwSetKeyCallback(pWnd, key_callback); glfwSetCursorPosCallback(pWnd, mouse_callback); //glfwSetInputMode(pWnd, GLFW_CURSOR, GLFW_CURSOR_DISABLED); glewExperimental = GL_TRUE; glewInit(); glViewport(0, 0, WIDTH, HEIGHT); // 立方体 GLfloat cubeVertices[] = { -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, -0.5f, 1.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, -0.5f, -0.5f, -0.5f, 0.0f, 1.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, -0.5f, 0.5f, -0.5f, 0.0f, 1.0f }; // 地面 GLfloat floorVertices[] = { 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, 5.0f, 0.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, 5.0f, -0.5f, 5.0f, 2.0f, 0.0f, -5.0f, -0.5f, -5.0f, 0.0f, 2.0f, 5.0f, -0.5f, -5.0f, 2.0f, 2.0f }; // 天空盒 GLfloat skyboxVertices[] = { -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f }; // 数据处理 // 地面 GLuint floorVAO, floorVBO; glGenVertexArrays(1, &floorVAO); glBindVertexArray(floorVAO); { glGenBuffers(1, &floorVBO); glBindBuffer(GL_ARRAY_BUFFER, floorVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(floorVertices), floorVertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (void*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); } glBindVertexArray(0); // 盒子 GLuint cubeVAO, cubeVBO; glGenVertexArrays(1, &cubeVAO); { glGenBuffers(1, &cubeVBO); glBindVertexArray(cubeVAO); glBindBuffer(GL_ARRAY_BUFFER, cubeVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), &cubeVertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); glEnableVertexAttribArray(1); } glBindVertexArray(0); // 天空 GLuint skyboxVAO, skyboxVBO; glGenVertexArrays(1, &skyboxVAO); glBindVertexArray(skyboxVAO); { glGenBuffers(1, &skyboxVBO); glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO); glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), skyboxVertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GL_FLOAT), (void*)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GL_FLOAT), (void*)(2 * sizeof(GL_FLOAT))); glEnableVertexAttribArray(1); } glBindVertexArray(0); // Shader Shader shaderCube("./Shader/cube_vertex", "./Shader/cube_fragement"); Shader shaderFloor("./Shader/floor_vertex", "./Shader/floor_fragement"); Shader shaderSkybox("./Shader/skybox_vertex", "./Shader/skybox_fragement"); // 纹理 GLuint textCube = loadTexture("./Img/cube.jpg"); GLuint textFloor = loadTexture("./Img/floor.jpg"); std::vector<const GLchar*> vecSkyfaces; vecSkyfaces.push_back("./img/skybox/right.jpg"); vecSkyfaces.push_back("./img/skybox/left.jpg"); vecSkyfaces.push_back("./img/skybox/top.jpg"); vecSkyfaces.push_back("./img/skybox/bottom.jpg"); vecSkyfaces.push_back("./img/skybox/back.jpg"); vecSkyfaces.push_back("./img/skybox/front.jpg"); GLuint textureCubemap = loadCubemapTexture(vecSkyfaces); // 视图设置 glm::mat4 model = glm::mat4(); glm::mat4 view = camera.GetViewMatrix(); glm::mat4 projection = glm::perspective(camera.Zoom, (float)WIDTH / (float)HEIGHT, 0.0f, 100.0f); // 主循环 while (!glfwWindowShouldClose(pWnd)) { GLfloat currentFrame = glfwGetTime(); deltaTime = currentFrame - lastFrame; lastFrame = currentFrame; glfwPollEvents(); Do_Movement(); glClearColor(0.1f, 0.2f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // 绘制天空盒 shaderSkybox.useShaderPrograme(); view = glm::mat4(glm::mat3(camera.GetViewMatrix())); glUniformMatrix4fv(glGetUniformLocation(shaderSkybox.getPrograme(), "view"), 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(glGetUniformLocation(shaderSkybox.getPrograme(), "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glBindVertexArray(cubeVAO); // 使用天空盒数据 { glActiveTexture(GL_TEXTURE0); glUniform1i(glGetUniformLocation(shaderSkybox.getPrograme(), "skybox"), 0); glBindTexture(GL_TEXTURE_CUBE_MAP, textureCubemap); // 使用天空盒数据纹理 { glDrawArrays(GL_TRIANGLES, 0, 36); } glBindTexture(GL_TEXTURE_CUBE_MAP, 0); } glBindVertexArray(0); view = camera.GetViewMatrix(); // 绘制地面 shaderFloor.useShaderPrograme(); glBindVertexArray(floorVAO); { glUniformMatrix4fv(glGetUniformLocation(shaderFloor.getPrograme(), "model"), 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(glGetUniformLocation(shaderFloor.getPrograme(), "view"), 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(glGetUniformLocation(shaderFloor.getPrograme(), "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textFloor); { glDrawArrays(GL_TRIANGLES, 0, 6); } glBindTexture(GL_TEXTURE_2D, 0); } glBindVertexArray(0); // 绘制立方体 shaderCube.useShaderPrograme(); glBindVertexArray(cubeVAO); // 使用立方体数据 { glUniformMatrix4fv(glGetUniformLocation(shaderCube.getPrograme(), "model"), 1, GL_FALSE, glm::value_ptr(model)); glUniformMatrix4fv(glGetUniformLocation(shaderCube.getPrograme(), "view"), 1, GL_FALSE, glm::value_ptr(view)); glUniformMatrix4fv(glGetUniformLocation(shaderCube.getPrograme(), "projection"), 1, GL_FALSE, glm::value_ptr(projection)); glUniform3f(glGetUniformLocation(shaderCube.getPrograme(), "cameraPos"), camera.Position.x, camera.Position.y, camera.Position.z); glActiveTexture(GL_TEXTURE0); glUniform1i(glGetUniformLocation(shaderCube.getPrograme(), "inTexture"), 0); glBindTexture(GL_TEXTURE_CUBE_MAP, skyboxVAO); // 使用天空盒的纹理 { glDrawArrays(GL_TRIANGLES, 0, 36); } glBindTexture(GL_TEXTURE_2D, 0); } glBindVertexArray(0); glfwSwapBuffers(pWnd); } // While 循环之后 清理资源,退出程序 glDeleteVertexArrays(1, &cubeVAO); glDeleteVertexArrays(1, &floorVAO); glDeleteVertexArrays(1, &skyboxVAO); glDeleteBuffers(1, &cubeVBO); glDeleteBuffers(1, &floorVBO); glDeleteBuffers(1, &skyboxVBO); glfwTerminate(); return 0; } // ****************************************************** // 加载纹理 GLuint loadTexture(GLchar* path, GLboolean alpha /*= false*/) { int nPicW = 0, nPicH = 0; unsigned char* pChImg = SOIL_load_image(path, &nPicW, &nPicH, 0, alpha ? SOIL_LOAD_RGBA : SOIL_LOAD_RGB); GLuint textureID = 0; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); { glTexImage2D(GL_TEXTURE_2D, 0, alpha ? GL_RGBA : GL_RGB, nPicW, nPicH, 0, alpha ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, pChImg); glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, alpha ? GL_CLAMP_TO_EDGE : GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, alpha ? GL_CLAMP_TO_EDGE : 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(pChImg); return textureID; } // ****************************************************** // 加载天空盒纹理 GLuint loadCubemapTexture(std::vector<const GLchar *> vecSkyfaces) { GLuint textureId = 0; glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_CUBE_MAP, textureId); { int nW = 0, nH = 0; unsigned char* pChImg = nullptr; for (int i = 0; i < vecSkyfaces.size(); i++) { pChImg = SOIL_load_image(vecSkyfaces[i], &nW, &nH, 0, SOIL_LOAD_RGB); glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, nW, nH, 0, GL_RGB, GL_UNSIGNED_BYTE, pChImg); SOIL_free_image_data(pChImg); } glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); } glBindTexture(GL_TEXTURE_CUBE_MAP, 0); return textureId; } // ****************************************************** 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); } // ****************************************************** void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) glfwSetWindowShouldClose(window, GL_TRUE); if (action == GLFW_PRESS) keys[key] = true; else if (action == GLFW_RELEASE) keys[key] = false; } // ****************************************************** void mouse_callback(GLFWwindow* window, 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); }
Camera.h Shader.h 参考之前的文章
*********************************************
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Shader GLSL 语言部分
地面 立方体 天空 绘制渲染方式不一样
所以分别给它们定义Shader
地面
floor_vertex
#version 330 core layout (location = 0) in vec3 position; layout (location = 1) in vec2 texCoords; out vec2 TexCoords; uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { gl_Position = projection * view * model * vec4(position, 1.0f); TexCoords = texCoords; }
floor_fragement
#version 330 core in vec2 TexCoords; out vec4 color; uniform sampler2D inTexture; void main() { color = texture(inTexture, TexCoords); }
立方体
cube_vertex
// ================ #version 330 core layout (location = 0) in vec3 pos; layout (location = 1) in vec3 normal; //out vec2 TexCoords; out vec3 Normal; out vec3 Pos; uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { gl_Position = projection * view * model * vec4(pos, 1.0f); //TexCoords = texCoords; Normal = mat3(transpose(inverse(model))) * normal; Pos = vec3(model * vec4(pos, 1.0f)); }
cube_fragement
// ================ #version 330 core //in vec2 TexCoords; in vec3 Normal; in vec3 Pos; out vec4 color; uniform vec3 cameraPos; uniform samplerCube skybox; //uniform sampler2D inTexture; void main() { //color = texture(inTexture, TexCoords); vec3 I = normalize(Pos - cameraPos); vec3 R = reflect(I, normalize(Normal)); color = texture(skybox, R); }
天空
skybox_vertex
#version 330 core layout (location = 0) in vec3 position; out vec3 TexCoords; uniform mat4 view; uniform mat4 projection; void main() { gl_Position = projection * view * vec4(position, 1.0f); TexCoords = position; }
skybox_fragement
// ================ #version 330 core in vec3 TexCoords; out vec4 color; uniform samplerCube skybox; void main() { color = texture(skybox, TexCoords); }
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: 使用OpenGL shader做一个能变灰的精灵
- 下一篇: opengl简单例子画rgb565数据