Friday, November 30. 2007
I continued to enhance the atmosphere calculations. Before I can do the next big step I had to implement a smaller one. Now the parameters for a layer are not calculated and stored for the middle of the layer, but for the lowest and highest position. Technically I wouldn't have to store both, as the highest position on a layer is the lowest of the next. But it makes the code simpler and so I just store the values twice. When I now need the absorption or scattering values, I pass the intersection points of the line I intend to integrate with the spheres representing the boundaries and get a factor to linearly interpolate between the low and high boundary values of absorption or scattering. That should help a bit against the banding, but also enhance the areal perspective. As the strongest absorption and scattering is taking place at the lowest part of the atmosphere, the parameters close to the surface were always a bit too low with the values I had available before. As the image shows, the code still works. It wasn't supposed to result in big differences yet. But I need that stuff to add the better integration function, as it will need access to the parameters at the start and end point of the lines as well. But still, I think the colors look better already, also some of the hard boundaries are already gone.
Thursday, November 29. 2007
 I have removed another factor of 4π, this time from the Mie scattering. I don't know if it is correct or not, because I don't really know, if the results from OPAC do include that factor or not. That at least restored the bright area around the sun, but it was still not right. I had to reenable reducing the Rayleigh scattering for primary rays (directly from the sun coming rays) or it was too yellow. I also think, that the contrast between sky and ground slowly starts to look realistic. What I still don't like is, that the horizon is glowing yellow. I have taken enough photos outside and have never seen anything like that at 10am (that is the time set for the image, 10am, November 27th of this year). One thing I was worried about was, if the sun rise (and sun set) still work or if they are now far too blue. So I set the time to about 7:30am, turned the camera slightly and rendered and got this:  I had to change the parameters of the tone mapping operator, as it tries to produce a well lit image and that made it way too bright. Also I reduced the burn value a bit. What is still wrong are the very well visible bands. I haven't checked, but I guess those are the layers of the atmosphere becoming visible. I think I know how to get rid of them by using the better integration I had come up with. That was, what I originally intended to add, before I reenginered all of the parameters.
Wednesday, November 28. 2007
I have changed the widths of the layers which fixed some problems, I had changed something long ago which resulted in very strange height layers. Especially the lowest layer was way too thick. I also fixed the small dot marking the sun and I think it has the correct size, I looked it up, the sun has an apparent diameter of 0.5°. What I still don't understand is, where the bright area around the sun has gone. I guess another round of looking at the scattering values will follow.
Tuesday, November 27. 2007
When I reworked some of the code I had missed one bit. It made the absorption of Rayleigh scattering higher (by 4π) and that was the reason for the rather dense atmosphere. It also explained why I lost so much of the blue. So here is a corrected rendering:  The greenish part is the lowest layer of the atmosphere where strong Mie scattering is observed, the hard boundary is an artifact. I have to try to fix that. But I also think, that the color is still unnatural. Before I had found that code part, I was thinking about how I can rationalize of not applying scattering to the light coming directly from the sun. I feel, that parts of the problems with a single scattering model come from the fact, that a lot of energy just vanishes by scattering, thereby turning scattering into absorption. To try that, I added a bit of code so that rays coming directly from the sun are only weakly attenuated by Rayleigh scattering. The result looks like this:  I think I will experiment with the ratio I diminish the scattering, currently only 10% are applied. I actually like the colder color with the more vivid blue. It also has the effect of making the sky a bit brighter which also looks better.
Monday, November 26. 2007
I have added the absorption of the ozone layer, but the image didn't change a lot. But at least I got the aerial perspective working, it turned out that the camera was too near to the ground and so couldn't see far enough. I also added some boxes to show the effect. The red boxes are 2km x 2km and 5km high, they are 100km (small to the right), 50km, 25km and 10 km (the one on the left) away. The green boxes are 200m x 200m and 500m high and are 5km, 2.5km and 1km away. The images are linked to bigger versions (1024x768).
Sunday, November 25. 2007
 Yesterday and today I was looking into the atmosphere rendering again. I basically want to fix the rather primitive integration. But first I needed to fix some formula, last time I more or less removed terms until I got something which at least looked somewhat good. After a lot of searching and calculating I finally seem to have gotten the calculations right. But there is still a problem. In the first picture you can see the current output. For my taste it is way to greenish and the area around the sun is too orange. I think the reason is the strong wavelength dependency of Rayleigh scattering. Blue light is scattered about 10 times more than red light. But that also means, that the extinction coefficient has the same properties, as pure air responsible for Rayleigh scattering has negligible absorption. So the light being scattered contains very low amounts of blue light and so scattering seems to produce the wrong color.  When I remove the Rayleigh scattering from the extinction coefficient of the atmosphere, the sky turns blue as now there is enough blue light to be scattered. There might be another reason I haven't tried, the greenish tint could be caused from my lack of filtering the sun spectrum through ozone. According to A survey of the modelling and rendering of the earth's atmosphere I found today ozone filters out green components of light. That paper is actually quite good and contains a lot of the coefficients needed to do this stuff. If I had found it sooner I would have saved some hunting around. But I fear, that the real reason is the single scattering model I use. Probably a multiple scattering model would result in better images, but also would take a lot more time. So I first plan to add filtering for ozone and then we will see. Another thing I miss is the aerial perspective. It still doesn't work and the green plane is 250km in size. After 500km there has to be a rather strong aerial perspective, so I will have to go in and try to find out, why it is so weak. I slowly believe there to be a program bug.
