ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

OpenGL画球面(6)

2022-05-20 00:31:25  阅读:258  来源: 互联网

标签:GL OpenGL int 球面 SEGMENTS GLFW 顶点 include


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

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

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

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

 

 

 

 

 

 

 注意看β的位置:

 

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

 

 “这一部分就是生成顶点的代码实现,Y_SEGMENTS 和 X_SEGMENTS 表 示将α 和β 分割了多少份,y 和 x 表示分别是第几份,以此进行遍历, xSegment*2.0f*PI 即β 角,ySegment*PI 即α 角。”--引用自实验

 

 “需要注意的是,在横向分割时,n=0 和 n= X_SEGMENTS 是位置相同的点, 如果后期需要加载纹理则不能随意将之舍去,所以顶点总数实际上是 (X_SEGMENTS + 1)* (Y_SEGMENTS+1)”--引用自万琳老师实验

 

3.2 

由于 opengl 中是以三角形为基本图元进行绘制的,所以在我们得到了球面 的顶点数组后,我们需要构造成基本的三角形图元。

 

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

 

 

 

 3.4 关于背面剔除

“       由于 opengl 中默认的绘 制方式为填充模式,所以我们需要改填充模式为线框模式,这样可以更好的检 查绘制结果”

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);线框模式

“      由于 opengl 中绘制时会同时绘制正面和背面,并且我们开启了线框模式后, 并不能通过深度测试将背面遮挡住,所以我们需要开启面剔除。来将背面剔除, 面剔除主要是剔除顶点绕法为顺时针的面”

  glEnable(GL_CULL_FACE);
  glCullFace(GL_BACK);

背面剔除效果展示:

                                                         

 

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

                                                 

 

 好了,到此圆球画完了

代码来源于万琳老师课件:

#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);
}

 

标签:GL,OpenGL,int,球面,SEGMENTS,GLFW,顶点,include
来源: https://www.cnblogs.com/8335IT/p/16290888.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有