2013-03-11 4 views
9

Я пытаюсь сделать некоторые raytracing в OpenGL через вычислительный шейдер, и я наткнулся на странную проблему. На данный момент я просто хочу отобразить сферу без затенения. Мой Compute Shader запускает луч для каждого пикселя и выглядит следующим образом:Raytracing в OpenGL через compute shader

#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)); 
     } 
    } 
} 

При запуске приложения я получаю следующее изображение: enter image description here

Но когда я запускаю тот же алгоритм на CPU, я получаю следующее более убедительное изображение: enter image description here

Сначала я думал, что не отгрузил достаточное количество рабочих групп, чтобы не каждый пиксель получал свой собственный вызов подсчета шага, но это не тот случай. Как вы видите на графическом графическом изображении, в середине есть красный пиксель, который вызывается последними строками в вычислительном шейдере. Это можно воспроизвести для каждого другого пикселя.

Я использую разрешение 1024x768 в данный момент, и это, как я послать мой Compute Shader:

#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); 
} 

Где ошибка? Может ли быть проблема с точностью вычислений с плавающей запятой?

+0

Weird это приложение выглядит точно так же, как то, что я сделал в субботу .. –

+0

ли вы встречаете такое странное поведение? – Stan

+0

Где ваша директива '# version'? – genpfault

ответ

3

Ошибка в этой строке:

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

Так как ширина, высота, х и у являются переменными UINT я получить проблемы, когда термин ширина/2-х становится Negativ.

Это решает проблему:

Ray r = {vec3(0,0,0), vec3(float(width)/2.0f-float(x), float(height)/2.0f-float(y), 1000)}; 
Смежные вопросы