I’ve been fiddling with 3D with the goal of implementing Shadow Mapping for almost a month now.
I spent quite a bit of time around the engine, ironing things, getting it ready to quickly plug-in shaders.. and now I’ve been stuck on the facking Shadow Mapping for several days !
In theory it’s nothing special, in practice 3D graphics sometimes really sucks !
The problem is that there is a general concept, a lot of half-assed implementations, many ambiguous discussions on the net, a million papers and books that focus on different details. But no real complete reference. This is for Shadow Mapping but also for many other things.
The main issue with 3D graphics is that one works with transformation matrices and different 3D spaces. Matrix manipulation is not that difficult, but millions of ambiguities raise with coordinate systems, order of concatenation, inversion of matrices… plus the fact that shaders are hard to impossible to debug.
Doing an actual implementation is a royal pain in the ass, and it’s especially sad that I tend to try solve by trial and error. Flip matrices, swap orders, try to do something like some reference implementation does… but never actually really being sure what details am I missing.
For example I saw some code arbitrarily adding w to (x,y,z) to the light-view homogeneous space vertex after being transformed in a shader. Why ?! Why the fuck ?! ..nobody knows, there is no telling. It’s something that needs to be done because of the specific situation.
I hate feeling stupid and fiddling for hours with parameters. Trying to grow a working implementation out of web-searches.
It doesn’t help that I still don’t have a credit card to buy English books via Internet, and the best library with English books I knew here in Tokyo seems to have given up on carrying the good coding books. Of course one can find a lot of shit on how to use Office and code in Perl and Ruby.. but who the fuck needs those ?! I need my 3D books !!!
…but I also know that to get something to work one needs about 10 books treating the same subject. That has always been the case, but more so now that there are tons of Game Programming Gems, GPU Gems, ShaderX. All written by hundreds of people.
If everyone is so good, why can’t I find a decent explanation on-line ?!
zzzzzzzzzzzzzzzz
Posted by Davide Pasca as Programming, 3D Graphics at 1:54 AM EST
11 Comments »
On my current 3D engine, I’m supporting both Direct3D 9 with HLSL and OpenGL with CG.
With some effort, I managed to get a hold on the CG interface for OpenGL.. cool !
Then I noticed that Microsoft is starting to push Direct3D 10. D3D 10 seems to make some effort to deal with state changes in an efficient way, and generally to keep up to date with the evolution of 3D hardware, while also removing a lot of ambiguities with the infamous “caps” and forcing hardware manufacturer to include a base set of capabilities on any hardware that wants to be certified as D3D 10 compatible.
cool cool.. what’s uncool is that OpenGL is starting to look very old ! I was once a great supporter of OpenGL, back when D3D was a real pain to use. D3D used to be almost as painful to use as DirectShow (be DS damned in hell !), but eventually grew to become actually more clean than OpenGL.
OpenGL is continuously developed by a committee, which takes ages to implement anything. Implementing a decent off-screen rendering interface took ages. There so so much bureaucracy.. bha ! Its main problem is that it’s stuck with a design thought for a client-server system, where a client terminal makes API calls to a server that renders. We are talking ancient times, stuff that suited SGI hardware (which BTW just recently filed chapter 11.. sad !). OpenGL functions don’t deal with structures, which are sometimes very useful, and don’t have return values, which makes error checking rather painful.
So I’ve been thinking on ditching OpenGL ! (imagine, me doing that !). The only valid argument for using OpenGL is if I want to write portable code for MacOS X and Linux and PS3. But.. that’s pretty much a bunch of horseshit ! The “portable API” is a joke when dealing with advanced 3D graphics. Plus, who cares about MacOS X and Linux ? It’s a geeky excuse. As for PS3.. who knows what sort of extensions does its OpenGL use ? Writing an engine on top of D3D and OpenGL is inevitably going to have to penalize one side of the porting while taking a lot of time to keep the development in synch: not worth it.
ummmmm.. I wrote a lot and it’s late. I actually meant to leave the second part of the update for something completely different. But that will have to go on the next bat-update on this same bat-site !
Posted by Davide Pasca as Programming, 3D Graphics at 2:08 AM EDT
6 Comments »
This Friday I had some sort of milestone to meet. I worked until about 12:35, got the last train at 12:43 (was actually a few minutes late) and headed back home. Unfortunately the last train only took me to catch a coincidence for a line which had already stopped. I waited in line 5-10 minutes and eventually took a taxi home. Woo !
The milestone didn’t go as well as I wished. I planned to put a lot of eye-candy in this phase of the project, but there was a lot of stuff outside my sphere of knowledge. The shaders, the off-screen rendering, etc.. I had to figure out how it all works on the XBox 360, which uses the well known Direct3D, with some important variations which makes things a bit more complicated to achieve.
Particle systems are also a pain to build without a proper tool that makes one experiment with some standard parameters. One could code a physics accurate explosion with particles, but that would be way too heavy (and require a degree in particle physics 8). Many compromises have to be done for games, compromises imply tricks, tricks imply fine tuning alternative representations.. basically a lot of trial-and-error work, therefore the need for tools that allow one to play around with parameters.
I hope I’ll have the time to do things right. I hope that what I did so far is good enough to pass the milestone ! I certainly tried to add some interesting new effects. The 360’s pumped up hardware was quite helpful, as I could draft CPU heavy systems without worrying too much to optimize performance along the way.
Cool.. but lets switch to the hot topic ! “God makes them, then couples them”. That’s the rough English translation of the title of this post. It means that some people are meant to be together, generally intended with a negative meaning.
I once (about a year ago ?) had some sort of relationship with some girl. It was a complex story. I basically thought that she was interesting and I decided to see what would come out of it. To this day, it has been the most instinctive, spoiled and flirtatious girl that I’ve ever met. An explosive cocktail, a “floating mine” as a friend of mine used to describe her.
The story is very complicated and the girl was truly something… she used to tell me that she didn’t like me because I wasn’t tall enough, and because I wasn’t blonde (although she didn’t mind Africans at all..). She’d hang out with me and say “I wish I was with XYZ instead ! He was tall, blonde, intelligent, the best ! I would really want to meet him now !!”. Once she plainly told me “I don’t want your genes !”. hohoho that surely has a special place in the history of the most funny and stupid (and honest ? 8) things that I’ve ever heard from the mouth of a girl !
Talking about mouth, she was certainly very cute, but the smile was a bit problematic.. (my nickname for her was “Alien”… 8). I remember once she was bragging about trying to buy a present for her boyfriend (some fat guy that she took pictures of in his underwear and she would show around !!), instinctively I told her “Try brush your teeth !” …ehehe that was funny, for me and my Italian friend, as I actually said that in Italian. “what ?” …”nothing nothing 8)” (that was mean, but nothing compared to what she could say).
As it might appear, I do have some resentment towards her.. probably, but I blame myself. I got myself acquainted with someone I knew it was only bad news, because I wanted to learn about it ! I wanted to learn how can someone be like that, flirt with such ease, jumping from friend to friend, continuously talking about marriage, being so lovely one minute and so mean the next.
I learned a lot but it’s not easy to try to convey most of it.
Japanese culture surely has its part in generating troubled girls. Some are brainwashed into having to find some good man to marry. “Get your college degree and then get married”. Her problem is that, although pretty young, she could already speak English. That means that she had access to most foreigners to spoil her. Japanese men are generally not willing to take 1/10th of the bullshit that foreigners do. She surely knew that well, as her target were continuously somewhat needy guys. She needed leverage and that’s easy on a foreigner.
So ! Recently I learned that she got married, actually I learned that her marriage isn’t doing so good. Her husband is a some guy I used to cheer for as he tried to stay in Japan, at some point considered a friend, but that actually grabbed his “golden opportunity” and pursued her as he disappeared form my sight… perhaps thinking that I would hold a grudge on him for messing with some girl with whom I was somewhat involved. Well, certainly I would have appreciated a little more honesty. Considering that I practically was their cupid (I jokinly once told her about this guy that was coming to Japan and back then she said she would marry him ! ..talk about being selective.. geez !)
I remember describing her to him and he’d say “Davide ! You can change her !!”, wtf ?! Forget it, I’m not going to try brainwash someone like that. She’s beyond hope ! Plus, anyone that can make such a 180 degrees turn, isn’t a very stable person…
Apparently he didn’t trust me, he believed that he would be able to change her and live happily everafter. Now I hear that the marriage quickly went sour. She ran off, and her parents asked him out of the house (wtf #2 ?!).
I remember that girl talking about marriage and all those other things with me. One day I met her and she had in the purse the paperworks for getting married to her current boyfriend (not the fatty one, that was only later). It was all so nuts, and for a nut job like that, there had to be some university-educated, super-gullible, somewhat tall, blonde (more or less) guy that would actually go for it !
I was right, it was good to get involved with her, she showed me some amazing things !
Sorry for the guy. I hope he learned the lesson.. ! He certainly isn’t going to get much active support from this side though.
Welllll.. funny how I learned about all this the day after that I met a nice girl !! It’s like, somehow someone took care of padding the floor with a pillow just right before I’d fall off my chair !
Also I would like to specify that I had no intimacy with the girl in question. Fack the random sexual relatioships, that’s bullshit !
Posted by Davide Pasca as Society, 3D Graphics, Diary, Japan at 3:49 AM EDT
11 Comments »
Last week, snowed in Tokyo !
Recently I had an hard-disk crash. Was the main HD of the server (mostly just the OS). It was a Maxtor (ehh !).
In light of that, I went on and bought a TeraStation. It’s a NAS (Network Attached Storage). A stand-alone system that holds 1 Terabyte of data on 4 250GB hard-disks.
Cool, but, I did the mistake of using it as RAID Spanning. Only later I fully realized that RAID Spanning is for speed and nothing else: it slices files in blocks of 8KB and spreads them on all the HD’s of the RAID.. without any parity ! I just wanted the RAID to be a continguous 1 TB of storage, no striping. I figured that the important data could be backed-up independently,
Apparently that’s not possible, so now I’m going to move data out, reformat the RAID as RAID 5. With RAID 5, 1TB becomes 750GB with parity, if one HD breaks, no data is lost.
I recently, succesfully used DSharingu to do mainteninance on my sister’s computer. It worked well, although some problems arised with her wireless LAN connection (what was the cause it’s beyond me !).
I’m working on a rewrite of the GUI. Moving onto wxWidgets. I don’t like wxWidgets reliance on inheritance. It’s actually a pain in the ass. The event table thing also looks kind of lame. But it’s the best option out there and I certainly prefer wxWidgets to MFC or plain Windows GUI programming.
I’m actually just trying to get a toolbar and other things like that. Nothing too fancy, functional stuff.
At work I finally re-implemented my spherical harmonics routines. Code written for PS2 has been ported on XBox 360. VLC asm to HLSL (high level shaders language, looks very much like C, practically same as Cg. Speaking of flakiness of memory.. I actually forgot in the process to properly port some code that was doing space transformation. That was something I had problems with in the past, a problem that I spent some time trying to solve, and then I completely overlooked it recetnyl as I was porting. Basically I had to “sandwich” a matrix between object<-world and world<-object (inverse of former), but, of course, I forgot that and started having problems.
In detail, the spherical harmonics matrices of the light-map were calculated in world space. To move them into object space, it goes:
obj_space_light_mtx = object<-world_mtx * world_space_light_mtx * world<-object_mtx
It’s 2AM.. we zzzzz !!!
Posted by Davide Pasca as Programming, 3D Graphics, Diary at 2:09 AM EST
5 Comments »
Luckily, I’m in a stage at work where I get again to actually design something, rather than rushing code out of the window.
I’ve continued to develop on M4D, but now I’m at the point in which M4D also has to produce some performing rendering.
M4D was meant to be some sort of scene graph. Also with code to deal with geometry more like a 3D creation software and less like a game engine. In fact, I’m convinced that I need to push the idea of creating code that helps to create 3D scenes, rather than a simple playback.. where one takes a scene created by an artist with a 3D package and attempts a faithful playback of the animation and quality of rendering.
I don’t want to create a new POV, but POV surely gives a hint to what 3D graphics can be about: coding and design can and should go along.
Nonetheless, I need to pull out some decent real-time performance, and so I’m working on a renderer interface for M4D. M4D gets to the point to generate vertex-packets and triangles. Where for a vertex-packet I mean a vertex which has all the attributes so that a triangle is defined only by three indices.
Further from that step, there is the actual geometry feed to the basic 3D API (OpenGL for PC and Direct3D for XBox 360). Vertex format, vertex streams and material selection.
M4D’s meshes, particle objects, materials and textures, have parallel objects on RendM4D (the rendering interface). This seems almost suitable for inheritance.. but not really ! Or at least, I can’t imagine it working.
I have M4D::Scene and M4D::Mesh. Now, with inheritance, I would end up with a RendM4D::Scene and RendM4D::Mesh. The problem is that, M4D::Scene and M4D::Mesh are directly related. A M4D::Scene links a bunch of M4D:Mesh…
For that reason, I went on to link renderables dynamically.
class M4D::Mesh
{
void *_client_objp; // store here the pointer to RendM4D::Mesh
…
};
class M4D::Scene
{
void *_client_objp; // store here the pointer to RendM4D::Scene
…
};
class RendM4D::Mesh
{
M4D::Mesh *_base_meshp;
…
};
class RendM4D::Scene
{
M4D::Scene *_base_scenep;
…
};
M4D::Scene and M4D::Mesh both have pointers to generic client objects (in this case the equivalent RendM4D objects). RendM4D::Scene and RendM4D::Mesh have the pointers to the original objects.
Now, a RendM4D::Scene can scan the scene tree by _base_scenep, which gives a bunch of M4D::Mesh, from which one can get the relative RendM4D:Mesh.
Seems like a bit of work, but it doesn’t get much simpler when dealing with dynamic links.
I also added callbacks for deletion and changes. For example when an M4D::Mesh has its geometry changed, it will call the OnModify() call-back routine with the given client object (the RendM4D::Mesh pointer).
In my case OnModify() points to a RendM4D method, and the client object is still the RendM4d::Mesh pointer. So that the renderable knows when source object’s geometry changes, and can update itself.
Same goes for the object deletion. A delete M4D::Mesh, will trigger an OnDelete() callback, which will call the relative RendM4D::Mesh and tell it to delete itself
I have a callback from the bed… time to sleep !
[Edit: I had forgot to specify _base_meshp and _base_scenep as pointers !]
Posted by Davide Pasca as Programming, 3D Graphics at 2:16 AM EST
5 Comments »
Today I picked up some work about walkchurch.
My goal continues to be to calculate only indirect global lighting. Basically I want to calculate some fancy ambient lighting to be added to normal dynamic direct lighting + stencil-volume shadows.
As I wrote before, indirect lighting, light that comes reflected by a secondary surface (like the Moon), has a rather low spatial frequency. The shadows that it casts aren’t sharp. It’s mostly about distributing a tint. For example, in a room with a red wall and a white floor, a light hits the red wall, making it “bleed” into the floor that will become reddish (this is more important than it seems !).
To calculate indirect lighting, I’m still going to do some sort of radiosity. Tesselation doesn’t matter as much, but still a decent level of subdivision is needed. I currently subdivide large triangles recursively. I split in half the longest edge, then see if any of the resulting two triangles need to be split again about their new longest edge.
Tesselating like this is very simple and also consistent, meaning that it doesn’t create any new T junctions.
Normally when one tesselates, should take care of not creating too many vertices. Ideally one should cut an edge using only one new vertex for two triangles share that edge.
I did some research about this. Some structure called half-edge seems to make it easier to deal with edges.. however it seemed to be more trouble than what is worth. So, I decided to split triangles individually, creating many duplicated vertices and eventually remove the duplicate vertices in a second pass. It’s just simpler this way, at least for the time being !
In order to create a first radiosity hit, I’m going to render the scene from the light source point of view with triangle IDs.
walkchurch/triangle_ids.png Then I’ll read back the frame-buffer and see which triangles are receiving the light. Color them with the light color and proceed onto the goal, to calculate the indirect lighting.
Again with the red wall and white floor. The red wall gets the light energy, while the floor gets the energy that bounces from the wall (namely light frequency mostly in the red spectrum (that’s the meaning of something being red !)).
Along with the triangle ID rendering, I implemented the object ID rendering. Useful to detect which objects are visible by the light source (will be useful later when calculating shadow volumes). In the picture, the scene is seen from the light source, red objects are hidden:
walkchurch/desk_hidden_objects.png
I did a test with the triangle IDs. I find out which triangles are hit by the light. Color them gray (could be any color) and render again the scene form again from the same light source point of view. They have to be all gray and they are indeed (except a few pixels by some weird artifacts). As I expected, when I render the scene at an higher resolution, triangles that weren’t previously visible, suddenly become visible (marked in red):
| walkchurch/visible_polys_11.png
|
walkchurch/visible_polys_zoom.png |
The reason is that the triangle ID test is performed off-screen at 512×512, and some tiny triangles aren’t rendered at all. When I render at higher resolution, some of those will become large enough to be visible.
This would be ugly if I were trying to make direct lighting with that system. However, indirect lighting of diffuse surfaces is a low frequency issue, and I expect to be hardly noticeable if a few small triangles don’t bounce back their portion of light.
Lezze zzzzz on this !
Posted by Davide Pasca as 3D Graphics at 1:17 AM EST
6 Comments »
I went back to my simple walkchurch demo to see what I could do to to get finally to some point where I can have some good lighting.
Because the church has no roof, and because the main problem with Radiosity is to get sharp shadows, I decided that the main light source for the time being will be the Sun. Or, generally, a directional light source. A light source so far away that can be considered as coming from infinite and thus casting hard shadows without penumbra.
Since the original light source is really just one and it’s a point, it would be a waste to go and do the full Radiosity hemicube calculation on the receiving triangles. It’s best to have a special case, where I avoid the hemicube calculation process (where for every triangle one has to render the whole scene 5 times (a whole hemisphere), just to, at most, spot the well known and unique light source).
The quick solution is to simply copy the light source energy into those triangles that are visible by the light source. To do that properly while using 3D acceleration, I decided to render the scene from the light source point of view, with triangle writing out unique IDs as their color. I will then read the frame buffer and see which triangles are actually visible (can tell by their IDs !). Because the point of view is the one form the light source, visible triangles are actually visible to the light source.
This thing is nothing really new, it’s a cheap mix between the Shadows Z-Buffer technique (the idea of rendering form the light source) and some accelerated Radiosity hemicube rendering implementations (the idea of assigning a triangle ID as a color).
I’m currently rendering the image from the light source point of view. I could read it already with glReadPixels(), but I decided that I want also to make a step further and take the time to implement the ARB_frame_buffer_object extension to get acquainted with the useful extension that allows to render offscreen and re-use that buffer for texturing.
The problems with this technique are however already evident. It doesn’t tell me if a triangle is completely in light or only partially (partially lit triangles will need special shadow casting to give the shadow edges).
The problem of aliasing also arises: when rendered, triangles could end up being as small as 0 pixels ! This means that if the resolution is relatively low, I may miss some triangles, which will be considered as not receiving any energy, while actually they are receiving some.
This is a signal theory issue.. it’s the price that one has to pay when dealing with discrete values, as opposed to geometrical ones.. which make for very accurate solutions but don’t map well to 3D hardware accelerators.
Posted by Davide Pasca as 3D Graphics at 3:41 AM EST
1 Comment »
Yesterday (Monday) night I dreamed that the World was reconfigured to work in frequency domain as opposed to time domain !!
This brought some changes. It all started with a centered white spot, plus some extra spots. A bit like when one visualizes an image that has been transformed with the FFT (Fast Fourier Transform).
It was mostly like seeing a cheap sci-fi movie. Not really interesting from a purely scientific point of view. Still, it was a clever dream to have in a sense 8)
I did more research about reading 3DS objects with faces being properly ordered.. and found out that I wasn’t doing anything wrong. The problem is that AutoCAD’s exported files have no sense of faces’ orientation. In order to render those objects properly, one has to render them with faces as having two sides.
That requires some extra rendering time, but also prevents from properly creating smooth vertex normals !
So, I wrote some code to fix the faces normals. The code works on the assumption that objects are closed. For each face, there must be a corresponding one that covers it. With that assumption and lots of ray-tracing activity, I can give the proper orientation to the faces. There are however a few exceptions 8(
Instead of trying to analyze the exceptions, I decided to manually fix those last few faces. The next step is to write an exporter to a common 3D object format (AC3D seems good), so that I can import the processed objects in Blender, modify the faces’ orientation by hand and then export the final objects. Hopefully by tomorrow I can finish that (yeah, right !).
More things to do: continue my mother’s website. I’ve been looking around for a simple BBS script, and it seems that only Japanese care to make simple BBS scripts. I’m planning to download one of those and adapt it to English/Italian.
Finally, I’ll also need to complete the first release of the video-chat app. Dind’t do any work in that sense. Although today I read some docs about neural networks applied to image compression. Interesting stuff, but I don’t know enough about neural networks to even start experimenting.. plus, that’s definitely a distraction, something diametrically opposed to the goal of releasing a working program 8)
Posted by Davide Pasca as Programming, 3D Graphics at 2:38 AM EDT
8 Comments »