球面渲染
但是还是存在拼接缝问题;X分的份越多这个缝越小,但是目前没有解决
#include "stdafx.h" #include <glad/glad.h> #include <GLFW/glfw3.h> #include <shader.h> #include <iostream> #include <cmath> #include <vector> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/type_ptr.hpp> #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" const unsigned int screen_width = 780; const unsigned int screen_height = 780; const GLfloat PI = 3.14159265358979323846f; const int Y_SEGMENTS = 50; const int X_SEGMENTS = 500; unsigned int textureID; GLuint pos_matrix_idx, face_matrix_idx, projID, viewID, texLoc; int main() { glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #ifdef __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif glfwWindowHint(GLFW_RESIZABLE, GL_FALSE); auto window = glfwCreateWindow(screen_width, screen_height, "Earth Sphere", nullptr, nullptr); if (window == nullptr) { std::cout << "Failed to Create OpenGL Context" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } glViewport(0, 0, screen_width, screen_height); Shader shader("vertexShader.glsl", "fragmentShader.glsl"); // 交错存储:3坐标 + 2UV std::vector<float> sphereVertices; sphereVertices.reserve((X_SEGMENTS + 1) * (Y_SEGMENTS + 1) * 5); for (int y = 0; y <= Y_SEGMENTS; y++) { float ySegment = static_cast<float>(y) / Y_SEGMENTS; float phi = ySegment * PI; for (int x = 0; x <= X_SEGMENTS; x++) { float xSegment = static_cast<float>(x) / X_SEGMENTS; float theta; float xPos, yPos, zPos; // 关键:最后一列顶点强制复用x=0的球面坐标,彻底消除浮点分离 if (x == X_SEGMENTS) { theta = 0.0f; } else { theta = xSegment * 2.0f * PI; } xPos = cos(theta) * sin(phi); yPos = cos(phi); zPos = sin(theta) * sin(phi); sphereVertices.push_back(xPos); sphereVertices.push_back(yPos); sphereVertices.push_back(zPos); sphereVertices.push_back(xSegment); sphereVertices.push_back(ySegment); } } // 索引 std::vector<unsigned int> sphereIndices; sphereIndices.reserve(X_SEGMENTS * Y_SEGMENTS * 6); int rowVtxCount = X_SEGMENTS + 1; for (int i = 0; i < Y_SEGMENTS; i++) { for (int j = 0; j < X_SEGMENTS; j++) { unsigned int p0 = i * rowVtxCount + j; unsigned int p1 = (i + 1) * rowVtxCount + j; unsigned int p2 = (i + 1) * rowVtxCount + (j + 1); unsigned int p3 = i * rowVtxCount + (j + 1); sphereIndices.push_back(p0); sphereIndices.push_back(p1); sphereIndices.push_back(p2); sphereIndices.push_back(p0); sphereIndices.push_back(p2); sphereIndices.push_back(p3); } } unsigned int VBO, VAO, EBO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); glGenBuffers(1, &EBO); glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sphereVertices.size() * sizeof(float), sphereVertices.data(), GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sphereIndices.size() * sizeof(unsigned int), sphereIndices.data(), GL_STATIC_DRAW); // 坐标 0,步长5 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // UV 1,偏移3float glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); glBindVertexArray(0); // 纹理:删除错误的单列镜像逻辑,简化加载 stbi_set_flip_vertically_on_load(true); int W = 0, H = 0, ch = 0; unsigned char* data = stbi_load("./dq2.jpg", &W, &H, &ch, 0); if (!data) { std::cout << "贴图 dq2.jpg 未找到或无法加载,请放到 exe 目录" << std::endl; } else { GLenum fmt = (ch == 4) ? GL_RGBA : GL_RGB; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, fmt, W, H, 0, fmt, GL_UNSIGNED_BYTE, data); stbi_image_free(data); } shader.use(); pos_matrix_idx = glGetUniformLocation(shader.ID, "pos_matrix"); face_matrix_idx = glGetUniformLocation(shader.ID, "face_matrix"); projID = glGetUniformLocation(shader.ID, "projection"); viewID = glGetUniformLocation(shader.ID, "view"); texLoc = glGetUniformLocation(shader.ID, "tex"); glUniform1i(texLoc, 0); //渲染循环 while (!glfwWindowShouldClose(window)) { glClearColor(0.0f, 0.34f, 0.57f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_DEPTH_TEST); shader.use(); glm::mat4 proj = glm::perspective(glm::radians(45.f), static_cast<float>(screen_width) / screen_height, 0.1f, 100.f); glUniformMatrix4fv(projID, 1, GL_FALSE, &proj[0][0]); glm::mat4 view = glm::lookAt(glm::vec3(0, 0, 3.2f), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); glUniformMatrix4fv(viewID, 1, GL_FALSE, &view[0][0]); float time = static_cast<float>(glfwGetTime()); glm::mat4 trans = glm::translate(glm::mat4(1), glm::vec3(0, 0.2f, 0)); glm::mat4 rot = glm::rotate(glm::mat4(1), time * 0.5f, glm::vec3(1, 0.5, 0)); glUniformMatrix4fv(pos_matrix_idx, 1, GL_FALSE, &trans[0][0]); glUniformMatrix4fv(face_matrix_idx, 1, GL_FALSE, &rot[0][0]); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textureID); glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(sphereIndices.size()), GL_UNSIGNED_INT, nullptr); glfwSwapBuffers(window); glfwPollEvents(); } glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &EBO); glfwTerminate(); return 0; }
#version 330 core in vec2 TexCoord; out vec4 FragColor; uniform sampler2D tex; void main() { vec2 uv = TexCoord; // 截断u最大为1,禁止硬件REPEAT跑到0 uv.x = min(uv.x, 1.0); FragColor = texture(tex, uv); }
#version 330 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec2 aTexCoord; out vec2 TexCoord; uniform mat4 projection; uniform mat4 view; uniform mat4 pos_matrix; uniform mat4 face_matrix; void main() { mat4 model = pos_matrix * face_matrix; gl_Position = projection * view * model * vec4(aPos, 1.0); TexCoord = aTexCoord; }

浙公网安备 33010602011771号