I'm currently working on a simple raytracer, and until now I've successfully implemented several features, like antialiasing, depth of field and soft shadows with area lights.
An image representing my work could be this one:
(there's no AA here)
The next step was adding reality to the render with some global illumination algorithm, so I decided to move to the photon mapping way, which seemed the easiest one.
To do so I read some papers I found on the web, such as this one: http://graphics.stanford.edu/courses/cs348b-01/course8.pdf
which is very well written.
Now my program can shoot photons in the scene and store them after the first bounce (diffuse or specular), then scale the power of every single photon to LIGHT_POWER / PHOTON_AMOUNT.
A direct visualization of this is represented in these images, where I shot 1000k and 50k photons, each allowed to bounce 6 times, for a total of 5000k and 250k photons in the global map:
I thought the effect is right, so I moved to the next part, the one where the photons within a certain radius over the intersection point of the raytraced rays are used to calculate the indirect illumination.
In my raytracer I do as follows:
for each pixel I send a ray trough it to intersect the scene and calculate the direct illumination (dot(N, L) * primitive.color * primitive.diffuseFactor * light.power), and the specular term;
Here is the tricky part: I look for the nearest photons which lie in a fixed radius disc around the point of intersection and sum the light produced by each one this way:
for each photon within radius
calculate light the same way as for direct lighting
(dot(-photonDir, N) * primitive.color * photonColor)
and sum everything up.
When every interesting photon has been processed and added its contribution to the final color I divide it by the area of the disc which defines the search area.
The problem is that doing so I don't get the desired result, in particular the ceiling is very dark compared to images I found on the web (I can't get how the ceiling can be as bright as the floor if the latter has an additional contribution from the direct lighting, and how it can be white if the photons on it are only red or green).
An image representing the problem is the following:
This has been rendered using 150k photons, with 4 bounces each, and the direct illumination has been divided by PI.
Also, if you know how I can remove those ugly artifacts from the corners, please tell me.
First, thanks a lot for all your help.
Second, I'm here to announce that after some trouble and after a period in which I didn't touch the code, I finally got it.
I haven't understood what I was doing wrong, maybe the algorithm to get a random direction within a hemisphere, maybe the photon gathering pass...
The point is that after reformatting a bit the code (and after implementing a final gathering step and a 2.2 gamma correction) I was able to render the following with 200k photons, 10 diffuse bounces, 20 samples for direct lighting and 100 samples of FG (taken in random - cosine weighted - direction).
I'm very happy with this since it looks almost the same as a reproduction of the scene in c4d path traced with V-Ray.
I still haven't clear what is the utility to store the photon's incident direction, ahahahahahahah, but it works, so it's ok.
Thank's again.
Related
I have a physics engine that uses AABB testing to detect object collisions and an animation system that does not use linear interpolation. Because of this, my collisions act erratically at times, especially at high speeds. Here is a glaringly obvious problem in my system...
For the sake of demonstration, assume a frame in our animation system lasts 1 second and we are given the following scenario at frame 0.
At frame 1, the collision of the objects will not bet detected, because c1 will have traveled past c2 on the next draw.
Although I'm not using it, I have a bit of a grasp on how linear interpolation works because I have used linear extrapolation in this project in a different context. I'm wondering if linear interpolation will solve the problems I'm experiencing, or if I will need other methods as well.
There is a part of me that is confused about how linear interpolation is used in the context of animation. The idea is that we can achieve smooth animation at low frame rates. In the above scenario, we cannot simply just set c1 to be centered at x=3 in frame 1. In reality, they would have collided somewhere between frame 0 and frame 1. Does linear interpolation automatically take care of this and allow for precise AABB testing? If not, what will it solve and what other methods should I look into to achieve smooth and precise collision detection and animation?
The phenomenon you are experiencing is called tunnelling, and is a problem inherent to discrete collision detection architectures. You are correct in feeling that linear interpolation may have something to do with the solution as it can allow you to, within a margin of error (usually), predict the path of an object between frames, but this is just one piece of a much larger solution. The terminology I've seen associated with these types of solutions is "Continuous Collision Detection". The topic is large and gets quite complex, and there are books that discuss it, such as Real Time Collision Detection and other online resources.
So to answer your question: no, linear interpolation on its own won't solve your problems*. Unless you're only dealing with circles or spheres.
What to Start Thinking About
The way the solutions look and behave are dependant on your design decisions and are generally large. So just to point in the direction of the solution, the fundamental idea of continuous collision detection is to figure out: How far between the early frame and the later frame does the collision happen, and in what position and rotation are the two objects at this point. Then you must calculate the configuration the objects will be in at the later frame time in response to this. Things get very interesting addressing these problems for anything other than circles in two dimensions.
I haven't implemented this but I've seen described a solution where you march the two candidates forward between the frames, advancing their position with linear interpolation and their orientation with spherical linear interpolation and checking with discrete algorithms whether they're intersecting (Gilbert-Johnson-Keerthi Algorithm). From here you continue to apply discrete algorithms to get the smallest penetration depth (Expanding Polytope Algorithm) and pass that and the remaining time between the frames, along to a solver to get how the objects look at your later frame time. This doesn't give an analytic answer but I don't have knowledge of an analytic answer for generalized 2 or 3D cases.
If you don't want to go down this path, your best weapon in the fight against complexity is assumptions: If you can assume your high velocity objects can be represented as a point things get easier, if you can assume the orientation of the objects doesn't matter (circles, spheres) things get easier, and it keeps going and going. The topic is beyond interesting and I'm still on the path of learning it, but it has provided some of the most satisfying moments in my programming period. I hope these ideas get you on that path as well.
Edit: Since you specified you're working on a billiard game.
First we'll check whether discrete or continuous is needed
Is any amount of tunnelling acceptable in this game? Not in billiards
no.
What is the speed at which we will see tunnelling? Using a 0.0285m
radius for the ball (standard American) and a 0.01s physics step, we
get 2.85m/s as the minimum speed that collisions start giving bad
response. I'm not familiar with the speed of billiard balls but that
number feels too low.
So just checking on every frame if two of the balls are intersecting is not enough, but we don't need to go completely continuous. If we use interpolation to subdivide each frame we can increase the velocity needed to create incorrect behaviour: With 2 subdivisions we get 5.7m/s, which is still low; 3 subdivisions gives us 8.55m/s, which seems reasonable; and 4 gives us 11.4m/s which feels higher than I imagine billiard balls are moving. So how do we accomplish this?
Discrete Collisions with Frame Subdivisions using Linear Interpolation
Using subdivisions is expensive so it's worth putting time into candidate detection to use it only where needed. This is another problem with a bunch of fun solutions, and unfortunately out of scope of the question.
So you have two candidate circles which will very probably collide between the current frame and the next frame. So in pseudo code the algorithm looks like:
dt = 0.01
subdivisions = 4
circle1.next_position = circle1.position + (circle1.velocity * dt)
circle2.next_position = circle2.position + (circle2.velocity * dt)
for i from 0 to subdivisions:
temp_c1.position = interpolate(circle1.position, circle1.next_position, (i + 1) / subdivisions)
temp_c2.position = interpolate(circle2.position, circle2.next_position, (i + 1) / subdivisions)
if intersecting(temp_c1, temp_c2):
intersection confirmed
no intersection
Where the interpolate signature is interpolate(start, end, alpha)
So here you have interpolation being used to "move" the circles along the path they would take between the current and the next frame. On a confirmed intersection you can get the penetration depth and pass the delta time (dt / subdivisions), the two circles, the penetration depth and the collision points along to a resolution step that determines how they should respond to the collision.
I have got a binary image/contour containing four human beings, and I want to detect/count all humans. Since there are occlusions, so I think it is best to get the head/maxima in the contour of all the humans. In that case human can be counted.
I am able to get the global maxima\topmost point (in terms of calculus language), but I want to get all the local maximas
The code for finding the topmost point is as suggested by Adrian in his blogpost i.e.:
topmost = tuple(biggest_contour[biggest_contour[:,:,1].argmin()][0])
Can anyone please suggest how to get all the local maximas, instead of just topmost location?
Here is the sample of my Image:
The definition of "local maximum" can be tricky to pin down, but if you start with a simple method you'll develop an intuition to look further. Even if there are methods available on the web to do this work for you, it's worth implementing a few basic techniques yourself before you go googling.
One simple method I've used in the path goes something like this:
Find the contours as arrays/lists/containers of (x,y) coordinates.
At each element N (a pixel) in the list, get the pixels at N - D and N + D; that is the pixels D ahead of the current pixel and D behind the current pixel
Calculate the point-to-point distance
Calculate the distance along the contour from N-D to N+D
Calculate (distanceAlongContour)/(point-to-point distance)
...
There are numerous other ways to do this, but this is quick to implement from scratch, and I think a reasonable starting point: Compare the "geodesic" distance and the Euclidean distance.
A few other possibilities:
Do a bunch of curve fits to chunks of pixels from the contour. (Lots of details to investigate here.)
Use Ramer-Puecker-Douglas to render the outlines as polygons, then choose parameters to ensure those polygons are appropriately simplified. (Second time I've mentioned R-P-D today; it's handy.) Check for vertices with angles that deviate much from 180 degrees.
Try a corner detector. Crude, but easy to implement.
Implement an edge follower that moves from one pixel to the next in the contour list, and calculate some kind of "inertia" as the pixel shifts direction. This wouldn't be useful on a pixel-by-pixel basis, but you could compare, say, pixels N-1,N,N+1 to pixels N+1,N+2,N+3. Or just calculate the angle between them.
I have a cube with known vertices position (bottom back left vertice, top front right, etc...). I also have a known center, and a known point. I want to express that point as a ratio of X/Y/Z of the lattices of that cube to use as a trilinear interpolation. So, for a given point, it has an X/Y/Z ratios that can be then be used to recalculate new positions when the cube is deformed.
So, my question is : What is the method to find the inverse trilinear interpolation to find out a point's ratio? Basically, from http://en.wikipedia.org/wiki/Trilinear_interpolation, I want a mean to find xd, yd and zd from a known point, and a deformed cube.
The closest I have come to finding a solution is http://www.grc.nasa.gov/WWW/winddocs/utilities/b4wind_guide/trilinear.html but I am not sure I understand it properly. Reading it, it seems that they guesstimate it a/b/g to be at 0, then run it through their formula, hopes it gets the proper answer. If not, calculate a delta from the expected vs received solution. If after 20 runs they don't have a good enough solution, they simply give up.
Sounds like an easy problem if you know how to relate cube displacements to a strain measure.
You don't say if the deformations are small or large.
The most general solution would be to assume a large strain measure based on original, undefored geometry: Green-Lagrange large strain tensor.
You can substitute the interpolation functions into the strain displacement relations to get what you want.
I try to create an illumination invariant image with openCV like in this paper here: http://www.cvc.uab.es/adas/publications/alvarez_2008.pdf
Has someone an idea how one can create that image from the log-log plot image in OpenCV?
+1 for the link to an interesting paper.
I guess I would build a function to convert to log, divide the channels, rotate by theta, and project onto one axis. Then I would build a function to measure the quality of the resulting invariant image. Then I would set up a search over theta to optimize the quality. That looks like what Alvarez is doing.
But first, I would study the Luv color space, it might be the closest approximation to this scheme that is possible without the special narrowband camera. Project the uv space onto a vector at angle theta, and see what happens.
As far as I can understand the two papers, they are proceeding from a false premise and arriving at an interesting method for getting 1D illumination invariant information from 2D (such as uv from Luv, HS from HSV, etc) color space.
They say illumination invariant, but they show a method of obtaining Color Temperature invariant information from log ratio of color pairs, say {log(R/G),log(B/G)}. You can imagine the setup, with a lamp on a dimmer, and they plot the color ratios: dim the lights, yes, the illumination changes, but so does the color temperature T.
Not to mention that light is not all blackbody color temperature Lambertian. How in the world can this method work? But their results look good.
So, on to the interesting method: Maximum Entropy
As in answer above, project the (log of) uv space onto a vector at angle theta. What should theta be? Search theta to maximize entropy of the result. That is, to get the sharpest peaks in the 1D result. Sort of like an auto-focus.
To answer your question though, use calcHist in opencv. After computing the log, of course.
I have a collsion map, and some places that I want to be light sources. The light source provides light that is actually a shape where I can see the ground. It now looks like this:
So the light goes through the walls. I want to make it look like this:
(I marked the collisions with walls with dark yellow)
So the light rays stop when meeting the wall. I want to get the shape of the correct light, the best would be bitmap containing it)
My first idea was to cast rays from the source and check when they collide with the wall (I know how to do this), but then I would need to cast ray each 0.001 deg for example, so its too much time to generate lights. The next thing is that The light shape isn't always circle, sometimes it can be ellipse or half-ellipse, even triangle or part of the circle. Generally, I have the bitmap with light that doesnt collide anything, and I want to subtract it a bit to make it look like on the second image.
And the last thing, Im using allegro 4.2.1, but all previously mentioned bitmaps are 2-dimmension arrays with 0's and 1's.
Thanx for any help, sorry for long question and my bad english.
The basic idea is that you calculate the shadow region of your walls and just not color that.
This article should give you a good start.
In your particular example you can easily brute-force it by checking the line-of-sight from each (empty) pixel to the center of your light source. If you have line-of-sight and the distance is within the falloff, then you have light there. If not, then it's dark.
The MadKeithV solution need O(number of pixels^2) time.
My solution is a expanded MadKeithV idea, but run in O(number of pixels) time. With some improvements, it will work in O(number of pixels in light)
First, start with the pixel containing the source of light. Then using BFS procedure 'infect' nearest pixels with light and store angle range of which direction the light can progress from each point.
In following BFS instances, repeat this procedure, considering only pixels in 'infect range'.