【问题标题】:Simple line rendering fails while trying to render pixel coordinates尝试渲染像素坐标时,简单线渲染失败
【发布时间】:2020-05-24 18:04:56
【问题描述】:

我很抱歉把它带到这里,但我花了大约 7 个小时也许是为了一件非常简单的事情。也许你们中的一些人发现了问题。

我尝试将一些像素坐标渲染到屏幕上。代码如下。

适用于 800x600 屏幕。只需尝试计算线条的位置,然后将其渲染到屏幕上。

例如:点 A(400, 300, 0) 和点 B(500,300,0) 应该是一条从屏幕中心向右的简单黑线。

当我在渲染中调用这个类函数时,我想我可能会创建一个单独的渲染会话。但是,当我编写诸如 glCleanColor 之类的内容时,背景会发生变化。


#include <GLFW/glfw3.h>
#include <GL/gl.h>
#include <GL/glew.h>

#include <iostream>
#include <vector>

顶点着色器:

const GLchar *vertex_shader =
    "#version 410\n"
    "layout (location = 0) in vec3 pos;\n"
    "layout (location = 1) in vec4 col;\n"
    "uniform mat4 projection;\n"
    "out vec4 Frag_Color;\n"
    "void main()\n"
    "{\n"
    "    Frag_Color = col;\n"
    "    gl_Position =projection*vec4(pos.xyz,1);\n"
    "}\n";

片段着色器:

const GLchar *fragment_shader =
    "#version 410\n"
    "in vec4 Frag_Color;\n"
    "layout (location = 0) out vec4 Out_Color;\n"
    "void main()\n"
    "{\n"
    "    Out_Color = Frag_Color;\n"
    "}\n";

顶点结构

struct Vrtx
{
    float pos[3];
    float col[4] = {0.0f, 0.0f, 0.0f, 1.0f};
};

坐标轴类:

class CoordinateAxis
{
public:
    void coordinate_axis()
    {
        vertices.resize(6);
        for (int i = 0; i < 3; i++)
        {
            vertices[2 * i].pos[0] = 400;
            vertices[2 * i].pos[1] = 300;
            vertices[2 * i].pos[2] = 0;
        }
        vertices[1].pos[0] = 500;
        vertices[1].pos[1] = 300;
        vertices[1].pos[2] = 0;
        vertices[3].pos[0] = 400;
        vertices[3].pos[1] = 400;
        vertices[3].pos[2] = 0;
        vertices[3].pos[0] = 400;
        vertices[3].pos[1] = 430;
        vertices[3].pos[2] = 100;

        setupRender();
        glBindVertexArray(VAO);
        glDrawElements(GL_LINE, 6, GL_UNSIGNED_INT, 0);
        glBindVertexArray(0);
        glUseProgram(0);
    }
    CoordinateAxis()
    {
        initShaderProgram();
    };

private:
    void initShaderProgram()
    {
        // Vertex shader
        GLuint vHandle = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vHandle, 1, &vertex_shader, NULL);
        glCompileShader(vHandle);

        // Fragment shader
        GLuint fHandle = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fHandle, 1, &fragment_shader, NULL);
        glCompileShader(fHandle);

        // Create Program
        handleProgram = glCreateProgram();
        glAttachShader(handleProgram, vHandle);
        glAttachShader(handleProgram, fHandle);
        glLinkProgram(handleProgram);

        attribLocationProj = glGetUniformLocation(handleProgram, "projection");

        glGenVertexArrays(1, &VAO);
        // CreateBuffers
        glGenBuffers(1, &vboHandle);
        glGenBuffers(1, &iboHandle);
    }
    void setupRender()
    {
        GLint last_viewport[4];
        glGetIntegerv(GL_VIEWPORT, last_viewport);
        float L = last_viewport[0];
        float R = L + last_viewport[2];
        float B = last_viewport[1];
        float T = B + last_viewport[3];

        const float ortho_projection[4][4] =
            {
                {2.0f / (R - L), 0.0f, 0.0f, 0.0f},
                {0.0f, 2.0f / (T - B), 0.0f, 0.0f},
                {0.0f, 0.0f, -1.0f, 0.0f},
                {(R + L) / (L - R), (T + B) / (B - T), 0.0f, 1.0f},
            };
        glUseProgram(handleProgram);
        glUniformMatrix4fv(attribLocationProj, 1, GL_FALSE, &ortho_projection[0][0]);
        glBindVertexArray(VAO);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboHandle);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW);

        glBindBuffer(GL_ARRAY_BUFFER, vboHandle);
        glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vrtx), vertices.data(), GL_STATIC_DRAW);

        glBindBuffer(GL_ARRAY_BUFFER, vboHandle);
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertices.size() * sizeof(Vrtx), 0);
        glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, vertices.size() * sizeof(Vrtx), (void *)(3 * sizeof(float)));

        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
    }

    std::vector<Vrtx> vertices;
    std::vector<GLuint> indices;
    GLuint handleProgram, VAO, vboHandle, iboHandle, attribLocationProj;
};

【问题讨论】:

    标签: c++ opengl graphics


    【解决方案1】:

    GL_LINE 不是有效的原始类型。 GL_LINEglPolygonMode 的一种模式。
    一个有效的line primitive 类型是GL_LINES

    glDrawElements(GL_LINE, 6, GL_UNSIGNED_INT, 0);

    glDrawElements(GL_LINES, 6, GL_UNSIGNED_INT, 0);
    

    此外,当您通过glVertexAttribPointer 设置顶点属性数据数组时存在问题。第 5 个参数 (strid) 是连续属性元组之间的字节偏移量,而不是缓冲区的大小。 sizeof(Vrtx) 而不是 vertices.size() * sizeof(Vrtx)

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vrtx), 0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(Vrtx), (void *)(3*sizeof(float)));
    

    注意,索引数组似乎是空的。要么初始化索引数组:

    indices = { 0, 1, 2, 3, 4, 5 };
    

    或改用glDrawArrays

    glDrawArrays(GL_LINES, 0, 6);
    

    【讨论】:

    • 在我向上帝抱怨这个问题之后,我可以拥抱你吗?
    • @sariug glVertexAttribPointer 中还有一个问题。我已经扩展了答案。
    猜你喜欢
    • 2021-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-25
    相关资源
    最近更新 更多