尝试在OpenGL中绘制球体,仅显示球体的一部分,似乎被裁剪?

n7taea2i  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(140)

我创建了一个最小的设置,用一个片段着色器来设置颜色,所以甚至没有一个参数。顶点着色器传入一个矩阵,并转换点。我们可以看到球体,但只是它的一部分。
我不想把整个代码都贴出来,我尽可能地把代码写得最少,但是包括着色器加载代码在内,大约有300行。我只会把核心部分贴出来,如果有人想要更多的话,我会把所有的都贴出来。
下面是演示代码,包括一个精简的Sphere类和glmain。


# include <GL/glew.h>

# include "common/common.hh"

# include <glm/glm.hpp>

# include <glm/ext.hpp>

# include <numbers>

# include <iostream>

# include <iomanip>

# include <cstdint>

# include <string>

using namespace std;
using namespace glm;
using namespace std::numbers;
class Sphere {
    private:
    uint32_t progid; // handle to the shader code
    uint32_t vao; // array object container for vbo and indices
    uint32_t vbo; // handle to the point data on the graphics card
    uint32_t lbo; // handle to buffer of indices for lines for wireframe sphere
    uint32_t latRes, lonRes;
    uint32_t resolution;
    public:
    /**
     * @brief Construct a sphere
     *
     * @param r radius of the sphere
     * @param latRes resolution of the grid in latitude
     * @param lonRes resolution of the grid in latitude
     */
    Sphere(double r, uint32_t latRes, uint32_t lonRes);
    ~Sphere() { cleanup(); }
    void render(mat4& trans);
    void cleanup();
};

Sphere::Sphere(double r, uint32_t latRes, uint32_t lonRes) : latRes(latRes), lonRes(lonRes),
    resolution((2*latRes-2)*lonRes + 2) {
    progid = loadShaders( "05_3d.vert", "02simple.frag" );
    double dlon = 2.0*numbers::pi / lonRes, dlat = numbers::pi / latRes;
    double z;
    double lat = -numbers::pi/2 + dlat; // latitude in radians
    double rcircle;
    float vert[resolution*3]; // x,y,z
    uint32_t c = 0;
    for (uint32_t j = 0; j < 2*latRes-2; j++, lat += dlat) {
    //what is the radius of hte circle at that height?
    rcircle = r* cos(lat); // size of the circle at this latitude
    z = r * sin(lat); // height of each circle
    double t = 0;
    for (uint32_t i = 0; i < lonRes; i++, t += dlon) {
        vert[c++] = rcircle * cos(t), vert[c++] = rcircle * sin(t);
        vert[c++] = z;
    }
    cout << endl;
    }
    // south pole
    vert[c++] = 0;
    vert[c++] = 0;
    vert[c++] = -r;

    // north pole
    vert[c++] = 0;
    vert[c++] = 0;
    vert[c++] = r;

    cout << "resolution: " << resolution << endl;
    cout << "predicted num vert components: " << resolution*3 << endl;  
    cout << "actual num vert components: " << c << endl;

    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, resolution, vert, GL_STATIC_DRAW);
    glBindVertexArray(0);
}

void Sphere::render(mat4& trans) {
    glUseProgram(progid);           // Use the shader
    uint32_t matrixID = glGetUniformLocation(progid, "trans");
    glUniformMatrix4fv(matrixID, 1, GL_FALSE, &trans[0][0]);

    glBindVertexArray(vao);
    glVertexAttribPointer(
    0,                  // first parameter to shader, numbered 0
        3,                  // 3 floating point numbers (x,y,z)
        GL_FLOAT,           // type
        GL_FALSE,           // normalized?
        0,                  // this is the entire set of data, move on
        (void*)0            // array buffer offset
    );
    glEnableVertexAttribArray(0); // pass x,y to shader

    glEnable(GL_PROGRAM_POINT_SIZE);

    //points don't work, why not? And how to set the size of the points?
    glPointSize(5);
    glDrawArrays(GL_POINT, 0, resolution);

    // line strips work, but incomplete (see screen shot)
    glDrawArrays(GL_LINE_STRIP, 0, resolution);
    glDisableVertexAttribArray(0);
}

void Sphere::cleanup() {
    glDeleteBuffers(1, &vbo);   // remove vbo memory from graphics card
    glDeleteVertexArrays(1, &vao); // remove vao from graphics card
    glDeleteProgram(progid);
}

using namespace std;

void glmain() {
    win = createWindow(800, 800, "Sphere demo");

    glClearColor(0.0f, 0.0f, 0.4f, 0.0f);   // Dark blue background
    Sphere sphere(1.0, 30, 15);
    mat4    trans= lookAt(vec3(0,0,0), vec3(10,5,10), vec3(0,1,0));
    do {
        glClear( GL_COLOR_BUFFER_BIT );     // Clear the screen
        //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glDisable(GL_DEPTH_TEST);
        //glDepthFunc(GL_LESS);
        sphere.render(trans);
        glfwSwapBuffers(win);             // double buffer
        glfwPollEvents();
    }   while( glfwGetKey(win, GLFW_KEY_ESCAPE ) != GLFW_PRESS &&
                        glfwWindowShouldClose(win) == 0 );
}

点完全没有显示,所以这个调用被注解掉了。我们画了一个线条带。这有点作用。为什么它被截断了?为什么它至少没有完成球体的图层?

着色器如下所示:


# version 330 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 v;
uniform mat4 trans;

void main(){
    gl_PointSize = 5;
    gl_Position = trans * vec4(v,1.0);
    gl_Position.w = 1.0;
}

片段着色器:


# version 330 core

out vec4 color;

void main()
{
    color = vec4(1,1,1,1);
}
r6l8ljro

r6l8ljro1#

glBufferDatasize 参数指定缓冲区对象的新数据存储的大小(以字节为单位):
glBufferData(GL_ARRAY_BUFFER, resolution, vert, GL_STATIC_DRAW);

glBufferData(GL_ARRAY_BUFFER, resolution * 3 * sizeof(float), vert, GL_STATIC_DRAW);

相关问题