Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Hubis
May 18, 2003

Boy, I wish we had one of those doomsday machines...

Mithaldu posted:

Disabling the depth buffer is not an option, as the z-culling needs to be kept functional for each z-layer. Sounds like a pretty neat approach though. (Although i'm confused by what you mean with shading work.)

To make things a bit more visual, some screenshots. The first one shows a normal view. You are looking at 5x5 blocks of 16x16 units each. Each unit can be a number of terrain features, as well as a building (red) or a number of items (blue). Currently i'm rendering all items, even if that means they overlap each other, as sorting out already rendered ones causes a performance impact on the cpu side that slows poo poo down. As such, there's probably 3000-6000 items rendered there (visible and underground), all in all coming together to a fuckton of polys.



The landscape blocks are rendered as one display-list each, with the coordinates for all vertices pre-calculated. The buildings and items are rendered as individual 0,0,0-centered display lists that get moved into place by being wrapped in gltranslate commands.

Additionally, each block has not only the top-faces of each landscape unit rendered, but also the no/so/we/ea faces of the edge units, since leaving them out would leave holes in the geometry. These are the first problem factor that i noticed: When zooming in, the begin to clip through the top faces.

Additionally the red building blocks are rarely problems and manage, again when zoomed in, to clip through the top faces *entirely*. Lastly, when just doing screenshots, i noticed that sometimes the stones on the ground that are part of the landscape display lists clip through the blue items.

The dimensions are such that each landscape unit is exactly 1x1x1 units big, speaking in floating point vertex coordinates. (Would it maybe help if i increased that?) Currently the clipping planes are being done by defining a bounding box around all visible content (since it's a neat rectangle) and selecting the two points that are furthest and closest from the screen-plane, when projected along the camera vector and using their distances as parameters.

I am using gluLookAt, with the target being the turquoise wireframe. If the camera is moved towards the target or away from it the clipping planes get adjusted to match the distances. If the near plane falls under 1.0, i adjust it to stay at 1.0.

And that's where my problem comes in. Looking at it all from afar is good and works, but when i zoom in by moving the camera closer, this happens:



Note how the rocks in the bottom left corner clip in front of the blue things, which should be straigh above them. Also note the side-faces at the block edge clipping through the top faces in the line in the bottom-right quarter as well as in the top middle on the dark ground.

I mitigated it a bit by switching from zooming by moving the camera to zooming by changing the fov, but even that doesn't fix it completely (and things tend to jerk and jump around a lot when moving the camera):



:words:

It's a dwarf fortress clone, by chance? :)

By shading cost, I meant the cost of doing all the texture lookups, combinations, and copying/blending to the framebuffer. If you're rendering 20 overlapping objects, your GPU is basically doing 20x more work than it has to ("overshading"). Of course, I just remembered that you're doing this in Perl, so it's almost certainly CPU limited :v:

OK, so you've got this world-space box enveloping the entire scene, and a camera position (which is either external or possibly internal, if you're zoomed in). You've also got Z-Near and Z-Far, which you say you're clamping to max(1.0f, <nearest point in the scene>) and <furthest point in the scene>, respectively. Do I understand correctly? This seems to be what I'd advise.

What I find strange is that the Z-sorting issues get worse the closer you get to the objects. Usually, problems arise when you get further away from the camera, and the distance between overlapping objects becomes smaller than the preceision at that distance (which, in turn, gets better closer to the camera). It almost seems like the scene is doing the opposite of what it should be doing...

Adbot
ADBOT LOVES YOU

Mithaldu
Sep 25, 2007

Let's cuddle. :3:
It's not a clone, it's this: http://code.google.com/p/dwarvis/ :) If you have the game and a decently complex map you can try it out for yourself with the version that's for download there.

And thanks for explaining the shading thing, yeah, OpenGL-wise i have massive amounts of performance left, even on my rather dinky quadro 140 mobile. CPU is the big bottle-neck, which is why i don't bother to cut out invisible stuff.

Regarding your understanding of what i'm doing: Exactly, thanks for summarizing it so well. :)

As for your last paragraph: You're suddenly disregarding your previous understanding there. :D The traditional "it get's worse in the distance" is only true if the clip planes are fixed at, for example, 1 and 1000. However in my case the clip planes are mobile and can wander from "1-150" to "1001-1150", which makes the distance thing irrelevant.

My theory on why it happens when zoomed in is that OpenGL has an easier time mapping objects between "1001-1150" than between "1-150", which is why i tried to fix it with zooming by adjusting FoV. On the other hand, it might simply be that the problems are universal, but too small to show up when viewed from a normal distance. :iiam:

shodanjr_gr
Nov 20, 2007
Are those "blue things" as well as the rocks spites (as in textures rendered on billboards)? If so, maybe you are rendering them right on top of each other (which would explain the z-fighting)...

To improve performance, you can look into lots of things, including geometry instancing (you have TONS of similar looking geometry in those pictures) and various occlusion-culling techniques. Furthermore, you could easily save lots of display-list calls, if you created lists for larger block sizes as well (for instance, instead of just keeping 1x1 block size lists, make some 2x2, 3x3, etc etc lists and call them, based on the size of your areas).

I think that the Z accuracy of opengl only depends on the Zfar - Znear value, but i could be wrong...When you create your frame buffer, try using a larger accuracy depth component (32 bits for instance) to rule out Z-issues.

Mithaldu
Sep 25, 2007

Let's cuddle. :3:

shodanjr_gr posted:

Are those "blue things" as well as the rocks spites (as in textures rendered on billboards)? If so, maybe you are rendering them right on top of each other (which would explain the z-fighting)...
Nah, they're bone fida models. You can see that in the video here: http://www.veoh.com/videos/v16314761MGwKDQR7 What's happening there is quite plain and simple OpenGL having problems keeping things straight. I'm also suspecting that i'm forcing it to keep the geometry at too accurate levels, as things tend to "jump around" when zoomed in and any kind of "detail" work happens behind the comma.

shodanjr_gr posted:

To improve performance, you can look into lots of things, including geometry instancing (you have TONS of similar looking geometry in those pictures) and various occlusion-culling techniques. Furthermore, you could easily save lots of display-list calls, if you created lists for larger block sizes as well (for instance, instead of just keeping 1x1 block size lists, make some 2x2, 3x3, etc etc lists and call them, based on the size of your areas).
As mentioned, i'm using Perl, so the most important performance aspects are those that allow me to reduce the number of function calls, since Perl has a horrible performance penalty on those. I'm pretty much already using what you mentioned. Every unique model is pre-rendered into a 0-centered display list, then the landscape is generated in 16x16x1 slices, consisting of [gltranslate, glcalllist, gltranslate], all saved in display lists, etc. etc. Overall performance is not an issue anyhow as things are moving pretty smooth. The only problem the current variant of the code has is that huge numbers of items slow it the gently caress down, as i'm not caching "dormant" items into displaylists yet, but that's already planned and not an issue that i'm concerned over.

shodanjr_gr posted:

I think that the Z accuracy of opengl only depends on the Zfar - Znear value, but i could be wrong...When you create your frame buffer, try using a larger accuracy depth component (32 bits for instance) to rule out Z-issues.
How would i do that in OpenGL? I've never seen an explicit option for that and from what i remember from older games (Giants: Citizen Kabuto) that pretty much depends on the display bit-depth. I think OpenGL actually uses the alpha channel for each pixel to store the depth value.

Relevant code is here if that'd help you point it out: http://code.google.com/p/dwarvis/source/browse/trunk/lifevis/Lifevis/Viewer.pm

Hubis
May 18, 2003

Boy, I wish we had one of those doomsday machines...

Mithaldu posted:

It's not a clone, it's this: http://code.google.com/p/dwarvis/ :) If you have the game and a decently complex map you can try it out for yourself with the version that's for download there.

And thanks for explaining the shading thing, yeah, OpenGL-wise i have massive amounts of performance left, even on my rather dinky quadro 140 mobile. CPU is the big bottle-neck, which is why i don't bother to cut out invisible stuff.


Very interesting! I'll have to give it a whirl ;)

From what I've been seeing, you're taking a very naive (though valid) approach to rendering -- I presume that each tile is a separate draw call, along with each creature, object etc? You're definitely going to introduce a lot of overhead, just in driver command stream alone, not even considering the function call overhead of perl. The way many games address these sorts of issues is by 'batching' draw calls together, wherever possible. Once you get to a place where you've got enough functionality to worry about performance, I can give some more advice if you'd like.

quote:

Regarding your understanding of what i'm doing: Exactly, thanks for summarizing it so well. :)

As for your last paragraph: You're suddenly disregarding your previous understanding there. :D The traditional "it get's worse in the distance" is only true if the clip planes are fixed at, for example, 1 and 1000. However in my case the clip planes are mobile and can wander from "1-150" to "1001-1150", which makes the distance thing irrelevant.

My theory on why it happens when zoomed in is that OpenGL has an easier time mapping objects between "1001-1150" than between "1-150", which is why i tried to fix it with zooming by adjusting FoV. On the other hand, it might simply be that the problems are universal, but too small to show up when viewed from a normal distance. :iiam:

Nonsense :) The Z-near and Z-far coordinates help you place the positions of the near and far planes of the view frustum, respectively, and in turn determine components of your projection transform matrix. This matrix is used to transform your vertices from "view coordinates" (which the Modelview matrix produces) to "clipping coordinates", which are in the range [0, 1] on all axes. The X- and Y-coordinates represent the screen position from (left, bottom) to (right, top), while the Z-coordinate represents the vertex's position between the near and far clip planes as a value between 0 and 1. You can think of the View-to-Clip transform as warping and re-scaling the dimensions of the pyramidal Frustum to a unit-cube.

