Jump to content
The Dark Mod Forums

SteveL

Member
  • Posts

    3666
  • Joined

  • Last visited

  • Days Won

    62

Posts posted by SteveL

  1. Also, it looks like any stage in the material declaration that isn't image shortcut adds the equivalent of total triangles for the model to the count. "TDM Ambient Method Related" is an exception. Every other operation that needs to be between { } is basically a multiplier to the triangle count of your model.

     

    That's right. 2 stages are the same as 2 materials. In theory it's slightly faster to draw a model twice in a row than to draw 2 models. But I doubt anyone will ever notice. I tried to "break" the renderer by multiplying these things up enormously in test maps without ever making much difference. General scene complexity and shadow complexity is much more important than optimising any one feature like tri counts or draw calls on a model. My best advice is to be aware of what makes for good performance and work with it but not worry about it otherwise. Everything else that happens in a real map will completely drown out the effect of trimming a few thousand tris here and there.

    • Like 4
  2. Suggested test for your 500 tri model if you still have questions for it:

    • Put it in a simple caulk box room so there is nothing to be drawn but the model. No visportals or walls obstructing the view.
    • Add an ambient_world light covering the map (if you try to use no ambient_world, the game will go ahead and generate one for you so you might as well place it yourself so you know for sure where and what it is).
    • Add a simple light covering everything and a trigger to turn it on and off every second. (EDIT: or not, see below)
    • launch the map, kick off r_showprimitives 1 and con_noprint 0 then close the console
    • You should now have a constant amount of console text on screen. The difference in tris as the light turns on and off should be the tris of your model.

    I'm not sure off hand whether model tris facing away from the light will be counted. There are so many optimisations in the engine that there's often a long explanation for the exact tri count. The engine has various ways to exclude parts of your model from being drawn, some of them in the engine itself (which means the tris won't be counted by r_showprimitives) and some in the GPU (which means the tris still get counted as "drawn", but they won't use up much GPU power as they don't get coloured in).

     

    EDIT: You probably don't need a trigger come to think of it. Simply facing away from the model will be enough to stop it being drawn as long as you are a little distance away (so not in its bounding box).

    • Like 2
  3. There's a certain base tri count that you will never get rid of. The HUD generates tris to be drawn. The biggest culprit is the console: every character shown on the console is 2 tris, and they do show up in the tri count. A console full of text is worth about 1500 tris if I remember right. Also the lightgem, and a few other things generate a handful of tris.

     

    I always found that irritating in my renderer test maps. I used empty maps, no skybox, everything made of caulk except the one thing I wanted to test but the console tri counts varied by more than the thing I was trying to count!

    • Like 2
  4. Is it md3_water_test_refraction you're using?

     

    There are a couple of variants in that material file but I think that's the one.... But I can't see (yet) what is causing the brighter posts and hull below the waterline. The only light being added in that material is from the specular highlights on the water. Are you using any other effects in the screenshot above? Like fog lights, or another material on a patch beneath the surface?

    • Like 1
  5. I always thought fog is resource consuming in games, but here it's kind of the other way around.

     

    Any light hitting a surface will cause its tris to be drawn again. Lights with multiple stages count as multiple lights, but we don't have many of those (if any).

     

    Fog is only considered "expensive" because of the relatively small effect that it gives for the cost. It's cheaper than other light types because it uses a very cheap shader: it just adds some static colour to the tris that it hits, so it draws the tris again but it doesn't use the surface's diffuse, bump, or specular maps to do any complex shading which is what normal lights and ambient_world do.

    • Like 3
  6. Is it possible to combine one with the other (ie. have the water darken with depth but with the animated mesh and normalmap on top which looks much better than the seawater01 texture)?

     

    Can you link the water shader you are using? Or is it packaged with the mod now? I remember both Arcturus and Obsttorte did clever things with bumpmapped transparent shaders but I'm a bit behind on latest developments :) I'll have a look how it works and see whether we can get the best of both worlds.

    • Like 3
  7. And for the text to be displayed, it also took some time to get, where to put quotation marks and where not, but it works right now and that is all that matters :-) Thanks again for the help.

    Cool. Feel free to post a line of code if you want any help. You can't use quotation marks in the text to be displayed, but it'd look something like this:

     

    $messageEnt.setKey("spawnargName", "You have " + myFloatVariable + " widgets");

    • Like 1
  8. Would be most effective if the script could assign an alpha to a material at runtime, but as far as I'm aware scripts can't influence materials. No matter what, I'm more than pleased with the options that are already available.

    Scripts can use setShaderParm() to do this, and the material can set alpha using parm3 (or whichever). It'd also need the translucent keyword, and I don't think it would cast shadows unless your model has a shadow mesh.

     

    Edit: I don't think this will work, on second thoughts. Translucent materials are drawn as an additive blend and they ignore the alpha channel. You could do it as a custom blend material, but it wouldn't be lit it'd be fullbright.

  9. void sewerhatch1_state(entity mover_lever, boolean bOpen, boolean bLocked, boolean bInterrupted)

    Ah, that's a "state_change_callback" script.

     

    @kingsal You could use one of those more simply than a script object to get the job done with the chest. state_change_callback is a way to call a script when a door is moved or a button is pressed. Unlike most ways to call a script, the script gets told which entity fired it.

     

    Chest lids are doors, so you could put your spawnargs on the lid along with "state_change_callback" "autoloot_chest"

     

    Then in your map script:

    void autoloot_chest(entity chest, boolean bOpen, boolean bLocked, boolean bInterrupted)
    {
        // Fire only if map has been open 3 seconds (avoiding map initialisation) and 
        // only the first time the door/lid is fully opened.
        if ( sys.getTime() > 3 && bOpen && !chest.getBoolKey("already_opened") )
        {
            chest.setKey("already_opened", "1");
            // Search through "random_spawn" spawnargs, and find a matching "random_chance" spawnarg
            string key = chest.getNextKey("random_spawn", "");
            while ( key != "" )
            { 
                float chance = chest.getFloatKey(sys.strReplace(key, "_spawn", "_chance"));
                float r = sys.random(1.0);
                if ( chance > r )
                {
                    entity newItem1 = sys.spawn(chest.getKey(key));
                    newItem1.addItemToInv($player1);
                    sys.wait(1.0);
                }
                key = chest.getNextKey("random_spawn", key);
            }
        }
    }
    
    The script disables a chest by adding a spawnarg to it in real time. You can use any random_spawnXYZ spawnarg naming scheme as long as there's a matching random_chanceXYZ sparnarg for each. Without the matching spawnarg, the chance will come out at 0 so the item won't ever be added.

     

    I tested it with these s/args on a chest lid:

    "random_spawn1" "atdm:ammo_firearrow"

    "random_spawn2" "atdm:ammo_mossarrow"

    "random_spawnA" "atdm:ammo_broadhead"

    "random_chanceA" "0.5"

    "random_chance1" "0.8"

    "random_chance2" "0.5"

    "state_change_callback" "autoloot_chest"

     

    You can make a new entity def with your preferred settings. Then changing the def will change all matching chest lids that haven't overridden the spawnargs.

     

    If you want to stick to your original plan of a separate script for each chest then Spooks' global variable is the quick way as you found, but that method only works with a separate script for each chest, because a script shared between chests wouldn't know which chest had triggered it (and so couldn't disable the right chest).

    • Like 1
  10. Have you re-dmapped since updating the materials?

     

    The keyword to make a material seal against the void is forceOpaque. It goes up top with surftype and description. You don't always need it, but the keyword will make even pure transparent blend materials seal.

     

    I've seen that borking mostly when messing with cubemaps, but I can't remember how I fixed it. It was something silly like re-dmapping.

  11. There is one small advantage to each chest having its own script, you can make edits to its contents without digging around for it in the editor. If for instance, you wanted to quickly balance the items across the entire map.

     

    You could probably use the menu function that selects all entities that have the same model as the one you have selected. That'd let you skip between chests in the map easily.

     

    The script object version would also let you balance the loot distribution by setting a probability against each item so you could have the same spawnargs on every chest and still keep the loot balanced.

     

    e.g.

    "random_spawn1" "atdm:weapon_shortsword"

    "random_chance1" "20"

     

    I don't mind providing the starter script object if you want to try it out. The documentation is a bit brief, both ours and ID's.

    • Like 1
  12. I am finalising a collection of twenty new decal textures, and there is a problem with the transparency:

    I saved the decals as DDS images, and used the standard TDM decals as the template for the material file. In GIMP, they show up with a proper transparent background, but in the game, they have a black outline. How do I fix this?

     

    In theory I don't think it should make any difference whether you use dds or tga. Which material did you use as a template? The clue might lie in there. Quite a few TDM decals depend on blending tricks that don't use the alpha channel from the image file at all.

     

    Unfortunately I don't think it's possible to have proper alpha transparency on solid materials that are affected by lights, and you'd need these signs to be opaque and lit. Our lit transparent materials are all translucent, like cobwebs, water ripples and glass that add an extra layer of brightness to the background without blocking it out. Can you stretch the image to fill the quad instead? if you need a frayed edge you can use an alphatest material instead. The edge won't be as smooth-looking as an alpha-blended image, but it's a way to get a wobbly edge from a flat quad.

  13. Concave means its's got a cavity. If you were to stretch a rubber sheet around your brush to find the smallest shape that can fully enclose your brush, would there be any empty space in there? If so it's concave. A round cake for example is convex. If you cut a slice out of it then it's concave.

     

    Your suggestion sounds reasonable. I don't know why CSG subtract has a problem dividing concave shapes into convex ones TBH. Maybe it's a Hard Problem for reasons I haven't got my head around, or maybe it could be improved.

  14. Grand thanks Steve, already had the "atdm::target_callscriptfunction" in place so testing now....

     

    [update]

     

    Got an error on map load, it complains about line " trap_trigger.Disable();" saying unknown value "Disable". So I changed first letter on Disable and Enable to lower case on a wild guess and that fixed it.

     

    Oops, my bad. Those functions are upper case in the c++ code, but lower case for game scripts. Not by accident, it's meant to stop them getting confused. Except that I did get confused and I remembered it the wrong way round. Cool you got it sorted :)

  15.  

    how do you make those algorithms not shit?
    Exactly... Don't we already have that functionality in DR, in the form of CSG Subtract? And it comes with a hazard warning NEVER USE THIS!!!!!!!! Because it creates millions of brush splinters in its attempt to surround your negative brush with a set of convex brushes.
    I don't know how CSG Subtract works, but the actual algorithms that do dmapping are a bit mind-bending. Brushes do not in fact store any vertex information in the map file. Each brush is defined by a set of planes, each plane being defined by an angle (the plane normal) and its distance from the world (or entity) origin. dmap reconstructs where the brush vertices would have been by where those planes intersect.
    That's why there can be no such thing as a concave brush -- it's logically impossible to define a concave brush using only planes. The planes that define the cut-away part will have more intersections outside of the concave volume, or in other words, the planes you need to make a concave brush will be ambiguous, always open to interpretation as a bigger convex brush.
    It's done that way because dmapping uses bsp trees to calculate collision models and visible models and portal regions, and bsp trees are just a list of planes. By using that format, DR makes sure that it doesn't ask dmap to do the impossible.
    The mind bending stuff doesn't end there though. The other weird aspect of all this is that there is no concept of inside and outside for a brush defined as a bunch of planes. The planes don't have any info about which side is the front or the back. Even though it is obvious in DR whether a given point is inside or outside the brush, dmap does without that information. It sets up all brush walls in its model and identifies the 3d spaces (gaps) between them. Then it uses the entities in the map to trace out (flood) the gaps. Any brush walls hit by flooding algorithm are considered part of the map. Any brush walls (or parts of brush walls) not reachable by flooding out from an entity are considered to be in the void and are stripped away before the visible and collision models are generated. That's the stage where the map looks like a subtractive map during dmapping. And that's why dmap fails unless you have at least one entity in the map -- it has no way to label the gaps between brush walls as "inside the map" vs "void".
    For anyone thirsting for even more detail :), Fabien Sanglard has a good illustrated summary here: http://fabiensanglard.net/doom3/dmap.php
    • Like 1
  16. I was thinking that you could use an atdm::target_postscriptevent to call the Enable() and Disable() methods on the trigger. You could, but you'd have to use a complicated setup involving atdm::target_changetargets to toggle between the enabler and the disabler.

    Easier just to go for a script like ERH+ suggested

     

    (untested) For your map script file:

    float pressure_plate_active = 1;
    void toggle_pressure_plate_trap()
    {
        entity trap_trigger = $trigger_multiple_1;   // PUT THE NAME OF YOUR TRIGGER HERE BETWEEN THE $ AND ;
        if ( pressure_plate_active == 1 )
        {
            trap_trigger.disable();
            pressure_plate_active = 0;
        } else {
            trap_trigger.enable();
            pressure_plate_active = 1;
        }
    }
    

    Then create an atdm::target_callscriptfunction and giuve it spawnarg "call" "toggle_pressure_plate_trap", and target it from your switch.

     

    Edit: Fixed per Biker's post below

  17. @Steve, the issue is I want to disable/enable the trap from the switch. I assume the func_remove would permanently remove it from the map? or will the func_remove replace the removed item when targted from a switch..?

    Ah, ok. The func_remove would remove it permanently.

     

    Gimme a few mins before you try a script. I am sure this can be done without...

×
×
  • Create New...