openCL ray tracing and branching kernel code issue - parallel-processing

So I'm trying to implement a ray/path tracer using openCL and it seems pretty straightforward - write a kernel that traces the path of a single ray/pixel/etc and have it execute on multiple rays in parallel.
However, when traversing a scene, a single ray has a considerable number of directions it can take. For instance, depending on the material of the hit object, a ray can either reflect or refract. Additionally, different materials require different shading algorithms. For instance, if one scene object requires a cook-torrance shader and another requires a ward anisotropic shader then different shading functions would need to be called within the kernel.
Based on what I've been reading it is unadvisable to have a kernel with branching code inside of it because it hinders performance. But this seems unavoidable in a ray tracer if I am parallelizing my code based on each ray.
So is a "branching" code structure really that much of a hindrance for Kernel performance? If so, how else would I go about structuring my code to account for this?

First pass(1M rays), unsigned char array(or even packed single bits)
ray 0 ------------------ render end --------------> 0 \
ray 1 ------------------ surface ---------------> 1 \
ray 2 ------------------ surface ---------------> 1 }-- bad for SIMD
ray 3 ------------------ render end --------------> 0 /
ray 4 ------------------ surface ---------------> 1 /
...
...
ray 1M ...
Sorting(cache or multiplex this for reuse for refraction and reflection)
with surface type(exists / non existent) and surface position (temporal coherency)
ray 1 \
ray 2 -------------------- all surfaces --------------> 1 good for simd
ray 4 /
ray 0 \
ray x -------------------- all render end ------------> 0 good for simd
ray 3 /
second pass (refraction) (1M rays)
ray 1 ..................... refract ...................> cast a new ray
ray 2 ..................... refract ...................> cast a new ray
ray 4 ..................... refract ...................> cast a new ray
ray 0 .................... no new ray casting .........> offload some other work/draw
ray x .................... no new ray casting .........> offload some other work/draw
ray 3 .................... no new ray casting .........> offload some other work/draw
third pass (reflection) (1M rays)
ray 1 ..................... reflect...................> cast a new ray
ray 2 ..................... reflect...................> cast a new ray
ray 4 ..................... reflect...................> cast a new ray
ray 0 .................... no new ray casting .........> offload some other work/draw
ray x .................... no new ray casting .........> offload some other work/draw
ray 3 .................... no new ray casting .........> offload some other work/draw
now there are two groups of 1M rays, doubling at each iteration. So if you have space for 256M elements, you should be able to cast rays until depth7 or 8. All these could be done on a single array with proper indexing.

Related

Three.js ligthing has recessed areas more lighted than surfaces

The Rubik's Cube I've modeled using STL parts is lighted from all 6 directions with directional lights. As can be seen, the recessed areas are more lighted than the surfaces. When I load and position the STL files into Blender, rendering is fine. So I think the files are OK.
So, how can I fix lighting? Note that setting castShadows/receiveShadows on light and materials (phong/lambert/standard) doesn't seem to change anything.
Code is at https://github.com/ittayd/rubiks_trainer/blob/master/js/three-cube.mjs#L134
I think what you're seeing makes sense. When a face is pointing straight down the axis they're only affected by the light in front of them. But when a face is halfway between axes, it's affected by more than one light, creating an additive effect. You could minimize this by adding shadows, but creating a new shadowmap for 3 lights is expensive.
The Rubik's cube has 26 pieces * 3 lights = 78 drawcalls
+26 pieces for the final render = 104 drawcalls per frame!
I recommend you just bake an ambient occlusion map with Blender, then use that in your material with .aoMap to simulate those darker crevasses very cheaply, and keep your performance smooth. Once you have your AO map, you can just use a single ambientLight to illuminate everything, without needing 5 different lights (More lights = more expensive renders).

What is the difference between ray tracing, ray casting, ray marching and path tracing?

As far as I know, all the techniques mentioned in the title are rendering algorithms that seem quite similar. All ray based techniques seem to revolve about casting rays through each pixel of an image which are supposed to represent rays of real light. This allows to render very realistic images.
As a matter of fact I am making a simple program that renders such images myself based on Raytracing in one Weekend.
Now the thing is that I wanted to somehow name this program. I used the term “ray tracer” as this is the one used in the book.
I have heard a lot of different terms however and I would be interested to know what exactly is the difference between ray tracing, ray matching, ray casting, path tracing and potentially any other common ray-related algorithms. I was able to find some comparisons of these techniques online, but they all compared only two of these and some definitions overlapped, so I wanted to ask this question about all four techniques.
My understanding of this is:
ray cast
is using raster image to hold the scene and usually stop on first hit (no reflections and ray splitting) and does not necessarily cast ray on per pixel basis (usually per row or column of screen). The 3D version of this is called Voxel space ray cast however the map is not voxel space instead 2 raster images RGB,Height are used.
For more info see:
ray cast
Voxel space ray casting
(back) ray trace
This usually follows physical properties of light so ray split in reflected and refracted and we stop usually after some number of hits. The scene is represented either with BR meshes or with Analytical equations or both.
for more info see:
GLSL 3D Mesh back raytracer
GLSL 3D Volumetric back raytracer
the back means we cast the rays from camera to scene (on per pixel basis) instead of from light source to everywhere ... to speed up the process a lot at the cost of wrong lighting (but that can be remedied with additional methods on top of this)...
The other therms I am not so sure as I do not use those techniques (at least knowingly):
path tracing
is optimization technique to avoid recursive ray split in ray trace using Monte Carlo (stochastic) approach. So it really does not split the ray but chose randomly between the 2 options (similarly how photons behave in real world) and more rendered frames are then blended together.
ray marching
is optimization technique to speed up ray trace by using SDF (signed distance function) to determine safe advance along the ray so it does not hit anything. But it is confined only to analytical scene.