These "clip" coordinates are what the hardware uses to do clipping to the edge of the screen, and what is fed to the Z-test unit as depth coordinates. Thus, [1, 150] and [1001, 1150] should be the same to the hardware, since they both get converted to [0, 1] in the vertex shader. Furthermore, if we're actually talking about being "outside" the scene versus being "inside" the scene, then the numbers would be more like outside=[1000, 1150] and inside=[1, 75] because your camera will by definition be closer to the far plane than the boundery of the scene is. This means that not only will these offending objects (like the blue item in the near field) be moving from the low precision far end of the depth buffer to the higher precision near-end, but that there will be more precision per unit in general! Of course, it's been a while since I worked with OpenGL, so I might be mis-thinking about something.

The OpenGL FAQ on Depth has some interesting things to say on the subject. In particular, they suggest doing something along the lines of your "Clear the depth between layers" approach for very large depth distances; however, I still think something else is going awry in your code, because again this seems like the opposite problem you should be having. Can you try just clamping your planes to something like [1, 1000] and moving around the world to see if you're still having issues?

Hubis fucked around with this message at 22:36 on Oct 25, 2008

shodanjr_gr
Nov 20, 2007

quote:

How would i do that in OpenGL? I've never seen an explicit option for that and from what i remember from older games (Giants: Citizen Kabuto) that pretty much depends on the display bit-depth. I think OpenGL actually uses the alpha channel for each pixel to store the depth value.

No, opengl uses a separate render-target sized buffer to store the depth information. The precision of that buffer is adjustable. Besides, imagine if OGL used the alpha channel to store depth info, how would you do alpha blending AND depth testing at the same time? :)

I only code in C, so im not sure if you can do this in perl, but in C, when you create your Frame Buffer Object, you can do something like this:

glGenTexture(blah, blah, blah, GL_DEPTH_COMPONENT_32, blah, blah, blah);


