szellmann / visionaray

A C++-based, cross platform ray tracing library

Home Page:https://vis.uni-koeln.de/visionaray.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Weird aliasing issue

jangxx opened this issue · comments

I'm currently getting started on trying to build a serious project using Visionaray. To familiarize myself with the library, I started with a minimal example, which uses the following simple kernel:

result_record<scalar_type> result;

auto hit = intersect(ray, m_testBbox);

auto hit_pos = ray.ori + hit.tnear * ray.dir;

if ( any(hit.hit) ) {
	result.color = color_type(
		abs(hit_pos.x),
		abs(hit_pos.y),
		abs(hit_pos.z),
		1.0
	);
} else {
	result.color = color_type(0.0f, 0.0f, 1.0f, 1.0f);
}

result.hit = hit.hit;
return result;

where m_testBbox is just a simple 2x2x2 cube. The resulting image looks weirdly aliased however:

Each of the jaggies is two pixels large, which seems wrong to me, since I expect the scheduler to emit at least one ray per pixel, so the jaggies would only be one pixel in size.

Is there any way to improve the quality without resorting to SSAA? Maybe increase the number of rays, or decrease the "size" of each ray?

Thanks for your answer and the great library.

Thank you!

Visionaray is very explicit about SIMD, i.e. if you use packets of rays (like you're probably doing here, I guess the scalar type is float4), you explicitly have to program as if you were using packets.

Option 1.) What you could do is use float instead of float4 as scalar type in your renderer.

Option 2.) Explicitly use packets:
You're doing that already in terms of the any(hr.hit) expression, but actually that whole expression would need to be evaluated per packet, as in:

result_record<scalar_type> result;

auto hit = intersect(ray, m_testBbox);

auto hit_pos = ray.ori + hit.tnear * ray.dir;

result.color = select(
    hit.hit,
    color_type(abs(x),abs(y),abs(z),1.0),
    color_type(0.0f, 0.0f, 1.0f, 1.0f)
);

result.hit = hit.hit;
return result;

(I haven't actually tested that code snippet but should work :-) )

Note how the select call replaces the if..else statement.

Visionaray is explicit about using packets b/c that can have a huge impact on performance; e.g. if you have a very incoherent workload, you might actually be better w/o packets but use simd inside the BVH (and no, Visionaray doesn't support that yet). That's different e.g. from ispc or CUDA where SIMD (or SIMT w/ CUDA) is implicit.

The any() function btw. reduces the result from multiple SIMD lanes to a single boolean, that's like saying: did any of the rays in that coherent packet of rays hit sth.

If you want to use ray packets or not btw. depends on your actual problem; i.e. if you expect the rays to be (and stay) very coherent (i.e. they'll have about the same direction and similar origin), go with packets; if they're pretty random, you're probably better of with single rays.

Thanks for the quick reply and the info dump - apparently there is still a lot to understand and learn for me as expected. I wasn't even aware what the different types like float4 meant and I also didn't know about ray packets, since the wiki entry unfortunately doesn't exist yet. Replacing the float4 ray type with float does yield the result I was expecting:

I also finally understand why these functions like select or any are even necessary - maybe I should've googled SIMD instead of wondering for hours what it means and assuming it wasn't important 🤦‍♂️

No trouble, just ask!

It is a bit unfortunate that users even have to think about such specific things such as SIMD. Still I decided to make certain things very explicit so that the user still has full control over performance. That's IMO better than having to guess what's going on :-)

Also note that supersampling is also implemented and can be used by instantiating the scheduler params struct with pixel_sampler::ssaa_type<N>; that way you could easily get rid of the remaining jaggies. There's also a sampler type for jittered sampling that would use a random sampling pattern.

The docs are unfortunately a bit behind. Contributions are very welcome though :-)