## Ideas request for a specific raytracing application

Practical and theoretical implementation discussion.
szellmann
Posts: 51
Joined: Fri Oct 10, 2014 9:15 am
Contact:

### Re: Ideas request for a specific raytracing application

I build an orthonormal basis with the normal being an axis - the cosine_sample_hemisphere() function (which just happens to be already there) assumes that the hemisphere is above the x/z plane. PBRT guys do it similarly (I believe), but doing it in object space would also be ok.
But this I also wrote in the program's comments, so it's probably not what you're worrying about. So AO means you sample the hemisphere above the intersection position. In order to find the hemisphere, you need the normal. Then you (may) form an orthonormal basis with the normal being the up direction. Then you sample the hemisphere. Rays that hit an occluder "darken" the resulting color.

Probably no news to you, just wasn't sure if I got your question right.

Best regards,
Stefan

mrluzeiro
Posts: 28
Joined: Tue May 26, 2015 2:27 pm

### Re: Ideas request for a specific raytracing application

szellmann wrote: But this I also wrote in the program's comments, so it's probably not what you're worrying about. So AO means you sample the hemisphere above the intersection position. In order to find the hemisphere, you need the normal. Then you (may) form an orthonormal basis with the normal being the up direction. Then you sample the hemisphere. Rays that hit an occluder "darken" the resulting color.

Probably no news to you, just wasn't sure if I got your question right.

Best regards,
Stefan
Yes that sounds all right for me, I was just confused looking in the code and the naming of w,u,v and the use of SIMD to calc the new direction (I am not familiar with hemispheres implementation).
I guess this could be used similar if you want to compute soft shadows from lights.. but in this case I should use the direction from point to light. (and adding a bit of jitter may help..)

szellmann
Posts: 51
Joined: Fri Oct 10, 2014 9:15 am
Contact:

### Re: Ideas request for a specific raytracing application

I am still working on that, but so far, the PCB can be represented by circles, round segments (== two circles + rectangle), and polygons for areas.
I can provide more detail later, but in face I have this 2D simple objects that I use to combine and construct the more complex CSG combinations. (All CSG operations are in the form (object A - object B) intersection object C, .. they can be really objects or can be 1 or 0, so, no intersection or always intersect ).. and so on.
Ok, so you probably have geometry that is curved in a way but has no closed form solution when intersecting it with a line (such as the curved creases of the main boards).

When going for real-time ray tracing you should minimize the number of supported primitive types (e.g. only triangles, or only quadrics). This is because you'll have some switch case (or similar) in your inner traversal loop, that must determine each time what primitive type you'd like to intersect. In the best case, you'd like to do away with the switch case completely (by only having a single primitive type).

In Visionaray we have a "generic_primitive". This is basically just:

Code: Select all

variant<prim_type1, prim_type2, ...>
When saying e.g.

Code: Select all

typedef generic_primitive<triangle, sphere> primitive_type;
instead of simply

Code: Select all

typedef triangle primitive_type
, performance drops significantly (I believe by 25% or so), even if the model we actually render consists only of triangles. This is only due to the switch case (that is hidden inside the variant).

szellmann
Posts: 51
Joined: Fri Oct 10, 2014 9:15 am
Contact:

### Re: Ideas request for a specific raytracing application

I guess this could be used similar if you want to compute soft shadows from lights.. but in this case I should use the direction from point to light. (and adding a bit of jitter may help..)
I believe you can think of AO as sampling an environmental light with uniform intensity (and no direct light sampling, for that matter).

Doing a lot of posting lately, don't want to scare off other potential posters

Best, Stefan

mrluzeiro
Posts: 28
Joined: Tue May 26, 2015 2:27 pm

### Re: Ideas request for a specific raytracing application

szellmann wrote: When going for real-time ray tracing you should minimize the number of supported primitive types (e.g. only triangles, or only quadrics). This is because you'll have some switch case (or similar) in your inner traversal loop, that must determine each time what primitive type you'd like to intersect. In the best case, you'd like to do away with the switch case completely (by only having a single primitive type).
, performance drops significantly (I believe by 25% or so), even if the model we actually render consists only of triangles. This is only due to the switch case (that is hidden inside the variant).
Yeah, I know it from the literature. Yes, I know that I am using this different primitives derived from a generic (C++) object with pure virtual functions and that don't help the performance
I cannot consider just triangles, because that will be back to the same issues before that I have to construct and compute the tessellation / triangle final scene.
Mind also that I should consider here the pre-compute time + rendering as a whole, so it is best to have a pre-compute time fast and get some image, the "final" render can take about (lets say.. ) 1 second or more. and the interactive low quality can be ~3 .. 5.. 10fps should be fine.

szellmann
Posts: 51
Joined: Fri Oct 10, 2014 9:15 am
Contact:

### Re: Ideas request for a specific raytracing application

Yeah, I know it from the literature. Yes, I know that I am using this different primitives derived from a generic (C++) object with pure virtual functions and that don't help the performance
I cannot consider just triangles, because that will be back to the same issues before that I have to construct and compute the tessellation / triangle final scene.
I would not suggest using virtual C++ objects. Problem is that you store pointers. What you want to do is store primitives contiguously in memory. With virtual objects, you just store pointers contiguously in memory, while the primitives are probably scattered. Bad for caches. A way to achieve the former would be to use unions:

Code: Select all

union primitive
{
sphere s;
triangle t;
};

and a function

Code: Select all

