试图在OpenGL中绘制球体,只有一部分球显示出来,似乎被夹住了吗?

发布于 2025-02-11 22:02:00 字数 5373 浏览 0 评论 0 原文

我创建了一个最小的设置,其中片段着色器设置要编写的颜色,甚至没有参数。 顶点着色器通过矩阵传递并转换点。我们可以看到球体,但只有一部分。

我犹豫要发布整个代码,尽可能努力地使用最低工作解决方案,但是大约300行(包括着色器加载代码)。我只会发布核心件,如果人们想要更多,我会发布所有内容。

这是演示的代码,包括被剥离的球体类和Glmain。 未显示的是main(),它确实不会显示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);
}

I created a minimal setup with a fragment shader setting the color to write, so not even a parameter.
The vertex shader passes in a matrix and transforms the points. We can see the sphere, but only part of it.

I hesitate to post the whole code, trying as hard as possible for a minimum working solution but it's about 300 lines including the shader loading code. I will post just the core pieces, and if people want more I will post it all.

Here is the code for the demo including a stripped down Sphere class and glmain.
Not shown is main() which does try..catch and calls 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 );
}

Points did not display at all so the call is commented out. We drew a line strip instead. That works somewhat. Why is it truncated? Why doesn't it at least finish the layer of the sphere?

The shaders are shown below:

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

fragment shader:

#version 330 core

out vec4 color;

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

陌路黄昏 2025-02-18 22:02:00

size 参数” glbufferdata 指定缓冲对象的新数据存储的字节中的大小:

glbufferdata(gl_array_buffer,nosolution,nosolution,vert,vert,gl_static_draw);

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

The size argument of glBufferData specifies the size in bytes of the buffer object's new data store:

glBufferData(GL_ARRAY_BUFFER, resolution, vert, GL_STATIC_DRAW);

glBufferData(GL_ARRAY_BUFFER, resolution * 3 * sizeof(float), vert, GL_STATIC_DRAW);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文