Jump to content

Josh

Staff
  • Posts

    23,504
  • Joined

  • Last visited

Blog Entries posted by Josh

  1. Josh
    Here's my list, as it stands today:
    Lua Interpreter project for iOS and Android (iOS is done, Aria is working on Android)
    Improve flowgraph visual style (will finish today, probably)
    Documentation (Chris is filling out the syntax, then I will go in and write descriptions)
    Brush rendering batches (to make editor rendering faster)
    Brush collapse on load (in engine only)
    Undo system

  2. Josh
    Here's my list of things left to do:
    Documentation
    Undo system
    Get character models for Darkness Awaits
    Prepare the super secret special surprise for deployment

     
    Undo functionality is my absolute least favorite thing to program, and I also want to get some more real-world testing done before implementing it, so it comes last. This evening I will start on the docs, in earnest.
     
    I hope everyone is having a good near-Christmas week.
  3. Josh
    I got the editor documentation written pretty quickly. It was hard to start, but once I figured out how I wanted to lay out the information, it all started flowing pretty easily.
     
    Documentation in Leadwerks Engine 2 was a weakness, especially in stuff other than the programming reference. This is unfortunate, because I have come to see documentation as the final product. Everything in the development cycle leads up to the ability to write good documentation.
     
    Good documentation starts with good program design. It would have been difficult to give the same attention to detail in Leadwerks Engine 2 as I am now, because there was much more behavior that was undefined, or left up to the user. Because Leadwerks 3 absorbs a lot of that complexity, I can definitively say "if you want to do X, press this button". It makes for documentation that is nice to read, and kind of fun to write.
     
    Here's a screenshot, just to give you an idea of the formatting and style I am using.

     
    I usually feel overwhelmed by the documentation when I look at game engines. It's hard to know where to start, and I just feel like I am picking up random bits of disorganized information. I am hoping the manner in which I have organized our docs will provide a streamlined learning experience, with the ability to drill down to more detail when needed. My organization is as follows:
     
    Editor
    This covers the entire Leadwerks workflow and art pipeline. You can find answers to all non-programming questions here.
     
    Script Reference
    This section describes all the object scripts included with Leadwerks, and how to use them to make game interaction.
     
    Programming
    This section discusses general information about programming with Leadwerks, in C++ and Lua.
     
    Command Reference
    This section provides detailed descriptions and examples for the entire Leadwerks API.
     
    Index
    This is a list of all pages in the documentation, in alphabetical order.
     
    It feels very easy to navigate and it doesn't take long to learn how the entire workflow and art pipeline work, but it's not lightweight by any means. The docs have more than 600 pages! Most of that is for individual class functions, which is information you will usually specifically seek out, rather than just reading through them all for fun.
     
    --EDIT--
    I added some additional fields for C++ and Lua examples, with a tabbed interface to view each:

  4. Josh
    Based on the excellent sales of the SciFi Interior Model Pack, I was able to get a deal to sell a new pack of high-quality first-person weapons. The following items are included:
    Pistol
    Combat shotgun
    MP5 Machne Gun
    M4 Rifle
    Grenade
    Machete

     
    Weapons are included as animated visual weapons, and as models that can be placed throughout the map to pick up.
     

     
    Instead of just distributing raw models, I want to offer game-ready items that can just be dropped into your game. This requires me to add sounds and perform some scripting to make the FPS player handle picking weapons up and switching between weapons. It also requires some new scripting for the new weapon types, like grenades and melee weapons. It's a challenge to design the scripts in a general-purpose manner, the benefit is everyone gets game-ready weapons they can simply drop into their map for the player to find and use. Plus, I get to design some cool explosion effects.
     
    The pack will be priced at $29.99, includes sounds, scripts, and special effects, and will be available in October.
     

  5. Josh
    Leadwerks 3.4 will be launched as soon as AMD releases their new driver, preferably by Monday. The three big features this introduces are:
    Vehicles
    Water
    Built-in Workshop browser

     
    As well as over 100 small fixes and improvements.
     
    The launch will coincide with a week-long sale. The results of the sale will give me an estimate of cash flows for 2015 and let me make decisions about what to invest in the company and continued development.
     
    Following the launch, we'll have a period until summer where I will work on new features for 3.5 and resolve a few remaining Linux issues. I expect to make some minor changes to the renderer and update system in particular, but nothing that breaks the API. I'm not going to attempt anything like this until the launch is over, as it is possible I might have to make some quick fixes the first week.
     
    Summer will see the release of Leadwerks 3.5 and the Leadwerks Summer Games Tournament. Leadwerks Game Player will have a private beta, and will launch to the public when there are 50 small games ready to play.
     
    You can help the 3.4 launch by spreading the news on social media, when it is released. Thank you.
  6. Josh
    The Leadwerks 2 vegetation system used a grid of "cells" that each contained a quantity of vegetation instances. If the cell was close enough, each instance was checked against the camera frustum like a regular entity and then all visible instances were rendered in a batch. Cells that were further away were collapsed into a single surface consisting of a quad for each instance. This is how we were able to draw massive amounts of foliage in the distance at a fast framerate:
     


     
    This was good, but limited by the scene management performed by the CPU. It also used very large amounts of memory to store all the 4x4 matrices of the individual instances. The above map used about half a gigabyte of data to store all positions for each tree int he scene.
     
    The Leadwerks 3 vegetation system is being designed around modern hardware capabilities, taking advantage of the features of OpenGL 4. This has two goals:
    Remove the overhead of scene management performed on the CPU.
    Reduce memory usage of vegetation data.


    Transform Feedback
    One of the most interesting things OpenGL 4 supports is transform feedback, which allows you to render data to an arbitrary buffer. This can be combined with a geometry shader to selectively output information in ways a normal render-to-texture can't. This schematic from RasterGrid's OpenGL blog shows how the system works: 

     
    Below you can see my implementation working. The scene consists of 91 million polygons, with about 28 million visible at any given time. (This number will be reduced through the use of billboards.) The edges of the camera frustum are pulled in to make the culling visible.
     


     
    Use of the transform feedback feature in OpenGL 4 relieves the CPU from the expensive overhead of large-scale scene management.

    Tiling Matrices
    The need for individual instance matrices is being totally eliminated by using a tiling grid of 4x4 matrices. This creates a repeating pattern of rotations across the scene. I think when the trees are placed on a hilly terrain the tiling appearance won't be visible, but there are other tricks I can use to increase the randomness. The physics system will work by dynamically retrieving the relevant 4x4 matrices of nearby instances, totally eliminating the need to store any of this massive data in memory. The fact that no instance data is being sent over the PCIE bridge also means this system will be much faster than Leadwerks 2. 
    Vegetation in Leadwerks 3 will be a virtually zero-overhead system and allow for much greater volumes of geometry than Leadwerks 2 could render, at effectively no cost on most hardware.
  7. Josh
    An update is now available on the beta branch.
     
    A new decal entity type is available. Decals are used to project an image into surrounding geometry. A decal requires a material using a decal shader, located in the "Shaders\Decals" folder. The FPSGun.lua script has been updated to add bullet marks and gunshot wounds to objects a bullet hits. You can also place a decal in a map for adding large details to walls, terrain, or anything else.
     

     
    Decals are rendered similarly to the way a deferred light works; they are rendered onto the screen gbuffer. This allows them to work on any geometry, including animated models and GPU-generated details like tessellation. They will also map onto any surface, based on the direction of the surface normal. There are two new commands, Decals::Create() and Decal::SetRenderMode().
     
    Because decals render onto the scene gbuffer, a way to differentiate pixels is needed. Otherwise, a scene decal will appear on objects that pass through that area. The Decal::SetRenderMode(int mode) command can be used to indicate whether a decal should be a static scene decal (mode=0) or a dynamic decal, like for a bullet mark (mode=1). Materials also have a new parameter for their decal mode, which can be 0 (static), 1 (dynamic), or 2 (none).
     
    The blending of decals required that I modify the channel allocation of the gbuffer, and the lighting and model shaders have changed. Previously, data was stored like this:
    0: Diffuse RGBA
    1: Normal XYZ, specular
    2: Emission RGB, material flags
     
    Now the gbuffer is storing information as follows:
    0: Diffuse RGBA
    1: Normal XYZ, material flags
    2: Emission RGB, specular
     
    Any modified model shaders or shaders that are rendered before lighting need to be changed to accommodate this change, as well as any post-processing effects that read the specular value or material flags.
     
    Particle emitters will now use simple collision if the emitter has a collision type other than zero. This is a nice touch that makes bullet shrapnel bounce off floors instead of going straight through.
     
    I previously talked about four big features I was researching, terrain tessellation, terrain horizontal offsets, deferred decals, and vegetation. I made headway on each of these, but discovered that deferred decals were fairly easy to wrap up, while the other three features were more involved. Based on this development, I am revising my plan to release a new version in August with decals and the other recent improvements, then focus on finishing the vegetation system for a subsequent update. The important thing is to have the final update with vegetation out by November 1, at the latest, although that could end up being much sooner if things go smoothly.
     
    I also expect to release the game launcher in August, as an early preview release on Steam.
     
    (Build #691949 was update to #711604.)
  8. Josh
    Billboards, transitions, and rendering are now done, and as you can see in the screenshot below, the idea works great. In Leadwerks 2, this application would have used hundreds of megabytes of data to store all the individual 4x4 matrices of each object. In Leadwerks 3, the instances are generated on the fly, so the application uses no more memory than a map with a blank terrain:
     

     
    Still to do:
    Fade out billboards as they approach max view distance.
    Add rows to break up generated billboard textures.
    Add DXT compression to generated billboard textures.
    Add sub-grid rendering so GPU is only evaluating instances within a certain distance to the camera.
    Add physics collision.
    Vegetation painting tools in editor.

  9. Josh
    Environment probes are now available on the beta branch. To access them, you must set the "UnlockBetaFeatures" setting in the config file to 1, then start the editor. Environment probes are available in the "Effects" object creation category.
     
    Environment probes should be placed with one in each room. Use the object scale to make the probe's volume fill the room. (Like decals, probes will display a bounding box when selected.) You do not have to worry about covering every single space as the GI effect will blend in pretty well with the regular old ambient light level. Outdoor scenes do not need probes covering everywhere. There is not presently an entity icon for probes so you will have to select them from the scene panel. The AI & Events map has been updated with probes added, and it just took a couple of minutes.
     

     
    The color value of the probe (under the "Appearance" tab in the object properties) is used to control the amount of ambient lighting the probe contributes. The specular color of the probe is used to control the strength of the reflections it casts.
     
    Materials can control their reflectivity with their specular color and specular texture, if it exists. You may find some materials are highly reflective and need to be toned down a bit, so just make their specular color darker. The roughness setting is used to control how sharp or blurry reflections are. Higher roughness = blurrier reflections.
     
    When you first create an environment probe, its cubemap will be rendered immediately. You should re-render it when you have made some changes to your map and want to see the updated global illumination. To do this, select the Tools > Build Global Illumination menu item, which will update all environment probes in the scene.
     
    Global illumination is an inexpensive effect because it is precomputed. However, environment probes will be skipped if the lighting quality is set to the lowest setting.
  10. Josh
    Leadwerks Game Engine 4.1 beta is now available on the beta branch on Steam. This is the final version 4.1, barring any bug fixes that are made before the release later this month. I am going to focus on just resolving bug reports and adding new documentation for the next two weeks.
     

     
    4.1 adds environment probes, which have been covered previously, and volumetric lighting. Point and spot lights can display a volumetric effect by adjusting the "Volume strength" setting, found under Light properties in the editor. You can also use the new commands Light::SetVolumetricStrength() and Light::GetVolumetricStrength(). At this time, directional lights should use the godray shader instead, but I might try this effect on directional lights as well before the release.
     
    Volumetric lighting is an expensive effect to render, but my Intel 5200 is running it at a fast speed, and high-end cards should have no problem with it. Lights with a large range are more expensive than lights with a small range. The performance will be exactly the same for any intensity level above zero (the default). The effect is disabled when the low-quality light setting is in use.
     
    Volumetric lighting looks best in dark scenes with lots of contrast. Spotlights tend to look a little better, as point lights don't have the same well-defined shape. Use these sparingly for dramatic lighting effects in key positions. It looks especially nice when you have a fence or grate in front of the light to create lots of interesting light beams.
     
    The bloom effect has also been improved, and SSAO, godrays, and iris adjustment post-processing effects have been added. The bloom effect is using the mixing equation from Leadwerks 2, along with an improved Gaussian blur function from the RasterGrid blog.
     

     
    New entity icons courtesy or reepblue have been created.
     
    Have fun with the new features and let me know if you have any questions.
  11. Josh
    A new build is available on the beta branch. The editor and Lua executables are updated, only on Windows at this time. Everything is updated, including the beta branch of Game Launcher, for Windows and Linux.
     
    I believe I have fixed the crashing in the new light management code. I also added a small optimization that checks if a moved light has the same 4x4 matrix it did at the time of the last shadow render. This makes it so if you are standing still and nothing is moving, the flashlight shadow won't update unnecessarily, even though your code is repositioning it each frame. This is a very small improvement, but I want your games to run as fast as possible.
     
    I've added experimental support for frame limiting. This works by passing a second optional parameters to the Context:Sync command specifying the max framerate. This can be used alone to cap the framerate without VSync:

    context:Sync(false,60)
     
    It can be used to cap the framerate at any arbitrary speed:

    context:Sync(false,90)
     
    Or it can be used together with VSync enabled to cap the framerate and prevent screen tearing:

    context:Sync(true,60)
     
    This is experimental, and may change before the final release of version 4.3.
  12. Josh
    An update is available on the beta branch for Windows, editor and Lua executables only. This fixes a problem in the new light update system:
    http://www.leadwerks.com/werkspace/topic/15713-shadow-update-editor-issues/
    http://www.leadwerks.com/werkspace/topic/15716-43-child-entities-do-not-cast-shadows/
     
    The animation shaders are also modified and they will appear better:
    http://www.leadwerks.com/werkspace/topic/15710-all-animated-shaders-have-wrongstatic-normals/
  13. Josh
    A new build is available on the beta branch.  I am putting it out tonight because I want to give you guys as much lead time as possible.
    I have not tested all hardware yet, and there were a lot of shader updates, so there could easily be a compile error on AMD or Intel cards.  Will test those out in the morning.
    New camera commands for fog:
    virtual void SetFogColor(const float r, const float g, const float b, const float a); virtual void SetFogAngle(const float start, const float stop); virtual void SetFogRange(const float start, const float stop); virtual void SetFogMode(const bool mode); virtual Vec4 GetFogColor(); virtual Vec2 GetFogAngle(); virtual Vec2 GetFogRange(); virtual bool GetFogMode(); This is scheduled to be released on the default branch this Tuesday.
    Also useful:
     
  14. Josh
    Leadwerks 5 is going to be developed alongside 4.5 with an extended period of beta testing and feedback.  My goal is to build the world's most advanced game design software, tailored to the needs of our community and clients.  Development will first focus on a new programming API updated for C++11 and then a completely new editor using Leadwerks GUI and based on the workflow developed with our current editor.
    The first beta will support the following features right away:
    Shared Pointers Unicode support 64-bit These features are already working.  Here is a working build you can try right now:
    Leadwerks5.zip
    This is the actual source code used to make this example.  Note that C++11 shared pointers have been implemented for all objects and the API has been simplified to make your code more readable:
    #include "Leadwerks.h" using namespace Leadwerks; int main(int argc, const char *argv[]) { auto window = CreateWindow(); auto context = CreateContext(window); auto world = CreateWorld(); auto camera = CreateCamera(world); camera->Move(0, 0, -3); auto light = CreateDirectionalLight(world); light->SetRotation(35, 35, 0); light->SetShadowMode(0); auto model = CreateBox(world); model->SetColor(0.0, 1.0, 0.92); while (not window->Closed()) { if (window->KeyHit(EscapeKey)) break; if (model) model->Turn(0, 1, 0); if (window->KeyHit(SpaceKey)) model = nullptr; world->Update(); world->Render(context); } return 0; } The beta will be available to developers who want to try the very latest game development technology, with a subscription plan of just $4.99 a month, available through our website.
  15. Josh
    This month I was working on a lot of NASA projects using Leadwerks. My goal with this is to build up enough business that I can start hiring more people to help. It's nice to make money using my own tools, and it gives me a lot of ideas for the new engine.
    This morning I felt like experimenting with the design of plugins in the new editor a bit. I came up with two types of plugins. One will add an new menu item to the model editor that flips the normals of the current model. The ProcessEvent() function intercepts a GUI event in the editor and performs new functionality:
    Plugin.title = "Flip Model Normals" Plugin.description = "Reverses the faces of all triangles in the model editor." function Plugin:Load() local menu = Editor.modelEditor.menu:FindMenu("Plugins") if menu~=nil then self.menuitem = menu:AddItem("Flip Normals") end end function Plugin:Unload() if self.menuitem~=nil then self.menuitem:Free() end end function Plugin:ProcessEvent(event) if event.id = EVENT_MENUACTION then if event.source = self.menuitem then if Editor.modelEditor.model~=nil then self:FlipNormals(Editor.modelEditor.model) Editor.modelEditor:Redraw() return false end end end return true end function Plugin:FlipNormals(model) local n,k,lod,mesh,i,a,b,c for n=0,#model.lods do lod = model.lods[n] for k=0,#lod.meshes do mesh = lod.meshes[k] mesh:Unlock() for i=0,#mesh.indices/3 do a = mesh.indices[i*3+0] b = mesh.indices[i*3+1] c = mesh.indices[i*3+2] mesh.indices[i*3+0] = c mesh.indices[i*3+2] = a end mesh:Lock() end end end Another type of plugin adds some new functionality to your game. This one is different because it loads a function from a dynamically linked library and passes the Lua state to a function: In this case, I decided to try separating analytics off into its own plugin, simply because it is a self-contained system that doesn't interfere with the rest of the engine:
    Plugin.name = "Example" Plugin.title = "Example Plugin" Plugin.description = "This is an example plugin." function Plugin:GetPath() local ext="" if GetOS()=="Windows" then ext = "dll" elseif GetOS()=="Linux" then ext = "so" elseif GetOS()=="MacOS" ext = "dylib" end return self.name..ext end function Plugin:Load() local f = package.loadlib(self:GetPath(),"Load") if type(f)=="function" then f(GetLuaState()) end end function Plugin:Unload() local f = package.loadlib(self:GetPath(),"Unload") if type(f)=="function" then f() end end The source code for the dynamic library would be something like this:
    #include "GameAnalytics.h" bool Load(sol::state* L) { L->set_function("EnableAnalytics", EnableAnalytics); } void Unload() { } bool EnableAnalytics(const bool state) { return true; } Once the plugin is loaded, the Lua state would be passed to the DLL (or .so, or .dylib) and the new commands would get inserted into the Lua state.
    So what does a plugin consist of?
    A ,lua or precompiled .luac file is required. If the plugin uses C++ code, a .dll, .so, and .dylib are required. Optional source code and project(s) for the dynamically linked library. And what can a plugin do?
    Add new features to the editor. Add new Lua commands to use in your game. That's all for now.
  16. Josh
    I wanted to get a working example of the plugin system together. One thing led to another, and...well, this is going to be a very different blog.
    GMF2
    The first thing I had to do is figure out a way for plugins to communicate with the main program. I considered using a structure they both share in memory, but those always inevitably get out of sync when either the structure changes or there is a small difference between the compilers used for the program and DLL. This scared me so I went with a standard file format to feed the data from the plugin to the main program.
    GLTF is a pretty good format but has some problems that makes me look for something else to use in our model loader plugins.
    It's text-based and loads slower. It's extremely complicated. There are 3-4 different versions of the file format and many many options to split it across multiple files, binary, text, or binary-to-text encoding. It's meant for web content, not PC games. Tons of missing functionality is added through a weird plugin system. For example, DDS is supported through a plugin, but a backup PNG has to be included in case the loaded doesn't support the extension. The GMF file format was used in Leadwerks. It's a custom fast-loading chunk-based binary file format. GMF2 is a simpler flat binary format updated with some extra features:
    Vertices are stored in a single array ready to load straight into GPU memory. Vertex displacement is supported. Compressed bitangents. Quad and line meshes are supported. LOD Materials and textures can be packed into the format or loaded from external files. PBR and Blinn-Phong materials Mesh bounding boxes are supported so they don't have to be calculated at load time. This means the vertex array never has to be iterated through, making large meshes load faster. I am not sure yet if GMF2 will be used for actual files or if it is just going to be an internal data format for plugins to use. GLTF will continue to be supported, but the format is too much of a mess to use for plugin data.
    Here's a cool five-minute logo:

    The format looks something like this:
    char[4] ID "GMF2" int version 200 int root //ID of the root entity int texture_count //number of textures int textures_pos //file position for texture array int materials_count //number of materials int materials_pos //file position for materials int nodes_count //number of nodes int nodes_pos //file position for nodes As you can see, it is really easy to read and really easy to write. There's enough complexity in this already. I'm not bored. I don't need to introduce unnecessary complexity into the design just so I can show off. There are real problems that need to be solved and making a "tricky" file format is not one of them.
    In Leadwerks 2, we had a bit of code called the "GMF SDK". This was written in BlitzMax, and allowed construction of a GMF file with easy commands. I've created new C++ code to create GMF2 files:
    //Create the file GMFFile* file = new GMFFile; //Create a model node = new GMFNode(file, GMF_TYPE_MODEL); //Add an LOD level GMFLOD* lod = node->AddLOD(); //Add a mesh GMFMesh* mesh = lod->AddMesh(3); //triangle mesh //Add a vertex mesh->AddVertex(0,0,0, 0,0,1, 0,0, 0,0, 255,255,255,255); mesh->AddVertex(0,0,1, 0,0,1, 0,0, 0,0, 255,255,255,255); mesh->AddVertex(0,1,1, 0,0,1, 0,0, 0,0, 255,255,255,255); //Add a triangle mesh->AddIndice(0); mesh->AddIndice(1); mesh->AddIndice(2); Once your GMFFile is constructed you can save it into memory with one command. The Turbo Plugin SDK is a little more low-level than the engine, so it includes a MemWriter class to help with this, since the engine Stream class is not present.
    As a test I am writing a Quake 3 MD3 import plugin and will provide the project and source as an example of how to use the Turbo Plugin SDK.

    Packages
    The ZIP virtual file system from Leadwerks is being expanded and formalized. You can load a Package object to add new virtual files to your project. These will also be loadable from the editor, so you can add new packages to a project, and the files will appear in the asset browser and file dialogs. (Package files are read-only.) Plugins will allow packages to be loaded from file formats besides ZIP, like Quake WADs or Half-Life GCF files. Notice we keep all our loaded items in variables or arrays because we don't want them to get auto-deleted.
    //Load Quake 3 plugins auto pk3reader = LoadPlugin("Plugins/PK3.dll"); auto md3loader = LoadPlugin("Plugins/MD3.dll"); auto bsploader = LoadPlugin("Plugins/Q3BSP.dll"); Next we load the game package files straight from the Quake game directory. This is just like the package system from Leadwerks.
    //Load Quake 3 game packages std::wstring q3apath = L"C:/Program Files (x86)/Steam/steamapps/common/Quake 3 Arena/baseq3"; auto dir = LoadDir(q3apath); std::vector<shared_ptr<Package> > q3apackages; for (auto file : dir) { if (Lower(ExtractExt(file)) == L"pk3") { auto pak = LoadPackage(q3apath + L"/" + file); if (pak) q3apackages.push_back(pak); } } Now we can start loading content directly from the game.
    //Load up some game content from Quake! auto head = LoadModel(world, "models/players/bitterman/head.md3"); auto upper = LoadModel(world, "models/players/bitterman/upper.md3"); auto lower = LoadModel(world, "models/players/bitterman/lower.md3"); auto scene = LoadScene(world, "maps/q3ctf2.bsp"); Modding
    I have a soft spot for modding because that is what originally got me into computer programming and game development. I was part of the team that made "Checkered Flag: Gold Cup" which was a spin-off on the wonderful Quake Rally mod:
    I expect in the new editor you will be able to browse through game files just as if they were uncompressed in your project file, so the new editor can act as a modding tool, for those who are so inclined. It's going to be interesting to see what people do with this. We can configure the new editor to run a launch script that handles map compiling and then launches the game. All the pieces are there to make the new editor a tool for modding games, like Discreet's old Gmax experiment.

    I am going to provide official support for Quake 3 because all the file formats are pretty easy to load, and because gmax can export to MD3 and it would be fun to load Gmax models. Other games can be supported by adding plugins.
    So here are some of the things the new plugin system will allow:
    Load content directly from other games and use it in your own game. I don't recommend using copyrighted game assets for commercial projects, but you could make a "mod" that replaces the engine and requires the player to own the original game. You could probably safely use content from any Valve games and release a commercial game on Steam. Use the editor as a tool to make Quake or other maps. Add plugin support for new file formats. This might all be a silly waste of time, but it's a way to get the plugin system working, and if we can make something flexible enough to build Quake maps, well that is a good test of the robustness of the system.
     
  17. Josh
    All this month I have been working on a sort of academic paper for a conference I will be speaking at towards the end of the year. This paper covers details of my work for the last three years, and includes benchmarks that demonstrate the performance gains I was able to get as a result of the new design, based on an analysis of modern graphics hardware.
    I feel like my time spent has not been very efficient. I have not written any code in a while, but it's not like I was working that whole time. I had to just let the ideas settle for a bit.
    Activity doesn't always mean progress.
    Anyways, I am wrapping up now, and am very pleased with the results. It all turned out much much better than I was expecting.
  18. Josh
    PBR materials look nice, but their reflections are only as good as the reflection data you have. Typically this is done with hand-placed environment probes that take a long time to lay out, and display a lot of visual artifacts. Nvidia's RTX raytracing technology is interesting, but it struggles to run old games on a super-expensive GPU, My goal in Leadwerks 5 is to have automatic reflections and global illumination that doesn't require any manual setup, with fast performance.
    I'm on the final step of integrating our voxel raytracing data into the standard lighting shader and the results are fantastic. I found I could compress the 3D textures in BC3 format in real-time and save a ton of memory that way. However, I discovered that only about 1% of the 3D voxel texture actually has any data in it! That means there could be a lot of room for improvement with a sparse voxel octree texture of some sort, which could allow greater resolution. In any case, the remaining implementation of this feature will be very interesting. (I believe the green area on the back wall is an artifact caused by the BC3 compression.)
    I think I can probably render the raytracing component of the scene in a separate smaller buffer and the denoise it like I did with SSAO to make the performance hit negligible on this. Another interesting thing is that the raytracing automatically creates it's own ambient occlusion effect.
    Here is the current state, showing the raytraced component only. It works great with our glass refraction effects.
    Next I will start blending it into the PBR material lighting calculation a little better.
    Here's an updated video that shows it worked into the lighting more:
     
  19. Josh

    Articles
    I haven't been blogging much because I am making so much progress that there would be too much to cover. In this article I will talk about one little system I spent the last week on and show the improvements I have made to the workflow over Leadwerks.
    In the asset editor, when the root of a model is selected, a "Collider" field appears in the physics properties. You can use this to quickly calculate and apply a collider to the model.

    The convex hull collider includes an option for tolerance. You can adjust this to get a more or less precise convex hull around the model:

    There is also an "optimize" option for the mesh collider. When this is activated it will attempt to merge adjacent coplanar polygons into a single face, and can result in fewer seams on colliding faces.
    Two new shapes are included, the capsule and the chamfer cylinder, so now all the shapes supported by Newton Dynamics are available. (The chamfer cylinder is good for vehicle tires.)
     
    Unlike Leadwerks, you no longer need to specify the axis cylindrical shapes are oriented around. The editor will calculate which bounding box axes are most like each other, and use the third axis to orient the shape. This works for long skinny objects:

    And it also works for short fat objects:

    It will even detect which direction a cone should be facing, by calculating the total distance from the shape the model vertices are with each direction, and selecting the orientation with the smallest error value. (A single cone is probably not the best choice of shape for this model, but the point is that it correctly guesses which direction the cone should point based on the model vertices.)

    For more advanced geometry, the convex decomposition tool is available in the Utilities panel. This exposes all the parameters available in V-HACD 4.0 and processes the task on a separate thread so you can continue to use the editor as the task runs in the background. It usually only takes a few seconds to compete, but it is nice to not have your workflow interrupted:

    You can export colliders as model files, so it's also possible to just use this to generate convex hulls and export them to .obj. (I could get a better fitting shape if I spent more time adjusting the settings, but I just quickly made this shape with very low settings in order to get this screenshot.)

    The new .collider file format, like everything else in Ultra, is JSON-based. Simple shapes can be stored in pure ASCII text, so they can be edited by hand if needed:
    { "collider": { "parts": [ { "offset": [ 0.0024815797805786133, -0.18715500831604004, -1.055002212524414e-05 ], "rotation": [ 0.0, 0.0, 0.0 ], "shape": "BOX", "size": [ 1.8899539709091187, 2.0, 1.8019688129425049 ] } ] } } More complex shapes like convex hulls and meshes use binary data appended to the end of the file to store their contents, so that they load quickly in the engine:
    { "collider": { "parts": [ { "data": 0, "shape": "CONVEXHULL", "vertices": 61 } ] } }�n�2��<�5�j�k��#�I3��ch�������=b[��I<��~d�I�D�` �[�\{4���A���?XO3���>��վ�v!���f��� ?]����I�!�����V� >�?���mdG�t9�a��@���X?W��0o��e�-�D��h�P?>����>��׾���@��=T�U?��ž�{����w�� ���G��3��ޑ?>V?c�����;���6�s�/?&�=����?q�e?j��N���[#b��bݽ(��>��Ǿ�ڽ�E��MV�ַؽ��8<�G������D?BYT?I���@"N?6?�";-�$?��콜�";��t>8�"�t�";�z��3�0���";����ݐ�)�%=}P?��0?���=/�E?BYT?'>�=�E��MV����={; ?"����>�־��c� �>��?q�e?�$>�ӽ��P��@>��,?�j|=�2�>[o/���P�C��>��?>V?Z�>�������Қ�>��h���@�>��E�CO2��.�>T��[A�y]�>L��=T�U?w4�>���>�쾛?#o��e�-�r?�����U?�"?.�v>��!?�R?�zv����>�@?(�0�S �>.(?�n_�C�?�|-?d�[��}?��4?��>��վ��6?2M4��*?�>?P��=_�s��F?V ���ྲAm?�#�I3�Lr?����� Leadwerks .phy collider files can also be loaded.
    Notice in the shots above, in the drop-down menu there is also a "Browse" option, so you can create a collider file with a low-resolution model and then load the resulting collider to use with a high-resolution model.
    I think this design strikes the right balance to let you do simple things quickly, but still allow for more advanced options when you need them. In the future I would like to add an additional in-depth collider editing utility that would allow you to select each sub-object, select model polygons and generate shapes just from those polys, and other advanced features.
    The pick mode feature has been revised. The original design was based on Blitz3D, which did not support collision primitives at all. Instead of specifying a sphere or other shape for picking, you can now just tell the entity to use the collider for picking. (PICK_SPHERE is removed.)
    On an unrelated note, I had to adjust the camera range based on the distance from the model being viewed, in order to make very small objects visible. This allows extreme close-up shots like in the blog header image that you probably aren't used to seeing except in VR. It's kind of interesting.
  20. Josh
    So here's what it took to get Leadwerks running on the iPhone:
     
    Let's start at the point we had the C++ code building and running with an OpenGL 1 renderer on OSX. I was worried OpenGLES might be a dramatically different API that required a whole new learning curve, but I was pleasantly surprised. It's just a stripped-down version of OpenGL, more like OpenGL 3.3 than anything else. Making the OpenGL2ES renderer was mostly just a copy and paste operation, and then I had to comment out a few unsupported commands.
     
    Building for the iPhone simulator was a bit harder. The first problem I ran into was that file paths on iOS are case-sensitive. (They aren't on OSX.) This was problematic, because my asset management code stored file paths in lowercase, so that had to be changed.
     
    Then there was the matter of setting the application's file path. A special function had to be written to set this at application startup.
     
    The hardest part was the context handling. The flow of an iOS app all revolves around Objective-C events, and this doesn't mix well with a C++ program. What I ended up doing was creating an App class like this:

    class App { public: bool Start(); bool Continue(); int Finish(); };
    Objective-C calls these class functions to keep the program loop running. Once the Continue() function returns false, the application calls Finish() and exits.
     
    I'm okay with using this same design across all platforms, if it means your C++ code will run on everything. of course, this is just a convention in the generated project files, and if you want you can code the engine with any program structure you want. This is just the best way to ensure your code runs on everything.
     
    The last challenge was setting up the provisioning profiles, certificate, and some other stuff I don't even remember. This was pretty tricky, and took most of the day to figure out. In the end, I just ran through the instructions a second time, and it magically worked.
     
    At the end of all that, it was nice to see Leadwerks running on the iPhone. iOS was the hardest platform to add support for, and I don't expect the same difficulty when we add support for Android:


     
    Thanks to Ed Upton and Simon Armstrong for their help and advice.
  21. Josh
    Lots of things are happening around here right now!
     
    First up, we've got some free professionally made animations for you to use with our futuristic soldier character. You can download the files here.
     
    Michael Betke of Pure3D has been cranking out AAA-quality 3D models ready to use in Leadwerks Engine. The following sets are available:

    Birch Trees 1.x (€22,00)
    Pine Trees 1.x (€22,00)
    Ground Plants 1.x (€19,00)
    Each set features new unreleased content. Buy a couple today and help support low-cost AAA media for independent developers.
     
    I've been spending a little time with C++, and it's not that bad. Mika Heinonen was kind enough to investigate a method of integrating Lua with C++. Here are the findings he reported:
     
     
    At this point, we have a simple C++ project with some math classes the engine uses, and we're making sure it compiles for all the various platforms I want to support.
     
    Finally, we're getting ready for the release of version 2.32. There are some physics features that need to be finished to support huge amounts of trees and rocks, and that information has been sent to the author of Newton Game Dynamics. Numerous bugs in the tracker have been resolved recently, and more fixes are on the way for small issues.
     
    That's all for now!
  22. Josh
    I implemented resizable viewports this morning. This is so much more fun than fiddling around with compiler settings.
     
    You can grab the bars between viewports, or the very center space, and drag it around to resize the four viewports. I usually prefer a smaller perspective view, and like to devote most of my space to the 2D views when doing serious editing:

     
    You can also drag the views around to make a single big viewport, or just have two viewports visible:

     
    In 3D World Studio, when you resize the window the program instantly redraws, even as you are still moving the window. This is nice looking but it can get slow when you have a large map loaded, and it makes the program feel slow. The problem is even worse with a deferred renderer, because you are constantly creating and deleting those big gbuffers. I don't like hearing the graphics card fan kick up just because I decided to resize a window.
     
    I'm getting better results by waiting for the user to let go of the mouse before redrawing viewports, but for window and viewport resizing. This has the effect of displaying "bad"/undefined screen regions while the user is resizing things, but it makes the program very fast and responsive. I used to consider those artifacts to be a sort of amateurish trait, but I think this actually works better. The program feels very fast and light, so I think this is actually a pretty good tradeoff. As soon as you let go of the mouse button, the viewports redraw at their new size.

     
    --EDIT--
    And now we have grids. Starting to look familiar, but new:

×
×
  • Create New...