Jump to content

Ultra Engine testing


Josh
 Share

Recommended Posts

New update:

Despite their limitations, depth shadow maps with PCF filter and hardware depth bias seem to produce the best overall results, so I have switched over to this, using a 3x3 sampling pattern. Directional lights are where the PCF filter tends to look much better. I was having a lot of issues with ESM and directional lights, mostly because the texels are so big compared to a spot or point light's texel density.

I found that ESM was really great for eliminating shadow acne but was bad at softening the shadow perpendicular to the light direction. I wish the hardware sampler could take an optional distance to interpolate the resulting sample over, so samples were softened in the W direction as well as just the U/V axis.

I also attempted to store perspective-projected (point and spot light) shadow maps in a linear depth but could only get it to work using a write to gl_FragDepth, which is not optimal, and the results weren't clearly better.

Basically what it boils down to is the post-compare linear hardware texture filter is so efficient that nothing else can compare to it, so we are locked into using that. It would be possible to reproduce that functionality in shader code, but prohibitively expensive.

  • Like 1
  • Thanks 1
  • Upvote 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Another update:

  • Stabilized directional shadow maps so the texels appear locked in place
  • Added Light::SetShadowSamples() method, can be 1, 2, 3 (default), or 4. Use this for softer or harder shadows.
  • Directional shadow map size is 2048 by default
  • Directional light color is 0.5 by default
  • World::SetIBLIntensity now works, default value is 0.5
  • Like 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

I am currently trying to get a bit more used with the UI-3D interactions and wrote a small but simple gltf-viewer based on the khronos viewer, it extracts the sample models from the khronos github and you can switch between the models and view them. Due the fact, that the models are in deifferent scales from very tiny ( < 0.01 units) to very big ( > 1000.0 units)  I try to scale them to a unified width, which works most of the time. 

But from time to time with different models i get unexpected results:

Sponza: (way too big)
-----------------------------------------
Original-AABB:29.7668, 12.447, 18.3059
ScaleFactor  :0.167972
New-AABB     :625, 261.344, 384.359

Engine: (correct)
-----------------------------------------
Original-AABB:1379.28, 954.6, 1093.35
ScaleFactor  :0.00362508
New-AABB     :5, 3.4605, 3.96346

This is a very basic sample to show it:

#include "UltraEngine.h"
#include "ComponentSystem.h"

using namespace UltraEngine;

int main(int argc, const char* argv[])
{
    auto plg = LoadPlugin("Plugins/KTX2TextureLoader");
    auto plg2 = 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 world
    auto world = CreateWorld();

    //Create a framebuffer
    auto framebuffer = CreateFramebuffer(window);

    //Create a camera
    auto camera = CreateCamera(world);
    camera->SetClearColor(0.125);
    camera->SetFOV(70);
    camera->SetPosition(0, 0, -3);
    
    //Create a light
    auto light = CreateDirectionalLight(world);
    light->SetRotation(35, 45, 0);


    float desiredWidth = 5.0;
    auto sponza = LoadModel(world, "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/Sponza/glTF/Sponza.gltf");
    auto originalAABB = sponza->GetBounds(BOUNDS_RECURSIVE);
    auto scaleFactor = desiredWidth / originalAABB.size.width;
    sponza->SetScale(scaleFactor);
    auto newAABB = sponza->GetBounds(BOUNDS_RECURSIVE);

    Print("Sponza:");
    Print("-----------------------------------------");
    Print("Original-AABB:" + WString(originalAABB.size));
    Print("ScaleFactor  :" + WString(scaleFactor));
    Print("New-AABB     :" + WString(newAABB.size));


    auto engine = LoadModel(world, "https://raw.githubusercontent.com/KhronosGroup/glTF-Sample-Models/master/2.0/2CylinderEngine/glTF/2CylinderEngine.gltf");
    auto originalAABB1 = engine->GetBounds(BOUNDS_RECURSIVE);
    auto scaleFactor1 = desiredWidth / originalAABB1.size.width;
    engine->SetScale(scaleFactor1);
    auto newAABB1 = engine->GetBounds(BOUNDS_RECURSIVE);

    Print("Engine:");
    Print("-----------------------------------------");
    Print("Original-AABB:" + WString(originalAABB1.size));
    Print("ScaleFactor  :" + WString(scaleFactor1));
    Print("New-AABB     :" + WString(newAABB1.size));


    //Main loop
    while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
    {
        world->Update();
        world->Render(framebuffer);
    }
    return 0;
}

 

  • Like 1
  • Windows 10 Pro 64-Bit-Version
  • NVIDIA Geforce 1080 TI