Saturday, November 24. 2007
Antialiasing of mirrored rays should now also work. It was quite easy to add, next are the transmitted rays. To show the difference, here are two images of the same model. I hope no other change is making a big difference:
Edit: The transmitted (respectively refracted) rays now also contain everything necessary to do antialiasing.
Friday, November 23. 2007
I have started to add antialiasing to the reflected and refracted rays. The first step was pretty mundane, I had to make sure the secondary rays are passed through to the material. That is done, so next I can add the code to actually use them, luckily this should be fairly easy as I some time ago combined handling of reflection and refraction into one function which all materials use. So implementing it once each for reflection and refraction and extending the interface of those two functions and the one handling transmission (the common part of refraction and simple transmission is also combined in one function) should be enough.
The antialiasing seems to work with the height field, though I don't see a big effect as I down sampled the tiles before already. But because of that I also found and fixed another bug in the image sampling function. The problem this time was, that the filter didn't work when the range to filter was smaller than a pixel. I also changed the calculation of the level of the mipmap to use (so the first bug should not even happen, though I fixed it nonetheless) and limited the factor the u- and v-sampling ranges can differ. In a test I saw a factor of 100, so I would have to sample 100 pixels in x direction for each one in y direction. That not only takes a lot of time, the result could also exhibit strange properties due to the large difference of sampled pixels.
Thursday, November 22. 2007
I had no time today and only managed to add the code to do the antialiasing to the height field. I don't even know, if it was successful as I didn't have time to test it. I hope it is visible. So next is the handling of antialiasing for reflected surfaces.
Wednesday, November 21. 2007
I think I got the antialiasing to work. Even my own interpolation function now doesn't look so bad at all. The main problem was, that I didn't calculate the size of the circle (or more correctly ellipse) in pixels, but in uv-space. For longish object that meant, that the area covered in u-direction was small, but the one covered in y-direction was large. As my mipmap-class gets the uv-coordinates and calculates the pixel sizes by itself, it meant, that when the longish object was textured with an image with an aspect ratio of about 1, that the size for interpolation along the v-direction wasn't bad, but along the u-direction it was very wrong (about a factor of 10). So the interpolation led to very blurry images. Now the mipmap-class gets the extents separated in u- and in v-directions and can calculate the pixel ratios to match those sizes. And that leads to much better interpolation. The next thing I will do is to add that code to the height field as well. Slowly I seem to make progress.
Tuesday, November 20. 2007
I finally understood where the big difference between PBRT and my raytracer is in regards to antialiasing. The data necessary was quite different from what I have at the point where I am making changes. The difference is, that PBRT uses a data structure called DifferentialGeometry to store some differentials describing the neighborhood of a hit as it won't give direct access to the geometry having been hit in the material processing. My program on the contrary is designed in a way to defer the calculation of data not necessary for hit processing to the latest possible point in time. To do that I have full access to the underlying geometry and quite some details about the hit. PBRT is therefore probably a bit susceptible if the SSS has cells with many objects as the processing of the DifferentialGeometry is done for each possible hit and has to be thrown away if a better hit is found. The advantage is, that the geometry is completely decoupled from the material handling. My way means that I only do the absolutely necessary steps in hit processing but have the problem that the processing needed to access materials has to be duplicated in all kinds of geometry. So what is better in the end is probably very dependent on the scene. For the antialiasing stuff this means, that PBRT only can do the calculations based on the differentials it has, which complicates some details. I on the other hand can do the calculations in the triangles plane. The steps necessary to get the size of the area which needs to be filtered are similar but have to be adapted. I have done quite some of the changes, but am not finished yet. I hope to finish the part tomorrow, then I should have two values describing how many pixels to combine in u and v direction respectively.
Monday, November 19. 2007
I tried to find out, what is wrong with my antialiasing function and what I have to change. I checked PBRT to see, how they did it. As I have chosen a different path I can't immediately use their solution, but I think my solution is similar enough to adapt the code. But before I can even go to the filtering code I suspect to be wrong, I have to make sure I have the right uv-partials to calculate the size of the area to filter. That is very important, because if it is wrong then I will either have aliasing (which is not a good result if you try to do the opposite) or I will have a very blurry result. And there I am not so sure if it works, I have now two ways to calculate that size and they differ considerably. I currently think the old code is correct, but to be sure I will have to make some more changes to the new one to make sure I am right. If the old code indeed is correct I will use that as it is simpler.
Sunday, November 18. 2007
I fixed the bug I had seen in the rendering of textures. But I also found out, that my idea to use an interpolation with stronger smoothing doesn't work. On photos it isn't apparent, but if a texture contains high frequency details (like thin lines or characters) the textures get smeared into an unidentifiable mess. So I guess I will have to use a different algorithm for that. This time I will use a proven algorithm. I will also try to add the antialiasing for mirroring surfaces. Currently that is not possible, but as I won't have a choice in the long run, I can do it now as well, I guess. Then I will try to fix another issue, the sky dome has problems, the calculations of the light scattering are not correct, I fear. As I have since come up with some formulas to do it right, I will see that I can integrate it into the sky dome code. I hope that then the aerial perspective also finally works. I will continue at the OpenGL-renderer after I have fixed the raytracer. The OpenGL-renderer has become fast enough to do what I wanted to do. So before working some more on it I first want to do the rendering. I am working on the background for the start page of this website.
Most of yesterday I spent with rewriting part of the grid used as Spacial Subdivision Structure (SSS). The SSS is the part of a raytracer which decides which triangles to check for intersection with the ray and is therefor one of the parts which decides over the speed of the program. My program is still quite slow as I don't use many of the available techniques. But as I still think that I am more lacking in modeling tools than raw speed of the raytracer, I don't do as much work on the raytracer as would be necessary to make it fast. But this time I fixed an old problem which became worse with time and growing complexity. The setup function of the grid was not good. It was slow and used a lot of memory. When I implemented it I had a "great" idea which I now removed. The problem is, that you won't get the faces in a sequence which makes it easy to build the grid structure. The SSS is made of two parts, the first is the part which gives it the name, e.g. a grid, a BVH (boundary volume hierarchy) or a kd-tree, the second one is shared by most of those structures, a list of faces in the respective part of space. So while the grid is traversed (or the BVH or the kd-tree) we have to check, if the ray hits any of the objects in the current cell, if not we move on to the next. The most important cells are the empty ones, as we can skip a lot of tests in those cases. My grid still uses a not optimal traversal algorithm, but this time I changed the back end structure. Basically each grid cell only contains a pointer to a list of objects it contains. All the rest of the data is global. Using a normal linked list would take up too much memory and would probably be too slow as it goes on hunting pointers through memory which defeats the caches. So I point to an array of face numbers which index into a big vector of all the faces under control by the SSS. But as I don't get the faces in the right order, I had that brilliant idea to first collect all the faces and while doing so calculate the length of the list needed for each grid cell. Then in a post processing step I would allocate a big array of the required size and fill the lists by going through the list of faces. I removed the first step completely now and create the necessary lists on the fly. This means that I copy data around a bit more and that I waste a bit more memory, but I save on doing work twice when finding out, which grid cells are covered by an object. As for some objects that is quite expensive I hope I save on run time. I haven't done any measurements, but I think it is noticeable. It also is a lot simpler and there is still room for improvement. Currently the memory management is not particularly good and I copy too much data around all the time, but I think I can fix that. There is also a big problem when very many objects go in few cells, then the loss of memory becomes very high. But in this case the structure also isn't really working, so it is more of a bug than a problem. Still I will have to fix that problem, the wave patches had a problem which resulted in thousands of faces going into on grid cell and then the necessary memory exploded. But as I have fixed the wave patches, it is working for now.
|