Когда я вызываю glDrawElements, я получаю странное поведение - PullRequest
0 голосов
/ 26 марта 2020

Я писал базовый c пакетный рендер для текстур, но каким-то образом он рендерит только одну текстуру, а не четыре. Что-то не так с кодом ниже? Я не могу найти ничего плохого в этом. Я использую GLEW и GLFW для управления окнами.

Классы VertexBuffer, VertexArray, IndexBuffer, Shader и Texture были протестированы, и они работают правильно.

void BatchRenderObjects(vector<ObjectInstance> texq, GLuint tex_id, Shader shader)
{
int current_index = 0;
int array_index = 0;
const size_t vb_size = 20 * (texq.size());
const size_t ib_size = 6 * texq.size();
const size_t texslot_size = 32;

VertexBuffer VBO(GL_ARRAY_BUFFER);
IndexBuffer IBO;
VertexArray VAO;

GLfloat *vertex_buffer = new GLfloat[vb_size];
GLuint *index_buffer = new GLuint[ib_size];

{
    unsigned int offset = 0;
    for (int i = 0; i < ib_size; i += 6)
    {
        index_buffer[i + 0] = 0 + offset;
        index_buffer[i + 1] = 1 + offset;
        index_buffer[i + 2] = 2 + offset;
        index_buffer[i + 3] = 2 + offset;
        index_buffer[i + 4] = 3 + offset;
        index_buffer[i + 5] = 0 + offset;

        offset += 4;
    }
}

{
    for (int i = 0; i < texq.size(); i++)
    {
        vertex_buffer[current_index + 0] = texq[i].coords[0];
        vertex_buffer[current_index + 1] = texq[i].coords[1];
        vertex_buffer[current_index + 2] = texq[i].coords[2];
        vertex_buffer[current_index + 3] = texq[i].tex_coords[0];
        vertex_buffer[current_index + 4] = texq[i].tex_coords[1];

        vertex_buffer[current_index + 5] = texq[i].coords[3];
        vertex_buffer[current_index + 6] = texq[i].coords[4];
        vertex_buffer[current_index + 7] = texq[i].coords[5];
        vertex_buffer[current_index + 8] = texq[i].tex_coords[2];
        vertex_buffer[current_index + 9] = texq[i].tex_coords[3];

        vertex_buffer[current_index + 10] = texq[i].coords[6];
        vertex_buffer[current_index + 11] = texq[i].coords[7];
        vertex_buffer[current_index + 12] = texq[i].coords[8];
        vertex_buffer[current_index + 13] = texq[i].tex_coords[4];
        vertex_buffer[current_index + 14] = texq[i].tex_coords[5];

        vertex_buffer[current_index + 15] = texq[i].coords[9];
        vertex_buffer[current_index + 16] = texq[i].coords[10];
        vertex_buffer[current_index + 17] = texq[i].coords[11];
        vertex_buffer[current_index + 18] = texq[i].tex_coords[6];
        vertex_buffer[current_index + 19] = texq[i].tex_coords[7];

        current_index = current_index + 20;
    }
}

// Setup vertex buffer, index buffer and vertex array
{
    VAO.Bind();
    VBO.BufferData(vb_size, vertex_buffer, GL_STATIC_DRAW);
    VBO.VertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)0);
    VBO.VertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    IBO.BufferData(ib_size, index_buffer, GL_STATIC_DRAW);
    VAO.Unbind();
}

shader.Use();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_id);
glUniform1i(glGetUniformLocation(shader.GetProgramID(), "u_Texture"), 0);
VAO.Bind();
glDrawElements(GL_TRIANGLES, 6 * texq.size(), GL_UNSIGNED_INT, 0);
//glDrawArrays(GL_TRIANGLES, 0, 24); 
VAO.Unbind();

return; 
}

На самом деле это очень просто c , Он генерирует Vertex Buffer и Index Buffer из структуры и выводит aws текстуру на экран. Вот структура ObjectInstance.

struct  ObjectInstance
{
    float coords[12]; 
    float tex_coords[8];
};

И, наконец, фрагмент моей основной функции.

ObjectInstance t1 = { {-1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f},
            {1.0f, 1.0f,  1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}};