intersect(primitive)
that dispatches (e.g. via a switch statement) to specialized functions. A more versatile union is called a variant. We found the boost implementation to slow for our needs, so we implemented one of our own. I cannot provide any numbers (using virtual inheritance vs. using unions), but intuition (and a particularly nice C++11 paper by Bjarne Stroustrup i can't find at the moment) tell me that you want to align your objects in memory.

mrluzeiro
Posts: 28
Joined: Tue May 26, 2015 2:27 pm

### Re: Ideas request for a specific raytracing application

szellmann wrote: I would not suggest using virtual C++ objects. Problem is that you store pointers. What you want to do is store primitives contiguously in memory. With virtual objects, you just store pointers contiguously in memory, while the primitives are probably scattered. Bad for caches. A way to achieve the former would be to use unions:

Code: Select all

union primitive
{
sphere s;
triangle t;
};

and a function

Code: Select all

intersect(primitive)
that dispatches (e.g. via a switch statement) to specialized functions. A more versatile union is called a variant. We found the boost implementation to slow for our needs, so we implemented one of our own. I cannot provide any numbers (using virtual inheritance vs. using unions), but intuition (and a particularly nice C++11 paper by Bjarne Stroustrup i can't find at the moment) tell me that you want to align your objects in memory.

I see thanks. I did something like that when I coded a plain C raytracing.
My plan is to first "make it work" getting use of this OOP capabilities so I can archive results faster.

I read also a bit about cache friendly algorithms and I understand your propose. But.. I plan to keep the things (class and structures) aligned with sizes multiple of cache lines, so if I consider that some "random position in RAM" need to be fetched .. it will stay sometime in the cache (.. lets say.. L2..)
Another idea is to try some "packet ray" (with no SIMD .. first) .. so lets say even if I got something from memory it will come in multiples of cache lines and should stay a bit in the cache.. so. I don't know how much I could gain / loose if I follow the OOP approach VS the array of primitives.

I am thinking, in triangles only RT the ideal situation would be to have all triangles in a big aligned array.. and process it in batch using SIMD packs.. but.. I think there is still no way that will make sure that you hit one triangle and the next one is placed right next to you in object space.. and . in memory space.

Well.. things to be investigated latter!..

szellmann
Posts: 51
Joined: Fri Oct 10, 2014 9:15 am
Contact:

### Re: Ideas request for a specific raytracing application

I think there is still no way that will make sure that you hit one triangle and the next one is placed right next to you in object space.. and . in memory space.
The primitives in your BVH node can and should be stored contiguously.

If you use polymorphism, you have to store (say) an std::vector<renderable*> rather than an std::vector<renderable> because the latter slices. And a renderable* you have to create with new(). You have no real control where (default) new() actually places the prims, even if your primitive struct has padding bytes and alignment attributes and so. During BVH construction you probably also sort them, so the prims stay somewhere in free store, and only the pointers are in order.

I don't want to drift off further by answering questions you didn't ask it's just that I wanted to point out (and here it relates to your original question) that the choice of primitives may also impact (rendering) performance. But then, if your use case demands only a few hundred primitives, it maybe doesn't matter at all. If you can do w/o the tessellation, it will probably in any way be a huge gain.

If you opt for using ray tracing, you should consider using a library for the low-level stuff

Cheers,
Stefan

mrluzeiro
Posts: 28
Joined: Tue May 26, 2015 2:27 pm

### Re: Ideas request for a specific raytracing application

szellmann wrote: The primitives in your BVH node can and should be stored contiguously.
I see, I was thinking that when you load a model from a file, you cannot assure that one polygon is next to the other. So I guess you mean that in BVH, you try to keep the polygons next to each other (as they are in object space)?

szellmann wrote: If you opt for using ray tracing, you should consider using a library for the low-level stuff
What do you mean / suggest?

I am developing almost everything from scratch. The libraries that I am (free to) using are:
OpenGL Mathematics (GLM) (for vectors, matrices, also it support SIMD, ...), Boost .. not much but I can use it if I need, OpenGL, Clipper (for polygon operations)..
Since this will integrated an already existent opensource project, there are some restrictions to add new (external or integrated) libraries (licences, team approve, etc)

Most of the parts I worked so far, are very specific to this project (primitive types and PCB model construction..etc)
I am reusing some source pieces from some other authors / projects that I am giving credits of course.

Mario

szellmann
Posts: 51
Joined: Fri Oct 10, 2014 9:15 am
Contact:

### Re: Ideas request for a specific raytracing application

I see, I was thinking that when you load a model from a file, you cannot assure that one polygon is next to the other. So I guess you mean that in BVH, you try to keep the polygons next to each other (as they are in object space)?
Yeah, BVHs are hierarchies of bounding boxes of spatially nearby triangles. Often you only store four tri's in a node, but if they are far apart in memory, that hurts performance.
What do you mean / suggest?
I would take the BVH code from somewhere else. It's tricky to get it right (and fast).

As a library developer, of course I recommend using my own library, Visionaray

Embree is the state of the art, but no GPU code unfortunately. Very cool for incoherent rays because of a special BVH type.

Aila and Laine's BVH kernels from 2009 are the GPGPU state of the art I think.

I like appleseed very much, their code is really, really clean. I'm not sure if it can actually be used as a library.

I also always think twice before depending on an additional external library - I believe all the ones I mentioned have a license where you can simply copy code (e.g. MIT license).
OpenGL Mathematics (GLM) (for vectors, matrices, also it support SIMD, ...)
GLM is a good choice