Better ways to load triangle vertices in your shader for ray tracer

currently i am trying to implement a ray tracer with triangle mesh in WebGL 2. So far i am loading the data in a buffer texture and then i unpack them like this:
for (int i = 0; i < vertsCount; i += 3) {
a = texelFetch(uMeshData, ivec2(i, 0), 0);
b = texelFetchOffset(uMeshData, ivec2(i, 0), 0, ivec2(1, 0));
c = texelFetchOffset(uMeshData, ivec2(i, 0), 0, ivec2(2, 0));
bool isHit = hitTriangleSecond(R_.orig, R_.dir, a.xyz, b.xyz, c.xyz, uvt, triangleNormal, intersect, z);;
if (isHit) {
if (z<mindist && z > 0.001) {
//weHitsomething
}
}
}
You know where the problem lies. When i try to load a mesh with many triangles it gets too slow, especially when i add reflection level like 4 times, because i have to check with every triangle, every frame... so not optimal.
I have heard about the Bounding box technique and some tree storage data. But i do not know how to do it.
It would be nice if someone provided some information about that. And besides that.
I am thinking also of a second texture with some information about each mesh that i load, but texelfetch is not like arrays when you have index, so you know which objects are in this direction that ray hits.
So my question is how to check the "nearest" triangles in the ray direction.
Implementing a raytracer in WebGL is quite an advanced task. I would advise starting simple. For example, using a 3D texture and storing up to 4 triangle indexes in each of its cells/pixels. (You will have to raymarch through the texture until you hit a triangle.) Once you have a triangle index, you can look up the vertices in a second texture (called uMeshData in your code.)
You can build the 3D texture data in Javascript, during your initialization phase. (Later, you could probably implement this on the GPU by rendering the triangles onto the 3D texture's 2D slices, using the depth buffer to select the nearest triangle to each pixel.)
This will fail to produce the correct result if there are more than 4 triangles overlapping a 3D texture cell/pixel. It is also not very efficient (due to the redundancy of the fixed-step raymarching), but at least moves you in the right direction. Once you've accomplished that, you can try more advanced solutions (which will probably involve a tree, e.g. a bounding volume hierarchy.)

how do I get a projection matrix I can use for a pointlight shadow map?

I'm currently working on a project that uses shadowtextures to render shadows.
It was pretty easy for spotlights, since only 1 texture in the direction of the spotlight is needed, but its a little more difficult since it needs either 6 textures in all directions or 1 texture that somehow renders all the obects around the pointlight.
And thats where my problem is. How can I generate a Projection matrix that somehow renders all the object in a 360 angle around the pointlight?
Basicly how do create a fisheye (or any other 360 degree camera) vertex shader?
How can I generate a Projection matrix that somehow renders all the object in a 360 angle around the pointlight?
You can't. A 4x4 projection matrix in homogenous space cannot represent any operation which would result in bending the edges of polygons. A straight line stays a straight line.
Basicly how do create a fisheye (or any other 360 degree camera) vertex shader?
You can't do that either, at least not in the general case. And this is not a limit of the projection matrix in use, but a general limit of the rasterizer. You could of course put the formula for fisheye distortion into the vertex shader. But the rasterizer will still rasterize each triangle with straight edges, you just distort the position of the corner points of each triangle. This means that it will only be correct for tiny triangles covering a single pixel. For larger triangles, you completely screw up the image. If you have stuff like T-joints, this even results in holes or overlaps in objects which actually should be perfectly closed.
It was pretty easy for spotlights, since only 1 texture in the direction of the spotlight is needed, but its a little more difficult since it needs either 6 textures in all directions or 1 texture that somehow renders all the obects around the pointlight.
The correct solution for this would be using a single cube map texture, with provides 6 faces. In a perfect cube, each face can then be rendered by a standard symmetric perspective projection with a field of view of 90 degrees both horizontally and vertically.
In modern OpenGL, you can use layered rendering. In that case, you attach each of the 6 faces of the cube map as a single layer to an FBO, and you can use the geometry shader to amplify your geomerty 6 times, and transform it according to the 6 different projection matrices, so that you still only need one render pass for the complete shadow map.
There are some other vendor-specific extensions which might be used to further optimize the cube map rendering, like Nvidia's NV_viewport_swizzle (available on Maxwell and newer GPUs), but I only mention this for completness.

Solar System using OpenGL-ES 2.0 and GLSL 1.0

I am trying to implement the classic solar system (Sun & Earth only - cubes in place of spheres) application using OpenGLES 2.0 and GLSL 1.0. I am not getting how to
write the translation and rotation matrix to get the Earth cube revolving around the Sun.
what should be order of matrix multiplication.
I am doing all the matrix operation in the vertex shader and have got the two cubes rotating along x and y axis respectively.
But facing problem in getting the Earth cube revolve around the Sun cube :-(
first you have to understand Matrix
ES 1.X is better If you dont't know exactly
1. translation matrix is
1000
0100
0010
xyz1
Change X and Z valute
2. angle matrix is
c s 00
-s c 00
0 0 1 0
0 0 0 1
also change X & Y axis
then operation martix in code ( not shader code )
and just give matirx to shader's uniforms each obejct

Resources