before attaching your texture to the color attachment point and your depth buffer is assigned a higher precision value.
If you arent using FBOs, use FBOs. Its one of the features of OpenGL that ive grown to ADORE ever since i learned about it.


Also, why are you using Perl?

fakedit: but as its been said already, i find it unlikely that these are depth precision issues. Its more likely that you have forgotten some sort of Z-test flag off at a point inside your rendering code...

shodanjr_gr fucked around with this message at 22:53 on Oct 25, 2008

Mithaldu
Sep 25, 2007

Let's cuddle. :3:
I'm taking a naive approach, in a manner, yes. The script is built by iterative design in such a manner i got one thing working, then multiplied its application, then figured out ways to optimize it properly. Simply helps me keep the whole thing straight in my mind and also helps me when i need to refactor things. (Going from immediate mode to vertex arrays was pretty painless.) However, as the post above yours shows, i'm not entirely clueless in how to leverage basic OpenGL features. :)

Back to the z-planes. I guess i expressed myself badly. Let me quote the article you linked to make it more clear:

quote:

The OpenGL Reference Manual description for glFrustum() relates depth precision to the zNear and zFar clipping planes by saying that roughly log2(zFar/zNear) bits of precision are lost.
Now, let's look at this:
code:
[1, 150]     |     150/1 = 150    | 7.22881869049588    bits lost
[1, 75]      |      75/1 =  75    | 6.22881869049588    bits lost
[1000, 1150] | 1150/1000 =   1,15 | 0.20163386116965043 bits lost
That's what i meant earlier when i said that it may be easier for Opengl to distribute the data of the third case.

I should maybe mention that due to the high density of objects i'm rendering combined with the uniform distribution, i'm thinking that a more evenly distributed z-buffer would be advantageous, as compared to one that's logarithmically skewed to the front. I'm thinking this mostly because i never had much of a problem with z-clipping in the distance. If and when it clipped, it did so uniformly and affected everything i'm drawing equally.

I also want to say thanks for taking the time to help me think about this, i appreciate that very much as it's kinda hard to find people to throw these concepts at.

As for clamping to [1, 1000], it produces hilarious results:

as compared to:


That's the whole reason i started looking into this in the first place. :)

Mithaldu
Sep 25, 2007

Let's cuddle. :3:

shodanjr_gr posted:

No, opengl uses a separate render-target sized buffer to store the depth information. The precision of that buffer is adjustable. Besides, imagine if OGL used the alpha channel to store depth info, how would you do alpha blending AND depth testing at the same time? :)
Ah, ok, guess i was being stupid there. :D

shodanjr_gr posted:

If you arent using FBOs, use FBOs. Its one of the features of OpenGL that ive grown to ADORE ever since i learned about it.
I'm not, since I have no idea what they are and what they do. I mentioned it earlier in the thread, but this is the first OpenGL app i'm doing and everything i'm using i'm literally learning as i go along. Could you maybe explain in plain english and shortly what they are and why i should be using them? :)

shodanjr_gr posted:

Also, why are you using Perl?
For the above reason. Hilariously fast prototyping that allows me to concentrate on learning what i'm dealing with instead of worrying about arcane intricacies of C++ memory handling. Aside from that it also allows me to keep everything Public Domain and increases the chance of someone coming after me and picking it up in case i ever decide to drop it.

shodanjr_gr posted:

fakedit: but as its been said already, i find it unlikely that these are depth precision issues. Its more likely that you have forgotten some sort of Z-test flag off at a point inside your rendering code...
Well, as far as i'm aware these are all relevant bits:
code:
# called once at the start
sub initialize_opengl {
    [snip]
    glClearDepth(1.0);
    glDepthFunc(GL_LESS);
    [snip]
}

# called once at the start and whenever the window is resized or the camera moved
sub resize_scene {
    [snip]

    glViewport( 0, 0, $width, $height );
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    [snip]

    gluPerspective( $cam_angle, $width / $height, $dist_min, $dist_max );
    glMatrixMode(GL_MODELVIEW);

    [snip]
}

# draws one frame
sub render_scene {
    [snip]
    glEnable(GL_DEPTH_TEST);

    glMatrixMode(GL_MODELVIEW);
    gluLookAt( $x_pos + $x_off, $y_pos + $y_off, $z_pos + $z_off, $x_pos, $y_pos, $z_pos, 0, 1, 0 );

    [snip]

    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    glColor3f( 0.75, 0.75, 0.75 );
        
    render_models();

    [snip]

    glLoadIdentity();
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();

    render_ui();

    glPopMatrix();
    glutSwapBuffers();
}
See anything missing?

shodanjr_gr
Nov 20, 2007

Mithaldu posted:

I'm not, since I have no idea what they are and what they do. I mentioned it earlier in the thread, but this is the first OpenGL app i'm doing and everything i'm using i'm literally learning as i go along. Could you maybe explain in plain english and shortly what they are and why i should be using them? :)