Link to comment
Share on other sites

Update

  • Fixed some errors in lighting equations
  • Terrain lighting now works

Terrain should be totally working now:
https://www.ultraengine.com/learn/Terrain_SetElevation?lang=cpp
https://www.ultraengine.com/learn/Terrain_SetMaterial?lang=cpp

If you add SSAO before SSR you'll get dark edges in the reflections:

Untitled.thumb.jpg.5971b21ad4e485c57c3616be879b5fc8.jpg

  • Like 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

5 hours ago, klepto2 said:

But from time to time with different models i get unexpected results:

auto scaleFactor = sponza->GetScale() * desiredWidth / originalAABB.size.width;

 

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Update:

What does the fox say???

  • Like 2

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

4 hours ago, Josh said:

auto scaleFactor = sponza->GetScale() * desiredWidth / originalAABB.size.width;

Oh my! Stupid mistake by myself. Of course the initial scale has to be taken into account as well.

looking forward testing the new updates :) 

i am currently cleaning up my code and hope to publish a first release of the compute library next week. I just need to add structure buffers and make the texture assignment more dynamic. But the whole thing works really nice. I am thinking about a simple sample. Which takes just a cubemap and calculates the ibl and diffuse textures on the fly. So no need using extra tools.

  • Windows 10 Pro 64-Bit-Version
  • NVIDIA Geforce 1080 TI
Link to comment
Share on other sites

I've tried out every major system that typically breaks down, and everything seems to work. I am going to focus now on making the loading routines as compatible as possible with Leadwerks special file formats so we can load maps from the editor.

Untitled.thumb.jpg.caf6752d047fb2d95acb99fcd3eb6c25.jpg

  • Like 4

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Testing the AI And Events example map, with all scripts and effects disabled, 1536 x 864 resolution, GeForce 1660:

FPS

Leadwerks: 278
Ultra: 461 570 583

GPU Utilization

Leadwerks: 60%
Ultra: 95%

  • Like 4

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

Maybe i am thinking wrong, but if a ENVIRONMAP_DIFFUSE is used, this should be used as a lookup for the ambientlight. 

In earlier versions this was clearly visible, but now it seems, that only the ambientlight setting is affecting the scene:

In this screenshot i have used the diffuse texture as a background to visualize it a bit better:

image.thumb.png.c1415fc803128425cdf97bc1846b88a9.png

 

  • Windows 10 Pro 64-Bit-Version
  • NVIDIA Geforce 1080 TI
Link to comment
Share on other sites

On 10/24/2022 at 10:20 AM, klepto2 said:

Maybe i am thinking wrong, but if a ENVIRONMAP_DIFFUSE is used, this should be used as a lookup for the ambientlight. 

I'm doing a lot of shader work right now. The next update will be a big one....

  • Like 2

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

I'm thinking about an API translation layer for Leadwerks to Ultra. Something like this:

#include "UltraEngine.h"

namespace Leadwerks
{
    class Context
    {
        static Context* current;
        shared_ptr<UltraEngine::Framebuffer> framebuffer;
        public:
    }

    Context* CreateContext(Leadwerks::Window* w)
    {
      auto c = new Leadwerks::Context;
      c->framebuffer = UltraEngine::CreateFramebuffer(w->window);
      Leadwerks::Context::current = c;
      return c;
    }

    class World
    {
        static World* current;
        shared_ptr<UltraEngine::World> world;
        public:
            void Render(const bool vsync)
            {
                if (Context::current == NULL) return;
                world->Render(Context::current->framebuffer, vsync);
            }
    };

    class Entity : public Leadwerks::Object
    {
        shared_ptr<UltraEngine::Entity> entity;
    public:
        void SetPosition(float x, float y, float z, bool g)
        {
            entity->SetPosition(x,y,z,g);
        }
    }

    class Pivot : public Leadwerks::Entity
    {
    }

    Leadwerks::Pivot* CreatePivot(Leadwerks::Entity* parent = NULL)
    {
        auto p = new leadwerks::Pivot;
        p->entity = UltraEngine::CreatePivot(Leadwerks::World::current);
        if (parent) p->entity->SetParent(parent->entity);
        return p;
    }
}

 

  • Upvote 2

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

I've tried this and that'll be a lot of translating you'll need to be doing but I would appreciate it. I recommend exposing the smart pointer as well just in-case something is missed.

I'm curious on how things like the world and actor system would port over. That, and getting context drawing simple text, shapes, and textures to the screen might be a challenge, but you will most likely figure it out. Only brought that up since I seen a lot of people draw things to the screen that way over the GUI system. 

