Jump to content

klepto2

Developers
  • Posts

    836
  • Joined

  • Last visited

Posts posted by klepto2

  1. While testing the new Effect feature in the Editor i encountered a small problem with my posteffect shaders.

    Some of my effects use a technique called reprojection, actually this is a very basic implementation but improves the perfromance a lot. What it does, is that it uses a 4*4 Bayer filter to determine which pixel needs to be calculated based on the fragment coordinate and the current frame. If a pixel is not meant to be calculated it reads the result from the previous frame (reprojecting the current uv to the previous uv). This means over a period of 16 frames the whole buffer is calculated.

    Unfortunatly this is not working in the editor. I believe it might be due to the fact (correct me @Josh if i am wrong), that the editor doesn't use async rendering and the camera is not rendered in realtime. so if we can get a flag which indicates if a shader is invoked from the editor, we could disable some features (reprojection in this case) and use the pfx correctly in the editor.

    I will write a very basic shader which will simulate the error and attach it later here.

  2. Download: VolumetricLighting0_9_5.zip

    This is a small but powerful posteffect with "real" VolumetricLighting for all lighttypes.

    It shows some basic powerful features of the UltraEngine pipeline:

    • Performance
    • Accesibility (you can get nearly everything in a shader at every time)

    The shader itself features Volumetric lighting based on the included shadowmap lookups and performs some calculations more or less like the screenspace godrays, but not depenfing on the backbuffer colors, but real shadow casting. It also features calculates only 1/16th of a buffer (plus out of scope pixels) per frame and reprojects the result of the previous buffer if possible.

    The shader itself is currently more or less for demonstration usage only, because there are no volumetric settings for lights available and adding these would require some kind of lua or cpp backend.

    image.thumb.png.d8bd6d28dcb82ce585fe9a2c76cf8cd7.png

    • Like 3
    • Upvote 1
  3. When you add Posteffects in the worldsettings dialog and reorder them. they are added mlutiple times to the cameras.

    At first when you reorder the effects it looks correct, but if you close the dialog and refresh the perspective viewport you can see artifacts and multiplied effects, eg the godrays will get brighter and brighter. When you reopen the settings you now see the effects multiple times (multiplied by the numbers of reorders you did previosly)

    Before reordering:

    image.thumb.png.fa5bbdb1822ba41824ca150752a22ca3.png

    And after reordering multiple times:

    image.thumb.png.aa3974eb077c1f1ce6edfa35b4eeb7cd.png

    As an addtional request hidden in here: Expand the posteffect api with Remove and sorting capabilities. Currently you can only add the posteffects and clear all, but not remove single items.

  4. Just some small things in the world-settings:

    • skybox/specular and diffuse are not loaded from previous maps
    • after assigning skybox/specular and diffuse textures and reopening the world-settings, the skybox value is empty
    • the posteffect tab is completely empty and nothing can be done in the tab except closing the window
    • when you open the world settings dialog he first tab is selected, but the content shown is the content of the last tab opened previously (open settings ⇾ select fog⇾ close ⇾ open again ⇾ selected tab is environment, but content is the fog settings)

     

  5. On 3/19/2024 at 2:35 PM, Alienhead said:

    Also, is all ambient light, fog, skybox etc done by code only? I couldn't find any settings in the editor.. just making sure.

    ty

    The scene settings is removed and is replaced with a world-settings dialog under Edit -> World Settings.

    image.png.36a716356b7679222f8eb008717d1e1f.png

    • Like 1
  6. This is a wierd one (at least it looks like a weird one) i have a simple scene with a terrain and a sphere.

    the sphere is set to a red color.

    In release: The result is always a white sphere but whith a correct looking terrain.

    In debug: sometimes the same result as in release, but sometimes the sphere gets its color (and can be changed at runtime) but then the terrain is pure black as long as the sphere is in view.

     

    #include "UltraEngine.h"
    #include "ComponentSystem.h"
    //#include "Steamworks/Steamworks.h"
    
    using namespace UltraEngine;
    
    int main(int argc, const char* argv[])
    {
    
    #ifdef STEAM_API_H
        if (not Steamworks::Initialize())
        {
            RuntimeError("Steamworks failed to initialize.");
            return 1;
        }
    #endif
    
        RegisterComponents();
    
        auto cl = ParseCommandLine(argc, argv);
    
        //Load FreeImage plugin (optional)
        auto fiplugin = LoadPlugin("Plugins/FITextureLoader");
    
        //Get the displays
        auto displays = GetDisplays();
    
        //Create a window
        auto window = CreateWindow("Ultra Engine", 0, 0, 1280 * displays[0]->scale, 720 * displays[0]->scale, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);
    
        //Create a framebuffer
        auto framebuffer = CreateFramebuffer(window);
    
        //Create a world
        auto world = CreateWorld();
    
        auto camera = CreateCamera(world);
        camera->SetClearColor(0.125);
        camera->SetFov(70);
        camera->Move(0, 2, -8);
        camera->AddComponent<CameraControls>();
    
    
        //Create light
        auto light = CreateDirectionalLight(world);
        light->SetRotation(45, 35, 0);
        light->SetColor(2);
        world->RecordStats(true);
    
    
        auto main_instance = CreateTerrain(world, 512, 512);
    
        auto sphere = CreateSphere(world, 2.0, 32);
        sphere->SetColor(1.0, 0.0, 0.0);
    
        //Main loop
        while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
        {
            if(window->KeyHit(KEY_F1))
                sphere->SetColor(1.0, 0.0, 0.0);
    
            if (window->KeyHit(KEY_F2))
                sphere->SetColor(0.0, 1.0, 0.0);
    
    
            world->Update();
            world->Render(framebuffer);
    
    #ifdef STEAM_API_H
            Steamworks::Update();
    #endif
        }
    
    #ifdef STEAM_API_H
        Steamworks::Shutdown();
    #endif
    
        return 0;
    }

    image.thumb.png.de9c870460b9fd174371dd95df42a311.png

    Above is release (everytime) /debug(not everytime)  ( color can't  be changed with F1/F2)

    image.thumb.png.8a857731ce9aa4f3bae08683e09fc2fc.png

    the same with debug build, sometimes the color works. (then the color can be changed with F1/F2)

    • Confused 1
  7. 2 hours ago, Josh said:

    I wanted to talk to you guys about this topic.

    In the Vulkan renderer we had a transfer and render hook. I don't see any need for these two hooks anymore. Do you?

    What information needs to be passed to the hook? I think everything can be retrieved with functions:

    wglGetCurrentContext();
    glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo);

    At what point in the renderer should this hook be called? I am thinking after all objects are rendered, before post-processing effects.

    Should it be set per-camera instead of per-world perhaps?

    I thought the same. Take a look here: 

    and here: 

    For the parameters i think the object which calls the hook should be included and an extra field for custom data. The most important thing for me is that it will be possible to get the internal opengl data. (not only the texture ids, but maybe also the buffers etc) .    

    As i posted in the first linked thread i would prefer hooks on the way BEFORE / AFTER and also one for the world update and then for the camera. 

    • Like 2
  8. As you mentioned physics:

    a callback into the function where the force is applied. (possibly needed for adding additional effectors like buoyancy or other forces)

    • Upvote 1
  9. There are already some hooks, but to have more flexibility and abilities to add more functionality i would suggest to add things like:

    • BEFORE_WORLD_UPDATE
    • AFTER_WORLD_UPDATE
    • BEFORE_CAMERA_RENDER (Used to update meshes based on the camera)
    • AFTER_CAMERA_RENDER (Maybe to reset some states)

    Also some more for the render pipeline:

    • RENDER_INIT (don't know if its the same in 0.9.5, but in < 0.9.5 the VKdevice etc was lazy initialized, so that you need to HOOK into the RENDER or TRANSFER Hook to get the data)
    • Some more detailed Hooks into RENDER and/or TRANSFER (to add commands before the actual commands or after)

    thats it for now. If someone has more ideas, you can add these here.

    • Upvote 2
  10. While this might not be needed for most users, and a lot can change in the Render* classes can change.
    It is needed to have access to have access to this classes from its highlevel counterparts. (eg: Texture -> RenderTexture)

    Why:

    • More flexibility
    • Easier to add extensions which require low level access like GLHandles or VK handles depending on the renderer
    • Integration of third party things will be easier.

    I noticed that there were some kind of methods to get this data. Like the commented Ultraengine::Render::GetRenderTexture function. something like this for all Render* items would be nice. 

    • Upvote 1
  11. 18 hours ago, Slastraf said:

    Hello.
    I tried the tool using the GUI and through command prompt. In the GUI it will crash and using the command prompt it will be stuck at Importing Cubemap.
    image.thumb.png.aba47f206e3f1a4beba210980f63423d.png
     

    The gui will load, but crash on importing either panorama or other import option, or canceling the import.

    I used this cubemap at 1k resolution (.hdr) https://polyhaven.com/a/symmetrical_garden_02
    Windows 11 updated graphics drivers rtx 4090

    I will rebuild and refactor it as soon as the new Ultra Engine version is out, as I think there will be some kind of refactoring needed. I think most work will go into the actual Compute-Pipeline. For my current Environment (atmosphere and ocean) WIP I already have optimized a lot which might cause issues in this build, but I need time to polish it further and make it more future prove and stable.

    • Like 2
  12. ok, this is a weird bug i have encountered while trying to optimze some texture generation.

    Sometimes a camera which is set to not render in realtime still renders in realtime.

    #include "UltraEngine.h"
    
    using namespace UltraEngine;
    
    int main(int argc, const char* argv[])
    {
        //Get the displays
        auto displays = GetDisplays();
    
        //Create a window
        auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);
    
        //Create a world
        auto world = CreateWorld();
    
        //Create a framebuffer
        auto framebuffer = CreateFramebuffer(window);
    
        //Create light
        auto light = CreateBoxLight(world);
        light->SetRange(-10, 10);
        light->SetRotation(15, 15, 0);
        light->SetColor(2);
    
        //Create camera
        auto camera = CreateCamera(world);
        camera->SetClearColor(0.125);
        camera->SetPosition(0, 0, -3);
        camera->SetFov(70);
    
        //Create scenery
        auto box = CreateBox(world);
    
        auto cone = CreateCone(world);
        cone->SetPosition(1.25, 0, 0);
        cone->SetColor(0, 0, 1);
    
        auto sphere = CreateSphere(world);
        sphere->SetPosition(-1.25, 0, 0);
        sphere->SetColor(1, 0, 0);
    
        //Create camera and texture buffer
        auto texbuffer = CreateTextureBuffer(256, 256);
        auto cam2 = CreateCamera(world);
        cam2->SetClearColor(1, 1, 1);
        cam2->SetRenderTarget(texbuffer);
        cam2->SetRealtime(false);
    
        //Create material
        auto mtl = CreateMaterial();
        auto tex = texbuffer->GetColorAttachment();
        mtl->SetTexture(tex);
        box->SetMaterial(mtl);
        cone->SetMaterial(mtl);
        sphere->SetMaterial(mtl);
    
        //Main loop
        while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
        {
            //Orient the texturebuffer camera
            //Play around with these values and restart the app, sometimes the cam2 is rendered constantly even it is not set to realtime
            cam2->SetPosition(0, 0, 0);
            cam2->Turn(0, 1, 0);
            cam2->Move(0, 0, -2);
            cam2->SetRange(0.1, 1000.0);
    
            //Press the space key to redraw the texture buffer camera
           // if (window->KeyHit(KEY_SPACE)) cam2->Render();
    
            world->Update();
            world->Render(framebuffer);
        }
        return 0;
    }

    Run this snippet in release mode, mutliple times. You may need to change the cam2 values (position, turn, move or range) in order too get the bug. in most cases you get the desired one time render, but (it seems randomly) you get realtime rendering sometimes as well. In my bigger project my non realtime cameras are updated all the time and i am not calling the render function at all.

  13. it might be that you need to invert the light_direction. 

    1 hour ago, SpiderPig said:

    I just noticed your texture creation method;

    _dataTexture = CreateTexture(TEXTURE_2D, 64, 32, TEXTURE_RGBA32, {}, 1, TEXTURE_DEFAULT, TEXTUREFILTER_NEAREST);

    I leave my type as TEXTURE_RGBA and convert to floats like this -

    float BytesToFloat( in vec4 pixel ) {
    	return intBitsToFloat( ( int( ( pixel.w * 255.0f ) ) << 24 ) | ( int( ( pixel.z * 255.0f ) ) << 16 ) | ( int( ( pixel.y * 255.0f ) ) << 8 ) | int( ( pixel.x * 255.0f ) ) );
    }

    Would that function still work with the type TEXTURE_RGBA32 you think? I also use TexelFetch instead of sample.

    The reason i use RGBA32 o RGBA16 is that you don't need to make any bitshifting etc. if you store a float in a RGBA32 texture the value will be the same as how you uploaded it. RGBA16 will just loose some precision, while RGBA will clamp the float to 0.0-1.0.  

    As long as you store values between 0.0 and 1.0 the bytes to float should work the same. But is not needed with a RGBA32/16 texture.

    I use also texelFetch, otherwise sampling might corrupt the actual value.

    I simply access the data in the shader like this:

    	vec4 data = texelFetch(texture2DSampler[configId],ivec2(0,i+1),0);
    			cascades[i].spectrumHandle = int(data.x);
    			cascades[i].normalHandle = int(data.y);
    			cascades[i].size = data.z;

     

    • Thanks 1
  14. I haven't seen this problem in my applications, of course the update might be a bit off, but i don't see flickering. But maybe its because i use WritePixel with a Float32 pixmap directly instead of a using a buffer.

    I have something like this:

    class MaterialExtensionInfo : public Object
    {
    private:
    	shared_ptr<Pixmap> _data;
    	shared_ptr<Texture> _dataTexture;
    	int current_ptr = 0;
    	
    public:
    	MaterialExtensionInfo();
    	void Sync();
    
    	shared_ptr<Texture> GetDataTexture();
    	void Add(int x, int y, Vec2 value);
    	void Add(int x, int y, Vec3 value);
    	void Add(int x, int y, Vec4 value);
    	void Add(int x, int y, Mat3 value);
    	void Add(int x, int y, Mat4 value);
    };
    
    MaterialExtensionInfo::MaterialExtensionInfo()
    {
        _dataTexture = CreateTexture(TEXTURE_2D, 64, 32, TEXTURE_RGBA32, {}, 1, TEXTURE_DEFAULT, TEXTUREFILTER_NEAREST);
        _data = CreatePixmap(64, 32, TEXTURE_RGBA32);
    }
    
    void MaterialExtensionInfo::Sync()
    {
        _dataTexture->SetPixels(_data);
    }
    
    shared_ptr<Texture> MaterialExtensionInfo::GetDataTexture()
    {
        return _dataTexture;
    }
    
    void MaterialExtensionInfo::Add(int x, int y, Vec2 value)
    {
        _data->WritePixel(x, y, Vec4(value.x, value.y, 0.0, 0.0));
    }
    
    void MaterialExtensionInfo::Add(int x, int y, Vec3 value)
    {
        _data->WritePixel(x, y, Vec4(value.x, value.y, value.z, 0.0));
    }
    
    void MaterialExtensionInfo::Add(int x, int y, Vec4 value)
    {
        _data->WritePixel(x, y, value);
    }
    
    void MaterialExtensionInfo::Add(int x, int y, Mat3 value)
    {
        _data->WritePixel(x, y, Vec4(value.i.x, value.i.y, value.i.z,0.0));
        _data->WritePixel(x + 1, y, Vec4(value.j.x, value.j.y, value.j.z, 0.0));
        _data->WritePixel(x + 2, y, Vec4(value.k.x, value.k.y, value.k.z, 0.0));
    }
    
    void MaterialExtensionInfo::Add(int x, int y, Mat4 value)
    {
        _data->WritePixel(x, y, value.i);
        _data->WritePixel(x + 1, y, value.j);
        _data->WritePixel(x + 2, y, value.k);
        _data->WritePixel(x + 3, y, value.t);
    }

    In your case, the sun direction is already available in the shader, you don't need to pass it down like that, In ultraEngine you can always access nearly anything at anytime in the shader. This itroduces a lot of possbilities: eg calculating combined atmospheric effects for multiple suns.

    to iterate over all Directional Lights you can do something like this in your shader:

    #include "../../Base/Lighting.glsl"
    
    ...
    
    in main() 
    
    ...
    uint n;
        uint lightIndex;
    
       	// Global lights (affects all cells)
        uint lightlistpos = GetGlobalLightsReadPosition();
    	uint countlights = ReadLightGridValue(lightlistpos);
        for (n = 0; n < countlights; ++n)
        {
            ++lightlistpos;
            lightIndex = ReadLightGridValue(lightlistpos);
            
            int ShadowSoftness = 2;
            const float minlight = 0.004f;
            vec3 lightDir, lightPosition;
            vec4 shadowCoord, color;
            bool transparent = false;
            mat4 lightmatrix;
            uint flags, lightflags;
            int shadowMapID, lighttype, shadowcachemapID;
            float attenuation = 1.0f;
            dFloat d;
        #ifdef DOUBLE_FLOAT
            dvec2 lightrange, coneangles, shadowrange;
        #else
            vec2 lightrange, coneangles, shadowrange;
        #endif
            int shadowkernel;
            
            ExtractEntityInfo(lightIndex, lightmatrix, color, flags);	
            ExtractLightInfo(lightIndex, shadowMapID, shadowcachemapID, lightrange, coneangles, shadowrange, lightflags, shadowkernel);
            
            const int falloffmode = ((lightflags & ENTITYFLAGS_LIGHT_LINEARFALLOFF) != 0) ? LIGHTFALLOFF_LINEAR : LIGHTFALLOFF_INVERSESQUARE;
            if ((lightflags & ENTITYFLAGS_LIGHT_STRIP) != 0) lighttype = LIGHT_STRIP; // This needs to come first because the flag is a combination of others
            else if ((lightflags & ENTITYFLAGS_LIGHT_BOX) != 0) lighttype = LIGHT_BOX;
            else if ((lightflags & ENTITYFLAGS_LIGHT_DIRECTIONAL) != 0) lighttype = LIGHT_DIRECTIONAL;
            else if ((lightflags & ENTITYFLAGS_LIGHT_SPOT) != 0) lighttype = LIGHT_SPOT;
            else lighttype = LIGHT_POINT;
            
            if(lighttype == LIGHT_DIRECTIONAL)
            {
            #ifdef DOUBLE_FLOAT
                    lightDir = vec3(normalize(lightmatrix[2].xyz));
            #else
                    lightDir = normalize(lightmatrix[2].xyz);
            #endif
              // Do calculations, break out if needed
              }
        }

     

    • Thanks 1
  15. Just to show a more extreme sample which i came up with (might be interesting for you as well @SpiderPig

    It is a combination of multiple factors and shows multiple problems at once.

    1. Instantiating still has a memleak, not that high than then previously but still visible in this scenario
    2. Debug leads to rendertimes > 4000 ms while release is much lower but still too high in my opinion (even if you comment out the extra rendertargets and cameras)
    3. Having too many instances at the same position leads to an exception in the physicsthread
    4. Having too many instances leads to vulkan buffer size and index validation errors.
    #include "UltraEngine.h"
    #include "ComponentSystem.h"
    //#include "Steamworks/Steamworks.h"
    
    using namespace UltraEngine;
    
    SIZE_T PrintMemoryInfo()
    {
        auto myHandle = GetCurrentProcess();
        //to fill in the process' memory usage details
        PROCESS_MEMORY_COUNTERS pmc;
        //return the usage (bytes), if I may
        if (GetProcessMemoryInfo(myHandle, &pmc, sizeof(pmc)))
            return(pmc.WorkingSetSize);
        else
            return 0;
    }
    
    
    int main(int argc, const char* argv[])
    {
        
    #ifdef STEAM_API_H
        if (not Steamworks::Initialize())
        {
            RuntimeError("Steamworks failed to initialize.");
            return 1;
        }
    #endif
    
        RegisterComponents();
    
        auto cl = ParseCommandLine(argc, argv);
        
        //Load FreeImage plugin (optional)
        auto fiplugin = LoadPlugin("Plugins/FITextureLoader");
    
        //Get the displays
        auto displays = GetDisplays();
    
        //Create a window
        auto window = CreateWindow("Ultra Engine", 0, 0, 1280 * displays[0]->scale, 720 * displays[0]->scale, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);
    
        if (!AttachConsole(ATTACH_PARENT_PROCESS))
        {
            if (AllocConsole())
            {
                freopen("conin$", "r", stdin);
                freopen("conout$", "w", stdout);
                freopen("conout$", "w", stderr);
            }
        }
        else
        {
            auto consoleHandleOut = GetStdHandle(STD_OUTPUT_HANDLE);
            auto consoleHandleIn = GetStdHandle(STD_INPUT_HANDLE);
            auto consoleHandleErr = GetStdHandle(STD_ERROR_HANDLE);
            if (consoleHandleOut != INVALID_HANDLE_VALUE) {
                freopen("conout$", "w", stdout);
                setvbuf(stdout, NULL, _IONBF, 0);
            }
            if (consoleHandleIn != INVALID_HANDLE_VALUE) {
                freopen("conin$", "r", stdin);
                setvbuf(stdin, NULL, _IONBF, 0);
            }
            if (consoleHandleErr != INVALID_HANDLE_VALUE) {
                freopen("conout$", "w", stderr);
                setvbuf(stderr, NULL, _IONBF, 0);
            }
        }
    
        //Create a framebuffer
        auto framebuffer = CreateFramebuffer(window);
    
        //Create a world
        auto world = CreateWorld();
    
        auto camera = CreateCamera(world);
        camera->SetClearColor(0.125);
        camera->SetFov(70);
        camera->Move(0, 2, -8);
        camera->AddComponent<CameraControls>();
    
    
        //Create light
        auto light = CreateDirectionalLight(world);
        light->SetRotation(45, 35, 0);
        light->SetColor(2);
    
        auto render_target = CreateTextureBuffer(framebuffer->size.x, framebuffer->size.y);
        auto render_target_2 = CreateTextureBuffer(framebuffer->size.x, framebuffer->size.y);
    
        auto test_camera = CreateCamera(world);
        test_camera->SetRenderTarget(render_target);
        auto test_camera_2 = CreateCamera(world);
        test_camera_2->SetRenderTarget(render_target_2);
     
        camera->SetSweptCulling(true);
    
        world->RecordStats(true);
    
        int waterLevel = 20;
    
        shared_ptr<Entity> main_instance = CreateTerrain(world, 1024, 1024);
    
        auto sphere = CreateSphere(nullptr, 2.0, 32);
    
        vector<shared_ptr<Entity>> test_instances;
    
        bool set_position = true; //Set to false and it leads to a exception in the Physicsthread
        int step_size = 32; //Lower that and it will lead to invalid buffersize indices / size in vulkan
    
        //Main loop
        while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
        {
            
    
            test_camera->SetMatrix(camera->GetMatrix());
            test_camera->SetRange(camera->GetRange());
            test_camera_2->SetRotation(camera->GetRotation() * Vec3(-1.0, 1.0, -1.0));
            test_camera_2->SetPosition(camera->position.x, -camera->position.y + 2 * (waterLevel + 5.0), camera->position.z);
            test_camera_2->SetRange(camera->GetRange());
    
            test_instances.clear();
    
            for (int x = -512; x <= 512; x += step_size)
                for (int z = -512; z <= 512; z += step_size)
                {
                    auto i = sphere->Instantiate(world);
    
                    if(set_position)
                        i->SetPosition(x, 1.0, z);
    
                    i->SetColor(Vec4(1.0, 0.0, 0.0, 1.0));
                    test_instances.push_back(i);
                }
    
    
            world->Update();
            world->Render(framebuffer);
    
    #ifdef STEAM_API_H
            Steamworks::Update();
    #endif
            window->SetText("rt: " +String(world->renderstats.rendertime) + " MEM: " + String(PrintMemoryInfo() / 1024) + " kb");
        }
    
    #ifdef STEAM_API_H
        Steamworks::Shutdown();
    #endif
    
        return 0;
    }

    this is the interesting part for the multiple errors:

     bool set_position = true; //Set to false and it leads to a exception in the Physicsthread
     int step_size = 32; //Lower that and it will lead to invalid buffersize indices / size in vulkan

    I hope you can resolve this as it breaks the in majority very fast  renderer.

    • Like 1
    • Upvote 1
  16. As the title said. In the header source, there is already a outcommented 

    void SetClipPlane(const int index, const Plane& p);

    function. 

    While this might not be needed for many people, it is a nice and simple feature. I would need it for a deifferent approach for the water renderer to support realtime reflections without ssr (while ssr is nice, it has some downsides and needs a lot of tweking to look right in larger environments.) and proper refraction without the need to modify the integrated refraction shader.

    • Upvote 1
  17. With the provided code I simulate the behaviour of a much more complex problem to show the problem in an extreme way. 

    In the production ready code i get a slower mem increase, but it slows down the program and leads to a out of memory exception.

    Things to notice in the program: 

    • The memusage increases fast
    • The displayed instance count is much higher than it should
      • I let the program instantiate 100 planes, so the actual count should be 101 (with the orignal plane)
      • In the loop the instances are cleared and reinstantiated.
    #include "UltraEngine.h"
    #include "ComponentSystem.h"
    //#include "Steamworks/Steamworks.h"
    
    using namespace UltraEngine;
    
    SIZE_T PrintMemoryInfo()
    {
        auto myHandle = GetCurrentProcess();
        //to fill in the process' memory usage details
        PROCESS_MEMORY_COUNTERS pmc;
        //return the usage (bytes), if I may
        if (GetProcessMemoryInfo(myHandle, &pmc, sizeof(pmc)))
            return(pmc.WorkingSetSize);
        else
            return 0;
    }
    
    
    int main(int argc, const char* argv[])
    {
        
    #ifdef STEAM_API_H
        if (not Steamworks::Initialize())
        {
            RuntimeError("Steamworks failed to initialize.");
            return 1;
        }
    #endif
    
        RegisterComponents();
    
        auto cl = ParseCommandLine(argc, argv);
        
        //Load FreeImage plugin (optional)
        auto fiplugin = LoadPlugin("Plugins/FITextureLoader");
    
        //Get the displays
        auto displays = GetDisplays();
    
        //Create a window
        auto window = CreateWindow("Ultra Engine", 0, 0, 1280 * displays[0]->scale, 720 * displays[0]->scale, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);
    
        if (!AttachConsole(ATTACH_PARENT_PROCESS))
        {
            if (AllocConsole())
            {
                freopen("conin$", "r", stdin);
                freopen("conout$", "w", stdout);
                freopen("conout$", "w", stderr);
            }
        }
        else
        {
            auto consoleHandleOut = GetStdHandle(STD_OUTPUT_HANDLE);
            auto consoleHandleIn = GetStdHandle(STD_INPUT_HANDLE);
            auto consoleHandleErr = GetStdHandle(STD_ERROR_HANDLE);
            if (consoleHandleOut != INVALID_HANDLE_VALUE) {
                freopen("conout$", "w", stdout);
                setvbuf(stdout, NULL, _IONBF, 0);
            }
            if (consoleHandleIn != INVALID_HANDLE_VALUE) {
                freopen("conin$", "r", stdin);
                setvbuf(stdin, NULL, _IONBF, 0);
            }
            if (consoleHandleErr != INVALID_HANDLE_VALUE) {
                freopen("conout$", "w", stderr);
                setvbuf(stderr, NULL, _IONBF, 0);
            }
        }
    
        //Create a framebuffer
        auto framebuffer = CreateFramebuffer(window);
    
        //Create a world
        auto world = CreateWorld();
    
        auto camera = CreateCamera(world);
        camera->SetClearColor(0.125);
        camera->SetFov(70);
        camera->Move(0, 2, -8);
    
        //Create light
        auto light = CreateDirectionalLight(world);
        light->SetRotation(45, 35, 0);
        light->SetColor(2);
    
     
        world->RecordStats(true);
    
        shared_ptr<Entity> main_instance = CreatePlane(world, 10.0,10.0, 256,256);
        vector<shared_ptr<Entity>> instances;
    
    
        //Main loop
        while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
        {
            instances.clear();
    
            for (int i = 0; i < 100; i++)
            {
                instances.push_back(main_instance->Instantiate(world));
            }
    
            world->Update();
            world->Render(framebuffer);
    
    #ifdef STEAM_API_H
            Steamworks::Update();
    #endif
            window->SetText("Instances: " +String(world->renderstats.instances) + " MEM: " + String(PrintMemoryInfo() / 1024) + " kb");
        }
    
    #ifdef STEAM_API_H
        Steamworks::Shutdown();
    #endif
    
        return 0;
    }

     

×
×
  • Create New...