-
Posts
854 -
Joined
-
Last visited
Content Type
Blogs
Forums
Store
Gallery
Videos
Posts posted by klepto2
-
-
I think so. Thts why i increased the sphere segments a bit. Otherwise the jitter is much more obvious at the segment points.
- 1
-
small experiment, i couldn't resist
#include "UltraEngine.h" #include "Components/Player/CameraControls.hpp" using namespace UltraEngine; const float G = 667.4f; const float planet_mass = 1000.0; Vec3 calculateForce(shared_ptr<Entity> planet, shared_ptr<Entity> target) { Vec3 direction = (planet->GetPosition() - target->GetPosition()); float distance = direction.Length(); if (distance == 0) return Vec3(0.0); float forceMagnitude = G * (target->GetMass() * planet_mass) / pow(distance, 2); Vec3 force = direction.Normalize() * forceMagnitude; return force; } int main(int argc, const char* argv[]) { auto displays = GetDisplays(); auto window = CreateWindow("Ultra Engine", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR); auto world = CreateWorld(); auto framebuffer = CreateFramebuffer(window); auto camera = CreateCamera(world); camera->SetClearColor(0.125); camera->SetFov(70); camera->SetPosition(0, 10, -5); auto light = CreateDirectionalLight(world); light->SetRotation(35, 45, 0); world->SetGravity(0.0, 0.0, 0.0); auto planet = CreateSphere(world, 100.0, 128); planet->SetMass(FLT_MAX - 1); planet->SetPosition(0.0f, -100.0f, 0.0f); planet->SetMaterial(LoadMaterial("Materials\\Developer\\bluegrid.mat")); camera->SetPosition(0.0f, 0.0f, -3.0f); camera->AddComponent<CameraControls>(); camera->SetDebugPhysicsMode(true); vector<shared_ptr<Entity>> boxes; auto box_main = CreateBox(world, 4.0); for(int i = 0; i < 200; i ++) { auto box = box_main->Instantiate(world); box->SetMass(1.0); box->SetColor(1.0, 0.0, 0.0, 1.0); box->SetPosition(Random(120.0, -120.0), Random(120.0, -120.0), Random(120.0, -120.0)); box->Move(0.0, -100.0, 0.0); boxes.push_back(box); } box_main = NULL; bool stage = 0; while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { if (window->KeyHit(KEY_F2) == true) { camera->SetWireframe(!camera->GetWireframe()); } if (window->KeyHit(KEY_F3) == true) { camera->SetDebugPhysicsMode(!camera->GetDebugPhysicsMode()); } bool hit_space = window->KeyHit(KEY_SPACE); for each (auto box in boxes) { box->AddForce(calculateForce(planet, box)); if (hit_space) { Vec3 direction = (planet->GetPosition() - box->GetPosition()).Normalize(); box->AddForce(-direction * 2500.0); } } world->Update(); world->Render(framebuffer); } return 0; }
- 3
-
If i remember correctly (@Josh correct me if i am wrong) , the gravity is applied to each object in the "NewtonBodySetForceAndTorqueCallback" which means, that while currently only a fixed gravity force is applied, this could be extended to add several "Attractors" or planets. So in theory you could simulate whole a whole universe with planets. and correct gravity. Maybe it would be an option to open up the Callback to override the force calculation for gravity?
Maybe something like this (more or less pseudo code):
vec3 world_gravity_callback(vec3 pos) { vec3 force = vec3(0); for(auto p : planets) { float distanceToPlanet = calcDistance(pos); force += calcForce(pos, distanceToPlanet); // as Newton engine uses real world units, you can actually use the real physics equations here } return force; } void cb_applyForce(const NewtonBody* const body, dFloat timestep, int threadIndex) { // Fetch user data and body position. UserData *mydata = (UserData*)NewtonBodyGetUserData(body); dFloat pos[4]; NewtonBodyGetPosition(body, pos); // Apply gravity. dFloat force[3] = world->Gravity; if(world->HasGravityCallback) // if custom gravity is used calculate this instead of the fixed gravity { force = world->CalculateGravityForPosition(pos); } NewtonBodySetForce(body, force); }
- 1
-
Indeed, a fresh install solved it. thx
- 1
-
With the latest update, the debug library is damaged.
-
One small addition: While this Ui-System is mainly for prototyping or debugging/dev things. It might come in handy, that it has a lot of lowlevel drawing functions. Which means, that when i have done the Rendertarget implementation, it could be possible to draw all kinds of 2d shapes, etc into a texture, which can then be rendered into a UltraEngine::Widget. Or you can combine these things and use the Widget system and ImGui together, e.g.: for something like this: https://github.com/thedmd/imgui-node-editor
- 1
-
yes, but that would mean, that the floor itself needs a mass otherwise the force methods will have no impact.
To make it physically correct, ( i believe i read that somewhere on the Newtondynamics forums back in Blitzmax times ) Would be to turn off gravity at all and for each object apply a force pointing to the center of your "planet" or maybe in this case just downwards. Of course in the case of a plane you need to conquer the forces applied to the plane to make it stable.
-
Next Step:
Finished the update to the "Dear ImGui" "docking"-branch. The docking branch is a stable dev branch which contains the latest features as docking or multi-viewport systems. Docking is self explaining and I show it in the image below. Essentially multi-viewport means, that you can move windows out of your application, i haven't tested that (new windows will be generated, etc.)
Other remarkable milestones:
-
Rendering is more or less optimized. (With some dirty hacks )
- I have refactored the Model/Mesh generation and updating method and the main loop still updates with 60fps even with high complex ui's
- Multiple Fonts rendering is also possible
- Texture-System is in place.
What needs to be done:
- Replace the current Win32 driver with a native UltraEngine way
- Add feature to allow render to texture and proper Input handling in this case
- and of course optimization
- 3
-
Rendering is more or less optimized. (With some dirty hacks )
-
I think the Physicsmatrix is only updated for the box itself, not taking the parent into account. You can see this in the first sample: While the box is moving you can actually move through it even though the collision shape is displayed correct. When you move to the original Position the collison will occur.
-
-
This shows the current state: It is really impressive what you can do. There are tons of widgets available (the colored Texteditor is a 3rd party plugin which works nativly with the integration).
Also Dear ImGui is meant to be used for tooling/prototyping and debugging, not for ingame usage. Therefore, there are other tools.
- 2
-
Maybe
1 hour ago, Josh said:The reason you can see flickering when a mesh changes is because the old visibility set is still being used, the old mesh goes out of scope and is deleted, but the new mesh has not cycled through the culling update yet. It's a tricky problem.
Maybe a flag to disable the Culling step for particular models/meshes might do the trick, in Orthographic projection (especially GUIs) it might be useful to always assume the mesh is visible as long as the model itself is not hidden.
I was able to optimize the rendering to be flicker free and still performant. The previous flickering was due to a misconception on my side earlier. This is how Imgui provides the render data:
- you notify ImGui that you will render a new frame
- you define the GUI
-
last you ask ImGui for the Renderdata
-
The RenderData consists of Displaylists (for each window, foreground or background operation)
- The Displaylists itself contains the VertexBuffer and the indexbuffer and a commandlist
- the commandlists specify which texture to use and which indices (by providing an Offset and an ElementCount)
- The Render data is ordered front to back representing the Z-Index.
-
The RenderData consists of Displaylists (for each window, foreground or background operation)
In my first implementations i assumed that I need a separate Model for each command in the commandlists, and i reused these models and reordered them every frame. The Problem: if in the previous frame a big window with lots of content was rendered focused, but the next frame a small and simple window was in front. The Model of the big window was resized to the smaller window and vice versa.
In the current implementation i only use one model per displaylist (which contains the _ownername) and add meshes according to the commandbuffer. So know i can identify which model belongs to a specific window (displaylist) and I only reuse this model for that particular window, when a window is closed I just hide the model and reuse it once the window is back. If a window has fewer commands than before i clear it and rebuild als meshes needed. Otherwise i use the resize approach.
Surprisingly, this eliminates all the flickering but still maintains a good performance.
1 hour ago, Josh said:I encountered a similar problem with the Sprite::SetText method, and I solved it like this:
- If the new mesh data is bigger than the existing mesh, get rid of the existing mesh and create a new mesh.
- If the new mesh data is smaller or equal to the size of the existing mesh, copy the new mesh data to the existing mesh and set the extra vertices to all use position (0,0,0), so they will be invisible.
This is what i do when the cmds are lower than the previously created meshes, but this only works by removing all meshes from the model and adding them again afterwards. There currently is no way to remove a specific mesh from a model.
-
I have found a very hackish workaround and this should not be used, unless you know exactly what you do:
class ModifiableMesh : public Mesh { public: void ResizeVertexBuffer(shared_ptr<Mesh> base, int newSize) { static_cast<ModifiableMesh*>(base.get())->Mesh::m_vertices.resize(newSize); }; void ResizeIndexBuffer(shared_ptr<Mesh> base, int newSize) { static_cast<ModifiableMesh*>(base.get())->Mesh::m_indices.resize(newSize); }; int VertexSize(shared_ptr<Mesh> base) { return static_cast<ModifiableMesh*>(base.get())->Mesh::m_vertices.size(); }; int IndexSize(shared_ptr<Mesh> base) { return static_cast<ModifiableMesh*>(base.get())->Mesh::m_indices.size(); }; }; const shared_ptr<ModifiableMesh> ModMesh = std::make_shared<ModifiableMesh>();
with this you can now resize the Vectors even when they are protected:
int v_size = ModMesh->VertexSize(mesh); int i_size = ModMesh->IndexSize(mesh); int v_diff = v_size - newVertices.size() - INDEX_FLOAT_RANGE; int i_diff = i_size - newIndices.size() - INDEX_FLOAT_RANGE; if (abs(v_diff) > INDEX_FLOAT_RANGE) { Print("Resizing (Vertex-Buffer): " + String(v_diff) + " | " + String(v_size) + "-" + String(newVertices.size())); ModMesh->ResizeVertexBuffer(mesh,newVertices.size() + INDEX_FLOAT_RANGE); } if (abs(i_diff) > INDEX_FLOAT_RANGE)//newIndices.size() > mesh->m_indices.size()) { Print("Resizing (Index-Buffer): " + String(i_diff) + " | " + String(i_size) + "-" + String(newIndices.size())); ModMesh->ResizeIndexBuffer(mesh,newIndices.size() + INDEX_FLOAT_RANGE); } mesh->Modify(newVertices); mesh->Modify(newIndices);
Not really a good way, but it will do it as long as we have no ability to access the vectors directly.
- 1
-
22 hours ago, klepto2 said:
Most Vulkan or modern DirectX/OpenGL use one VertexBuffer for big models, and just separate Indexbuffers per material.
Maybe I should clarify this a bit. The Architecture of 3rd party libraries (including Dear ImGui, or most nvidia libs) normalliy provide a shared VertexStructure and then just an Indexbuffer for each "surface". To replicate this behaviour in UltraEngine, you currently have to create multiple meshs and recalculate the Vertexbuffer (I have done so for ImGui) or you need to duplicate the Vertexbuffer for each mesh.
The above thing is a nice to have but not essential.
What is most important for me is the abillity to resize the Vertices and Indices at will. While I understand that Ultraengine is layedout for high performance I believe that some parts should also be a bit flexible. (It doesn't cost to much if you just need to resize every now and then and just upload small bits to the gpu instead of a big buffer where just a small bit is used anyway).
- 1
-
While the Mesh API is very fast and also flexible, I think it could be more flexible.
Background:
I am working on this:
and I have encountered a small issue with the mesh API. While you're able to modify vertices and indices on the fly it is not possible to change and update the size of these Vectors. I found a post where Josh describes this by design and i agree that from a performance point this is useful. On the other side it limits the usage of the class. Lets take the "Dear ImGui' as a sample:
As this is an intermediate Gui system the layout is not calculated once, but instead each frame, This means that a window with small content has a small vertex and index count, but when you modify (eg: expand trees or add text) the mesh is regenerated and the vertex size and index buffer changes in size.
Currently there are 2 ways to solve this:
-
Recreate meshes on the fly (delete the old mesh, and create a new one with the new size)
- Surprisingly fast, but due to sync with the graphics card it leads to high flickering
-
Create the meshes with hight vertex and inddex counts (lets say 10000 / 30000) and use the Mesh::Modify methods
- Works without flickering, but is extremly slow, not because of the modifcation itself, but the extreme size and unneeded uploads to the gpu.
I have tested something which i assumed will not work, but surprisingly this worked flawless with nearly no impact:
-
I modfied mesh.h and changed the protected modifier to public
- This gave me access to the actual Vectors for vertices and indices
- With access to these Vectors i can now resize them at will.
- I give them just a small bigger size (around 300 items) than needed to not perform resizing every frame
- After that i just use the Mesh::Modify methods
Results:
- with the recreation method i get around 150 to 180 fps, but flickering
- with the preserved Size method i get 20 to 50 fps (depending on debug or release mode)
- with the resizing method i get 180 to 240 fps
So maybe the resizing should be added optionaly to the Modify methods or maybe another DynamicMesh class.
Another thing which might be useful for some scenarios:
Shared VertexBuffers per Model or MeshGroup:
Most Vulkan or modern DirectX/OpenGL use one VertexBuffer for big models, and just separate Indexbuffers per material.
In Ultraengine this could be used to further increase the GPU-Bandwidth: I could Imagine that you define a Main-Mesh and this mesh can be assigned to other Meshs as parent. Then these Child meshes only need to provide indices and the vertexbuffer is the same as the the parent mesh.
Use Cases: Lod, Voxel terrains etc.
- 1
-
Recreate meshes on the fly (delete the old mesh, and create a new one with the new size)
-
Made a lot of progress today
I have finished the basic ImGuiManager for UltraEngine (not yet commited) with some additional features:
-
you can now register your own UltraEngine Textures to be used by ImGui
- ImGuiManager::RegisterTexture(texture) will return an ImTextureID which can be used then by eg: ImGui::Image(...)
- Multiple-Fonts are now supported + reload and recreation of the texture-atlas
This is a small sample which i am using to test some features:
#include "UltraEngine.h" #include "Components/Motion/Mover.hpp" #include "imgui-integration/ImGuiManager.h" using namespace UltraEngine; using namespace UltraEngine::ImGuiIntegration; using namespace std; #define MAX_FRAMES 100 struct StatCounter { float data[MAX_FRAMES]; float getMax() { return *max_element(data, data + MAX_FRAMES); } float getAvarge() { float average = 0.0f; int removeCounts = 0; for (int n = 0; n < IM_ARRAYSIZE(data); n++) { auto v = data[n]; if (v < 0.0) { v = 0.0; removeCounts++; } average += v; } average /= (float)(MAX_FRAMES - removeCounts); return average; } }; class ImDebugRenderer : public Object { shared_ptr<World> _world; StatCounter _fpsCounter; StatCounter _cullCounter; StatCounter _renderCounter; int _currentFrame = 0; bool _isOpen = true; public: ImDebugRenderer(shared_ptr<World> world) : _world(world) { _world->RecordStats(true); } void CollectStatistics() { _fpsCounter.data[_currentFrame] = _world->renderstats.framerate; _cullCounter.data[_currentFrame] = _world->renderstats.cullingtime; _renderCounter.data[_currentFrame] = _world->renderstats.rendertime; } void Render() { CollectStatistics(); if (_isOpen) { ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_Appearing); ImGui::SetNextWindowBgAlpha(0.5); //ImGui::SetNextWindowSize(ImVec2(350, 420), ImGuiCond_Appearing); ImGui::Begin("Debug", &_isOpen, ImGuiWindowFlags_AlwaysAutoResize); ImGui::PlotLines(("Framerate (" + String(_world->renderstats.framerate) + " fps )").c_str(), _fpsCounter.data, IM_ARRAYSIZE(_fpsCounter.data), _currentFrame, ("average : " + String(_fpsCounter.getAvarge())).c_str(), 0.0, _fpsCounter.getMax(), ImVec2(0, 80.0f)); ImGui::PlotLines(("Culltime (" + String(_world->renderstats.cullingtime) + " ms)").c_str(), _cullCounter.data, IM_ARRAYSIZE(_cullCounter.data), _currentFrame, ("average : " + String(_cullCounter.getAvarge())).c_str(), 0.0, _cullCounter.getMax(), ImVec2(0, 80.0f)); ImGui::PlotLines(("Rendertime (" + String(_world->renderstats.rendertime) + " ms)").c_str(), _renderCounter.data, IM_ARRAYSIZE(_renderCounter.data), _currentFrame, ("average : " + String(_renderCounter.getAvarge())).c_str(), 0.0, _renderCounter.getMax(), ImVec2(0, 80.0f)); ImGui::Text("Cameras : %d", _world->renderstats.cameras); ImGui::Text("Meshbatches : %d", _world->renderstats.meshbatches); ImGui::Text("Pipelines : %d", _world->renderstats.pipelines); ImGui::Text("Polygons : %d", _world->renderstats.polygons); ImGui::Text("Vertices : %d", _world->renderstats.vertices); ImGui::Text("Instances : %d", _world->renderstats.instances); ImGui::Text("Shadows : %d", _world->renderstats.shadows); ImGui::Text("Shadowpolygons: %d", _world->renderstats.shadowpolygons); ImGui::Text("VRam : %d", _world->renderstats.vram); ImGui::End(); } _currentFrame = (_currentFrame + 1) % MAX_FRAMES; } void Show() { _isOpen = true; }; void Toggle() { _isOpen = !_isOpen; }; }; int main(int argc, const char* argv[]) { auto plg = LoadPlugin("Plugins/FITextureLoader"); auto plg2 = LoadPlugin("Plugins/KTX2TextureLoader"); //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 a camera auto camera = CreateCamera(world); camera->SetPosition(0, 0, -1); camera->SetFov(70); camera->SetClearColor(0.125); camera->SetTessellation(4); //Create a light auto light = CreateBoxLight(world); light->SetRange(-10, 10); light->SetRotation(35, 35, 0); light->SetColor(4); //Display material auto model = CreateCubeSphere(world, 0.5, 8, MESH_QUADS); auto mtl = LoadMaterial("Materials/rocks_ground_02.json"); mtl->SetTessellation(true); mtl->SetDisplacement(0.075f); model->SetMaterial(mtl); //Entity component system auto component = model->AddComponent<Mover>(); component->rotationspeed.y = 45; // Init the Manager auto imGuiManager = CreateImGuiManager(window, world); auto debugRenderer = make_shared<ImDebugRenderer>(world); // A custom class to render debug information for the world auto sampleTexture = mtl->GetTexture(0); // Get the diffuse Texture auto imGuiTexture = imGuiManager->RegisterTexture(sampleTexture); // Register the texture for usage with ImGui //Define some settings to control the camera and material settings bool camera_wireFrame = false; float tesselation_level = 4.0; Vec2 mtl_displacement = mtl->GetDisplacement(); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { //Begin the ui-definition imGuiManager->BeginFrame(); debugRenderer->Render(); //render the debug panel (only when open) //Start rendering of the Settings ImGui::Begin("Settings", NULL, ImGuiWindowFlags_AlwaysAutoResize); ImGui::Checkbox("Wireframe", &camera_wireFrame); ImGui::SliderFloat("Tesselation-Level", &tesselation_level,0.0,32); ImGui::SliderFloat2("Displacement", &mtl_displacement[0], -1.0, 1.0); if (ImGui::Button("Toggle Debug-Window")) { debugRenderer->Toggle(); } ImGui::End(); //Render a window containing the UltraEngine texture ImGui::Begin("Texture", NULL, ImGuiWindowFlags_AlwaysAutoResize); ImGui::Image(imGuiTexture,ImVec2(128,128)); ImGui::End(); //Stop UI-Recording and update/create the models for UltraEngine imGuiManager->Sync(); //Update the Settings modified by the UI camera->SetWireframe(camera_wireFrame); camera->SetTessellation(tesselation_level); mtl->SetDisplacement(mtl_displacement.x, mtl_displacement.y); world->Update(); world->Render(framebuffer); } return 0; }
- 3
-
you can now register your own UltraEngine Textures to be used by ImGui
-
small update:
clipping errors and z-order problems are fixed.
Now working on the simplyfied (ultralike) access and setting up a github repo for this to give access to this gem to everyone.
- 2
-
I already posted a small screenshot in the Gallery showing an early proof of concept for integrating ImGui into UltraEngine.
https://www.ultraengine.com/community/gallery/image/2676-imgui-integration-in-ultraengine/
Now I have made some progress and finished a lot of the integration stuff.
- Ordered Rendering (not completely working, sometimes the order seems a bit off)
- Keyboard and MouseInput
- Shader and Material stuff
- General-Rendering is working
What is still to do:
- Resolve some clipping errors
- Make the whole integration more Ultra-like not the c approach ImGui is normally using for initialisation
- Add multiple texture and font support (for images or framebuffer display)
This small gif shows a small sample with the provided demo window and a custom debug window showing the renderstats:
Here is a small code snippet showing the debug window code:
#define MAX_FRAMES 100 struct StatCounter { float data[MAX_FRAMES]; float getMax() { return *max_element(data, data + MAX_FRAMES); } float getAvarge() { float average = 0.0f; int removeCounts = 0; for (int n = 0; n < IM_ARRAYSIZE(data); n++) { auto v = data[n]; if (v < 0.0) { v = 0.0; removeCounts++; } average += v; } average /= (float)(MAX_FRAMES - removeCounts); return average; } }; class ImDebugRenderer : public Object { shared_ptr<World> _world; StatCounter _fpsCounter; StatCounter _cullCounter; StatCounter _renderCounter; int _currentFrame = 0; bool _isOpen = true; public: ImDebugRenderer(shared_ptr<World> world) : _world(world) { _world->RecordStats(true); } void CollectStatistics() { _fpsCounter.data[_currentFrame] = _world->renderstats.framerate; _cullCounter.data[_currentFrame] = _world->renderstats.cullingtime; _renderCounter.data[_currentFrame] = _world->renderstats.rendertime; } void Render() { CollectStatistics(); if (_isOpen) { ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_Appearing); ImGui::SetNextWindowBgAlpha(0.5); //ImGui::SetNextWindowSize(ImVec2(350, 420), ImGuiCond_Appearing); ImGui::Begin("Debug", &_isOpen, ImGuiWindowFlags_AlwaysAutoResize); ImGui::PlotLines(("Framerate (" + String(_world->renderstats.framerate) + " fps )").c_str(), _fpsCounter.data, IM_ARRAYSIZE(_fpsCounter.data), _currentFrame, ("average : " + String(_fpsCounter.getAvarge())).c_str(), 0.0, _fpsCounter.getMax(), ImVec2(0, 80.0f)); ImGui::PlotLines(("Culltime (" + String(_world->renderstats.cullingtime) + " ms)").c_str(), _cullCounter.data, IM_ARRAYSIZE(_cullCounter.data), _currentFrame, ("average : " + String(_cullCounter.getAvarge())).c_str(), 0.0, _cullCounter.getMax(), ImVec2(0, 80.0f)); ImGui::PlotLines(("Rendertime (" + String(_world->renderstats.rendertime) + " ms)").c_str(), _renderCounter.data, IM_ARRAYSIZE(_renderCounter.data), _currentFrame, ("average : " + String(_renderCounter.getAvarge())).c_str(), 0.0, _renderCounter.getMax(), ImVec2(0, 80.0f)); ImGui::Text("Cameras : %d", _world->renderstats.cameras); ImGui::Text("Meshbatches : %d", _world->renderstats.meshbatches); ImGui::Text("Pipelines : %d", _world->renderstats.pipelines); ImGui::Text("Polygons : %d", _world->renderstats.polygons); ImGui::Text("Vertices : %d", _world->renderstats.vertices); ImGui::Text("Instances : %d", _world->renderstats.instances); ImGui::Text("Shadows : %d", _world->renderstats.shadows); ImGui::Text("Shadowpolygons: %d", _world->renderstats.shadowpolygons); ImGui::Text("VRam : %d", _world->renderstats.vram); ImGui::End(); } _currentFrame = (_currentFrame + 1) % MAX_FRAMES; } void Show() { _isOpen = true; }; };
The setup is more or less the same as for the default GUI, you need an orthographic camera and a separate renderlayer. But then you can simply call:
// This is how i imagine a more ultra-way of rendering the ImGui auto ui_manager = ImGuiUltraManager::Create(window, world, renderlayer); //Framebuffer will work as well void main() { ui_manager->BeginFrame(); // Begins the frame-recording debugWindow->Render(); // Add the commands to draw the debug window (code from above) ui_manager->Render(); // Stops the frame-recording and prepares the models for rendering world->Update(); world->Render(framebuffer,true); }
- 2
- 1
-
For the reprojection i noticed, that i don't need it, but it will come in handy to render masks etc. for godrays eg. the same time you render the more complicated stuff.
-
I have the need to write to 2 colorattachments and i have set it up like this:
"textures": [ { "size": [0.5, 0.5], "format": 97 }, { "size": [0.5, 0.5], "format": 97 } ], "subpasses": [ { "samplers": ["DEPTH", "NORMAL", "PREVPASS"], "colorAttachments": [0,1], "shader": { "float32": { "fragment": "Shaders/Environment/environment_clouds.frag.spv" } } },
in the shader file i have something like this (very simplfied):
layout(location = 0) out vec4 outColor[2]; void main() { outColor[0] = vec4(1.0,0.0,0.0,1.0); outColor[1] = vec4(0.0,1.0,0.0,1.0); }
only the red value is stored to the texture, the second one is still unmodified. Ate multiple attachemnts currently not supported?
-
or (TextureFormat)VK_FORMAT_R16_UINT if you want to save the shorts. the previous solution will store normlaized floats.
- 1
-
Try it with this:
auto map = CreatePixmap(size, size, (TextureFormat)VK_FORMAT_R16_UNORM, data);
- 1
-
Also Terrain::GetElevation doesn't take the Terrain-Position into account. Which is understandable as the terrain matrix is fully modifiable (scale, position and rotation), but it should be mentioned in the Docs.
- 1
-
Hi,
while i am working on my "Environement / Atmosphere / Weather" - system i'm working a lot with the terrain system and found some bugs and missing functionality from the API.
Bugs:
The layer system works only when you first assign a material to the terrain. In my opinion, this should not be required and a default terrain material should be set until it is overridden by the user (later planetary implementation or streaming terrain).
On further investigation this was just a one time bug for me, but i let it here for reference.
#include "UltraEngine.h" #include "Components/CameraControls.hpp" using namespace UltraEngine; int main(int argc, const char* argv[]) { //Get the display list 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(); world->SetAmbientLight(0); //Create a framebuffer auto framebuffer = CreateFramebuffer(window); //Create a camera auto camera = CreateCamera(world); camera->SetFov(70); camera->SetPosition(0, 50, 0); camera->SetRotation(45, 0, 0); camera->SetClearColor(0.125); //Sunlight auto light = CreateDirectionalLight(world); light->SetRotation(45, 35, 0); light->SetColor(2); //Create terrain auto terrain = CreateTerrain(world, 512); terrain->LoadHeightmap("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Terrain/512.r16"); terrain->SetScale(1, 100, 1); //Create base material auto ground = CreateMaterial(); auto diffusemap = LoadTexture("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Materials/Ground/river_small_rocks_diff_4k.dds"); auto normalmap = LoadTexture("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Materials/Ground/river_small_rocks_nor_gl_4k.dds"); ground->SetTexture(diffusemap, TEXTURE_DIFFUSE); ground->SetTexture(normalmap, TEXTURE_NORMAL); terrain->SetMaterial(ground); // Comment out this line and the whole terrain will be black //Create paint material auto rocks = CreateMaterial(); diffusemap = LoadTexture("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Materials/Ground/Rocks_Dirt_Ground_2k.dds"); normalmap = LoadTexture("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Materials/Ground/Rocks_Dirt_Ground_2k_dot3.dds"); auto dispmap = LoadTexture("https://raw.githubusercontent.com/UltraEngine/Documentation/master/Assets/Materials/Ground/Rocks_Dirt_Ground_2k_disp.dds"); rocks->SetTexture(diffusemap, TEXTURE_DIFFUSE); rocks->SetTexture(normalmap, TEXTURE_NORMAL); rocks->SetTexture(dispmap, TEXTURE_DISPLACEMENT); int layer = terrain->AddLayer(rocks); terrain->SetLayerTextureMapping(layer, TERRAINMAPPING_VERTICAL); //Apply material based on terrain slope for (int x = 0; x < terrain->resolution.x; ++x) { for (int y = 0; y < terrain->resolution.y; ++y) { float slope = terrain->GetSlope(x, y); if (slope > 15.0f) { float wt = Min((slope - 15.0f) / 10.0f, 1.0f); terrain->SetLayerWeight(layer,x, y, wt); } } } //Camera controls camera->AddComponent<CameraControls>(); //Main loop while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false) { world->Update(); world->Render(framebuffer); } return 0; }
Missing methods:
1. The Fill method is commented out in the header file and my should maybe renamed to FillLayer(int layerid)
2. The methods to set and get the layer scaling are missing, or better: they are in the protected area.
3 All get Methods for LayerProperties should be provided. Currently it is not possible to access things like the Slope / height constraints of a specific layer.
- 1
- 1
ImGui - Integration
in Showcase
Posted
You*re completely right. And with the new updates, it is even better The only thing is that in debug mode the culling takes a lot of time (10 - 13ms at average), which leads to a lower update even only one mesh is on screen. I remember that @SpiderPig has made the suggestion, to be able to disable the culling for certain cameras. And for orthographic cameras i fully agree with him. Normally in a 2d space it could be leed to the programmer, what to render and what not.
Here are some progress screens of the current Statistics panel i have done with Dear ImGui: