球面渲染

但是还是存在拼接缝问题;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;
}

image

 

posted on 2026-06-16 02:03  邗影  阅读(0)  评论(0)    收藏  举报

导航