1. Hey! Guest! The 35th GMC Jam will take place between November 28th, 12:00 UTC - December 2nd, 12:00 UTC. Why not join in! Click here to find out more!
    Dismiss Notice

3D When using a 3D camera all transparency is filled in with the room background color

Discussion in 'Programming' started by Bayesian, Oct 21, 2018.

  1. Bayesian

    Bayesian Member

    Joined:
    Sep 13, 2016
    Posts:
    423
    All my sprites and primitives' alpha are being filled in with what ever the background color is. Deleting or making the background transparent isn't an option because then transparent areas will get smeared with pixels that don't clear.

    How can I fix this?
     
  2. flyingsaucerinvasion

    flyingsaucerinvasion Member

    Joined:
    Jun 20, 2016
    Posts:
    2,182
    can you give a screenshot so we can be sure of what you mean?

    Transparency is often a problem in 3d because of the way the zbuffer works.
     
  3. FredFredrickson

    FredFredrickson Member GMC Elder

    Joined:
    Jun 21, 2016
    Posts:
    118
    You have to draw the transparent stuff after the stuff you want to show through it. The draw order is hugely important in 3D.
     
    TheSnidr and BattleRifle BR55 like this.
  4. BattleRifle BR55

    BattleRifle BR55 Member

    Joined:
    Jun 24, 2016
    Posts:
    976
    I'm happy you're still around <3
     
    FredFredrickson likes this.
  5. FredFredrickson

    FredFredrickson Member GMC Elder

    Joined:
    Jun 21, 2016
    Posts:
    118
    Hey thanks - same to you man, I remember you from long ago! :cool:
     
    BattleRifle BR55 likes this.
  6. BattleRifle BR55

    BattleRifle BR55 Member

    Joined:
    Jun 24, 2016
    Posts:
    976
    I'm not going anywhere. Still working on the same FPS from long ago, still inspired by your early 3D games!
     
  7. FredFredrickson

    FredFredrickson Member GMC Elder

    Joined:
    Jun 21, 2016
    Posts:
    118
    Hehe, nice! I bet it's come a long way since then.

    Someday I'd love to revisit some of those old 3D games I'd made - either to remake them in GMS2 with my current knowledge, or to take them into another game engine entirely - but there are only so many hours in the day, unfortunately... and I [try to] run a business during the day. :D
     
    BattleRifle BR55 likes this.
  8. Bayesian

    Bayesian Member

    Joined:
    Sep 13, 2016
    Posts:
    423
    Here's a screen shot. I made the background layer in the room red so you can very clearly see the problem. The problem still clearly exists no matter the color though. The trails and rain are primates, only te rain has a texture. The blue player is a sprite and the grey enemies are all draw calls which is what I was going to switch to before I realized the actual problem.

    [​IMG]

    I could be wrong but this is my understanding of what my draw order should be in my project based on creation order, what should I change?
    1. Room
      1. Tile layer(for checkered background)
      2. Instances layer
      3. Mangers layer
        1. Create oGame
      4. Background layer(red)
    2. oGame
      1. Create
        1. Set tile data
        2. Create oRain on instances layer
        3. Create Platforms on instances layer
        4. Create oPlayer on instances layer
          1. Create trail object
        5. Create 3D camera
      2. Step
        1. Create oEnemy on instances layer
          1. Create trail object
     
  9. flyingsaucerinvasion

    flyingsaucerinvasion Member

    Joined:
    Jun 20, 2016
    Posts:
    2,182
    what is the checkerboard pattern in your screenshot?

    EDIT: don't you have an object that controls the order in which things are drawn? Also, are you just pointing the camera downard (toward +z)?
     
  10. guyinboots

    guyinboots Member

    Joined:
    Oct 1, 2018
    Posts:
    29
    If your using gms2 do this in create event to fix that problem

    gpu_set_alphatestenable(true);
    gpu_set_alphatestref(0);

    This will disable anything with a an alpha value of 0 or less from drawing, so weird borders around objects that are just sprites will go away
     
  11. Bart

    Bart Member

    Joined:
    Jun 21, 2016
    Posts:
    190
    As said above, make sure to draw transparent stuff last so it gets drawn above everything.
    Also, before doing that, set z-writing to false using gpu_set_zwriteenable and z-testing to true using gpu_set_ztestenable.
    Lastly, you might want to turn off culling using gpu_set_cullmode so both sides of transparent faces are visible.
    Code:
    // Start of translucent drawing
    gpu_set_zwriteenable(false);
    gpu_set_ztestenable(true);            // set to true for non-translucent models as well
    gpu_set_cullmode(cull_noculling);
     
    Last edited: Oct 22, 2018
  12. Bayesian

    Bayesian Member

    Joined:
    Sep 13, 2016
    Posts:
    423
    Sorry for the ridiculously late reply guys,
    Its a tile set that I set programmaticly, sorry for not mentioning that.
    I wasn't aware I could do that. How would I do that? Is it different from depth sorting?
    My understanding is that its pointing toward -z, increasing the depth moves it closer to the camera and my camera's look at xup yup zup is 0,-1,0
    I already experimented with gpu_set_alphatestenable, set to true it changes the red corners into a jagged red outline
    gpu_set_alphatestref(0) doesn't do anything. even when I use both
    gpu_set_zwriteenable(false) seems to reverse my draw order, I had to remove the checkered tile background to see anything and the trails draw on top of the player or enemies sprite even though I draw them before calling draw_self also my 3D platforms are doing this, I changed the room background layer color so your eyes don't bleed.
     
    Last edited: Oct 25, 2018
  13. flyingsaucerinvasion

    flyingsaucerinvasion Member

    Joined:
    Jun 20, 2016
    Posts:
    2,182
    I think it is a good idea in pretty much any 3d game to take over completely the drawing order from gamemaker. In other words, in one controller object's draw event, you do all of the drawing for your 3d scene. This way, there can be no confusion about the order in which things are drawn.

    Draw your background stuff first. Then draw foreground stuff. If you have partially transparent stuff you are drawing in the foreground, you must do one of two things... either draw them in order from greatest depth (z distance in camera space) to lowest depth, or else enable alpha testing (which simply won't draw fragments below a certain alpha). Anthing that is partially transparent should probalby be drawn after all opaque stuff has been drawn. When drawing anything fully opaque, make sure zwriting is turned on. Also, in most cases you'll want to turn on backface culling for anthing that can have faces that could point away from the camera.
     
  14. Bart

    Bart Member

    Joined:
    Jun 21, 2016
    Posts:
    190
    It doesn't actually reverse the draw order. Although it might seem that way.
    Did you re-enable z-writing after drawing the transparent stuff? It should still be enabled for all other drawing.
     
  15. Bayesian

    Bayesian Member

    Joined:
    Sep 13, 2016
    Posts:
    423
    Ok I didn't understand that I was supposed to be switching it back and forth, check out my code below.
    Ok I have this partially set up, I can't figure out how to control the room background and tile layer's draw order with the method I'm using.

    This is at the beginning of oGame

    Code:
    gpu_set_zwriteenable(true)
    gpu_set_ztestenable(true)
    gpu_set_alphatestenable(true)
    gpu_set_cullmode(cull_noculling);
    gpu_set_alphatestref(0);
    
    This is my oDraw controller

    Code:
    gpu_set_zwriteenable(false)
    with(oPlayer){
        draw_self()
    }
    with(oEnemy){
        draw_self()
    }
    with(oTrail){
        if(abs(owner.vx)>owner.vxTemp||abs(owner.vy)>-owner.vyJump){
            trailAlpha = Approach(trailAlpha,0.5,0.01)
        }else{
            trailAlpha = Approach(trailAlpha,0,0.01)
        }
       
        if(trailAlpha>0){
            DrawTrail(16,48,c_white,-1,true,trailAlpha)  
        }else{
            ArrayTrail = 0
        }
    }
    with(oRain){
      //I have to cut this because its a marketplace asset
    }
    gpu_set_zwriteenable(true)
    
    The problem now is that I can't see anything drawn with oDraw. But at least my platforms draw correctly.
    [​IMG]

    Removing the tile set like last time reveals that everything is being drawn under it, though misaligned, I didn't change my sprite's origin and I just copied their draw code into oDraw's draw event

    [​IMG]
     
  16. Bart

    Bart Member

    Joined:
    Jun 21, 2016
    Posts:
    190
    That's almost right :).
    But the order should really be: draw all stuff with no transparent textures, disable z-writing, draw all stuff with transparent textures, next re-enable z-writing so drawing happens correctly again on higher layers or in later draw events (Draw End, Draw GUI, ...)
    Here's how it should look in the code:
    Code:
    with(oPlayer){
       draw_self()
    }
    with(oEnemy){
       draw_self()
    }
    with(oTrail){
       if(abs(owner.vx)>owner.vxTemp||abs(owner.vy)>-owner.vyJump){
           trailAlpha = Approach(trailAlpha,0.5,0.01)
       }else{
           trailAlpha = Approach(trailAlpha,0,0.01)
       }
     
       if(trailAlpha>0){
           DrawTrail(16,48,c_white,-1,true,trailAlpha)
       }else{
           ArrayTrail = 0
       }
    }
    gpu_set_zwriteenable(false)
    // Draw everything with transparent textures between these two calls to gpu_set_zwriteenable.
    with(oRain){
      //I have to cut this because its a marketplace asset
    }
    with(some_other_transparent_stuff) {
      // Draw me
    }
    gpu_set_zwriteenable(true)
     
    FredFredrickson likes this.
  17. Bayesian

    Bayesian Member

    Joined:
    Sep 13, 2016
    Posts:
    423
    That's exactly what I did, oPlayer and oEnemy all have transparency in their sprites and oTrail is an array of semi transparent primitives. The only things that don't have transparency are the platforms which are fine and the tile set which now covers everything for some reason which is my only current problem. I figured out the misalignment was my fault and was just a depth sorting error. Here's my current room layer setup.
    Code:
    Instances 0
    Managers -100
    Tiles -200
    Background -300
     
  18. Bart

    Bart Member

    Joined:
    Jun 21, 2016
    Posts:
    190
    Indeed, your code was right. My mistake there..
    To continue on your current issue, in GM's Room Editor, +z points into the screen and -z points out of the screen. That's also the order in which the layers are drawn: from +z to -z (or higher depth to lower depth).
    So it seems like your Tiles layer is actually closer than the Instances and Managers layers.
    That would explain why it covers everything (assuming you don't have the background set).
     
  19. Bayesian

    Bayesian Member

    Joined:
    Sep 13, 2016
    Posts:
    423
    This is extremely confusing. +z gets closer to the screen as it should yet high z gets drawn first then overwritten by things that are supposed to be behind it since they are drawn after.

    What exactly am I expected to do here? Point my camera the other way and invert the z and x axis?

    Closer to the camera? I set up my camera the way I thought it was supposed to work, pointing down -z. So the tile layer is 2nd furthest from the camera to the background layer. Besides my player, enemies and platforms are all on the instances layer, yet only the platforms show
    I've had the background set this entire time and never disabled it.
     
  20. Bart

    Bart Member

    Joined:
    Jun 21, 2016
    Posts:
    190
    The manual has a nice image on this on the layer_depth page.
    As you can see there, when looking downward from the camera, depth values (or z values) become more positive. If you now apply the same logic to your own layer setup, you notice that drawing happens in the following order:
    Code:
    Camera
     v v
    Instances 0        // Drawn first/below everything
    Managers -100
    Tiles -200
    Background -300    // Drawn last/on top of everything
     ^ ^
    Screen
    I added the camera to show that you're actually looking towards -z here.

    But here's the catch. Although you have inverted the layers' depth/z values and setup the camera to correspond to that, the layers are still drawn from highest (most +) depth to lowest (most -) depth.
    Most important is that each layer's contents are drawn and then that layer is finished.
    It's as if you would draw that layer's contents to a surface and immediately draw that surface to the screen (or the 'back buffer', I guess). Then the next layer (more negative z/depth) is drawn and, once again, drawn to the screen. The order in which that happens is fixed and is from highest depth to lowest depth.
    In fact this means that depth comparisons occur between primitives on the same layer but not between primitives on different layers (because of the above).
    So it's best to indeed point the camera to +z, "into the screen", and then also change the depth (i.e. draw order) of the layers.
    Another way would be to put everything onto one (instance) layer, but then you loose the ease of use for layers like the Tiles layer.

    Admittedly, 3D in GMS does get a bit confusing when combined with layers :).
    Not sure about this, though..
     
    Last edited: Oct 27, 2018
  21. Bayesian

    Bayesian Member

    Joined:
    Sep 13, 2016
    Posts:
    423
    I swear to god YoYo...

    Thanks for all the help everyone, everything I wanted is working now!
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice