球面渲染
但是还是存在拼接缝问题;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); #endifglfwWindowHint(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坐标 + 2UVstd::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,步长5glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// UV 1,偏移3floatglVertexAttribPointer(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跑到0uv.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; }

