буфер хранения и неправильно выровненные данные - PullRequest
1 голос
/ 18 июня 2020

Я даю некоторые материалы в буфер хранилища, чтобы мой шейдер мог иметь материалы объектов, которые я пытаюсь нарисовать, но цвета не соответствуют, я думаю, это из-за выравнивания памяти, но я новичок в opengl, чтобы я не нашел ошибку

struct Material
{
    Color diffuse;
    Color specular;
    Color emission;
    float ns;

    Material( ) : diffuse(0.8f, 0.8f, 0.8f), specular(Black()), emission(), ns(0) {}
};
struct Color
{
    float r, g, b, a;
};

и мой шейдер фрагмента

struct Material
{
    vec4 diffuse;
    vec4 specular;
    vec4 emission;
    float ns;
};

layout(binding=1) readonly buffer IndexBlock{
    uint color_indices[];
};

layout(binding=2) readonly buffer MaterialBlock {
    Material materials[];
};

в основном:

uint color_index = color_indices[gl_PrimitiveID];
vec3 frag_color = materials[color_index].diffuse.xyz;

Ответы [ 2 ]

1 голос
/ 18 июня 2020

Я рекомендую использовать std140 или std430 спецификатор макета .

См. OpenGL 4.6 API Core Profile Specification; 7.6.2.2 Стандартная единообразная компоновка блока :

[...]

Если член является структурой, базовое выравнивание структуры равно N, где N - наибольшее базовое значение выравнивания любого из его элементов, [...] Если член является массивом S-структур элементы S-массива располагаются по порядку в соответствии с правилом (9).

Вы можете добавить 3 числа с плавающей запятой в структуру c ++. Но было бы лучше использовать спецификатор alignas и выровнять структуру по 16 байтам:

struct alignas(16) Material
{
    Color    diffuse;
    Color    specular;
    Color    emission;
    float    ns;

    // [...]
}

Шейдер:

struct Material
{
    vec4 diffuse;
    vec4 specular;
    vec4 emission;
    float ns;
};

layout(binding=1, std430) readonly buffer IndexBlock{
    uint color_indices[];
};

layout(binding=2, std430) readonly buffer MaterialBlock {
    Material materials[];
};

Разница между std140 и std430 означает, что для std140 базовое выравнивание и шаг массивов скаляров, векторов и структур округляется до кратного значения базового выравнивания vec4. Это не относится к std430.

0 голосов
/ 18 июня 2020

Вы можете легко проверить, совпадает ли Color с vec4.

std::cout<< sizeof(Color) <<std::endl;
std::cout<< sizeof(vec4) <<std::endl;

если размеры разные, то можете остановиться здесь.

если размеры равны, попробуйте для инициализации тех же значений для Color и vec4

Color c(1.0,2.0,3.0,4.0);
vec4  v(1.0,2.0,3.0,4.0);
unsigned char buf1[sizeof(Color)];
unsigned char buf2[sizeof(vec4)];
memcpy(buf1, &c, sizeof(Color));
memcpy(buf2, &v, sizeof(vec4));
bool equal = (memcmp(buf1, buf2, sizeof(Color)) == 0);
std::cout<< "Is equal? " << equal ? "yes" : "no" <<std::endl; 

BTW: я думаю, что vec4 использует double, а не float.

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