Framebuffer objects are basically off-screen framebuffers. You can render to them as you could render to your screen, but nothing shows up on your screen, everything is stored in textures. When you create a framebuffer objects, you "attach" textures to its "attachment points". You can have many "color attachments" (so you can do something that's called Multiple Render-target rendering), one "depth attachment" (a depth buffer, of varying precision), and an accumulation buffer (i think). So you generate your FBO, generate your textures, bind them to your FBO, then use your FBO in the same way you would normaly. This is really useful if you want to do post processing, or use a render pass' output as input in a shader, etc etc. Also its pretty easy to do. A goon made a tutorial at some point, its either in here or in the Game Development thread, so you should check it out.

quote:

For the above reason. Hilariously fast prototyping that allows me to concentrate on learning what i'm dealing with instead of worrying about arcane intricacies of C++ memory handling. Aside from that it also allows me to keep everything Public Domain and increases the chance of someone coming after me and picking it up in case i ever decide to drop it.

Oh well, whatever floats yer boat :P. I am terrible with C, but i havent had issues with coding OpenGL for it (although i mainly focus on shader development, so my C code rarely changes).

quote:

Well, as far as i'm aware these are all relevant bits:
code:
# called once at the start
sub initialize_opengl {
    [snip]
    glClearDepth(1.0);
    glDepthFunc(GL_LESS);
    [snip]
}[/quote]

Out of curiousity, change the GL_LESS to GL_LEQUAL (i doubt it will change much though).

[quote]
[code]        
    render_models();

See anything missing?

Post your render_models(); code as well.

Mithaldu
Sep 25, 2007

Let's cuddle. :3:

shodanjr_gr posted:

Framebuffers
Alright, thanks for the explanation. I think glut already uses that internally when dealing with the backbuffer or something, but i'll be sure to try it out. :)

shodanjr_gr posted:

Oh well, whatever floats yer boat :P. I am terrible with C, but i havent had issues with coding OpenGL for it (although i mainly focus on shader development, so my C code rarely changes).
Let me put it like this: This thing needs to read the memory of another program byte-by-byte, continuously, update an internal represantation of that memory, render it and deal with user input. By the time i noticed how much of a pain it is to even do something simple as creating a 5-dimensional array of indeterminate size in C i decided i didn't want to bother with learning how to do that AND all the other crap when i can take a performance hit and just plain *do it*.

shodanjr_gr posted:

Out of curiousity, change the GL_LESS to GL_LEQUAL (i doubt it will change much though).
No noticeable change for the better. Might even have made it a bit worse.

shodanjr_gr posted:

Post your render_models(); code as well.
Nothing relevant in there imo. Lots of perl logic and looping through arrays, this when appropiate:

quote:


glColor3f($brightness, $brightness, $brightness);
glTranslatef( $x, $z, $y );

glBindTexture( GL_TEXTURE_2D, $texture_ID[creature] );
for my $part ( 0..$#{ $DRAW_MODEL{$model_name} } ) {
next if !defined $model_display_lists{$model_name}[$part];
glCallList($model_display_lists{$model_name}[$part]);
}
glTranslatef( -$x, -$z, -$y );
and at the end once this: glCallLists_p (@landscape_displaylists);


One thing i noticed: Is it normal that when z problems occur that one polygon that is orthogonal to another one pokes partly through it? When playing around with the clamped z-buffer i noticed that it sometimes looks as if the landscape-slices are not just drawing in the wrong order, but being shifted downwards by 0.1 units entirely.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Mithaldu posted:

Got a question about z-fighting issues. I'm rendering layers of roughly 80*80 objects, with roughly 20-40 layers stacked atop each other at any time. There is no computationally non-expensive way to cut out invisible geometry that i am aware of, so i pretty much have to render everything at all times. This leads to the z-buffer getting filled up pretty fast, resulting in rather ugly occasions of polys clipping through other polys.

I've already restricted the near and far clipping planes as much as possible so the geometry has the full z-buffer to play with
What are you using for the z-buffer that you're only getting 40 layers of precision? Make sure your nearplane isn't too close in particular.

As for a computationally-inexpensive way to occlude objects, try zoning them using occlusion queries. An occlusion query lets you know if and how much of some geometry is visible. Draw the world (occluders), then disable color/depth write and "draw" the bounding of a zone a bunch of objects could be contained in. Repeat for all zones. If the zone isn't visible, don't draw any objects fully contained in it.

For voxel-based stuff there's also octree occlusion, but I'm less familiar with that.

Mithaldu
Sep 25, 2007

Let's cuddle. :3:

OneEightHundred posted:

What are you using for the z-buffer that you're only getting 40 layers of precision? Make sure your nearplane isn't too close in particular.
Try scrolling up the page to see screenshots. :)

OneEightHundred posted:

As for a computationally-inexpensive way to occlude objects, try zoning them using occlusion queries. An occlusion query lets you know if and how much of some geometry is visible. Draw the world (occluders), then disable color/depth write and "draw" the bounding of a zone a bunch of objects could be contained in. Repeat for all zones. If the zone isn't visible, don't draw any objects fully contained in it.
That might actually work ... Do you maybe have some kind of example code for that? I should maybe elaborate on computationally inexpensive: Basically, anything that requires me to check each item on its own is useless, since it's faster for me to simply call a draw on it than to figure out whether it should be drawn. (Heck, the draw calls are even less expensive than for-looping over my item arrays.)

OneEightHundred posted:

For voxel-based stuff there's also octree occlusion, but I'm less familiar with that.
I thought about that too, but i'm only working with cubes at the smallest level here. Anything above that can only be sub-divided in 2d.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Mithaldu posted:

Try scrolling up the page to see screenshots. :)
Still not sure I understand where it's breaking down. What precision are you creating the depth buffer at?

If you're creating a complete 3D voxel grid, then you can draw it in order by just using the view axis. i.e. take the sign of each component of the view direction of the camera, and use that to determine which order to iterate through those components in the voxel array.

You can also squeeze more precision out by segmenting the world and doing multiple draw calls. This means that you'd chop your near/far range up into segments, draw anything visible in the farthest segment, clear your depth buffer, draw anything visible in the next-closest segment, repeat.

quote:

That might actually work ... Do you maybe have some kind of example code for that?
No.

You don't want to check each item, you want to check zones, and if the zone hull is culled, then everything in the zone is considered not visible. A zone would be a room, for example, and what you'd "draw" is a box for the bounds of the room.

I don't have example code, but it's asynchronous, it works by creating an occlusion query, drawing some stuff, ending the occlusion query, and then later when the card has the query finished, you can check how much it drew. You don't want to check immediately if you have other queries you can run.

By disabling depth/color write, it won't actually draw anything, but it will check the visibility of the polygons you're sending.

There's some trivial sample code here:
http://oss.sgi.com/projects/ogl-sample/registry/ARB/occlusion_query.txt

Mithaldu
Sep 25, 2007

Let's cuddle. :3:

OneEightHundred posted:

Still not sure I understand where it's breaking down. What precision are you creating the depth buffer at?
No idea. As mentioned before, so far i'm using glut and whatever its basic settings are.

OneEightHundred posted:

If you're creating a complete 3D voxel grid, then you can draw it in order by just using the view axis. i.e. take the sign of each component of the view direction of the camera, and use that to determine which order to iterate through those components in the voxel array.
I'm not sure why you're talking about voxels now. I've never mentioned them and am rendering a 3d grid of even-sized objects which are either cubes or more complex objects that can fit inside cubes.

All in all i'm probably rendering ~20000 distinct objects with roughly 2-100 polys each, using display lists

When looking at that from some distance and clipping range settings [46.5098639640652, 145.702191155173] everything looks fine. When zooming in a bit, causing the clipping settings to change to [1, 107.441455160607] it all goes to hell.

OneEightHundred posted:

You can also squeeze more precision out by segmenting the world and doing multiple draw calls. This means that you'd chop your near/far range up into segments, draw anything visible in the farthest segment, clear your depth buffer, draw anything visible in the next-closest segment, repeat.
Yea, that's what i've been talking about above. :) However instead of segmenting it with vertical walls, i'll do that horizontal floors, metaphorically speaking. Reason for that being that the main problem i seem to be having is too many objects, which only horizontal seperation would do anything good for.

OneEightHundred posted:

You don't want to check each item, you want to check zones, and if the zone hull is culled, then everything in the zone is considered not visible. A zone would be a room, for example, and what you'd "draw" is a box for the bounds of the room.

I don't have example code, but it's asynchronous, it works by creating an occlusion query, drawing some stuff, ending the occlusion query, and then later when the card has the query finished, you can check how much it drew. You don't want to check immediately if you have other queries you can run.

By disabling depth/color write, it won't actually draw anything, but it will check the visibility of the polygons you're sending.

There's some trivial sample code here:
http://oss.sgi.com/projects/ogl-sample/registry/ARB/occlusion_query.txt
Yea, that's the kind of example i need, contains only the minimum requirements. To be honest, this method, if it works with the Perl OpenGL library, will actually help me a lot in solving another problem that's been sucking performance, so thanks a lot! :D

haveblue
Aug 15, 2005



Toilet Rascal

Mithaldu posted:

I'm not sure why you're talking about voxels now. I've never mentioned them and am rendering a 3d grid of even-sized objects which are either cubes or more complex objects that can fit inside cubes.

He's talking about how visibility techniques intended for voxel objects could also be applied to a dense 3D grid of anything in general. A voxel world is just a 3D grid of objects where the objects all happen to be cubes.

Mithaldu
Sep 25, 2007

Let's cuddle. :3:
Ah, i see. He's suggesting i do the job of the z-buffer in-code. Sadly that's not an option although i'll need to do it later on for objects with transparency. Reason for that not being an option is that it would massively increase the amount of work that Perl needs to do, which is what i'm trying to avoid. :)

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Mithaldu posted:

Ah, i see. He's suggesting i do the job of the z-buffer in-code. Sadly that's not an option although i'll need to do it later on for objects with transparency. Reason for that not being an option is that it would massively increase the amount of work that Perl needs to do, which is what i'm trying to avoid. :)
Just use range buckets for the objects.

Mithaldu
Sep 25, 2007

Let's cuddle. :3:
I was tempted to post an image of a golf ball bucket here. But to be serious, I do not know what "range buckets" are. I can make vague guesses, which lead me to believe two things: Either you are talking about some technique that is completely unknown to me, or you're ignoring the display list structures i described in earlier posts around which i cannot work around. Color me confused.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Mithaldu posted:

I was tempted to post an image of a golf ball bucket here. But to be serious, I do not know what "range buckets" are. I can make vague guesses, which lead me to believe two things: Either you are talking about some technique that is completely unknown to me, or you're ignoring the display list structures i described in earlier posts around which i cannot work around. Color me confused.
It just means having a bunch of lists of objects in various distance ranges (range "buckets") because it's faster and simpler than re-sorting an object list with qsort or something. You distance-sort the scene by just adding objects to the buckets they belong in, then drawing the buckets in order, possibly sorting the bucket contents.

Although you're right, it won't work with display lists. (Stuff like this is why I don't like display lists!)

Mithaldu
Sep 25, 2007

Let's cuddle. :3:
Pretty much a ghetto depth filter for pre-sorting then. Would actualls also work with my display lists, but i don't think it'd give me the granularity i'm aiming for.

I also jsut tried to get the occlusion stuff implemented, but ran into a few roadblocks, so i have a few questions: Is it possible to do the occlusion query stuff in another way than using glBeginQueryARB, etc? I know it's not very likely, but better to ask than to stay ignorant.

Secondly, there's a similar HP extension for that. Does it only work on special gfx cards or why would glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP, &result) return the error "Unknown param"?

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Mithaldu posted:

but i don't think it'd give me the granularity i'm aiming for.
The point is that it'll let you get more resolution out of the depth buffer since you can adjust the near/farplane for each bucket.

quote:

I also jsut tried to get the occlusion stuff implemented, but ran into a few roadblocks, so i have a few questions: Is it possible to do the occlusion query stuff in another way than using glBeginQueryARB, etc? I know it's not very likely, but better to ask than to stay ignorant.
No. What roadblocks are you running into?

quote:

Secondly, there's a similar HP extension for that. Does it only work on special gfx cards or why would glGetBooleanv(GL_OCCLUSION_TEST_RESULT_HP, &result) return the error "Unknown param"?
The HP extension stalls if you're running multiple queries and occlusion is all-or-nothing, and beyond that the only thing you need to do is create/destroy query objects once in a while so I'd recommend using the ARB one instead.

OneEightHundred fucked around with this message at 02:53 on Nov 1, 2008

Mithaldu
Sep 25, 2007

Let's cuddle. :3:

OneEightHundred posted:

The point is that it'll let you get more resolution out of the depth buffer since you can adjust the near/farplane for each bucket.
I'm aware, just commenting that the z-layer seperation i mentioned before would give the depth buffer a good bit more of resolution, with nearly no computational overhead.

OneEightHundred posted:

No. What roadblocks are you running into?
glBeginQueryARB and associated commands are not yet implemented in the Perl OpenGL library. :)

