【问题标题】:GLSL Uniform Struct Array only Defines first Element仅 GLSL 统一结构数组定义第一个元素
【发布时间】:2019-10-14 23:39:06
【问题描述】:

我最近开始编写一个新的 3D 游戏,并开始从搅拌机及其相关的 .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]];?我听说不推荐使用带有可变索引的索引,这会降低 GPU 的速度。

在我看来,每次提出这个问题(并且以某种形式或形式提出)时,要么被忽略,要么找到了次优解决方案。

【问题讨论】:

  • 你的意思是什么找到了。”?这是一个重复的问题吗? passMtlIndex[0] 是有效索引吗?如果您使用materials[0]materials[1],它是否有效? passMtlIndex 来自一个整体属性?你如何定义顶点属性数据的数组? glVertexAttribPointerglVertexAttribIPointer(关注中间的I)?
  • Java 中的 OpenGL 实际上并没有该功能。我已经解决了这个问题。事实证明,我传递给顶点着色器的整数值以某种方式发生了变化,所以我只使用浮点数并将它们转换为着色器中的整数

标签: java opengl glsl


【解决方案1】:

事实证明,我的着色器代码很好,但我的想法却完全相反。问题是我将 int 值作为顶点数组属性加载。 GPU 没有很好地处理这个问题,任何超过 0 的值都被转换为一些(看似)随机数,这导致只有索引 0 起作用,给我一种错觉,即我错误地加载了我的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 2011-06-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 1970-01-01
    相关资源
    最近更新 更多