• OpenGL画球面(6)


    1 画球,先要把球面按照经纬线,分成N等分;在每两条经纬线包着的区域就相当于是一个四边形,这个四边形是两个三角形拼成的;

    2 画球要计算球面上顶点的坐标,我们暂时不做球面贴图,不考虑纹理坐标

    3本博客根据华科万琳老师的讲义进行编写;如有冒犯,请及时评论联系;

    3.1如何计算球面上某一个点P的坐标:

     

     注意看β的位置:不要被俯视图的那条灰色的线迷惑;

     上边你已经知道P的X,Y, Z坐标要如何计算了,那关键是找到α和β,下边看如何找到某一个点的的这个两个角度

    顶点的坐标的计算(R=1):

    3.2 通过三角形图元构造球体面片

    3.3下边要开始构造顶点索引:顶点索引的代码会在后边统一贴出

     

     3.4 关于背面剔除

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);线框模式

    glEnable(GL_CULL_FACE);//背面剔除
    glCullFace(GL_BACK);

    背面剔除效果展示:

                                                             

    如果不剔除背面会怎么样:

                                                     

     好了,到此圆球画完了

    代码来源于万琳老师课件:支持老师官方地址观看:计算机图形学_华中科技大学_中国大学MOOC(慕课) (icourse163.org)

    #include <glad/glad.h>
    #include <GLFW/glfw3.h>
    #include <shader.h>  这个头文件你下载了learnopengl的源码里边就有了
    #include <iostream>
    #include <math.h>
    #include <vector>
    const unsigned int screen_width = 780;
    const unsigned int screen_height = 780;
    
    const GLfloat  PI = 3.14159265358979323846f;
    
    //将球横纵划分成X*Y的网格
    const int Y_SEGMENTS = 10;
    const int X_SEGMENTS = 10;
    
    
    int main()
    {
        // 初始化GLFW
        glfwInit();                                                     // 初始化GLFW
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);                  // OpenGL版本为3.3,主次版本号均设为3
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
        glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);  // 使用核心模式(无需向后兼容性)
        glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);            // 如果使用的是Mac OS X系统,需加上这行
        glfwWindowHint(GLFW_RESIZABLE, 0);                            // 不可改变窗口大小
    
                                                                        // 创建窗口(宽、高、窗口名称)
        auto window = glfwCreateWindow(screen_width, screen_height, "Sphere", nullptr, nullptr);
        if (window == nullptr) {                                        // 如果窗口创建失败,输出Failed to Create OpenGL Context
            std::cout << "Failed to Create OpenGL Context" << std::endl;
            glfwTerminate();
            return -1;
        }
        glfwMakeContextCurrent(window);                                 // 将窗口的上下文设置为当前线程的主上下文
    
                                                                        // 初始化GLAD,加载OpenGL函数指针地址的函数
        if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
        {
            std::cout << "Failed to initialize GLAD" << std::endl;
            return -1;
        }
    
        // 指定当前视口尺寸(前两个参数为左下角位置,后两个参数是渲染窗口宽、高)
        glViewport(0, 0, screen_width, screen_height);
    
    
    
    
        Shader shader("res/shader/task3.vs", "res/shader/task3.fs");//加载着色器
    
        std::vector<float> sphereVertices;
        std::vector<int> sphereIndices;
    
    
        // 生成球的顶点
        for (int y = 0; y <= Y_SEGMENTS; y++)
        {
            for (int x = 0; x <= X_SEGMENTS; x++)
            {
                float xSegment = (float)x / (float)X_SEGMENTS;
                float ySegment = (float)y / (float)Y_SEGMENTS;
                float xPos = std::cos(xSegment * 2.0f * PI) * std::sin(ySegment * PI);
                float yPos = std::cos(ySegment * PI);
                float zPos = std::sin(xSegment * 2.0f * PI) * std::sin(ySegment * PI);
    
    
                sphereVertices.push_back(xPos);
                sphereVertices.push_back(yPos);
                sphereVertices.push_back(zPos);
            }
        }
    
        // 生成球的;三角形面索引
        for (int i = 0; i < Y_SEGMENTS; i++)
        {
            for (int j = 0; j < X_SEGMENTS; j++)
            {
    
                sphereIndices.push_back(i * (X_SEGMENTS + 1) + j);
                sphereIndices.push_back((i + 1) * (X_SEGMENTS + 1) + j);
                sphereIndices.push_back((i + 1) * (X_SEGMENTS + 1) + j + 1);
    
                sphereIndices.push_back(i * (X_SEGMENTS + 1) + j);
                sphereIndices.push_back((i + 1) * (X_SEGMENTS + 1) + j + 1);
                sphereIndices.push_back(i * (X_SEGMENTS + 1) + j + 1);
            }
        }
    
    
        //
        unsigned int VBO, VAO;
        glGenVertexArrays(1, &VAO);
        glGenBuffers(1, &VBO);
        //生成并绑定球体的VAO和VBO
        glBindVertexArray(VAO);
    
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        // 将顶点数据绑定至当前默认的缓冲中
        glBufferData(GL_ARRAY_BUFFER, sphereVertices.size() * sizeof(float), &sphereVertices[0], GL_STATIC_DRAW);
    
        GLuint element_buffer_object; //EBO
        glGenBuffers(1, &element_buffer_object);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, element_buffer_object);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sphereIndices.size() * sizeof(int), &sphereIndices[0], GL_STATIC_DRAW);
    
        // 设置顶点属性指针
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);
    
        // 解绑VAO和VBO
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        glBindVertexArray(0);
    
    
        // 渲染循环
        while (!glfwWindowShouldClose(window))
        {
            // 清空颜色缓冲
            glClearColor(0.0f, 0.34f, 0.57f, 1.0f);
            glClear(GL_COLOR_BUFFER_BIT);
    
            shader.use();
            //绘制球
            //开启面剔除(只需要展示一个面,否则会有重合)
            //glEnable(GL_CULL_FACE);
            //glCullFace(GL_BACK);
            glBindVertexArray(VAO);
            //使用线框模式绘制
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
            glDrawElements(GL_TRIANGLES, X_SEGMENTS*Y_SEGMENTS * 6, GL_UNSIGNED_INT, 0);
            //点阵模式绘制
            //glPointSize(5);
            //glDrawElements(GL_POINTS, X_SEGMENTS*Y_SEGMENTS*6, GL_UNSIGNED_INT, 0);
            //交换缓冲并且检查是否有触发事件(比如键盘输入、鼠标移动等)
            glfwSwapBuffers(window);
            glfwPollEvents();
        }
    
        // 删除VAO和VBO,EBO
        glDeleteVertexArrays(1, &VAO);
        glDeleteBuffers(1, &VBO);
        glDeleteBuffers(1, &element_buffer_object);
    
        // 清理所有的资源并正确退出程序
        glfwTerminate();
        return 0;
    }
    #version 330 core
    layout (location = 0) in vec3 aPos;
    
    
    void main()
    {
        gl_Position =vec4(aPos, 1.0);
    }
    ---------------------------------------
    #version 330 core
    out vec4 FragColor;
    
    void main()
    {
        FragColor = vec4(1.0,0.635,0.345,1.0);
    }
  • 相关阅读:
    java线程
    面向切面编程
    控制反转IOC与依赖注入DI
    phpexecel 导入导出,格式
    PHPExcel设置数据格式的几种方法
    九度oj 题目1416:猴子吃坚果
    九度oj 题目1397:查找数段
    poj 1065 Wooden Sticks
    poj 3181 Dollar Dayz
    poj 1742 Coins
  • 原文地址:https://www.cnblogs.com/8335IT/p/16290888.html
Copyright © 2020-2023  润新知