• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!
  • Hello [name]! Thanks for joining the GMC. Before making any posts in the Tech Support forum, can we suggest you read the forum rules? These are simple guidelines that we ask you to follow so that you can get the best help possible for your issue.

Legacy GM Gm 3D has no Frustrum Culling.

M

Misty

Guest
Gm d3d has no frustrum culling, and it's frustrating.

Please don't tell me to put angle_difference(Point_dir
calls in every object...

That lags it a bit...

For all I know, it doesn't even not render objects out of camera range...

I don't think it has occlusion culling (no bsp)


But seriously, isn't frustrum culling built in to d3d?
 
I would also like to know, because the angle_difference method is okay for anything that is relatively flat, but once you have verticality, things can slow down because it is drawing everything above and below.
 

Roa

Member
I simply batch models by normals, and just read the players facing direction for which model should be drawn
 

chance

predictably random
Forum Staff
Moderator
d3d_set_projection_perspective(x, y, w, h, angle) essentially creates a view frustum. I've always been satisfied with the effect I get. And then cull by depth or distance.
 

Roa

Member
d3d_set_projection_perspective(x, y, w, h, angle) essentially creates a view frustum. I've always been satisfied with the effect I get. And then cull by depth or distance.
I dont even think the clipping planes are real clipping planes. I've never really obsreved a real FPS increase when decreasing them. Once a model is called on to draw, its going ot draw the model with no regard for the clipping planes.

Its something I find kind of silly cause I was always under the impression that this could be done for any application antively with directX functions. I'm not really sure why we can't do that.
 
M

Misty

Guest
d3d_set_projection_perspective(x, y, w, h, angle) essentially creates a view frustum. I've always been satisfied with the effect I get. And then cull by depth or distance.
Thanks, the last part though might be a bit laggy, having point_distance_3d calls in every object.
 
M

Misty

Guest
I doubt that will help you, its just a more limited d3d_set_projection_ext for top down only.
So basically his post was spinning my wheels, and GM doesn't have frustum, distance, or occlusion culling of any kind.
 
I

icuurd12b42

Guest
Culling is handled by the video card!
The actual issue at hand is how do you prevent the engine from submitting a vertex batch to the video card that is out of view. Since Studio has no idea the shape and size of the object you are sending to the video card it can't know what not to send so it is your responsibility to exclude data OR, simple solution, use frozen buffers or models. More complete solution is implement your own culling/exclusion since you know the size and shape of the object. I use a sphere system (a bubble encompassing the object) with simple angle difference method and simple distance method, yes in every object draw.

frustum culling: I uses a sphere intersects cone method, to add to the exclusion
occlusion culling is enabled with d3d_set_heidden(true); You cant add to this
distance culling is defined with the near far value of projection ext, You can combine it with the d3d fog... You can add to the exclusion comparing the distance and radius of your object to the far value
facet culling is done with d3d_set_culling(true). you cant add to this.
 
M

Misty

Guest
Tried frozen buffers, didn't notice any speed improvement, doubt they have frustum culling.

d3d_set_hidden doesn't enable occlusion culling, just depth sorting, this sounds like another post spinning my wheels...
 

Fern

Member
So basically his post was spinning my wheels, and GM doesn't have frustum, distance, or occlusion culling of any kind.
Tried frozen buffers, didn't notice any speed improvement, doubt they have frustum culling.

d3d_set_hidden doesn't enable occlusion culling, just depth sorting, this sounds like another post spinning my wheels...
Not to sound like a jerk here but you are just giving people negative responses when they are trying to help you. Nobody is trying to "spin your wheels". They are giving you invaluable tips they have learned.

Aside from all that, you are using Game Maker. An engine primarily focused on 2D games. In the documentation, they even advise against using the 3D functionalities and tell you how they do not plan on adding anything to it. There is nothing wrong with trying to create a 3D game with the tools available but you are trying to create something that it wasn't designed for. You will face issues when you do this and the best help you are going to find is the advice you have been given here.
 
M

Misty

Guest
False and misleading info isn't really an "invaluable tip"....

I also said in my original post not to give me advice of putting angle difference in every object, so he basically plowed over my original wishes....
His sphere idea seemed interesting but he didn't elaborate on what his code was so I have no idea how to do it (if you notice the angle difference method does not return accurate intersection points and can overclip meshes, his code gave no advice on how to solve that at all other than vaguities about "spheres"...

Furthermore, he seems to have misconceptions about occlusion culling, and what culling is, d3d_set_hidden does not enable occlusion culling, all objects are still drawn, they are not culled at all, they are just depth sorted. Occlusion culling usually requires bsp or else the culling method could be laggier than the render.

If I can recall, Direct 3D 6 games made in C++ or similar engines had frustrum culling inherently built into the game, I could be mistaken though.
 
M

Misty

Guest
What exactly did your friend do, be specific.

