Mark.. Blitz's Z-buffer accessible, but...

Blitz3D Forums/Blitz3D Programming/Mark.. Blitz's Z-buffer accessible, but...

Tom(Posted 2004) [#1]
... there's no way to find it from within Blitz, we need a native pointer to it (please!).


I weren't familiar with Zbuffers until MasterBeaker showed me a little demo, and explained why access to it could be useful for shadows. After my messing with banks/imagebuffers the other day, I thought I'd see if I could hunt the Zbuffer down.

I sniffed through Blitz allocated memory and come across this image



I noticed the polygons had definiton, even though the colors are screwed up. After some tinkering about (cheers Beaker & Andreas) we managed to figure out how to convert the values into something visibly pleasing

http://www.tomspeed.com/z-buffer.avi (600k Divx)

For those that don't understand the theory, this is what I learned after reading up on it:



If this could speed up the creation of shadows, and it's just sitting there doing nothing, that's a terrible waste.

PLEASE can we have a pointer to it :)

Cheers!
Tom


Rob(Posted 2004) [#2]
I have to support any request for z buffer access. Thumbs up!


fredborg(Posted 2004) [#3]
The ability to access the z buffer directly, would be nothing short of: lękkert :)

Any chance of posting some code, so that we can start poking away now?


Beaker(Posted 2004) [#4]
To add to the argument here is my toon stencil shadow demo:
Click

This would be much improved (speed and functionality) with any of the following:
full access to the z-buffer
a pointer to z-buffer
triple buffered flipping


Tom(Posted 2004) [#5]
Fredborg, unfortunately the buffer will appear in different places on everyones PC, and I had more than a fair few craches trying to look at memory I shouldn't have been looking at :P

If Mark kindly supplies a pointer in a new build, or can indicate if maybe the backbuffer() or frontbuffer() memory heaps have a definite link to it, then it's as simple as peeking the buffer address+offset

To clamp the value to within 0 - 255 for a bitmap:

v=peekmemint(Zbuffer + offset) Shr 24

The buffer's 16 or 24bit, not entirely sure :) In the case of creating realtime shadows using the method above, you can avoid the need to convert the backbuffer to a bitmap, and just peek the X,Y value when you need it, so it should be very quick.

One thing I did notice, was that when using CameraRange cam,near,far only the 'near' value seemed to have an effect on the Z range.

Might I also suggest you check the other thread I started about redirecting Banks to imagebuffers which allows direct poking/peeking, and also the ability to pass an imagebuffer to a DLL for processing. Andreas has made some nice functions that act just like Blitz+ equivalents, they come in handy when messing with buffers.

Tom

p.s What is 'lękkert'? :P


fredborg(Posted 2004) [#6]
Ok, I figured there would be a direct pointer from the screen buffers to the zbuffer. I can see how it becomes nasty if you have to second guess it's memory location.

lękkert = nice in a corny way :)


Warren(Posted 2004) [#7]
Fredborg, unfortunately the buffer will appear in different places on everyones PC, and I had more than a fair few craches trying to look at memory I shouldn't have been looking at

Yeah, I really would advise against using this technique to any great extent. Different cards and different machines are going to store things in different places.


sswift(Posted 2004) [#8]
I find it odd that the zbuffer would be in memory.

I'm pretty sure that the zbuffer is generated on the 3D card, and copying it to memory would have the same speed hit as copying a full screen buffer to memory, which is to say, a significant one, which is why people want to be able to render directly to a texture instead of to video ram. So why is Mark copying it to ram if it's not used?

I admit I don't know exactly what goes on when one renders a scene, but I'd like to understand why this is in ram.


Tom(Posted 2004) [#9]
sswift: Would having zbuffer access benefit your shadow routines?

The bottom address in the AVI is the starting memory address for that instance of the program, is there a way I could tell if that was video memory?

EpicBoy: Indeed, I don't recommend anyone tries this manualy.

A simple Zbuffer pointer would do the job!

Tom


sswift(Posted 2004) [#10]
"sswift: Would having zbuffer access benefit your shadow routines?"


No, not really.

In fact, without pixel shaders, I'm not sure that having access to the zbuffer would allow us to generate zbuffer shadows in realtime.

The traditional way would be to generate a zbuffer for the camera, and a zbuffer for the light source, and then using the distance of each pixel in the camera view from the camera, transform that pixel to light space to camera space, and then determine if the pixel's Z value in light space is greater than the distance of the pixel at that location which is in the light's zbuffer. If so, then it is in shadow.

This would be expensive.


sswift(Posted 2004) [#11]
I'm not even sure how one would convert a 2D screen coordinate + Z value to camera space. Anyone know a good way that doesn't reuqire you to know the camera's FOV?


Tom(Posted 2004) [#12]
Wouldn't you be doing each lightmap pixel, and not each camera pixel?


Koriolis(Posted 2004) [#13]
In fact, without pixel shaders, I'm not sure that having access to the zbuffer would allow us to generate zbuffer shadows in realtime
Sure it does. Using shadow volumes. What you're refering to are shadow maps, a pretty different technique.


sswift(Posted 2004) [#14]
No. Because then you would miss a lot of camera pixels and hit a lot of them twice.

It's kind of like trying to draw a circle by detrmine if each point in a sqaure is in a circle, or drawing the circle by drawing circles of increasing size until you reach the radius you want. In the latter you miss some pixels and hit quite a few others more than once.


sswift(Posted 2004) [#15]
"Sure it does. Using shadow volumes. What you're refering to are shadow maps, a pretty different technique."

Uh... shadow volumes? Shadow maps?

Shadow maps are what I use. Shadow volumes sounds like the technique used for stencil shadows.

Neither sounds like it has any realtion to zbuffer shadows, which use the method I described and which is probably one of the only methods for which calculating a zbuffer of the scene would be useful.

But feel free to find a webpage proving me wrong. :-)


sswift(Posted 2004) [#16]
I found one papaer from NVidia referring to z-buffer shadows as "shadow mapping", but most pages I see are refering to stencil shadows when they mention shadow volumes, with no mention of zbuffers.


Koriolis(Posted 2004) [#17]
Doh!
... I must be tired (well, I am) ...
Somehow I read "Stendil buffer" when it was "z-buffer".
Erm, my bad.
I must say it seemed a bit weird that *you* used the wrong terms :p

Side note: I probably thought "stencil buffer" (when it was z buffer) because actually that is the buffer whos access lacks the most in blitz, and especially regarding the ability it would give to do fast stencil shadows. I don't even consider for one second z-buffer as an option for shadows (multiple lights -> nightmare).


sswift(Posted 2004) [#18]
Actually, even if we had access to the stencil buffer in Blitz we still couldn't do shadows because there is no way to get the vertex locations in an animated mesh. Thus we could not extrude a volume from one and thus we could not render that volume to the stencil buffer. In addition, because stencil buffers require such low ploygon models, and we lack pixel shaders to do proper dot3 normal mapping, we'd be stuck using very crappy looking low polygon models instead of svery snazzy looking low polygons models like Doom 3.

Neither zbuffer access nor stencil buffer access alone is a magic bullet for fast, great looking shadows.


Koriolis(Posted 2004) [#19]
Actually, even if we had access to the stencil buffer in Blitz we still couldn't do shadows because there is no way to get the vertex locations in an animated mesh
Yep, I know. Actually there are alternatives, but too kludgy for being that appealing.

In addition, because stencil buffers require such low ploygon models
I don't see the problem. You're not forced to use the same model for rendering and for collisions/shadows. It's not that uncommon to use a low-poly version for the latter 2 cases.


(tu) sinu(Posted 2004) [#20]
that coming from the shadow expert, so it's final for now :)


sswift(Posted 2004) [#21]
If you use a low poly version of the model for stencil shadows you'll get all sorts of glitches in self shadowing situations.

It's probably not possible to do stencil shadows and NOT enable self shadowing, but I'm not sure about that.


Koriolis(Posted 2004) [#22]
If you use a low poly version of the model for stencil shadows you'll get all sorts of glitches in self shadowing situations
Eh eh, true. It was mainly for the sake of keeping discussing about it :p
I'm sure there is some trick to cope with this problem.

It's probably not possible to do stencil shadows and NOT enable self shadowing, but I'm not sure about that.
Indeed, AFAIK you can't do this (in a reasonably fast way). As it would require a way to determine what "self" is. And the beauty of the tecnique is precisely that it works blindly on the whole framebuffer, without any geometry knowledge.

BTW, do you provide in your lib any mean to associate a low-poly version of the shadow casting meshes? Even if you don't render them (for shadows) each frame, it would be better with a low poly version. Please bear with me, I never really checked your lib.


sswift(Posted 2004) [#23]
"BTW, do you provide in your lib any mean to associate a low-poly version of the shadow casting meshes?"
"Even if you don't render them (for shadows) each frame, it would be better with a low poly version."

I don't understand what you mean.

Even if you don't render them (the low poly mesh) (for shadows) each frame it would be better with low poly mesh?

Huh?



I presume you are asking if you can cast a shadow from a low poly version of the mesh instead of casting the shadow from the high poly mesh.

The answer to that is yes. You can hide a mesh and still cast a shadow from it. So you can have a visible high poly mesh that does not cast shadows, and an invisible low poly mesh that moves with it that casts shadows which then will appear to be originating from the high poly mesh.

I'm not really sure how much of a speed benefit you would gain from this, but I suppose if your shadow casting meshes were very high polygon you might get some benefit.


Koriolis(Posted 2004) [#24]
I presume you are asking if you can cast a shadow from a low poly version of the mesh instead of casting the shadow from the high poly mesh
Er, yes, what I said that is.
[edit]Oh I see, you understood "even if you don't render them at all". I said "even if you don't render them *each frame*" but rather like each N frames, which is already far more efficient. You use some error threshold if I understood correctly.[/edit]

Anyway, that answers the question, thanks.


sswift(Posted 2004) [#25]
Ah.

Yes, there is an error threshold, so the shadow maps do not get rendered every frame. However, this only applies to objects which are not animating. (By animating I mean an animated boned mesh) I have not yet implemented a way to have a threshold for animated meshes. For optimal results one would have to set a custom threshhold for each animated mesh, but even that is not the most idea solution because you could desire a large threshhold for portions of an animation which don't move much, and a small threshold for those which move a lot, like when one swings an arm.

I suppose then the ideal solution would be animation thrresholds which one could specify per mesh, and a function to change the animtion threshhold of an object which is already casting shadows. Then at least you could have one threashold for the standing idle animation and then change it when the character is walking and change it again when he breaks into a run.

Of course right now you can't even cast shadows from MD2's and semgented 3D model animations require multiple shadows. That being the case boned B3D models are the ideal choice for animated models, and as such if it were possible to determine which children of a model were boned then it might be possible to algorithmically determine the best threshold to use.

Hm...