ObjectInstance t2 = { {-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f},
                    {1.0f, 1.0f,  1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}};

ObjectInstance t3 = { {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f},
                {1.0f, 1.0f,  1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}};

ObjectInstance t4 = { {0.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f},
                {1.0f, 1.0f,  1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}};

std::vector<ObjectInstance> test_vector;

test_vector.push_back(t1);
test_vector.push_back(t2);
test_vector.push_back(t3);
test_vector.push_back(t4);

Я вызываю функцию с соответствующими аргументами в игре l oop.

Наконец, вот мой вершинный и фрагментный шейдер. VERTEX SHADER:

#version 330 core
layout(location = 0) in vec3 position;
layout(location = 1) in vec2 texCoord;

out vec2 TexCoord;

void main()
{
    gl_Position = vec4(position, 1.0f);
    TexCoord = texCoord; 
}

FRAGMENT SHADER

#version 330 core

in vec2 TexCoord;
out vec4 color; // the color outputted

uniform sampler2D u_Texture;

void main()
{
    color = texture(u_Texture, TexCoord); 
}

Нет, у меня есть одна текстура, которую я хочу нарисовать 4 раза. Это всего лишь одна текстура, которую я хочу нарисовать в разных координатах экрана. Но, видимо, я получаю только один из тех, что напечатаны в левом нижнем углу. У вас есть идея, почему я получаю эту ошибку?

Ответы [ 4 ]

2 голосов
/ 26 марта 2020

Давайте начнем с этого кода:

const size_t vb_size = 20 * (texq.size());of GLfloats
const size_t ib_size = 6 * texq.size();

Не имею представления о вашем конкретном классе абстракции объекта буфера, но glBufferData в GL ожидает размер в байтах , поэтому

VBO.BufferData(vb_size, ...);
IBO.BufferData(ib_size, ...);

будет загружать только 1/4 ваших фактических данных (совпадение точно с первым из четырех ваших объектов случайно).

1 голос
/ 29 марта 2020

У меня проблема. Дело в том, что opengl принимает размеры в байтах. Как сказал Самуэль ..

Эй, вот в чем проблема.

const size_t vb_size = 20 * (texq.size());
const size_t ib_size = 6 * texq.size();

Должно быть

const size_t vb_size = (20 * (texq.size())) * sizeof(GLfloat); 
const size_t ib_size = (6 * texq.size()) * sizeof(GLfloat);
1 голос
/ 29 марта 2020

Эй, вот проблема.

const size_t vb_size = 20 * (texq.size());
const size_t ib_size = 6 * texq.size();

Должно быть

const size_t vb_size = (20 * (texq.size())) * sizeof(GLfloat); 
const size_t ib_size = (6 * texq.size()) * sizeof(GLfloat);

Это потому, что OpenGL принимает размер в необработанных байтах.

1 голос
/ 26 марта 2020

Все ваши объекты имеют одинаковые координаты текстуры. Так как вы пишете пакетный рендер, все ваши объекты визуализируются одним вызовом отрисовки, что означает единственную текстуру (по крайней мере, если смотреть на ваш код, это кажется вам подходящим, поскольку вы связываете только одну текстуру и существует нет кода в вашем шейдере, чтобы использовать какую-либо другую текстуру, кроме единственной в настоящее время связанной).

Итак, я предполагаю, что у вас есть ОДНА текстура, которая состоит из четырех разных изображений? Если это так, вы должны получить ваши 4 объекта, но каждый объект показывает все четыре изображения в этой одной текстуре. Чтобы это исправить, вы должны настроить координаты текстуры следующим образом:

ObjectInstance t1 = { {-1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f},
            {0.5f, 0.5f,  0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f}};

ObjectInstance t2 = { {-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f},
                    {0.5, 1.0f,  0.5f, 0.5f, 0.0f, 0.5f, 0.0f, 1.0f}};

и так далее. Я не проверял их, но это должно быть причиной вашей проблемы.

Другой вариант - связать несколько текстур и дать каждому объекту некоторый идентификатор, который вы можете использовать в фрагментном шейдере, чтобы определить, к какой единице текстуры использовать. В этом случае у вас есть еще немного работы в вашем коде установки и фрагментном шейдере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...