And what do you mean disabling the surface? I already disable automatic drawing of the application surface.
 

chance

predictably random
Forum Staff
Moderator
I dont even think the clipping planes are real clipping planes. I've never really obsreved a real FPS increase when decreasing them.
That's interesting. It would be good to know either way.

In my games, I'm generally more concerned about perspective and visual effect, rather than frame rate. So I haven't tested to see whether objects are drawn outside the view frustum. I've always assumed they were not drawn. But I'll do some tests to see if narrowing the view within a large field of 3D object changes the frame rate at all.

Or maybe a YYG developer could comment on this.
 
M

Misty

Guest
I will give you 2 scripts he made for frustum culling they are very useful!
Made by Uniqc A.K.A Maarten Jensen ~ uniqc.nl
frustum_culling_init
:
Code:
// frustum_culling_init(xfrom, yfrom, zfrom, xto, yto, zto, xup, yup, zup, angle, aspect, znear, zfar)
var d;

/* CUSTOM CODE */
globalvar objectscut, objectstotal;
objectscut = 0;
objectstotal = 0;
/* CUSTOM CODE */

global.frustum_culling_xfrom = argument0;
global.frustum_culling_yfrom = argument1;
global.frustum_culling_zfrom = argument2;

global.frustum_culling_xto = argument3-global.frustum_culling_xfrom;
global.frustum_culling_yto = argument4-global.frustum_culling_yfrom;
global.frustum_culling_zto = argument5-global.frustum_culling_zfrom;
d = sqrt(global.frustum_culling_xto*global.frustum_culling_xto+global.frustum_culling_yto*global.frustum_culling_yto+global.frustum_culling_zto*global.frustum_culling_zto);
global.frustum_culling_xto /= d;
global.frustum_culling_yto /= d;
global.frustum_culling_zto /= d;

global.frustum_culling_xup = argument6;
global.frustum_culling_yup = argument7;
global.frustum_culling_zup = argument8;
d = global.frustum_culling_xup*global.frustum_culling_xto+global.frustum_culling_yup*global.frustum_culling_yto+global.frustum_culling_zup*global.frustum_culling_zto;
global.frustum_culling_xup -= d*global.frustum_culling_xto;
global.frustum_culling_yup -= d*global.frustum_culling_yto;
global.frustum_culling_zup -= d*global.frustum_culling_zto;
d = sqrt(global.frustum_culling_xup*global.frustum_culling_xup+global.frustum_culling_yup*global.frustum_culling_yup+global.frustum_culling_zup*global.frustum_culling_zup);
global.frustum_culling_xup /= d;
global.frustum_culling_yup /= d;
global.frustum_culling_zup /= d;

global.frustum_culling_xcross = global.frustum_culling_yup*global.frustum_culling_zto-global.frustum_culling_zup*global.frustum_culling_yto;
global.frustum_culling_ycross = global.frustum_culling_zup*global.frustum_culling_xto-global.frustum_culling_xup*global.frustum_culling_zto;
global.frustum_culling_zcross = global.frustum_culling_xup*global.frustum_culling_yto-global.frustum_culling_yup*global.frustum_culling_xto;

global.frustum_culling_ytan = tan(degtorad(argument9)/2);
global.frustum_culling_xtan = global.frustum_culling_ytan*argument10;
global.frustum_culling_xsec = sqrt(1+sqr(global.frustum_culling_xtan));
global.frustum_culling_ysec = sqrt(1+sqr(global.frustum_culling_ytan));
global.frustum_culling_znear = argument11;
global.frustum_culling_zfar = argument12;
And frustum_culling:
Code:
// frustum_culling(x, y, z, radius)
// x, y, z = de positie van het object
// radius = de straal van de bounding sphere (stel dit groot genoeg in zodat je hele object erin past)
var xx, yy, zz;

/* CUSTOM CODE */ objectstotal += 1;

zz = global.frustum_culling_xto*(argument0-global.frustum_culling_xfrom)
    +global.frustum_culling_yto*(argument1-global.frustum_culling_yfrom)
    +global.frustum_culling_zto*(argument2-global.frustum_culling_zfrom);
if zz<global.frustum_culling_znear-argument3 or zz>global.frustum_culling_zfar+argument3 { /* CUSTOM CODE */ objectscut += 1;
    return false;
}

xx = global.frustum_culling_xcross*(argument0-global.frustum_culling_xfrom)
    +global.frustum_culling_ycross*(argument1-global.frustum_culling_yfrom)
    +global.frustum_culling_zcross*(argument2-global.frustum_culling_zfrom);
if abs(xx)>zz*global.frustum_culling_xtan+argument3*global.frustum_culling_xsec { /* CUSTOM CODE */ objectscut += 1;
    return false;
}

yy = global.frustum_culling_xup*(argument0-global.frustum_culling_xfrom)
    +global.frustum_culling_yup*(argument1-global.frustum_culling_yfrom)
    +global.frustum_culling_zup*(argument2-global.frustum_culling_zfrom);