OneEightHundred posted:

The HP extension stalls if you're running multiple queries and occlusion is all-or-nothing, and beyond that the only thing you need to do is create/destroy query objects once in a while so I'd recommend using the ARB one instead.
I know it's pretty horrible in comparison, but if i can get it to work, it just may suffice. Since it only relies on commands that are actually implemented already, it might work; unless it's hardware-specific.

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Mithaldu posted:

glBeginQueryARB and associated commands are not yet implemented in the Perl OpenGL library. :)
I'm pretty sure POGL will let you make core OpenGL 1.5 contexts, in which case everything will work the same except the occlusion query ARB functions are core, meaning they don't have "ARB" at the end.

quote:

I know it's pretty horrible in comparison, but if i can get it to work, it just may suffice. Since it only relies on commands that are actually implemented already, it might work; unless it's hardware-specific.
I see no reason it shouldn't, are you sure you're getting a context from the ICD and not the lovely stock Windows OpenGL implementation?

Mithaldu
Sep 25, 2007

Let's cuddle. :3:

OneEightHundred posted:

I'm pretty sure POGL will let you make core OpenGL 1.5 contexts,
No idea what that means.

OneEightHundred posted:

in which case everything will work the same except the occlusion query ARB functions are core, meaning they don't have "ARB" at the end.
As far as i am aware i can only use the functions that are defined in the .xs, compiled into the .dll and exported in the .pm. The only function with the word "query" in the name for which this is true is glpXQueryPointer.
I'm thinking about trying to see if they're easy enough to implement in the .xs and compile my own version, as well as mailing graphcomp about it, but i want to exhaust my options first.

OneEightHundred posted:

I see no reason it shouldn't, are you sure you're getting a context from the ICD and not the lovely stock Windows OpenGL implementation?
Again, i don't know what that means. Sorry. :/

shodanjr_gr
Nov 20, 2007
Ive got an Screen Space Ambient Occlusion related question (far more about graphics "theory" than OpenGL technicalities). Ive written my first SSAO shader, and am quite pleased with the initial results.

However, the results get less pronounced the further the object is inside the view frustrum. This is a result of the farther objects recieving less precision, and thus the difference between adjacent Z-values being almost zero. Can anyone suggest ways to "counter" this, other than expanding the sampling kernel (which i am already doing)?

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Mithaldu posted:

As far as i am aware i can only use the functions that are defined in the .xs, compiled into the .dll and exported in the .pm. The only function with the word "query" in the name for which this is true is glpXQueryPointer.
POGL definitely has a glBeginQuery binding in everything starting from the OpenGL 1.5 bindings and up. How to get that working, I don't know.

quote:

Again, i don't know what that means. Sorry. :/
If you link against opengl32.lib then for whatever reason, the entry points (read: functions) you get are from the lovely stock Windows OpenGL library. You need to make sure that the project is set up to dynamically load the DLL and get the entrypoints with GetProcAddress, which will use the ICD version (a.k.a. the one that comes with your video drivers, which is fully-featured) instead.

Mithaldu
Sep 25, 2007

Let's cuddle. :3:

OneEightHundred posted:

POGL definitely has a glBeginQuery binding in everything starting from the OpenGL 1.5 bindings and up.
Can you point out where you get that information from so i at least have a clue where to start looking? I mean, i'm looking at the source code for the module here, straight from CPAN, BEFORE compiling etc., and the only mentions of these functions are in the opengl includes files, but NOT in the perl files themselves.

OneEightHundred posted:

If you link against opengl32.lib then for whatever reason, the entry points (read: functions) you get are from the lovely stock Windows OpenGL library. You need to make sure that the project is set up to dynamically load the DLL and get the entrypoints with GetProcAddress, which will use the ICD version (a.k.a. the one that comes with your video drivers, which is fully-featured) instead.
Ah, alright. Thanks for the explanation. I'll be looking into that.

Edit: Looked into it. It loads "C:\Programme\Microsoft SDKs\Windows\v6.0A\Lib\OpenGL32.Lib". Tried removing that file to see if Makefile.PL can cope with that, but that only resulted in a broken build. Definitely thinking about trying to add the missing commands manually now.

Is there a good way to check whether glBeginQuery was executed correctly or am i gonna have to fly blind?

Mithaldu fucked around with this message at 07:29 on Nov 2, 2008

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!
I'm just going off what I see in the package and I really don't know what the gently caress, so the best I can do is tell you where I see things that look like what you want.

Mithaldu posted:

Can you point out where you get that information from so i at least have a clue where to start looking? I mean, i'm looking at the source code for the module here, straight from CPAN, BEFORE compiling etc., and the only mentions of these functions are in the opengl includes files, but NOT in the perl files themselves.
I can't read Perl anyway, and unfortunately I don't feel like dissecting a makefile written in it. POGL has bindings for OpenGL 1.5 in utils/gl_1_5.txt, and the .xs file LOOKS like it should be using GetProcAddress for everything and just grabbing entrypoints from your own opengl32.dll, but that doesn't explain why it's refusing to compile without opengl32.lib so I have no idea.

quote:

Is there a good way to check whether glBeginQuery was executed correctly or am i gonna have to fly blind?
Easy way to verify it's working at least is to just BeginQuery, draw something, EndQuery, then get the pixel count and see if it's actually what you expect it to be.

