【问题标题】:Raytracing in OpenGL via compute shader通过计算着色器在 OpenGL 中进行光线追踪
【发布时间】:2013-02-26 23:10:46
【问题描述】:

我正在尝试通过计算着色器在 OpenGL 中进行一些光线追踪,但遇到了一个奇怪的问题。目前我只想显示一个没有任何阴影的球体。我的计算着色器为每个像素发射一条射线,如下所示:

#version 430
struct Sphere{
    vec4    position;
    float   radius;
};

struct Ray{
    vec3    origin;
    vec3    dir;
};

uniform image2D outputTexture;
uniform uint        width;
uniform uint        height;

float hitSphere(Ray r, Sphere s){

    float s_vv = dot(r.dir, r.dir);
    float s_ov = dot(r.origin, r.dir);
    float s_mv = dot(s.position.xyz, r.dir);
    float s_mm = dot(s.position.xyz, s.position.xyz);
    float s_mo = dot(s.position.xyz, r.origin);
    float s_oo = dot(r.origin, r.origin);

    float d = s_ov*s_ov-2*s_ov*s_mv+s_mv*s_mv-s_vv*(s_mm-2*s_mo*s_oo-s.radius*s.radius);

    if(d < 0){
        return -1.0f;
    } else if(d == 0){
        return (s_mv-s_ov)/s_vv;
    } else {
        float t1 = 0, t2 = 0;
        t1 = s_mv-s_ov;

        t2 = (t1-sqrt(d))/s_vv;
        t1 = (t1+sqrt(d))/s_vv;

        return t1>t2? t2 : t1 ; 
    }
}

layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in;
void main(){
    uint x = gl_GlobalInvocationID.x;
    uint y = gl_GlobalInvocationID.y;

    if(x < 1024 && y < 768){
        float t = 0.0f;
        Ray r = {vec3(0,0,0), vec3(width/2-x, height/2-y, 1000)};
        Sphere sp ={vec4(0, 0, 35, 1), 5.0f};

        t = hitSphere(r, sp);

        if(t <= -0.001f){
            imageStore(outputTexture, ivec2(x, y), vec4(0.0, 0.0, 0.0, 1.0));
        } else {
            imageStore(outputTexture, ivec2(x, y), vec4(0.0, 1.0, 0.0, 1.0));
        }

        if(x == 550 && y == 390){
            imageStore(outputTexture, ivec2(x, y), vec4(1.0, 0.0, 0.0, 1.0));
        }
    } 
}

当我运行应用程序时,我得到以下图像:

但是当我在 CPU 上运行相同的算法时,我会得到以下更令人信服的图像:

首先,我认为我没有分派足够多的工作组,因此并非每个像素都有自己的计算着色器调用,但事实并非如此。正如您在 GPU 渲染图像中看到的那样,中间有一个红色像素,这是由计算着色器中的最后一行引起的。这可以为每个其他像素复制。

我目前使用 1024x768 的分辨率,这就是我调度计算着色器的方式:

#define WORK_GROUP_SIZE 16
void OpenGLRaytracer::renderScene(int width, int height){
    glUseProgram(_progID);

    glDispatchCompute(width/WORK_GROUP_SIZE, height/WORK_GROUP_SIZE,1);

    glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT);
}

错在哪里?浮点计算的准确性会不会有问题?

【问题讨论】:

  • 奇怪的是这个应用看起来和我周六做的一模一样..
  • 你遇到过这种奇怪的行为吗?
  • 你的#version指令在哪里?
  • 忘记复制了。我去编辑一下。
  • 什么是“WORK_GROUP_SIZE”?

标签: opengl gpgpu raytracing compute-shader


【解决方案1】:

错误在这一行:

Ray r = {vec3(0,0,0), vec3(width/2-x, height/2-y, 1000)};

由于 width、height、x 和 y 是无符号变量,当术语 width/2-x 变为负数时,您会遇到问题。

这样就解决了问题:

Ray r = {vec3(0,0,0), vec3(float(width)/2.0f-float(x), float(height)/2.0f-float(y), 1000)};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-19
    • 2012-05-23
    • 2019-03-20
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 2011-04-09
    • 1970-01-01
    相关资源
    最近更新 更多