openCl路径跟踪器会创建奇怪的噪声模式

时间:2018-12-07 05:44:42

标签: c++ gpu opencl raytracing

按照本教程的基本结构,我使用openCl和c ++制作了路径跟踪器:http://raytracey.blogspot.com/2016/11/opencl-path-tracing-tutorial-2-path.html。据我所知,路径跟踪算法本身没有什么问题,但是图像中出现了奇怪的条纹图案,这些条纹图案与常规的路径跟踪噪声不匹配。 striped image

有明显的垂直条纹和更窄的水平条纹,无论我每个像素采样多少个样本,这些图像都会使颗粒看起来更细腻。再次,逐像素,路径跟踪器似乎正在工作(即使对象的轮廓在中间条纹处,对象的轮廓也是正确的),如下所示:close-up

我的代码和我所链接的教程之间的唯一区别是Sam Lapere似乎对openCl使用c ++包装器,并且我添加了一些功能,例如运动。我处理轻弹的方式也有一些差异。

我是openCl的新手。是什么原因造成的?看来这与我的光线跟踪器本身无关,但是以某种方式实现了OpenCl。我还使用SDL纹理和渲染器将图像显示在屏幕上

以下是跟踪代码,如果有帮助的话:

内核:

__kernel void render_kernel
(__constant struct Sphere* spheres, const int width, const int height, 
const int sphere_count, __global int * output, __global float3* 
pixel_buckets, __global int* counter, __constant struct Ray* camera, 
__global bool* reset){

int gid = get_global_id(0);

//for movement
if (*reset){
    pixel_buckets[gid] = (float3)(0,0,0);
    counter[gid] = 0;
}

int xcoord = gid % width;
int ycoord = gid / width;

struct Ray camray = createCamRay(xcoord, ycoord, width, height, counter[gid], camera);

float3 final_color = trace(spheres, &camray, sphere_count, xcoord, ycoord);

counter[gid] ++;

//average colors
pixel_buckets[gid] += final_color;
output[gid] = colorInt(clampColor(pixel_buckets[gid] / counter[gid]));


}

跟踪:

float3 trace(__constant struct Sphere* spheres, struct Ray* camray, const int sphere_count,
         unsigned int seed0, unsigned int seed1){

struct Ray ray = *camray;

struct Sphere sphere1;
sphere1.center = (float3)(0, 0, 3);
sphere1.radius = 0.7;
sphere1.color = (float3)(1,1,0);

const int bounce_count = 8;
float3 colors[20];
float3 emiss[20];

for (int bounce = 0; bounce < bounce_count; bounce ++){

    int sphere_id = 0;
    float hit_distance = intersectScene(spheres, &ray, &sphere_id, sphere_count);
    struct Sphere hit_sphere = spheres[sphere_id];
    float3 hit_point = ray.origin + (ray.direction * hit_distance);

    float3 normal = normalize(hit_point - hit_sphere.center);
    if (dot(normal, -ray.direction) < 0){
        normal = -normal;
    }

    //random bounce angles
    float rand_theta = get_random(seed0, seed1);
    float theta = acos(sqrt(rand_theta));
    float rand_phi = get_random(seed0, seed1);
    float phi = 2 * PI * rand_phi;

    //scales the tnb vectors
    float x = sin(theta) * sin(phi);
    float y = sin(theta) * cos(phi);
    float n = cos(theta);

    float3 hemx = normalize(cross(ray.direction, normal)) * x;
    float3 hemy = normalize(cross(hemx, normal)) * y;
    normal = normal * n;

    float3 new_ray = normalize(hemx + hemy + normal);

    ray.origin = hit_point + (normal * EPSILON);
    ray.direction = new_ray;

    colors[bounce] = hit_sphere.color;
    emiss[bounce] = hit_sphere.emmissive;

}

colors[bounce_count] = (float3)(0,0,0);
emiss[bounce_count] = (float3)(0,0,0);
for (int i = bounce_count - 1; i >= 0; i--){
    colors[i] = (colors[i] * emiss[i]) + (colors[i] * colors[i + 1]);
}
return colors[0];

}

随机数生成器:

float get_random(unsigned int *seed0, unsigned int *seed1) {

/* hash the seeds using bitwise AND operations and bitshifts */
*seed0 = 36969 * ((*seed0) & 65535) + ((*seed0) >> 16);
*seed1 = 18000 * ((*seed1) & 65535) + ((*seed1) >> 16);

unsigned int ires = ((*seed0) << 16) + (*seed1);

/* use union struct to convert int to float */
union {
    float f;
    unsigned int ui;
} res;

res.ui = (ires & 0x007fffff) | 0x40000000;  /* bitwise AND, bitwise OR */
return (res.f - 2.0f) / 2.0f;

}

谢谢

0 个答案:

没有答案