Would be really cool just to link Leadwerks code to Ultra and have everything or most things just work.

Cyclone - Ultra Game System - Component PreprocessorTex2TGA - Darkness Awaits Template (Leadwerks)

If you like my work, consider supporting me on Patreon!

Link to comment
Share on other sites

 Update:

  • LoadCollider example now works: https://www.ultraengine.com/learn/LoadCollider?lang=cpp
  • Sound::Play will now store a handle to the generated speaker so you an just call the command without hanging onto the returned speaker: https://www.ultraengine.com/learn/Sound_Play?lang=cpp
  • All Leadwerks legacy file formats are now supported natively by the engine (no plugin needed). I have not tested terrain yet. If you load a Leadwerks map, ChangeDir to the project's folder so it can find all the models and textures the map uses.
  • Directional light default color changed back to 1,1,1,1
  • Animation speed is now loaded correctly from glTF files
  • Moved some code out of the main rendering loop that run faster in complex scenes with many different objects. It's unlikely it will make any noticeable difference in simple scenes.

Note that the environment probe shading is not going to be correctly for non-PBR materials when SSR is in use. Still working that out.

Transparency will use maximum roughness when refraction is enabled, because I was testing it. This is temporary.

First attempt at Leadwerks translation layer is included. This code will actually work in both Leadwerks and Ultra: (You need to switch main.cpp to "Not using precompiled headers" in the settings for that file.)

#include "Leadwerks.h"

using namespace Leadwerks;

int main(int argc, const char* argv[])
{
    Window* window = Window::Create();
    Context* context = Context::Create(window);
    World* world = World::Create();
    Camera* camera = Camera::Create();
    camera->Move(0, 0, -3);
    Light* light = DirectionalLight::Create();
    light->SetRotation(35, 35, 0);

    Model* model = Model::Box();
    model->SetColor(0.0, 0.0, 1.0);

    while (true)
    {
        if (window->Closed() || window->KeyDown(Key::Escape)) return false;

        model->Turn(0, Time::GetSpeed(), 0);

        Time::Update();
        world->Update();
        world->Render();
        context->Sync(false);

    }
    return 0;
}

 

  • Like 1

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

I get an access violation with the new version with a blank new project and all other projects:

>	NewVersionTest_d.exe!std::_Ptr_base<class UltraRender::GPUBuffer>::get(void)	Unbekannt
 	NewVersionTest_d.exe!std::shared_ptr<class UltraRender::GPUBuffer>::operator-><class UltraRender::GPUBuffer,0>(void)	Unbekannt
 	NewVersionTest_d.exe!UltraRender::RenderMaterial::Submit(void)	Unbekannt
 	NewVersionTest_d.exe!UltraRender::RenderingThreadManager::GetDefaultMaterial(void)	Unbekannt
 	NewVersionTest_d.exe!UltraRender::RenderMesh::Initialize(void)	Unbekannt
 	NewVersionTest_d.exe!std::invoke<void ( UltraRender::RenderMesh::*&)(void),class std::shared_ptr<class UltraRender::RenderMesh> &>(void ( UltraRender::RenderMesh::*&)(void),class std::shared_ptr<class UltraRender::RenderMesh> &)	Unbekannt
 	NewVersionTest_d.exe!std::_Invoker_ret<struct std::_Unforced>::_Call<void ( UltraRender::RenderMesh::*&)(void),class std::shared_ptr<class UltraRender::RenderMesh> &>(void ( UltraRender::RenderMesh::*&)(void),class std::shared_ptr<class UltraRender::RenderMesh> &)	Unbekannt
 	NewVersionTest_d.exe!std::_Call_binder<struct std::_Unforced,0,void ( UltraRender::RenderMesh::*)(void),class std::tuple<class std::shared_ptr<class UltraRender::RenderMesh> >,class std::tuple<> >(struct std::_Invoker_ret<struct std::_Unforced>,struct std::integer_sequence<unsigned __int64,0>,void ( UltraRender::RenderMesh::*&)(void),class std::tuple<class std::shared_ptr<class UltraRender::RenderMesh> > &,class std::tuple<> &&)	Unbekannt
 	NewVersionTest_d.exe!std::_Binder<struct std::_Unforced,void ( UltraRender::RenderMesh::*)(void),class std::shared_ptr<class UltraRender::RenderMesh> &>::operator()<>(void)	Unbekannt
 	NewVersionTest_d.exe!std::invoke<class std::_Binder<struct std::_Unforced,void ( UltraRender::RenderMesh::*)(void),class std::shared_ptr<class UltraRender::RenderMesh> &> &>(class std::_Binder<struct std::_Unforced,void ( UltraRender::RenderMesh::*)(void),class std::shared_ptr<class UltraRender::RenderMesh> &> &)	Unbekannt
 	NewVersionTest_d.exe!std::_Invoker_ret<void>::_Call<class std::_Binder<struct std::_Unforced,void ( UltraRender::RenderMesh::*)(void),class std::shared_ptr<class UltraRender::RenderMesh> &> &>(class std::_Binder<struct std::_Unforced,void ( UltraRender::RenderMesh::*)(void),class std::shared_ptr<class UltraRender::RenderMesh> &> &)	Unbekannt
 	NewVersionTest_d.exe!std::_Func_impl_no_alloc<class std::_Binder<struct std::_Unforced,void ( UltraRender::RenderMesh::*)(void),class std::shared_ptr<class UltraRender::RenderMesh> &>,void>::_Do_call(void)	Unbekannt
 	NewVersionTest_d.exe!std::_Func_class<void>::operator()(void)	Unbekannt
 	NewVersionTest_d.exe!UltraCore::ThreadManager::Update(bool)	Unbekannt
 	NewVersionTest_d.exe!UltraRender::RenderingThreadManager::Update(bool)	Unbekannt
 	NewVersionTest_d.exe!UltraCore::ThreadManager::EntryPoint(class std::shared_ptr<class UltraEngine::Object>)	Unbekannt
 	NewVersionTest_d.exe!UltraEngine::Thread::thread_function(void *)	Unbekannt
 	ucrtbased.dll!00007ff820a73010()	Unbekannt
 	kernel32.dll!00007ff8f29a7034()	Unbekannt
 	ntdll.dll!00007ff8f48e26a1()	Unbekannt

 

Error: Failed to load shader module "Shaders/Downsample.frag.spv"
Ausnahme ausgelöst bei 0x00007FF6F99739C6 in NewVersionTest_d.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x0000000000000258.

 

  • Windows 10 Pro 64-Bit-Version
  • NVIDIA Geforce 1080 TI
Link to comment
Share on other sites

My bad, the basic sample works. but using SetEnvironmentMap throws errors now:

>	VolumetricLighting_d.exe!std::_Ptr_base<class UltraRender::RenderMaterial>::get(void)	Unbekannt
 	VolumetricLighting_d.exe!std::shared_ptr<class UltraRender::RenderMaterial>::operator-><class UltraRender::RenderMaterial,0>(void)	Unbekannt
 	VolumetricLighting_d.exe!UltraRender::RenderWorld::SetEnvironmentMap(class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap)	Unbekannt
 	VolumetricLighting_d.exe!std::invoke<void ( UltraRender::RenderWorld::*&)(class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap),class std::shared_ptr<class UltraRender::RenderWorld> &,class std::shared_ptr<class UltraRender::RenderTexture> &,enum UltraEngine::EnvironmentMap &>(void ( UltraRender::RenderWorld::*&)(class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap),class std::shared_ptr<class UltraRender::RenderWorld> &,class std::shared_ptr<class UltraRender::RenderTexture> &,enum UltraEngine::EnvironmentMap &)	Unbekannt
 	VolumetricLighting_d.exe!std::_Invoker_ret<struct std::_Unforced>::_Call<void ( UltraRender::RenderWorld::*&)(class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap),class std::shared_ptr<class UltraRender::RenderWorld> &,class std::shared_ptr<class UltraRender::RenderTexture> &,enum UltraEngine::EnvironmentMap &>(void ( UltraRender::RenderWorld::*&)(class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap),class std::shared_ptr<class UltraRender::RenderWorld> &,class std::shared_ptr<class UltraRender::RenderTexture> &,enum UltraEngine::EnvironmentMap &)	Unbekannt
 	VolumetricLighting_d.exe!std::_Call_binder<struct std::_Unforced,0,1,2,void ( UltraRender::RenderWorld::*)(class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap),class std::tuple<class std::shared_ptr<class UltraRender::RenderWorld>,class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap>,class std::tuple<> >(struct std::_Invoker_ret<struct std::_Unforced>,struct std::integer_sequence<unsigned __int64,0,1,2>,void ( UltraRender::RenderWorld::*&)(class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap),class std::tuple<class std::shared_ptr<class UltraRender::RenderWorld>,class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap> &,class std::tuple<> &&)	Unbekannt
 	VolumetricLighting_d.exe!std::_Binder<struct std::_Unforced,void ( UltraRender::RenderWorld::*)(class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap),class std::shared_ptr<class UltraRender::RenderWorld> &,class std::shared_ptr<class UltraRender::RenderTexture> &,enum UltraEngine::EnvironmentMap const &>::operator()<>(void)	Unbekannt
 	VolumetricLighting_d.exe!std::invoke<class std::_Binder<struct std::_Unforced,void ( UltraRender::RenderWorld::*)(class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap),class std::shared_ptr<class UltraRender::RenderWorld> &,class std::shared_ptr<class UltraRender::RenderTexture> &,enum UltraEngine::EnvironmentMap const &> &>(class std::_Binder<struct std::_Unforced,void ( UltraRender::RenderWorld::*)(class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap),class std::shared_ptr<class UltraRender::RenderWorld> &,class std::shared_ptr<class UltraRender::RenderTexture> &,enum UltraEngine::EnvironmentMap const &> &)	Unbekannt
 	VolumetricLighting_d.exe!std::_Invoker_ret<void>::_Call<class std::_Binder<struct std::_Unforced,void ( UltraRender::RenderWorld::*)(class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap),class std::shared_ptr<class UltraRender::RenderWorld> &,class std::shared_ptr<class UltraRender::RenderTexture> &,enum UltraEngine::EnvironmentMap const &> &>(class std::_Binder<struct std::_Unforced,void ( UltraRender::RenderWorld::*)(class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap),class std::shared_ptr<class UltraRender::RenderWorld> &,class std::shared_ptr<class UltraRender::RenderTexture> &,enum UltraEngine::EnvironmentMap const &> &)	Unbekannt
 	VolumetricLighting_d.exe!std::_Func_impl_no_alloc<class std::_Binder<struct std::_Unforced,void ( UltraRender::RenderWorld::*)(class std::shared_ptr<class UltraRender::RenderTexture>,enum UltraEngine::EnvironmentMap),class std::shared_ptr<class UltraRender::RenderWorld> &,class std::shared_ptr<class UltraRender::RenderTexture> &,enum UltraEngine::EnvironmentMap const &>,void>::_Do_call(void)	Unbekannt
 	VolumetricLighting_d.exe!std::_Func_class<void>::operator()(void)	Unbekannt
 	VolumetricLighting_d.exe!UltraCore::ThreadManager::Update(bool)	Unbekannt
 	VolumetricLighting_d.exe!UltraRender::RenderingThreadManager::Update(bool)	Unbekannt
 	VolumetricLighting_d.exe!UltraCore::ThreadManager::EntryPoint(class std::shared_ptr<class UltraEngine::Object>)	Unbekannt
 	VolumetricLighting_d.exe!UltraEngine::Thread::thread_function(void *)	Unbekannt
 	ucrtbased.dll!00007ff84fa73010()	Unbekannt
 	kernel32.dll!00007ff8f29a7034()	Unbekannt
 	ntdll.dll!00007ff8f48e26a1()	Unbekannt

 

  • Windows 10 Pro 64-Bit-Version
  • NVIDIA Geforce 1080 TI
Link to comment
Share on other sites

Works now perfectly. One sidenote: I know a backup of the changed files is made, but i believe the template files especially the main.cpp or other possibly heavily modified files by users should not be changed by an update. Shaders etc. provided by the engine should be updated, but nothing else.

  • Windows 10 Pro 64-Bit-Version
  • NVIDIA Geforce 1080 TI
Link to comment
Share on other sites

2 minutes ago, klepto2 said:

Works now perfectly. One sidenote: I know a backup of the changed files is made, but i believe the template files especially the main.cpp or other possibly heavily modified files by users should not be changed by an update. Shaders etc. provided by the engine should be updated, but nothing else.

The diff tool lets you see what was changed. If you resave main.cpp it will be newer than the template file, so it will no longer be considered outdated.

Ideally, files like main.cpp will never change after the initial release.

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

At this point, the only things I know of that need to be finished are:

  • Test if terrain is working in Leadwerks maps
  • Resolve SSR reflections when using shader families other than the default PBR metal / roughness model

I can't think of anything else. That means I will just be doing documentation, which will undoubtedtly result in a lot of bug fixes

  • Like 2

My job is to make tools you love, with the features you want, and performance you can't live without.

Link to comment
Share on other sites

  • Josh changed the title to Ultra Engine testing
  • Josh locked this topic
Guest
This topic is now closed to further replies.
 Share

×
×
  • Create New...