Although realistically, if your program doesn't instantly crash from calling a bad entry point, it probably executed correctly.

Mithaldu
Sep 25, 2007

Let's cuddle. :3:
Ah, i see what's going wrong now. You're looking at an older release. This is the most current and has a bunch of cruft removed: http://search.cpan.org/CPAN/authors/id/B/BF/BFREE/OpenGL-0.57.tar.gz

As for the file you were looking at there, i believe they weren't meant to reflect POGL, but only serve as documentation for the maintainer.

Also, Perl doesn't quite work that way. If you have visual studio express installed as well as ActivePerl, you can use the "Visual Studio 2008 Command Prompt" to run "perl Makefile.PL", which then generates the makefile like so: http://rafb.net/p/0x8xHQ38.html After that you do "nmake" and it generates the OpenGL.c file from the .xs file, which is then used to compile the dll. The .c file looks like this: http://www.mediafire.com/download.php?mttmnzzkto1

OneEightHundred posted:

Although realistically, if your program doesn't instantly crash from calling a bad entry point, it probably executed correctly.
That seems to happen. Build went fine, but the program exits without even as much as an error message when i try to call glGenQueries. (Chosen because i can copy/paste the glGenTextures entry for it.)

Edit: Narrowed it down a bit by inserting debug statements in the .c file. It crashes exactly when trying to call glGenQueries in the c part.

Also, poking at the perl process with Process Explorer shows it's using OpenGL32.DLL from the system32 directory. Would maybe replacing that with a more capable version work?

Edit2: Apparently i'd need to convince it to load nvoglnt.dll somehow. As i'm not too firm in c (beyond basic syntax and compiling stuff in visual studio), is there a simple way to edit the makefile/c file to make that happen?

Edit3: Nvm, got it. They apparently do both, link against the windows opengl library AND automatically load from the driver. Adding the following before the actual code section of the function in the .xs file made it work properly for this one function:
code:
INIT:
	loadProc(glGenQueries,"glGenQueries");
Now i only need to hope the rest of the functions will behave as well. :)

Also, thanks a lot for all the information you've given me. I doubt i would've gotten this far stumbling along on my own. :haw:

Edit4: I found out what the "Unknown param" i mentioned earlier means. In order to feed back data that is given by creating arrays, the xs code needs to allocate the memory for that. In order to allocate said memory it checks a function which has the size of the feedback array for different possible parameters stored. The HP occlusion testing feedback parameter was simply not listed there, so it doesn't know how much memory to allocate and bails out.

Edit5: All functions implemented and the occlusion queries are working now in the test implementation. I hope with that the hard part is over ...

Mithaldu fucked around with this message at 11:05 on Nov 2, 2008

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Mithaldu posted:

Edit2: Apparently i'd need to convince it to load nvoglnt.dll somehow. As i'm not too firm in c (beyond basic syntax and compiling stuff in visual studio), is there a simple way to edit the makefile/c file to make that happen?
Using LoadLibrary on opengl32.dll should do this automatically. I don't know why it works this way, all I know is that static-linking opengl32.lib is bad for your health.

quote:

Edit3: Nvm, got it. They apparently do both, link against the windows opengl library AND automatically load from the driver.
You should try getting rid of whatever dependencies on the opengl32.lib it has, last thing you want to do is mix calls.

quote:

Edit5: All functions implemented and the occlusion queries are working now in the test implementation. I hope with that the hard part is over ...
:hellyeah:

Mithaldu
Sep 25, 2007

Let's cuddle. :3:

OneEightHundred posted:

Using LoadLibrary on opengl32.dll should do this automatically. I don't know why it works this way, all I know is that static-linking opengl32.lib is bad for your health.

You should try getting rid of whatever dependencies on the opengl32.lib it has, last thing you want to do is mix calls.
They're not using LoadLibrary at all and instead use wglGetProcAddress, which seems to be meant for loading nv/ati/hp/whatever extensions. No idea why they're doing it that way, but looking at MSDN it seems to be the way to go.

I actually think it's meant to be that way, since, uh, if you do it manually with LoadLibrary, you'd need to try for all possible driver dlls, and keep your code up-to-date as drivers change, right? If i'm wrong there, do you have example code for what's the "right way"?

OneEightHundred posted:

:hellyeah:
That's just me, but i believe i've also managed to make the syntax a bit nicer. :)
code:
# draw occluder

my @array = glGenQueries_p(1);
    
glDepthMask(GL_FALSE);
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);

glBeginQuery(GL_SAMPLES_PASSED, $array[0]);
# draw occludee-shape
glEndQuery(GL_SAMPLES_PASSED);

glDepthMask(GL_TRUE);
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);

glFlush();

while( !glGetQueryObjectiv($array[0], GL_QUERY_RESULT_AVAILABLE) ) {}

if( glGetQueryObjectuiv($array[0], GL_QUERY_RESULT) > 0 ) {
# draw ocludee
}
Also, while i'm looking at it. What's the glFlush there good for?

Oh, and thanks again. The endorphine rush when you look at your code and realize "gently caress, it works" is always great. :haw:

Mithaldu fucked around with this message at 12:27 on Nov 2, 2008

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Mithaldu posted:

I actually think it's meant to be that way, since, uh, if you do it manually with LoadLibrary, you'd need to try for all possible driver dlls, and keep your code up-to-date as drivers change, right?
Loading opengl32.dll will get the appropriate DLLs. Apparently you'd want to use vanilla GetProcAddress for the regular entry points and wglGetProcAddress for everything else, but I really don't know how well that behaves with various OpenGL versions. Best practice is to use GPA for the whole interface.

I may be wrong on this whole thing too.

quote:

Also, while i'm looking at it. What's the glFlush there good for?
It's redundant, checking query availability automatically flushes. NV_occlusion_query didn't do that so it's probably a leftover from that.

It's not a terrible idea to flush if you're going to do other things before you request the query results though.

