Jump to content

Josh

Staff
  • Posts

    23,353
  • Joined

  • Last visited

Blog Entries posted by Josh

  1. Josh
    A new update on the beta branch on Steam adds selective file inclusion on publishing a project. This works by scanning map files and building a list of required files, and only packing up files that are actually used in your game. Here's how it works:
    All map files are always included, and scanned for required files.
    All script files are always included, and scanned for required files.
    Included prefab files are scanned for required files.
    Included model files are scanned for required material files.
    Included material files are scanned for required texture files.
    All shaders are always included.

     
    The bulk of file sizes in any project are textures, and to some extent, model files. Although it is possible for this system to generate some "false positives" it will greatly reduce the size of published projects, and errs on the side of caution.
     
    I am concerned some required material files may not be caught. If you find a situation where this feature is not working properly please upload your project and send me a link to download it.
     
    This is the default behavior, and is always active when publishing your project.
     
    I hope to have this up on the default branch in time for the last few days of the Winter Games tournament.
  2. Josh
    Previously, I talked about my plan for Leadwerks for the next 6-12 months:
     
    Leadwerks Editor
    Adding new tools to make life easier.
    Refining the workflow to eliminate any remaining"sticky" points.
    Bug fixes, to make it a super slick and polished experience.

     
    The Engine
    New features in graphics, physics, networking, etc.
    Performance optimization.
    Improved compatibility across all OpenGL 4 hardware.

     
    Third-Party Technologies
    Blender, SteamOS, Steam Workshop, virtual reality, etc.

     
    With C++ support now added on Steam, I am getting ready to add the Linux build on Steam and elsewhere. This week will give me a chance to fix some minor problems and streamline the installation process a bit.
     
    The Blender exporter has not been done yet. I originally underestimated the value that having a bridge between various third party modeling applications can add. In order to make it easier to write exporters for various modeling packages, I am creating a C library that has commands for adding model limbs, mesh data, and animations, and then saving the resulting structure as a .mdl file. This library can then be used with lots of different plugin systems to create export plugins for various programs. (For Blender support, I will hire a contractor to write this and make the source code available for tinkering.)
     
    This month will mostly be about addressing any outstanding bug reports and making small improvements to the workflow and art pipeline. This is a necessary prerequisite to support for Steam Workshop; if I can find a few small ways to make the art pipeline more efficient, it will provide a big reduction in time spent prepping models for the Workshop. So it's time to eat my own dog food, as they say. Although the Leadwerks 3 art pipeline is largely frictionless, there's a few sticky points I would like to make easier in the workflow.
     
    OSX support is also on my list for the near future. I don't anticipate any problems here, as I just have to go into Objective-C and set up some OpenGL 4 contexts, which are only possible since OSX Mavericks was released last November.
     
    As always, this is an intended development plan, and may not be exactly what gets implemented as things change.
  3. Josh
    Three things I am working on right now:
    We need a high quality default skybox. I'm pretty happy with the results I got, after a lot of experimentation and different programs. This will be a whole huge blog post itself.
    Commissioning development of one high-end character model. I'm going with a fairly expensive option this time. My goal is to just get ONE character I am happy with, with the idea that if we can do it once we can do it again. More on this later.
    Investigating a better default vwep. Nothing more to say about it at the moment.

     
    This is very difficult stuff to progress on, but I think it is critical to develop the company's productive capability for game artwork.
  4. Josh
    I added a raycast function to the voxel tree class and now I can perform raycasts between any two positions. This is perfect for calculating direct lighting. Shadows are calculated by performing a raycast between the voxel position and the light position, as shown in the screenshot below. Fortunately the algorithm seems to work great an there are no gaps or cracks in the shadow:

    Here is the same scene using a voxel size of 10 centimeters:

    If we move the light a little lower, you can see a shadow appearing near two edges of the floor:

    Why is this happening? Well, the problem is that at those angles, the raycast is hitting the neighboring voxel on the floor next to the voxel we are testing:

    You might think that if we just move one end of the ray up to the top of the voxel it will work fine, and you'd be right, in this situation.

    But with slightly different geometry, we have a new problem.

    So how do we solve this? At any given time, a voxel can have up to three faces that face the light (but it might have as few as one). In the image below I have highlighted the two voxel faces on the right-most voxel that face the light:

    If we check the neighboring voxels we can see that the voxel to the left is occupied, and therefore the left face does not make a good position to test from:

    But the top voxel is clear, so we will test from there:

    If we apply the same logic to the other geometry configuration I showed, we also get a correct result. Of course, if both neighboring voxels were solid then we would not need to perform a raycast at all because we know the light would be completely blocked at this position.
    The code to do this just checks which side of a voxel the light position is on. As it is written now, up to three raycasts may be performed per voxel:
    if (lightpos.x < voxel->bounds.min.x) { if (GetSolid(ix - 1, iy, iz) == false) { result = IntersectsRay(p0 - Vec3(voxelsize * 0.5f, 0.0f, 0.0f), lightpos); } } if (lightpos.x > voxel->bounds.max.x and result == false) { if (GetSolid(ix + 1, iy, iz) == false) { result = IntersectsRay(p0 + Vec3(voxelsize * 0.5f, 0.0f, 0.0f), lightpos); } } if (lightpos.y < voxel->bounds.min.y and result == false) { if (GetSolid(ix, iy - 1, iz) == false) { result = IntersectsRay(p0 - Vec3(0.0f, voxelsize * 0.5f, 0.0f), lightpos); } } if (lightpos.y > voxel->bounds.max.y and result == false) { if (GetSolid(ix, iy + 1, iz) == false) { result = IntersectsRay(p0 + Vec3(0.0f, voxelsize * 0.5f, 0.0f), lightpos); } } if (lightpos.z < voxel->bounds.min.z and result == false) { if (GetSolid(ix, iy, iz - 1) == false) { result = IntersectsRay(p0 - Vec3(0.0f, 0.0f, voxelsize * 0.5f), lightpos); } } if (lightpos.z > voxel->bounds.max.z and result == false) { if (GetSolid(ix, iy, iz + 1) == false) { result = IntersectsRay(p0 + Vec3(0.0f, 0.0f, voxelsize * 0.5f), lightpos); } } .With this correction the artifact disappears:

    It even works correctly at a lower resolution:

    Now our voxel raycast algorithm is complete. The next step will be to calculate direct lighting on the voxelized scene using the lights that are present.
  5. 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

  6. Josh
    I first connected with Valve Software during GDC 2013. I recognized an opportunity to work together, so last week I paid a visit to Bellevue, Washington and met with Valve employees (no one has job titles in the company except Gabe) and discussed Leadwerks and the evolving Steam platform.
     
    Today, I'm excited to announce our Greenlight campaign for Leadwerks 3: Steam Edition.
     


     
    This software will be distributed through Steam and allow you to build games with Lua script and publish them to Windows and Mac through Steam. We think Steam users will love Leadwerks, for a few reasons.
     
    Constructive Solid Geometry
    First, we use a level editor based on constructive solid geometry. This lets everyone create game levels, without having to be an expert. If you're familiar with Valve's Hammer Editor, you'll feel right at home in Leadwerks. It's fun to make game levels, and anyone can do it.
     
    Write Games with Lua Script
    Second, we use Lua script, just like in Garry's Mod, World of Warcraft, Crysis, and hundreds of other games. We have a built-in script editor so you don't have to switch back and forth between Leadwerks and an external program. It's even got a built-in debugger so you can step through your script and see everything that's going on in the game.
     
    Visual Scripting
    Finally, we use a flowgraph editor to connect scripted objects and make gameplay happen. You can view the functions of scripted objects and just click and connect them. This lets map designers create sequences of events and complex gameplay, with no programming required.
     
    But it's not enough to just put Leadwerks on Steam. We want to fully integrate these technologies to deliver a complete game development platform, running within Steam.
     
    Steam Workshop Integration
    We're hooking into the Steam Workshop to deliver game assets. This includes models, textures, scripts, and maps, so you can get everything you need to make games. When you find an object in the Steam Workshop you want to use in your game, just hit the "Subscribe" button and it will show up right away, ready to use in Leadwerks.
     
    Support for Valve Asset Formats
    We're also addng support for Valve's asset formats so you can access lots of great content from the rest of the Steam Workshop and add it to your game.
     
    Export for Steam
    We're working with the Steam SDK to make it easier to submit your games to Greenlight. Just press a button and your game files will be packaged up ready to send to Steam.
     
    Our dream is to unite the entire Steam community into this big global game-producing factory, where everyone can do what they're best at. We need your help to make it happen. Please vote for us on Greenlight and show Valve the Steam community wants to build their own 3D games with Leadwerks.
     
    We'll do our best to make sure all current Leadwerks users can get Leadwerks 3: Steam Edition added to their Steam account for free. To help facilitate this, please add your Steam ID to your Werkspace profile.
     
    Vote for Leadwerks
    To vote for Leadwerks 3: Steam Edition on Greenlight, visit www.leadwerks.com/greenlight or find us in the Greenlight software section in Steam.
  7. Josh
    In this article I am going to explain some simple color tricks you can use to give your game environments a much more cohesive color scheme and look much better.
    Now if you look at most indie game environments that are thrown together from random models they will look something like this:

    It looks awful, with no consistent color scheme and saturation levels all over the place.  In fact, most look much worse than this.  I'm going to show you how to fix this.
    Control Saturation Levels
    The first step is to limit your saturation levels.  You can see the rocks and plants have fairly muted colors but the building, train engine, and cargo containers stick out like sore thumbs.  They sky also looks like a smurf.  You want to limit your saturation levels so that you can later apply lighting to the scene and get a more uniform look.  To do this you need to open the source images of your textures in Photoshop or another paint program and run a desaturation filter on any that look too colorful.  The image below shows a more desaturated scene, which still doesn't look great but it's a step in the right direction.

    Use a Good Skybox
    In an outdoor scene the sky typically takes up about 50% of your screen pixels, so it's important for this to look good.  There are only two types of good skyboxes.  You can either used one based on real photos of the sky, or use one created in the Vue Esprit software program.  Anything else is bad.  (Please do not use Terragen to make your skies!)  Photo-based skyboxes have the advantage of almost always looking great, while procedural skies created in Vue give you a lot more control over exactly how the sky should look.  (I used Vue for the default skybox that comes with Leadwerks.)  The scene below shows the photo-based skybox we used for The Zone DLC:

    Colored Lighting
    In nature, light is almost never white, but there's not really any such thing as "colored light", there's just light.  Light has properties of both particles and waves, and can travel at different wavelengths.  You have three types of photoreceptors in your eyes that each detect a different range of wavelengths.  These different receptors perceive light as red, green, and blue, but it's really all just light.  The combination of these different receptors inputs gives us all the colors in-between like turquoise (blue + green), yellow (red + green), and purple (red + blue).

    Blue light has the shortest wavelength and is the most powerful, while red has the longest wavelengths and is weakest.  Consequently, when light is dim it actually appears tinted blue because we can see the blue wavelengths more strongly.  This is easily visible at night when everything you see has a subtle blue tint.

    In the screenshot below I changed the ambient light level from RGB 64,64,64 to RGB 61,61,86.  It's not an extreme change but you can see the rocks look a little more natural.

    The ambient light level is added to the entire scene on top of any other lighting.  If our sunlight is pure white then our entire scene will have a blue tint when we add in the blue ambience.  Just to counteract this we need to tint the sunlight a little bit with a color that is low in blue light.  RGB 255,255,0 is bright yellow, and guess what color sunlight tends to be?  It usually range anywhere from yellow to pink depending on the time of day and atmospheric conditions.

    *The high school I attended Is actually named after this mountain in California.

    Since our skybox already has a nice orange glow in some places, I decided to use that for our sun color.

    Because my saturation levels are kept in check the whole scene now has a nice orange tint to it, while retaining the original reds, yellows, and greens of the environment.  The orange counteracts the ambient blue in areas that have direct sunlight, while a subtle blue tint is retained on shaded surfaces.
    Post-Process Effects
    My basic stack of post-processing effects I use are SSAO and standard bloom.  I also add the iris adjustment effect for outdoor scenes, as this allows us to simulate a greater range of lighting intensities.  Here is the final scene with these post-process effects added.

    Notice the whole scene has an overall theme of blue, orange, and very subtle green/brown.  The bloom filter tends to increase perceived color saturation a bit, so the blue shadows are clearly visible now when contrasted to the orange glow.  Compare this to our image at the beginning of this article.  Which looks better to you?
    This is the process I use for pretty much any game level I make, and it will make your games look 200% better.
  8. Josh
    I can now load models in Leadwerks Engine 3 (as of this morning):

    Edit - Here's a demonstration of buffers working (as of this afternoon):

    Edit - And here's a comparison of a multisampled buffer next to a regular one (as of this evening):

    It's nice to see a feature in Leadwerks 3.0 that 2.0 doesn't have.
     
    I'm getting my iMac this week. I'm going for the dual core 3.2 ghz with an upgrade to an ATI Radeon 5750. Mac is still using OpenGL 2.1, and I have no idea how good the drivers are, but at least I know it will be stable. I am working with the OpenGL 3.3 renderer right now, which requires a Shader Model 4 card. OpenGL 4.0 is just like 3.3, with a few added features, and it will need a separate renderer. So right now we are looking at:
    -OpenGL 4.0
    -OpenGL 3.3
    -OpenGL 2.1 (for Mac)
     
    Those versions are just variations of one another, and I know OpenGL pretty well, so it's mostly just a matter of copying and pasting code. Since I have to deal with three versions of OpenGL anyways, it's not a big deal to add an OpenGL 1 renderer using the fixed function pipeline. Then of course we have OpenGL ES for the mobile platforms, but I won't be dealing with that myself. A DirectX renderer will only be needed for XBox 360, when the time comes.
     
    That's all for now. The material / shader / model systems are pretty crucial to LE3, especially how they are designed to be reloadable, so I have plenty of work to do! The most critical features in LE3 are the asset handling and the interaction system. In LE2 we created a system whereby programmers could share programmed game objects with Lua script, but we found that without an official visual interaction system, there were limits to how interesting your game components could get. With LE3, a totally new visual system will provide a framework with which your game components can interact, so everyone can create complex game interactions. In plain terms, that means I can easily drop a character into the scene, and set it up so when they die, a door opens, or something like that...with no programming.
     
    By the way, I recommend catching "The Social Network" in theaters. Some of the dialog is cheesy, but it's an interesting look into tech startups (and an unflattering portait of Mark Zuckerberg). The most interesting parts to me were the scenes in Palo Alto, which were a lot more familiar to me than the Boston setting. Plus, the soundtrack is by Trent Reznor:
     

    http://www.youtube.com/watch?v=qy8qDXQQZ3U
  9. Josh
    I think of the Leadwerks community as a big loosely affiliated collaborative game studio. I see people working together to add value in different ways. Some are dedicated to a single project, and others bounce around and participate in different projects. I like that everyone can just find what they like doing best and provide value in that way.
     
    Voluntary collaboration, without being too restrictive, allows us to achieve economies of scale, while diversifying risk. Basically that means it's more cost-effective to batch some things together, like promotion and content production. At the same time, we remain innovative and keep taking risks with new ideas.
     
    We're going to build Leadwerks into a series of educational materials and services that is capable of taking any person of reasonable intelligence and commitment from total noob to professional game developer. I want to have a well-defined series of lessons that once completed, tell you everything you need to know to program games, design artwork, or manage a team of developers working on a title. Leadwerks can help with promotion and distribution. You'll see a lot more of this idea with the Leadwerks Workshop on Steam.
     
    The steps below plot the progress a Leadwerker goes through as they gain xp:
     
    Education
    Tutorials and documentation

    Collaboration
    Communication tools on Leadwerks.com
    Steam Workshop

    Promotion
    Games page
    Leadwerks feeds and social media accounts

    Distribution
    TBA

     
    I think more can be done in each of the areas above as we continue to grow. Just some thoughts this evening.
  10. Josh
    I finally got a textured surface rendering in Vulkan so we now have officially surpassed StarFox (SNES) graphics:

    Although StarFox did have distance fog. ?

    Vulkan uses a sort of "baked" graphics pipeline. Each surface you want to render uses an object you have to create in code that contains all material, texture, shader, and other settings. There is no concept of "just change this one setting" like in OpenGL. Consequently, the new renderer may be a bit more rigid than what Leadwerks 4 uses, in the interest of speed. For example, the idea of 2D drawing commands you call each frame is absolutely a no-go. (This was likely anyways, due to the multithreaded design.) A better approach for that would be to use persistent 2D primitive objects you create and destroy. I won't lose any sleep over this because our overarching design goal is performance.
    Right now I have everything hard-coded and am using only one shader and one texture, in a single graphics pipeline object. Next I need to make this more dynamic so that a new graphics pipeline can be created whenever a new combination of settings is needed. A graphics pipeline object corresponds pretty closely to a material. I am leaning towards storing a lot of settings we presently store in texture files in material files instead. This does also resolve the problem of storing these extra settings in a DDS file. Textures become more of a dumb image format while material settings are used to control them. Vulkan is a "closer to the metal" API and that may pull the engine in that direction a bit. That's not bad.
    I like using JSON data for file formats, so the new material files might look something like this:
    { "material": { "color": "1.0, 1.0, 1.0, 1.0", "albedoMap": { "file": "brick01_albedo.dds", "addressModeU": "repeat", "addressModeV": "repeat", "addressModeW": "repeat", "filter": "linear" }, "normalMap": { "file": "brick01_normal.dds", "addressModeU": "repeat", "addressModeV": "repeat", "addressModeW": "repeat", "filter": "linear" }, "metalRoughnessMap": { "file": "brick01_metalRoughness.dds", "addressModeU": "repeat", "addressModeV": "repeat", "addressModeW": "repeat", "filter": "linear" }, "emissiveMap": { "file": "brick01_emissive.dds", "addressModeU": "repeat", "addressModeV": "repeat", "addressModeW": "repeat", "filter": "linear" } } } Of course getting this to work in Vulkan required another mountain of code, but I am starting to get the hang of it.
  11. Josh
    Leadwerks Game Player is now in beta. If you recently posted a game on our site or entered one of the recent game tournaments, you were sent a pre-release Steam key to access the application.
     

     
    Leadwerks Game Player provides you with a route to self-publish your games to Steam Workshop. Because it is a free application, the entire Steam userbase of 125 million people can access your game. Your Lua game is run in sandboxed mode using an interpreter application we provide, so that Steam users can freely download and play games without fear of computer viruses. Your game is playable on Windows and Linux (including SteamOS), even if you didn't develop it in Linux.
     
    Sharing Your Game
    Share your game with your friends and fans with a simple link that installs the game player (about 4 MB) and downloads and plays your game automatically:

    steam://run/355500//405800821
     
    Or the more hyperlink-friendly variation:
    http://www.leadwerks.com/run?405800821
     
    When running, your game appears as a normal Steam application, shown here with the overlay enabled:

     
    This allows you to get your game in front of players and start building a community of fans.
     
    Publishing
    The next update to Leadwerks Game Engine (beta branch only) adds the ability to self-publish games to Steam Workshop. These will appear in the Leadwerks Game Player Workshop, as it is a separate application.
     
    To publish your game, first publish a standalone game from the project manager. After that, open the Workshop > Publish File menu item and select the game data zip file as the uploaded file. Be sure to select "Game" as the type of file you are publishing. This process will be streamlined as we near launch.
     
    After publishing, I must manually add your game to the interface, as the Steam web API cannot be used while the application is still unreleased. Please contact me to add your game after publishing.
     
    You may need to opt into the Steam client beta (not the Leadwerks beta branch) to successfully publish games, as cross-app Workshop publish is a relatively new feature.
  12. Josh
    In Leadwerks 4, render-to-texture was accomplished with the SetRenderTarget command, which allowed a camera to draw directly to a specified texture, while hiding the underlying framebuffer object (FBO). In the new engine we have a bit more explicit handling of this behavior. This is largely in part due to the use of Vulkan's bindless design, which greatly improves the context-binding design of OpenGL. The Leadwerks "Buffer" class was never documented or officially supported because the underlying OpenGL functionality made the system pretty messy, but the design of Vulkan simplifies this aspect of graphics.
    We have seen that the Framebuffer classes replaces the LE4 context. I've added a TextureBuffer class which can be created similarly:
    shared_ptr<TextureBuffer> CreateTextureBuffer(const int width, const int height, const int colorcomponents = 1, const bool depthcomponent = true, const int samples = 0); Once a TextureBuffer is created, you can set a camera to target it for rendering:
    camera->SetRenderTarget(texbuffer); You can also apply its color component(s) to a material:
    material->SetTexture(texbuffer->GetColorBuffer(0), TEXTURE_BASE); You could also retrieve the depth buffer and apply that to a material, rendering the scene from the top down and using the depth in a rain or snow shader, for example.
    This functionality will later be used to render the GUI system to a texture for use in VR or with in-game menus painted onto 3D surfaces.
    Like everything with Vulkan, this involved a very long process of figuring out everything we need to use, discarding the things we don't, and packaging it up in a structure that is actually usable by the end user. However, once all that is done we have a very powerful system that is optimized for exactly the way modern GPUs work. Here is a small sample of some of my code, just to give you an idea of how complicated this stuff is:
    for (auto pair : visset->cameravislists) { auto cam = pair.first; clear[1].color = { cam->clearcolor.r, cam->clearcolor.g, cam->clearcolor.b, cam->clearcolor.a }; auto light = dynamic_pointer_cast<RenderLight>(cam); if (light == nullptr and cam->rendertarget == nullptr) continue; renderpass[0] = device->shadowpass; renderpass[1] = device->renderpass[CLEAR_COLOR | CLEAR_DEPTH]; int faces = 1; if (light) { if (light->description.type == LIGHT_POINT) faces = 6; } if (MULTIPASS_CUBEMAP) faces = 1; for (int face = 0; face < faces; ++face) { renderPassBeginInfo.clearValueCount = 2; if (light) { renderPassBeginInfo.renderPass = device->shadowpass->pass; if (light->description.type == LIGHT_POINT and MULTIPASS_CUBEMAP == true) { renderPassBeginInfo.renderPass = device->cubeshadowpass->pass; } renderPassBeginInfo.framebuffer = light->shadowbuffer[face]->framebuffer; renderPassBeginInfo.renderArea.extent.width = light->shadowbuffer[face]->size.width; renderPassBeginInfo.renderArea.extent.height = light->shadowbuffer[face]->size.height; } else { renderpass[0] = device->renderpass[CLEAR_COLOR | CLEAR_DEPTH]; int cc = cam->rendertarget->CountColorTextures(); renderPassBeginInfo.renderPass = device->rendertotexturepass[cc][int(cam->rendertarget->depthtexture != nullptr)]->pass; renderPassBeginInfo.framebuffer = cam->rendertarget->framebuffer; renderPassBeginInfo.renderArea.extent.width = cam->rendertarget->size.width; renderPassBeginInfo.renderArea.extent.height = cam->rendertarget->size.height; } vkCmdBeginRenderPass(commandbuffers[currentFrame]->commandbuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); RecordDraw(currentFrame, cam, pair.second, renderpass[0], face); commandbuffers[currentFrame]->EndRenderPass(); if (light) commandbuffers[currentFrame]->BindResource(light->shadowbuffer[face]); //Copy output to render texture if (cam->rendertarget) { for (int n = 0; n < cam->rendertarget->colortarget.size(); ++n) { if (cam->rendertarget->colortarget[n] != nullptr) { commandbuffers[currentFrame]->TransitionImageLayout(pair.first->rendertarget->colortexture[n], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, -1); commandbuffers[currentFrame]->TransitionImageLayout(pair.first->rendertarget->colortarget[n], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, -1); VkImageCopy regions = {}; regions.dstOffset = {0u,0u,0u}; regions.extent = { uint32_t(cam->rendertarget->colortarget[n]->size.x), uint32_t(cam->rendertarget->colortarget[n]->size.y), 1u}; regions.srcOffset = regions.dstOffset; regions.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; regions.dstSubresource.baseArrayLayer = 0; regions.dstSubresource.layerCount = 1; regions.dstSubresource.mipLevel = 0; regions.srcSubresource = regions.dstSubresource; vkCmdCopyImage(commandbuffers[currentFrame]->commandbuffer, cam->rendertarget->colortexture[n]->vkimage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, cam->rendertarget->colortarget[n]->vkimage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &regions); commandbuffers[currentFrame]->TransitionImageLayout(pair.first->rendertarget->colortarget[n], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, -1); } } } } } Below is a simple Lua program that sets up a scene with two cameras, and renders one camera to a texture buffer which is displayed on the middle box itself.
    --Get the primary display local displaylist = ListDisplays() local display = displaylist[1]; if display == nil then DebugError("Primary display not found.") end local displayscale = display:GetScale() --Create a window local window = CreateWindow(display, "Render to Texture", 0, 0, math.min(1280 * displayscale.x, display.size.x), math.min(720 * displayscale.y, display.size.y), WINDOW_TITLEBAR) --Create a rendering framebuffer local framebuffer = CreateFramebuffer(window); --Create a world local world = CreateWorld() --Create second camera local texcam = CreateCamera(world) texcam:SetClearColor(1,0,1,1) --Create a camera local camera = CreateCamera(world) camera:Move(0,0,-2) camera:SetClearColor(0,0,1,1) --Create a texture buffer local texbuffer = CreateTextureBuffer(512,512,1,true) texcam:SetRenderTarget(texbuffer) --Create scene local box = CreateBox(world) local cone = CreateCone(world) cone:SetPosition(2,0,0) cone:SetColor(1,0,0,1) local sphere = CreateSphere(world) sphere:SetPosition(-2,0,0) sphere:SetColor(0,1,0,1) --Create render-to-texture material local material = CreateMaterial() local tex = texbuffer:GetColorBuffer() material:SetTexture(tex, TEXTURE_BASE) box:SetMaterial(material) --Create a light local light = CreateLight(world,LIGHT_DIRECTIONAL) light:SetRotation(35,-55,0) --Main loop while window:Closed() == false do texcam:SetPosition(0,0,0) texcam:Turn(0,1,0) texcam:Move(0,0,-2) world:Update() world:Render(framebuffer) end Here is the result. Look how simple it is to control this powerful system!

  13. 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:

  14. Josh
    One of the coolest things I'm seeing in Leadwerks 3 is a lot of minigames being made. These are finished products, without super high expectations, but they are complete, don't take long to make, and some are quite fun. Seeing these gave me an idea for a feature that's been in development in the background for some time, and when you see what it does, it will explain some of the design decisions I've made over the last few months.
     
    The next build on the beta branch on Steam will support Lua sandboxing. Lua games can be sandboxed by passing "-sandbox" in the command line. This prevents the application from accessing file write and OS commands, and prevents Lua from loading external libraries. When games are launched from the editor, this is turned on by default:

     
    Why is this cool? Sandboxing makes Lua code safe to run on any computer. Along with assets, games can now be published in the Steam Workshop beta. The editor has a new game player that lets you select a game you are subscribed to and play it, like the ones below from YouGroove and Rick:

     
    This minimizes the editor window and launches the Lua executable found in the "Templates\Lua" folder. The selected game is passed to the executable in the command line, and the executable loads all game assets, scripts, and maps from an encrypted zip file containing the game contents. Because our own executable is being run with only sandboxed Lua code, it's safe to run any game in the Workshop. And most of the Lua games found in the downloads section of this site work with no changes, due to the stability and backwards compatibility of the Leadwerks 3 API.

     
    We're filling the Workshop with content right now, including assets from "The Zone" project from Leadwerks 2, as well as third party content from popular artists. When the Workshop launches next month, you will also be able to publish your Lua games straight to Steam, with no approval process and no waiting period. You can update your game at any time to keep all your fans up to date, and you can safely play other people's games while always running the latest build of the Leadwerks executable.
  15. Josh
    The revision of our vehicle system has been a long time coming, and I am happy to say the wait will soon be worthwhile.  The new system uses a hyperrealistic slip differencial system to adjust the power given to each wheel.

    The results are a clear cut above any game vehicle physics you've ever seen.
    I am also taking steps to make the vehicle system easier to use.  The AddTire() command can now accept an entity as a parameter for the tire object.  This would typically be a child limb found within a loaded car model.  The object's size can be used to calculate the exact width and radius for the tire.  This simplifies the vehicle setup code so you just load up the model, find the wheel limbs, add tires and axles, and build the vehicle:
    //Load car model auto chassis = Model::Load("Models/Desert Patrol/Desert Patrol.mdl"); chassis->SetMass(2000); vehicle = Vehicle::Create(chassis); //Add tires vehicle->AddTire(chassis->FindChild("WheelFL"), true); vehicle->AddTire(chassis->FindChild("wheelFR"), true); vehicle->AddTire(chassis->FindChild("WheelBL14")); vehicle->AddTire(chassis->FindChild("WheelBL15")); //Add axles vehicle->AddAxle(0, 1); vehicle->AddAxle(2, 3); //Finalize the vehicle vehicle->Build(); It's very easy to load up a model and turn it into a working vehicle without worrying about the exact tire sizes and positions.

    You no longer have to position the visible tire models yourself to match the tire orientations, as this is all done automatically.  So we've taken a very complicated advanced system and made it very accessible and quick to get running.
  16. Josh
    I signed up for a free year of OnLive. I received a response email within 24 hours, so I think they just are choosing applicants based on connection speed and location. I've been extremely skeptical of this service, but I can report that it works, and it doesn't suck. I can play UT3 on my netbook. There is some slight lag, but it's not bad. Fast mouse looking can amplify it, so I slowed down my mouse speed to compensate. I had no trouble getting headshots with the sniper rifle, and the gameplay experience was very good. As far as technical performance, OnLive has delivered.
     
    As for the product itself, I don't see any reason to jump onboard yet. Wi-fi connections aren't allowed, so the fun of using my netbook anywhere in the house is mitigated. Without that, there's no reason not to use my desktop PC. The lineup of games is very limited. No Crysis, and it looks like the servers have the games running on low to medium settings. This puzzles me, because the quality settings the servers run with should be trivial. That's the whole point of OnLive. With the games and settings they are offering right now, you could get the same results with a five year old PC.
     
    The pricing model is where OnLive fails. After the first year, you pay $4.95 a month for the service. On top of that, you have to "buy" each game you play, but you don't really own it, and the game may be taken down after 2013. With a revolutionary new delivery system like this, the choice to use an outdated purchasing model is baffling. What if you had to pay a monthly cable TV bill, and then "buy" each show you wanted to enable? It doesn't make sense. OnLive should charge a higher monthly fee, around $29.99-49.99 for access to all games on their servers. OnLive would take their cut of the sale, and the rest would be divided up among the game providers based on the percentage time players spent in their game. This would encourage developers to make games with long-term replay value. It would create a continuous revenue stream for developers, instead of just making money off one-time purchases. It would lessen the complaints people have when an old game if retired off OnLive's servers. And finally, it would deliver a lot of value to the customer. Which would you rather pay for, a $200 XBox plus $60 for a game, or pay $40 this month and play every game? The choice for a lot of people would be obvious. Hopefully OnLive will come to see this. I am surprised it isn't already obvious to them.
     
    As of right now, I don't know who would use this service. Who is the target market? People who can't afford a decent PC, but still have $50 to spend on a game they don't own? Maybe some Mac owners will pay for it. I think they should be targeting console players who want the ultimate graphics, but the OnLive console isn't available yet.
     
    Still, OnLive has delivered from a technical standpoint, and they may become something amazing and unique. I look forward to seeing what it might grow into.
  17. Josh
    Previously I talked about array textures acting as "bindless" textures, but there is an actual OpenGL extension that allows a shader to access any texture without the stupid texture binding / slot convention that limits OpenGL 4.0 shaders to a minimum of 16 textures. Implemenation was surprisingly easy, although Mac hardware apparently does not support this extension. When combined with the multi-draw commands in OpenGL 4.3, and some other tricks, it is possible to render multiple sets of objects in one single draw call. Below you can see six instances of three different objects, with different materials applied to them, all rendered in one single command, for ultimate performance.
    This is basically the final goal of the whole crazy architecture I've been working on for over a year.
    I will test this a bit more, release an update for the new engine beta, and then at that point I think it will be time to move everything over to Vulkan / Metal.

  18. Josh

    Articles
    You probably have noticed that our entire community has been migrated from the leadwerks.com domain to our new ultraengine.com domain. In this article I am going to describe recent changes to our website, the process by which these decisions were made, and the expected outcomes. These are not just superficial changes, but rather it is a fundamental restructuring of the way our business works. This is the execution of a plan I have had for several years.
    When we first starting selling on Steam and I saw the revenue it was bringing in, my reaction was to focus entirely on Steam and try to align everything we did to that. The idea was that if I could bring that advantage to you, we would all benefit from the massive gaming traffic that goes through Steam. I replaced many of our community features with Steam-centric equivalents. Our website gallery, videos, and downloads were replaced by the Steam equivalent. To view this content on our website I used the Steam web API to hook into our application ID and retrieve content.
    The screenshots and videos were a success. Leadwerks Editor allows publishing a screenshot directly to Steam, and we have gained a very big collection of screenshots and videos on Steam. However, there are two problems that have caused me rethink this approach:
    First, when it came to monetization, Steam seems to be a one-trick pony. Try as I could, Steam users just don't buy things through Steam Workshop. Our own sales in the web-based Marketplace are outperforming Steam.

    Second, Steam has flooded their marketplace with new titles. This incentivizes competition for digital shelf space. Instead of investing in Steam features for one application ID, it makes more sense to release multiple products on Steam and not tie yourself to one Steam application ID. Valve's position seems to be that you are responsible for driving traffic to your game, but if that is the case why are they still charging 30%? Our situation on Steam is still good, but I am not throwing everything 100% into Steam in the future and I prefer to drive traffic to our store on our own website.

    Based on what I have seen, it makes sense to move our center of activity back to our own website. Recent technological advances have made this easier. Cheap file storage backend systems have eliminated the expenses and technical problems of storing large amounts of user data. RSS feed importers have allowed us to hook into the Steam web API to feed all our Steam screenshots and videos into our own system.
    Videos
    We have a new video section on our site. You can paste a YouTube link through our web interface or upload a video file directly. Any videos you publish on Steam will be automatically fed in as well. You will notice in the tutorials section I am now hosting tutorial videos on our own site. They are also uploaded on YouTube, but I am not relying on YouTube anymore for video hosting.

    In the future I plan to support user-created paid video tutorials, with the same rules as paid items in the Marketplace.
    Gallery
    A new screenshot gallery is up, with images hosted on our own site again. I hope to find a way to migrate all our content on Steam into this system, like we did with videos. I also want to bulk upload all our old screenshots from before Steam.
    The Steam-based gallery and videos can still be viewed on the leadwerks.com website, as well as the Leadwerks documentation.
    Marketplace Games
    The Marketplace we have now is a 2.0 version of our original system before Steam, with a new Games category. Back in the days before Steam it always amazed me that Furious Frank had over 20,000 downloads. This was from the days before itch.io and gamejolt, and there was a big appetite for indie games. The Games database of our website never reached that level, and I think the reason was that we should have focused on the content. If people want to watch videos they will go to the videos section. If people want to download free games they will go to the Games category in the Marketplace. Having a customized page on our website with a lot of information and links all in one place is about as pointless as having a Facebook fan page. There's no reason for it, all it does is slow down the delivery of the actual content. It looks kind of cool, but I think the viewer just wants to get to the content (download the game, watch videos, view screenshots) instead of wading through a lot of custom CSS pages. If you want to drive traffic to your website or to your Steam page, post a video and put links in the description where you want the viewer to go next.
    In addition to uploading free games, you can now sell your games in the Marketplace. I have plans to attract a lot of new traffic to the site in 2021, so maybe your games can get more sales at the same time. The same 70/30 split we use for Marketplace assets applies to games.
    Furious Frank is starting over from zero and I realize he would have been enjoyed by over 100,000 players had I not pushed our traffic towards Steam so hard.
    Email Marketing (and leaving social media behind)
    At a startup event I attended years ago, one of the speakers told me that email was actually their best marketing tool. I was kind of surprised because to me it seemed archaic, but that conversation stuck in my mind. According to conventional wisdom, if you want to get the word out about your product you should crete an Instagram account, upload your images, and then when you invariably get no traffic you should blame yourself because your content sucks. Who is pushing this "conventional wisdom"? It is being pushed by giant tech companies that seek to absorb and monetize all your content, and a network of parasitical "gurus" who want to sell you useless advice and then blame you when it fails. This is not the way online customer acquisition actually works.
    I started looking at traffic on our social media accounts and comparing it to email and web traffic, and the results are shocking. Our email newsletters regularly result in 30x more clicks than anything I write on social media. Not only are they failing to bring in an acceptable level of traffic, Twitter and even Steam are actively preventing us from reaching our customers by censoring our content.
    Email is the only direct line of communication you have with your own customers. All third-party middlemen have the potential to abuse their position. They will flood their marketplace with products, change their algorithms, arbitrarily censor or shadowban content. The only thing that will provide a counterweight to that abuse is a good BATNA. If you don't have that you can expect to be treated badly. (It's really a miracle that email was invented early enough to become a common open standard. This would never happen today. "Blue Sky" is probably a sabotage effort.)
    In that light, the advice I got makes a lot of sense. Once I realized this I stopped posting on Facebook and Twitter and just left a pinned message directing people to the mailing list:

    Our new website also features a mailing list sign-up form featured prominently in the website footer.

    Instead of wasting time shouting into the wind on (anti)social media I am going to instead focus on writing quality articles that will be posted on our site and sent out to the email list.
    Store
    Valve has made it clear that game developers should not rely on Steam alone to drive traffic to their game. Okay, well if I am responsible for bringing in traffic, I am going to direct it to my own store, not to Steam.
    The MBA in me realizes two things:
    Getting a user's email address is good and has a quantifiable value. Getting a user's credit card system stored in our system is even better. (It doesn't actually store credit cards on our server, it stores a token that can only be used with our domain.) These two steps are serious hurdles to overcome for any web store. Now that I am selling Ultra App Kit directly on our own site, I have seen an increase in sales of items in our Marketplace. This is not a coincidence. People buy one thing and then it becomes a habit. A subscription option will be available for future software products. All new software I release is going to require an initial sign-in to your forum account. We have tens of thousands of users on Steam that I have no email addresses for or ability to contact, and that is not going to work going forward. (I will make sure an override is built into the software that can be activated by a dead man switch.)

    This system gives me the ability to offer software products under a subscription model for the first time ever. This is preferable from my point of view, but I understand it's not for everyone and a conventional software license will also be available.
    We also have an automated system to send out Steam keys, so I am now able to sell Steam keys directly in our store. When you order you will receive an email with a link to retrieve your key. Once you enter the key in Steam it is added to your Steam account just as if you bought it on Steam.
    To make payments easier we are now accepting PayPal and cryptocurrency payments, in addition to credit cards.
    (Valve clearly recognizes a problem with visibility on Steam and is desperately trying to convince you to stay engaged in their system so they can take their 30%. I don't mean to say they are bad guys, I am just saying in any partnership both parties will have some divergent interests and must stick up for themselves. The day that mine is the only company selling products on Steam is when I will consider going Steam-exclusive again. What indie developers should be doing right now is selling their own games on their own websites, in addition to third-party stores like Steam.)
    Rolling Out Ultra Engine (Leadwerks 5)
    Breaking off the GUI features of the new engine and releasing it early as the standalone product Ultra App Kit was a great idea because it allows me to implement all these things early, test them out, and ensures a smoother release of the finished 3D engine later this year. The basic theme we see here is that these social and gaming platforms are no longer doing their job effectively and we must build something of our own. Withdrawing our content from them and building up our own website only makes sense if there is a way to drive more traffic here. If Steam is flooded and social media is saturated, how can we attract traffic? Email is good for engaging customers you have already made contact with, but how do you attract new people in large numbers? I have an answer to that, but it really deserves a whole article itself.
    Conclusion
    Here is where we were before:
    Domain name no one could pronounce or spell. It was literally impossible to tell someone to go to our website without explaining the spelling. User content hosted on Steam and YouTube Almost all sales through Steam Ineffective outreach through social media Single product for sale with perpetual free upgrades No ability to collect customer information Here is where we are now:
    Domain name that can easily spread by word of mouth Most user content hosted on our own website Direct sales through our own website and many third-party stores Effective outreach through email (and other means I will talk about later) Ability to sell annual paid updates or subscription model Growing customer database of people I can directly contact I hope I have shown how all these changes were not just random decisions I made, but are part of a "holistic" strategy, for lack of a better word.
  19. Josh
    Leadwerks has historically had a small group of customers outside of the game industry who use our software for simulations, training, and visualization.  Customers using our software products include NASA, Lockheed Martin, Northrop Grumman, and the British Royal Navy.  Today I am happy to announce that in response to overwhelming demand we are now offering our services to build custom VR applications with Leadwerks.
     
     
    This puts us in head-to-head competition with other services firms who are mostly using the Unity3D engine to put out quick results.  However, longstanding design decisions going back years have put Leadwerks Software in a position that gives us very strong advantages in the VR market.  In this article I will explain how we are leveraging our unique competitive advantages to provide the most compelling results for your VR project.
    Leadwerks vs. Unity3D for Virtual Reality
    Most of our competitors have tried to take shortcuts by building on a platform with severe limitations, using the Unity 3D engine together with the C# programming language. This 3D engine is primarily used for mobile games, and the C# programming language was originally created for event-driven business applications.
    We on the other hand have built our own 3D development system that is specifically designed to capture the maximum capabilities of VR.  Our 3D engine is built specifically for high-end PCs, with graphical fidelity and performance as our overarching principles. We use the C++ programming language which is the standard for any computationally intensive code, including operating systems, device drivers, high-frequency trading software, and virtual reality applications, which must operate at a steady 90 frames per second to prevent nausea. Our development approach brings several significant competitive advantages we can now offer to you.
    C/C++ Interoperability
    Virtually all major scientific and engineering libraries like MATLAB, etc. are written in C or C++.  Because our VR development platform is written in pure C++ we can seamlessly integrate with all of your existing C and C++ code. For example, actual satellite control code could be compiled into a simulation and run seamlessly to test how the spacecraft would react to a variety of simulated conditions. All scientific and engineering code libraries are easily accessible from a Leadwerks project.
     
    Competitors using C# and the Unity 3D engine will encounter roadblocks when they attempt to interface with C/C++ code. An intermediate wrapper has to be written that converts object-oriented code into procedural commands. This process is time-intensive and prone to breakage when APIs change with new versions. Integration of C/C++ code with Leadwerks, on the other hand, is instantaneous and seamless.
    Performance
    Nausea is a serious consideration in VR. If a discrepancy exists between the inputs received by the operator’s ocular and vestibular systems, it will result in motion sickness. An engineering tool designed to be used for long periods of time must maintain a steady 90 frames per second, allowing only 11 milliseconds for each frame render. Unfortunately, C# is a memory-managed language meaning it suffers overall slower performance, as well as periodic pauses in program execution while garbage collection is performed. All of our code is written in C++ and will perform at the maximum speed allowed by the hardware. This allows us to create richer VR applications with expanded capabilities while our competitors will run into performance problems that cause unpleasant physiological symptoms.
     

    Benchmark showing execution time of C++ vs. C#.
    Source: https://www.codeproject.com/Articles/212856/Head-to-head-benchmark-Csharp-vs-NET
    Source Code Modification
    Because we developed our own 3D engine we have full access to the entire source code and can make modifications to expand its capabilities (5). For example, we learned that some aerospace clients were experiencing problems with 32-floating point precision in some applications, so we re-compiled our software using 64-bit floating points, raising the maximum area we can simulate up to one cubic light year with sub-millimeter precision. Because our competitors do not have source code access to the 3D engine they are using, their ability to elastically scale their capabilities and customize their 3D engine for your needs will be greatly impeded.
    Accuracy of Simulated Physics
    Our software features a fast and stable Newtonian physics system that provides the most realistic physics simulation possible at real-time speeds. As the video above demonstrates, this can be used to simulate robotic arms and other moving mechanical features with a high degree of realism.
     
    The Unity physics system was designed for games and runs on the graphical processing unit (GPU). GPUs are good at performing massive parallel processing computations but are not good at problems that involve a lot of data exchange. Unfortunately, colliding objects are a problem that involves a high degree of data exchange between threads, so the accuracy of the simulation is compromised. This has two significant consequences. First, physics in Unity tend to be much less stable than in Leadwerks, making it difficult to simulate complex jointed systems like a robotic arm. A video showing the difference can be seen here.
     

    Rigid body stacking test: Leadwerks physics (green) are stable while Unity physics (yellow) spontaneously collapse.
    Second, physics in Unity are non-deterministic. This means that each time a simulation is run, the result will be different, making it very difficult to predict outcomes. The Leadwerks physics system is deterministic and will provide the exact same result each time it is run, even if new objects are introduced into the simulation.
    The competitive advantages we can put to work for your VR project are summarized below.  Simply put, we can build applications that are bigger, faster, and have more capabilities.
     
      Other firms using Unity
    Leadwerks VR Services
    Primary platform of 3D engine
    Mobile phones
    High-end PCs
    C/C++ Interoperability
    Requires C# wrapper
    Seamless
    Performance
    Slower with GC pauses, results in nausea
    Fastest possible performance
    3D engine source code modification
    No
    Yes
    Physics simulation
    Unstable, non-deterministic
    Stable, deterministic
    Maximum range with sub-mm precision
    Eight kilometers
    One light year
    If you are interested in taking advantage of our capabilities to build VR applications send us an email, or catch me at I/ITSEC later this week.
  20. Josh

    Articles
    I've been working hard getting all the rendering features to work together in one unified system. Ultra Engine, more than any renderer I have worked on, takes a lot of different features and integrates them into one physically-based graphics system. A lot of this is due to the excellent PBR materials system that Khronos glTF provides, and then there are my own features that are worked into this, like combined screen-space and voxel ray traced reflections.
    Anyways, it's a lot of difficult work, and I decided to take a "break" and focus something else for a few days.
    Before Leadwerks was on Steam, it had a web installer that would fetch a list of files from our server and any files that were missing, or were newer than the locally stored ones. There was no system for detecting updates, you just pressed the update button and the updater ran. The backend for this system was designed by @klepto2 and it functioned well for what it needed to do.

    With Ultra App Kit, I created a simple tool to generate projects. This introduced the account authentication / signin system, which was sort of superfluous for this application, but it was a good way to test it out:

    With Ultra Engine, I wanted some characteristics of both these applications. I wrote a new backend in about a day that handles updates. A PHP script authenticates the user and verifies product ownership, fetches a list of files, and retrieves files. Since C++ library files tend to be huge, I found it was necessary to add a compression system, so the script returns a zip compressed file. Of course, you don't want the server to be constantly creating zip files, so it caches the file and updates the zip only when I upload a new copy of the file. There's also a cache for the info retrieval, which is returned in JSON format, so it's easy to read in C++.
    For the front end, I took inspiration from the Github settings page, which I thought looked nice:

    And here's what I came up with. Projects will show when they are outdated and need to be updated (if a file in the template the project came from was changed). Each of the sections contains info and links to various topics. There's a lot there, but none of it feels extraneous to me. This is all made with the built-in GUI system. No HTML is used at all:

    The Invision Power REST API is extremely interesting. It allows authentication of accounts and purchases, but it can be made to do a lot of other things.
    Post a forum topic: https://invisioncommunity.com/developers/rest-api?endpoint=forums/topics/POSTindex Upload an image to the gallery: https://invisioncommunity.com/developers/rest-api?endpoint=gallery/images/GETindex Download a file: https://invisioncommunity.com/developers/rest-api?endpoint=downloads/files/GETitem Unlock achievements: https://invisioncommunity.com/developers/rest-api?endpoint=core/members/POSTitem_achievements_awardbadge None of that is very important right now, but it does provide some interesting ideas for future development of the game engine.
  21. Josh
    Their prices are more than 250% the price of a comparable PC. Even their "most expensive" laptop is using a budget GPU! So for less than half the price, you can actually get a laptop with a much better GPU!
     
    $999:
    http://www.newegg.co...=laptop%209800m
     
    $2499:
    http://store.apple.c...mco=MTM3NDcyOTc
     
    Just for fun, I checked all the most expensive options. The grand total was $7305.35. Who spends $7000 on a laptop with a budget GPU???
     
    I can't believe how dense their management is. It's as if they don't want to succeed.
  22. Josh
    Smoothing groups are one of the most frequently requested features for 3D World Studio, so I am happy to show you their implementation in Leadwerks3D, finally. Smoothing groups are usually stored as a bitwise flag. When two faces share a vertex at a certain position, if they have one or more smoothing groups in common, their vertex normal is calculated as if they are sharing a vertex.
     
    I first attempted to write an algorithm based on edges, which worked great for cylinders but failed for geometry that had faces that influence vertex normals they are not connected to by an edge. I wrote another routine, which uses an n*n*n loop (big programming no-no, but sometimes it's necessary) and got good results with cylinders and spheres. Cones are a difficult case, and if you don't believe me, just crack out a cone in your favorite 3D modeling app and inspect the tip. I got around this problem by adding a max smoothing angle member to the brush class, which allows the smoothing algorithm to discard faces that are too 'different' from the one being processed.
     
    Here's the result:

     
    In order to make shapes like arches appear smoothed, the smoothing algorithm has to span multiple objects. This will be accomplished by first grabbing all the brushes in the nearby vicinity to the brush being processed, and then searching for vertices that occupy the same position, on faces that have a smoothing group in common.
     
    In the past, we've seen some pretty advanced modeling done with 3D World Studio, but the lack of smoothing groups always limited it. It will be awesome to see what people come up with, when those limits are removed and they can model exactly what they want.





  23. Josh
    The new docs system is mostly working now:
    https://www.leadwerks.com/learn?page=API-Reference_Object_Entity_SetPosition
     
    Features:
    Treeview list of all tutorials and API classes and functions.
    Alphabetical index (generated automatically from the table of contents).
    Search (with autogenerated search index).
    Switch back and forth between languages, with cookies to remember your preference.
    Entire examples are automatically selected when you click on them.

    Todo:
    Table of contents doesn't yet navigate.
    I would like to pretty-up the URLs using .htaccess rewrite rules.

     
    Documentation is being loaded from XML files. I find this easier than a database, which is quite opaque to me. You can access some of the XML files being used here. MartyJ even made a cool template for the data on his site here.
     
    At this point I think I can outsource the actual content creation to Upwork. This will involve copying and formatting our existing documentation into XML files, as well as updating all the examples to work by just using a main() function instead of the old App() class that we don't really need. I will be posting the job on that site soon.
  24. 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.
×
×
  • Create New...