GLSL Uniform Struct Array Только определяет первый элемент - PullRequest
1 голос
/ 15 октября 2019

Я недавно начал программировать новую 3D-игру и начал импортировать модели из blender и связанные с ними файлы .mtl. Я создал систему для загрузки модели с несколькими материалами в одной сетке, назначив индекс каждому примитиву и затем получив доступ к структуре материала из единого массива с указанным индексом. Как ни странно, это работает для 0-го индекса, но для любого индекса выше, чем тот, который терпит неудачу.

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

Код шейдера:

#version 400 core

layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;

in vec3 passVertex[];
in int passMtlIndex[]; // I don't have actual per-primitive values but I just use the first index in the array

out vec4 color;

struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
    float dissolve;
};

struct Light {
    vec3 position;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

uniform mat4 projection;
uniform mat4 view;

const int MAX_MATERIALS = 10;

uniform Material materials[MAX_MATERIALS];
uniform Light light;

void doVertex(int index, vec4 baseColor) {
    gl_Position = projection * view * vec4(passVertex[index], 1.0);
    color = baseColor;
    EmitVertex();
}

mat4 inverseAffine(mat4 matrix) {
    return mat4(
            matrix[0].x, matrix[1].x, matrix[2].x, 0,
            matrix[0].y, matrix[1].y, matrix[2].y, 0,
            matrix[0].z, matrix[1].z, matrix[2].z, 0,
            -dot(matrix[3].xyz, matrix[0].xyz), -dot(matrix[3].xyz, matrix[1].xyz), -dot(matrix[3].xyz, matrix[2].xyz), 1);
}

void main() {
    vec3 toEye = normalize(inverseAffine(view)[3].xyz - passVertex[0]);
    vec3 norm = normalize(cross(passVertex[1] - passVertex[0], passVertex[2] - passVertex[0]));
    vec3 lightDir = normalize(light.position - passVertex[0]);

    Material material = materials[passMtlIndex[0]];

    vec3 ambient = light.ambient * material.ambient;

    float diff = max(dot(norm, lightDir), 0.2);
    vec3 diffuse = light.diffuse * (diff * material.diffuse);

    float spec = pow(max(dot(reflect(-lightDir, norm), toEye), 0.0), material.shininess);
    vec3 specular = light.specular * (spec * material.specular);

    vec4 baseColor = vec4(ambient + diffuse + specular, material.dissolve);

    doVertex(0, baseColor);
    doVertex(1, baseColor);
    doVertex(2, baseColor);

    EndPrimitive();
}

Код рендеринга:

// use program
shader.loadMaterial("materials[0]", grassMtl);
shader.loadMaterial("materials[1]", dirtMtl);
// render

Код шейдера:

public void loadMaterial(String name, Material value) {
    loadVector(name + ".ambient", value.getAmbient());
    loadVector(name + ".diffuse", value.getDiffuse());
    loadVector(name + ".specular", value.getSpecular());
    loadFloat(name + ".shininess", value.getShininess());
    loadFloat(name + ".dissolve", value.getDissolve());
}

public void loadVector(String name, Vector3f value) {
    GL20.glUniform3f(GL20.glGetUniformLocation(programID, name), value.x, value.y, value.z);
}

public void loadFloat(String name, float value) {
    GL20.glUniform1f(GL20.glGetUniformLocation(programID, name), value);
}

РЕДАКТИРОВАТЬ: Я на самом деле пытался просто передать два отдельных материала в шейдер, и это прекрасно работает, но по какой-то причине массив все еще не работает.

Я также пытался преобразовать массив из массива структуры в пять массивов, содержащих все члены структуры, но это дает те же результаты (только первый определенный элемент)

Кроме того, как я могу улучшитьстрока: Material material = materials[passMtlIndex[0]];? Я слышал, что индекс с переменным индексом не рекомендуется и замедляет работу графического процессора.

Мне кажется, что каждый раз, когда задают этот вопрос (и он имеет, в той или иной форме), этолибо были проигнорированы, либо найдено неоптимальное решение.

1 Ответ

0 голосов
/ 17 октября 2019

Как оказалось, мой код шейдера был в порядке, и мой разум двигался в совершенно противоположном направлении. Проблема была в том, что я загружал значения int как атрибуты массива вершин. Это не очень хорошо обрабатывается графическим процессором, и любое значение свыше 0 было преобразовано в какое-то (на первый взгляд) случайное число, из-за которого работал только индекс 0, создавая иллюзию, что я неправильно загружал свои значения.

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