OneEightHundred fucked around with this message at 20:12 on Nov 2, 2008

Mithaldu
Sep 25, 2007

Let's cuddle. :3:

OneEightHundred posted:

Loading opengl32.dll will get the appropriate DLLs. Apparently you'd want to use vanilla GetProcAddress for the regular entry points and wglGetProcAddress for everything else, but I really don't know how well that behaves with various OpenGL versions. Best practice is to use GPA for the whole interface.

I may be wrong on this whole thing too.
Alright, googled around for a while and found this: http://www.gamedev.net/reference/programming/features/q3opengl/ as well as comments that the only reason they did that in Q3 was to make it possible to switch 3d drivers at runtime without restarting the game. Furthermore, if i read that code right, all it does is use the plain OpenGL32.dll function calls for core functions anyhow and extensions like this occlusion stuff have to be loaded with wglGetProcAddress either way as it's already happening.

Unless i'm missing something, i'd only be doing lots of work to duplicate something that's already there.

OneEightHundred posted:

It's redundant, checking query availability automatically flushes. NV_occlusion_query didn't do that so it's probably a leftover from that.
Nice, less code. :)

OneEightHundred posted:

It's not a terrible idea to flush if you're going to do other things before you request the query results though.
I'm only gonna be doing some Perl logic preparation, so that shouldn't be necessary.

BernieLomax
May 29, 2002
Sorry if this has been asked before, but I have problems with precision using the depth buffer. First I'm rendering stuff to several depth buffers, and afterwards I want to merge them by drawing them on top of each other with depth testing enabled. And afterwards I am using the depth test GL_EQUAL in order to shade everything. However it does not work very well. I do find that by using buffers with the same precision I get better results, but I have yet to find a combination that works. Any ideas?

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

BernieLomax posted:

Sorry if this has been asked before, but I have problems with precision using the depth buffer. First I'm rendering stuff to several depth buffers, and afterwards I want to merge them by drawing them on top of each other with depth testing enabled. And afterwards I am using the depth test GL_EQUAL in order to shade everything. However it does not work very well. I do find that by using buffers with the same precision I get better results, but I have yet to find a combination that works. Any ideas?
You can't really do this because the depth buffer values range from 0-1, the projection matrix remaps distances between the nearplane and farplane to that range. That means if have, say, one depth range...

Camera --> N[----A----B----]F
... and chop it into two depth slices...
Camera --> N[----A--]F N[--B----]F

... then you need to clear the depth buffer after after you draw the distant slice anyway, otherwise you can get out-of-order objects like this crap:
Camera --> N[--B-A--]F

The drawback of course is that by clearing the depth buffer, you are eliminating B from the depth buffer. What you need to do is make sure that any objects that are in a depth slice (even partially) get drawn in that slice.

.... Alternately, make sure you're creating the depth buffer with a reasonable precision and try adjusting your nearplane/farplane values.

OneEightHundred fucked around with this message at 21:36 on Nov 3, 2008

BernieLomax
May 29, 2002

OneEightHundred posted:

You can't really do this because the depth buffer values range from 0-1, the projection matrix remaps distances between the nearplane and farplane to that range. That means if have, say, one depth range...

Camera --> N[----A----B----]F
... and chop it into two depth slices...
Camera --> N[----A--]F N[--B----]F

... then you need to clear the depth buffer after after you draw the distant slice anyway, otherwise you can get out-of-order objects like this crap:
Camera --> N[--B-A--]F

The drawback of course is that by clearing the depth buffer, you are eliminating B from the depth buffer. What you need to do is make sure that any objects that are in a depth slice (even partially) get drawn in that slice.

.... Alternately, make sure you're creating the depth buffer with a reasonable precision and try adjusting your nearplane/farplane values.
What I need to do is to exactly copy the depth buffer from one FBO to another (or the main output). The stuff I am rendering is the exact same on both, but with differing stencils etc. However the internal format differs from what you read, so you'll lose some details.

I'm trying to work around this, but still would love if there was a way.

edit: Solved. I made a fragments-shader that reads from a depth texture and compares the fragment-z and draws with a threshold. Works extremely well.

BernieLomax fucked around with this message at 09:40 on Nov 5, 2008

Mithaldu
Sep 25, 2007

Let's cuddle. :3:
Just a random note to anyone following the occlusion query stuff above: Don't forget to delete the queries once you're done with 'em. :gonk:

Edit: Also, question: How would i go about making a polygon render visibly from both sides without rendering it twice?

Mithaldu fucked around with this message at 13:10 on Nov 11, 2008

OneEightHundred
Feb 28, 2008

Soon, we will be unstoppable!

Mithaldu posted:

Edit: Also, question: How would i go about making a polygon render visibly from both sides without rendering it twice?
glDisable(GL_CULL_FACE)


If you want the two sides to render differently, you either need to render twice or use two-sided rendering pixel shaders which I haven't dealt with yet.

Mithaldu
Sep 25, 2007

Let's cuddle. :3:

OneEightHundred posted:

glDisable(GL_CULL_FACE)
Of course. :doh:

Thanks. I needed it to make the occlusion check shapes also render when the camera is inside them.

Now i only need to make the shapes a bit more fine-grained with the help of the stuff from the gamedev thread and then i can get back to the fun stuff. :D

Adbot
ADBOT LOVES YOU

Tap
Apr 12, 2003

Note to self: Do not shove foreign objects in mouth.
I've recently been inspired to start game programming as a hobby, but I know virtually nothing about the subject. Do you guys have any literature you'd recommend for a beginner? I'd like to get started with basic stuff like vertexes and pixel shading, etc..

I have an idea for a game I'd like to create for the iPhone, so I opened the PDF for the OpenGL ES v1.1 spec and most of it was foreign to me. The first page they stated "We assume that the reader has at least a rudimentary understanding of computer graphics." So I'd like to get to that level within the next year or so.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply