opengl 根据片段着色器,UBO的内容都是相同的

xqkwcwgp  于 2023-05-06  发布在  其他
关注(0)|答案(1)|浏览(152)

我有一个UBO初始化如下:

glGenBuffers(1, &sphereUBO);
glBindBuffer(GL_UNIFORM_BUFFER, sphereUBO);
glBufferData(GL_UNIFORM_BUFFER, sizeof(SphereUBO) * sphereData.size(), nullptr, GL_DYNAMIC_DRAW);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, sphereUBO);

glUniformBlockBinding(rtShader.ID, glGetUniformBlockIndex(shaderProgram, "Spheres"), 0);

rtShader.setInt("u_numSpheres", sphereData.size());

在此之上,我初始化我的球体数据如下:

Scene scene = Scene();
scene.addSphere(glm::vec3(-1.0, 1.0, -1.0), 1.0);
scene.addSphere(glm::vec3(0.0, 1.0, 0.0), 0.1);
scene.addSphere(glm::vec3(5.0, 0.5, 0.0), 0.5);
scene.addSphere(glm::vec3(5.0, 3.5, 0.0), 0.75);

std::vector<SphereUBO> sphereData;
for (int i = 0; i < scene.spheres.size(); i++) {
    SphereUBO sphere;
    sphere.position = scene.spheres[i].position;
    sphere.radius = scene.spheres[i].radius;
    sphere.albedo = glm::vec3(scene.spheres[i].material.albedo[0], scene.spheres[i].material.albedo[1], scene.spheres[i].material.albedo[2]);
    sphereData.push_back(sphere);
}

我已经打印出sphereData以确保数据正确传递。最后,我更新了缓冲区的内容:

glBindBuffer(GL_UNIFORM_BUFFER, sphereUBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(SphereUBO) * sphereData.size(), sphereData.data());

但是,我只看到一个渲染的球体!我已经确认了所有的球体都在渲染,但它们在某种程度上都是一样的。我在我的片段着色器中有这个函数:

bool raycast(Ray ray, out HitPoint hitPoint) {
    bool hit = false;
    float minHitDistance = 10000;
    float hitDistance;

    for (int i = 0; i < u_numSpheres; i++) {
        if (sphereIntersection(u_spheres[i].position, u_spheres[i].radius, ray, hitDistance)) {
            hit = true;

            if (hitDistance < minHitDistance) {
                minHitDistance = hitDistance;
                hitPoint.position = ray.origin + ray.direction * minHitDistance;
                hitPoint.normal = normalize(hitPoint.position - u_spheres[i].position);
                hitPoint.material = Material(u_spheres[i].albedo);
            }
        }
    }

return hit;

}
我知道它们都是一样的,因为当我不做for循环,只检查第一个或第二个球体时,它们的渲染结果是一样的。
我有我的缓冲/制服声明在这里:

uniform int u_numSpheres;

layout(std140) uniform Sphere{
    vec3 position;
    float radius;
    vec3 albedo;
} u_spheres[32];
kulphzqa

kulphzqa1#

glGetUniformBlockIndex(shaderProgram, "Spheres")

首先是typo:“Spheres”不是一个有效的统一块名,所以这几乎肯定会返回GL_INVALID_INDEX,这将导致对glUniformBlockBinding的调用失败。
但更重要的是,即使你把它命名为“球体”,以符合你的UBO定义...仍然没有统一的块命名为“球体”。但是,有一个统一的块名为Sphere[0]。还有一个叫Sphere[1]。诸如此类。
你看,问题是你认为Sphere是一个统一的块。它不是。它是一个数组 * 的统一块 *,而不是一个统一块 * 包含 * 一个数组。这就是将接口块声明为数组的意思。你有32个统一块(这真的应该会导致编译错误)。
您真正需要的是声明一个名为Spherestruct,然后有一个包含此类类型数组的统一块。stop using vec3

相关问题