if abs(yy)>zz*global.frustum_culling_ytan+argument3*global.frustum_culling_ysec { /* CUSTOM CODE */ objectscut += 1;
    return false;
}

return true;
The first script has some arguments, Make a d3d_set_projection_ext() and use the arguments you used with d3d_set_projection_ext() in the frustum_culling_init(); and use the second script with the object you want to set frustum culling with it, except 4 arugemnts, x,y,z,radius, The radius is sprite width / 2.
Thanks for the code, but that's an awful lot amount of lines of code to add to every object, might defeat the whole purpose of frustrum culling.
 
M

Misty

Guest
I was talking about the second one. Seems like a bunch of ifs, ands, pluses and multiplication calls.

Also I will have to call the first one every step since the projection will change direction when I move the mouse.
 

Roa

Member
I was talking about the second one. Seems like a bunch of ifs, ands, pluses and multiplication calls.

Also I will have to call the first one every step since the projection will change direction when I move the mouse.
That's what computers do best. We're talking 3d anyways. You're not getting away from it regardless.
 

Fern

Member
I was talking about the second one. Seems like a bunch of ifs, ands, pluses and multiplication calls.

Also I will have to call the first one every step since the projection will change direction when I move the mouse.
I only see like, 4 ifs in there. 100 ifs don't take up more than two microseconds. I think you will be ok.
 

BlueBurn

Member
If you really want to boost some fps, the best way would be to call frustum_culling just once every few steps,
also you shouldn't use dynamic objects like d3d_draw_block, but instead you should create model once and draw it with d3d_model_draw (or even better would be to use vertex buffers).

Also, it would be good to use only one object that renders all others:
Code:
with(obj_block)
{
    if (visible)
    {
        d3d_model_draw(mBlock, x, y, z, tex);      
    }
}
and if you for example use draw_set_blend_mode (or any other effect), you should call it just once:
Code:
draw_set_blend_mode(bm_add);
with(obj_light)
{
    if (visible)
    {
        d3d_model_draw(mLight, x, y, z, tex);      
    }
}
draw_set_blend_mode(bm_normal);
For opaque objects you should disable draw_enable_alphablend and draw_set_alpha_test.
 
M

Multimagyar

Guest
If you really want to boost some fps, the best way would be to call frustum_culling just once every few steps,
In most cases I would agree that calling a script only every now and then is more efficient than every step. Like updating a skeleton animation every 2nd frame so the computer does not constantly iterate between data. However I would like to point out this method with frustum culling probably going to cause artifacts as you physically would see maybe just with a frame delay that an object would pop into existence which for instance in an editor is not an issue but your game will be judged based on that artifact. However I do agree that using vertex buffers over default d3d draws or d3d model draw calls is faster.

On the part where only one draws, well honestly for my project I also have only "one" object rendering but it actually calls other invisible objects drawing events. But it does has it downsides which I'm not quite happy about.
 
I

icuurd12b42

Guest
>>However I do agree that using vertex buffers over default d3d draws or d3d model draw calls is faster.
vertex buffer are slow unless they are frozen
3d model should be as fast a frozen buffers, because that is what they become after the first draw
regular buffers are about as slow as sending primitives. save from the speed gain of having the buffer generated (like a 3d model) in a structured format.
 

Mike

nobody important
GMC Elder
CLIPPING is handled by the GPU - not culling.

CULLING is done by the CPU, and means you shouldn't submit objects you know aren't in view. There is no "3D culling" in Studio, you have to do it yourself.

If you submit 20,000,000 polys that are off screen, the GPU will process them and "clip" them, but they still go over the BUS and will take lots of time to clip. Best clipping is to never submit them - i.e. CULL.
 

Roa

Member
CLIPPING is handled by the GPU - not culling.

CULLING is done by the CPU, and means you shouldn't submit objects you know aren't in view. There is no "3D culling" in Studio, you have to do it yourself.

If you submit 20,000,000 polys that are off screen, the GPU will process them and "clip" them, but they still go over the BUS and will take lots of time to clip. Best clipping is to never submit them - i.e. CULL.
Makes sense once I watched and read some OGL tuts on this. It seems almost more costly to run culling in gamemaker on the CPU than to let the GPU run with wild abandon with draw calls. It doesn't feel like it equalizes the load unless you start dumping insane amounts of render passes like modern triple A engines.
 

Mike

nobody important
GMC Elder
No, not at all. You don't cull polys, you cull models. If you can cull a single model of 20,000 polys using a simple sphere to frustum, you've save LOADS of cpu and gpu time.

If you can cull half your world because it's behind you....well, you figure it out :)

Remember, submitting a model takes a lot of CPU time as well as the code heads on down deep into DirectX and the HAL driver.

The fastest model, is the one you don't draw.
 
  • Like
Reactions: Roa
Top