Jump to content

Josh

Staff
  • Posts

    23,219
  • Joined

  • Last visited

Blog Entries posted by Josh

  1. Josh
    Here are some of my thoughts on how a future engine might look. I am not devoting any time to this, and it would not come to exist for several years, but it's fun to think about technology and design:
     
    I've been fascinated with the game "Fuel". This game has an enormous playable area that is streamed from the hard drive. You can drive for hours and barely cover a fraction of the map. For some reason the game has been given bad reviews. I played Motorstorm on the PS3, and I think Fuel is a lot better than that game, not even considering the impressive technical features. Anyways, I love the large open world. Fully dynamic lighting was one holy grail of game development, and I think a continuous open world is another.
     
    I would start this with a concept of "regions". Each region is a square on the grid, perhaps 1024x1024 units. The region has a terrain heightmap, terrain normal map, and an SBX file for all entities in the region. As you move around the world, regions are loaded from the hard drive in a square of playable area around you. Maybe there are 16 regions active at any given time. This number should be adjustable. Only physics and scripts of the entities within this active region are updated. When a region goes out of the playable area, it is saved to a file, and this new file is loaded if that region re-enters the playable area. So you aren't going to have enemies fighting and moving around when they are a million miles away. The engine just updates the regions nearby, because it would be simply impossible to update millions of entities. The AI in STALKER actually uses a technique similar to this, and I think they originally were planning on a huge continuous world but weren't able to pull it off. Each region can be culled on a separate thread, so this design lends itself to multithreading.
     
    So far what I have described is a big challenge, but it seems feasible. The real nightmare begins when we talk about networking. If your friend walks ten miles away and interacts with a person who's attitude towards you changes based on the interaction, well the server needs to be running two simulations. One simulation is for you and everything around you. The other simulation is for your friend and everything around them. What your friend does will change the world outside your playable area, so that when you enter that region it will be different than when you left. Now consider physics. Due to the massive distances, there would need to be two separate physics simulations running. Then they would need to be merged together when you approached each other. Wow, no wonder no one has done this yet! Fuel has a multiplayer mode, but it's just a racing game. Your actions don't have any permanent consequences on the world around you. An FPS, adventure, or RPG game will be quite different. I'm not even sure this is technically possible, without severe restrictions in flexibility.
     
    Fortunately, real-time rendering is not going to change much in the next ten years. We'll be able to do more as hardware advances, but I think we'll still be using the same basic techniques for a long time. That means that every feature and technique we add now will still be useful for a long time, even in a new engine.
  2. Josh
    Textures in LE3 give you more control. You can retrieve all or part of any mipmap of a texture to system memory, edit the texture, then send it back to the GPU. Fortunately, the engine checks the bounds of the texture so you don't have to worry about producing any blue screens of death, as can happen when you're having too much fun with GPU memory.
     
    Here's some simple code to retrieve the texture from video memory into a system memory bank, modify it, and send it back to the graphics card:

    Bank* pixels = new Bank( texture->GetMipmapSize(0) ); texture->GetPixels( pixels ); pixels->PokeByte( (x*height + y)*4, 255 ); texture->SetPixels( pixmap );
    There are overloaded functions for raw memory pointers, but the bank syntax has a little extra error checking, since this kind of thing can easily produce BSODs.
     
    If you want to get really fancy, there are additional parameters that will let your retrieve or send part of a texture to and from the GPU. This is something I use extensively in the terrain editing routines, which take place on the GPU (that's why terrain editing is so fast). I use a shader to modify part of the terrain heightmap, and then I have to retrieve the modified heightmap back to system memory. Because the textures can be pretty big, it's more efficient to retrieve a sub-rectangle of pixels instead of the whole texture.
     
    I ran into some trouble with DDS compression, as the image below demonstrates. This is what happens when you accidentally offset DDS mipmap data by four bytes. (This has been fixed):

    The texture loader can handle background texture loading, so if you want you can have those cool blurry textures when a level starts, and they get sharper after a few seconds. This cuts the texture load time down to practically zero. If you have a large scene with lots of large textures, this will be nice to cut level load times down.
     
    All media files in LE3 can be reloaded with a Reload() class function. This is necessary for some of the art pipeline features in the editor, so it's being built in from the very beginning. It is pretty cool to tap a key and watch your textures reload one mipmap at a time. This also means you can change the texture quality setting on the fly and not worry about reloading textures manually...when you change the texture quality setting the engine will automatically reload all textures that came from a file.
     
    As we saw last week, here is the proper way to load a texture and apply it to a material in LE3:

    Texture* tex = LoadTexture("brickwall01.dds"); mat->SetTexture(tex); delete tex;
    It occurred to me this can be simplified with an alternate overloaded function:

    mat->SetTexture("brickwall01.dds");
    The same can be done with shaders. If it succeeds, true is returned, otherwise false is returned:

    mat->SetShader("Shaders/simple.shader");
    So that's a nice convenient feature.
     
    It was pointed out that my Copy(int unique) syntax was confusing, and I agree, because I couldn't even remember which was which. Therefore you will have an Instance() and Copy() function for textures, shaders, entities, materials, etc. The Instance() function will act like LE2's CopyEntity(), and the Copy() function will make a unique copy that can be modified without altering the original.
     
    Texture animation is supported, out of the box. I'm using the old Quake naming convention where you add +framenumber to the end of the texture to specify an animation. For example, if you load "fire+01.dds", the engine will look for "fire+02.dds", "fire+03.dds", etc., until all frames are loaded. The texture will automatically switch frames with an animation speed you specify. It should be possible to convert AVI files into a sequence of separate frames, but I haven't looked into it yet.
     
    That's all I have for now. It feels like I am really in the thick of LE3 development now. I've already done most of the graphics stuff with LE2, so I know how to do that. What I am really looking forward to is the high-level features, particularly the script and flowgraph implementation. I like to attack unknowns first, because the more I know, the better I can design the engine. We already know we can do fantastic graphics, and I understand how that all works. It would make sense to focus on areas that I haven't developed as extensively in the past...networking, gameplay, and the art pipeline. Therefore, we may see a Leadwerks 3 beta with just basic graphics and a focus on gameplay features first.
     
    Please "like" this blog!
  3. Josh
    Last week I compiled the engine into a DLL and a static lib. That was pretty painless, and I have the project set up so it's easy to switch back and forth. I still haven't got Code::Blocks compiling right, which I will need for the Linux build. It can't seem to find any libs, but it's not too important yet.
     
    After altering the behavior of the MaxGUI canvas slightly, I was able to load the engine DLL in BlitzMax and display 3D rendering on a windowed application. It's very easy to do this in LE3:

    gadget:Byte Ptr = CreateWindowsCustomGadget( QueryGadget(canvas,QUERY_HWND) ) context:Byte Ptr = CreateContext( gadget )
    Or with C:

    Gadget* gadget = CreateWindowsCustomGadget( HWND hwnd ); Context* context = CreateContext( gadget );
    The editor is taking shape, though it is still very early. It feels like a cross between Visual Studio and Valve Hammer Editor (Worldcraft) which are both programs I like a lot.

    I knew from the beginning the only acceptable way to display assets would be a draggable, multi-select treeview with icons. For the scene hierarchy, I wanted checkboxes and icons. I looked at ways to hack the Windows treeviews and I looked at wxWidgets, and didn't find anything suitable that would work on all platforms. At last resort, I started writing my own custom control on a graphics window, and I'm getting surprisingly good results with that. The behavior is about 60% functional now, and it's faster than the Windows tree view because it's completely hardware accelerated. The only problem is that the FreeType text does not match the Windows GUI font 100% completely, even though it's using the same font and size. I'll see if there's anything I can do to make it match more closely.
     
    The reason I am spending so much time on this tree control is because drag and drop is used everywhere in the new editor. You can drag a texture onto a material, drag a material onto a model, rearrange nodes in the scene hierarchy, and even move files around on your hard drive. So it's not surprising if some customization is needed to support this functionality.
     
    Knowing the kinds of things people want to do like copy all used assets into a folder ("Publish") and import a bunch of models they downloaded off the internets, it's kind of fun to design interfaces to make development easier. My goal for the LE3 editor is to have more of an established official procedure for everything, along with extensive documentation. I've gotten lots of feedback from some fantastic artists, so I know what will help them get a large project done faster.
     
    That's all for now. I've got a lot to do!
  4. Josh
    Here's something I've been thinking about. What do you think?
     
    Apple
    Locking down OSX.
    No optical drive. The Mac software shelf at Fry's is now obsolete.
    Mac App Store.
    Gatekeeper only allows "signed" applications, by default.
    [*]Miniaturization of computer hardware, at the cost of graphical performance.
    [*]Move to non-upgradable hardware (glued-in memory).
    [*]Moving away from file system access (iCloud).
    [*]Hardware is expensive, and will always be a luxury item.


     
    Windows
    The people who made Windows 2000 and XP have retired. Microsoft does not appear to possess the same talents it once had.
    Artificial upgrade requirements for DirectX are impeding development (tessellation works fine on Windows XP with OpenGL).
    Attempting to lock down Windows like iOS.
    Intel attempting to absorb entire PC (socketless CPUs).
    Moving away from file system access.
    MS failures tend to encourage them, so I expect the trend to continue:
    Office ribbon sucked, so they added it to everything.
    Zune interface sucked, so they used it for everything.



     
    Ubuntu
    Valve and THQ coming to Ubuntu.
    Less fragmented than Windows.
    One UI (GTK).
    vs. MFC, WPF, .NET, and Modern UI.
    [*]GUI applications can be developed with one language (C++) instead of C#/Objective-C.
    [*]One environment.

    vs. Legacy/Modern division.
    [*]One version (12.10).

    vs. XP, Vista, 7, 8, and Blue.


    [*]Competition between Linux distros.

    If Ubuntu really pisses developers off, they can easily switch to a competing one like Mint.
    Can never be "locked down".
    [*]Fastest performance.
    [*]Still sucks, but getting better while Windows and Mac get worse.


     
    Maybe in five years, computing will look like this:
    Office workers will use Windows.
    Gamers wil use Linux.
    The general population will use a cheap tablet for Email and web browsing.

     
    What do you think?
  5. Josh
    Today I added the visible guides in the editor for point and spot lights. I also tested out the new FBX converter, recompiled with the 2012 FBX SDK. It works. (There are no file format changes in the 2013 FBX SDK, so this will load everything.) Our character models still have to be rescaled, so I added a resize option in the model editor. That way models can be resized and the model file saved, so you don't have to rescale a model every single time you place it in the editor. Having models I obtained from a third party who had never used Leadwerks gave me models that required slight fixing, but I didn't mind because it was a chance to test the art pipeline and improve the import process.
     
    The command reference is just about finished up. Chris just needs to add a few missing pages. I still have to write most of the editor documentation.
     
    Literally, the only thing left to program is the undo system. I expect there are still a few bugs to fix, but there's no new features that have to be implemented.
     
    We are meeting with a packaging manufacturer tomorrow...
  6. Josh
    Last week we launched our Steam Greenlight campaign to get Leadwerks into the hands of the Steam community. This week, we're rolling out the second stage of our plan with a Kickstarter campaign to bring Leadwerks to Linux. This will let you build and play games, without ever leaving Linux. The result of this campaign will be Leadwerks 3.1 with a high-end AAA renderer running on Linux, Mac, and Windows, with an estimated release date before Christmas.
     
    Valve has given Linux users a taste of PC gaming, so now it's up to us to reach the Linux community with our message. If you dig this, please help spread the word that someone is trying to put game development on Linux:
    http://www.kickstarter.com/projects/1937035674/leadwerks-build-linux-games-on-linux
     



     
    Leadwerks for Linux
    Linux is a solid and secure operating system that’s perfect for gaming, but at this time Windows remains the lead platform for PC games. We want to change that by putting the game development process right on Linux, with Leadwerks for Linux. This will allow you to build and play games without ever leaving the Linux operating system.
     
    Leadwerks is a visual tool for building any kind of 3D game, including dungeon crawlers, first-person shooters, and side-scrollers.. We want to put game development on Linux with Leadwerks for Linux. Our campaign has three goals:
     
    Linux Game Development. On Linux.
    It’s not enough just to export games to Linux. We want to put the game development process on Linux, so you can build and play games, without ever leaving the Linux operating system. We have a complete visual editor that handles all aspects of the game development process, and we’re porting it to run natively on Linux. We’re using GTK for the user interface, so our editor will look and feel like a native Linux application.
     
    We're targeting Ubuntu 12.04 to start with, and will support other distros as we make progress. You'll also be able to compile games for Windows and Mac...if you feel like sharing.
     

     
    Expand the Linux Library of Games
    Our second goal is to facilitate expansion of the Linux library of games, and encourage the production of Linux-exclusive titles. The Linux community is pretty intelligent, and they have a lot of good programmers. We think by putting the appropriate tools in their hands, it will enable them to make great Linux games.
     

    Hoodwink by E-One Studio
     
    AAA Graphics on Linux
    Leadwerks is known for having great graphics. We want to push Linux graphics beyond anything that’s ever been done. Linux is the perfect platform for triple-A graphics, because it has OpenGL performance faster than Windows or Mac. We’re taking advantage of this performance with deferred lighting, hardware tessellation, and up to 32x multisample antialiasing.
     

    The Zone by Dave Lee
     
    Steam Integration
    When Valve announced Steam was coming to Linux, that was a clear sign to us that Linux is ready for PC gaming. We’re working to integrate Leadwerks with Steam and take advantage of new features Steam offers for developers.
     

     
    Steam Workshop
    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. We’re also adding 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 Linux games to Greenlight. Just press a button, and your game files will be packaged up, ready to send to Steam.[/color]
     
    Features
    Leadwerks is a powerful yet easy to use game engine with thousands of users worldwide. Here are just a few of the main reasons we think Linux users will love Leadwerks.
     
    C++ Programming
    Programming with Leadwerks is a breeze. Underneath our visual editor lies a powerful yet easy to use programming API that can be accessed in C++, Lua, and other languages. With documentation and examples for every single command, you’ve got everything you need to make any kind of game.
     
    Visual Scripting
    For scripting, we use the Lua script language, just like in Crysis, World of Warcraft, and hundreds of other games. We’ve got a built-in script editor, so you don’t have to switch back and forth between Leadwerks and an external editor. 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. The flowgraph editor is used to connect scripted objects and make gameplay happen. This lets map designers set up sequences of events and complex gameplay, with no programming required.
     
    Constructive Solid Geometry
    Finally, we use a level editor based on constructive solid geometry. This lets everyone make 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.
     

    Combat Helo by Tricubic Studios
     
    We plan to deliver a visual editor that handles every aspect of the game development process, a powerful yet easy to use programming API, with triple-A graphics, all running natively in Linux. By working with Steam and the Linux community, our goal is to make Linux the number one platform for PC gaming. Thank you for helping us take Linux gaming to the next level.
     

    Big Five Game Hunter by Unidev
     
    Risks and challenges
    We expect to encounter some graphics driver bugs. This is always the case when you are pushing advanced graphics. Fortunately, we have good relationships with the major graphics hardware vendors, and have been able to get driver bugs fixed on other platforms in the past. Valve Software has done some of the heavy lifting for us here, by prompting the graphics hardware vendors to get their drivers in good shape.
     
    Our GUI has a GTK implementation for Linux, but we expect to encounter some problems that have to be overcome. Our GTK Scintilla implementation (for the code editor) has not been written, and it's a complex library.
     
    Since the Linux file system is case-sensitive, we expect to have to modify some code to work properly on Linux.
     
    We're implementing a new method for terrain layers using virtual texturing. We do not anticipate any problems here, but it is one of the few features we haven't fully prototyped.
     
    Although building Leadwerks for Linux will undoubtedly present some difficult problems, our team has a lot of experience with multi-platform development and I'm confident we can deal with all issues we encounter.
  7. Josh
    The first step to building a character model is to establish the concept. Here are the images I have received. I have my favorite in mind, but what do you think? The purpose of this character is to serve as an enemy for a wide range of games. It could also be used as a main character with a third-person camera.
     
    Which one do you like best?
     

  8. Josh
    I recently had a strange interest in looking at Lego sets online and watching reviews. There was something about them that I felt like related to game development and level design. Something very interesting I noticed was that each set would include several extra elements that formed a story line. This added "play potential" to the set. For example, the raft below includes three pirates loaded with weapons, one who is obviously the leader, a treasure map, so the crew has an objective, and a shark, which serves as an adversary or obstacle to overcome. This is a lot more interesting than if they had just made a simple raft and sold it on its own.
     

     
    Sets of 3D models tend to be sold as a collection of objects. You buy five cars, and hopefully you've got that car problem taken care of for the rest of your life. It's kind of dull and tends to become a chore of "collecting" things that don't add a lot of value to a game.
     
    Based on this idea, I have several DLCs planned that are made up of items that create unique gameplay opportunities. Each pack includes unique scripted items that don't exist anywhere else, and sets up new "play potential" for your games. This could also allow me to distribute the cost of character models across several packs. At $6000 / model I can't quickly recover the cost of production of a pack of AAA characters. If they were distributed in a DLC with environment props I can offset the cost of production and build new content in a sustainable manner. I hope to have some of these available before Christmas.
     
    We're also experimenting with building higher quality content. Game assets are still a huge problem. The fact is that most of the third-party content available on the web just isn't that good, or is very inconsistent. In fact the phrase "unity asset" has become a common derogatory term for "bad artwork", regardless of its origin. If making large collections of high-quality content was profitable, people would be doing it. So it seems to me this is a sales problem.
     
    The modding community tends to have a ton of high-quality original artwork, while the indie game development community tends to have terrible artwork and presentation, as a general thing. This has always confused me. I'm not talking about pre-made game content, I mean the work the community itself produces. Modders always have much better art and presentation. You can even see this in Vectronic, a game that began as a Source Engine mod. Why does indie game artwork have to be instantly recognizable and kind of amateurish? This needs to change.
     
    Fortunately, our DLC sales are quite high, higher than anything else on the web, from what I have heard talking to various artists. We can produce high-quality content and recoup the costs, even making a small profit. This has to be carefully planned though. Contracted work works best when you have a longstanding relationship with the contractor. It can be difficult to get things started initially.
     
    For environment art, I've relied on Ancient Idol Studio for several years. I've talked to Rich about the need to raise our art standards, and he thinks he can produce better output with a bigger budget. We're starting by modeling a new pickup truck as a test.
     

     
    His instructions are to produce something similar in quality to the vehicles in "SpinTires", with a 6000 poly budget:
     

     

     
    Eventually, we're going to revise the entire demo level. I'm starting slowly by focusing on one item so we can learn what we need to, establish our art style, and then ramp up production of more content.
     
    I also have someone working to replace our default pistol vwep. If this works out, I plan to rely on them to produce more weapons.
     
    I'm still looking for a freelancer or shop for character models. It's difficult to find someone with work that isn't overly stylized, is cost-effective, and good with communication. I'm willing to be flexible on costs, but spending more money doesn't necessarily mean you get a better result. This is made more difficult by the fact that most portfolios tends to show off the most outlandish art...which isn't a good representation of what I am looking for.
     
    My goal right now is to get one good environment model, one good vwep, and one good character, with a cost that can be quickly recovered. If we can get one of each, we can keep producing more and DLC sales will cover the costs.
  9. 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.
  10. Josh
    The stock scripts that come with Leadwerks form a continually expanding game framework that can be used in many different ways. The reuse we get out of the door, switch, trigger, and AI scripts is really great. Every time I add a new script I can count on it being used in many different ways.
     
    Sometimes this requires a custom model in order to develop and demonstrate usage of the script. It's best for me to have one model made exactly to my specs, and then make everything else conform to that template.
     
    There are additional scripts I want to release in the near future that add more gameplay elements:
    TurretAI, with custom model.
    Enterable vehicles with controls for guns, if present.
    Third-person player controls, with options for fixed rotation or over-the-shoulder views.

     
    I also want to make the projectile prefab loaded by the soldierAI script a modifiable script value, so that we can easily add new types of projectiles. This would also work with turrets or vehicle-mounted guns.
     
    What other ideas for widely reusable scripts do you have?
  11. Josh
    Just thinking out loud here, and I am considering designing the GUI like this:
     
    The GUI class handles events, window clipping, widget layout, etc. Rather than having a bunch of C++ classes that extend a base Widget class, there would just be the Widget class with a Lua script attached to it. The Lua script would handle all events and drawing, so it would determine what kind of widget the C++ object is. For example, here's a script for a simple button:
     

    function Script:Draw(x,y,width,height) if self.pointerhovered==true then self.widget.window:SetColor(self.background.r*1.2,self.background.g*1.2,self.background.b*1.2) else self.widget.window:SetColor(self.background.r,self.background.g,self.background.b) end self.widget.window:DrawRect(self.x,self.y,self.width,self.height) self.widget.window:SetColor(self.background.r,self.background.g,self.background.b) self.widget.window:DrawText(self.text,self.x,self.y,self.width,self.height,Text.Center+Text.VCenter) end function Script:MouseEnter(x,y) self.pointerhovered=true self:Draw(self.x,self.y,self.width,self.height) end function Script:MouseLeave(x,y) self.pointerhovered=false self:Draw(self.x,self.y,self.width,self.height) end function Script:MouseUp(x,y) if self.pointerhovered==true then self.widget.gui:EmitEvent(Widget.ActionEvent) end self.buttonpressed=false end function Script:MouseDown(x,y) if self.pointerhovered==true then self.buttonpressed=true end end
     
    The upside:
    It's infinitely extensible and can be used to make literally any kind of widget.

     
    The downside:
    The script needs to contains the logic and the drawing, so although skinning is possible, it's not as simple as choosing a couple of colors.
    Complexity in the interaction between C++ and Lua widget logic.
    Debugging editor scripts as they are running = not fun. If people modify the editor GUI scripts it could introduce crashes.
    Coding advanced widgets like a treeview will be quite complex in Lua.

     
    Anyways, I'm just experimenting with it for now.
     

  12. Josh
    An early build of Leadwerks Game Engine 4.2 beta is available on the beta branch on Steam. This release will update the engine with the latest C++ tools and add new graphics and other features.
    Visual Studio 2017 support
    Compatible with the latest C++11 / GCC on Linux
    Refraction: apply "Materials\Effects\glass.mat" onto any object to see this in action.
    Heat haze: drag the heat haze emitter prefab into the scene to view ("Prefabs\Effects\heathaze.pfb").
    Spotlight texture: you can add a material to a spotlight and the first texture will be rendered onto the light (for flashlights).
    New animation commands
    Analytics (not working yet)

     
    It's funny that transparency with refraction used to be explained in a
    12 minute tutorial (in Leadwerks Game Engine 2), and now it is a simple effect you can drag into the scene. 

     

     


  13. Josh
    A full update is available now on the beta branch.
     
    Leadwerks Game Engine 4.2 features:
    Visual Studio 2017 support
    Compatible with the latest C++11 / GCC on Linux
    Refraction and heat haze effects.
    Analytics through gameanalytics.com
    New animation commands
    Spotlight texture: you can add a material to a spotlight and the first texture will be rendered onto the light (for flashlights).
    New material blend mode can be used to make objects that only appear in editor.

     
    Analytics are available (thanks MartyJ for his help on this!), on Windows only at this time. These are the commands:

    class Analytics { static bool Enable() static void Disable() static void SetKeys(const std::string& gamekey, const std::string& secretkey) static bool SendGenericEvent(const std::string& eventid) static bool SendGenericEvent(const std::string& eventid, const float value) static bool SendErrorEvent(const std::string& severity, const std::string& message) static bool SendProgressEvent(const std::string& status, const std::string& levelname) static bool SendProgressEvent(const std::string& status, const std::string& levelname, const int score) static bool SendProgressEvent(const std::string& status, const std::string& levelname, const int score, const int attempt_num) static bool SendResourceEvent(const std::string& flowType, const std::string& currency, const std::string& itemType, const std::string& itemid, const float amount) static bool SendBusinessEvent(const std::string& itemType, const std::string& itemid, const int amount, const std::string& currency, const uint64_t transaction_num, const std::string& cart_type = "", const std::string& receipt_info="")
     
    I had it working, but I am getting a lot of "rejected events" on my server now, so there's probably something else I need to do.
     
    C++ projects with Visual Studio need the following changes. This is now a complete list of changes since 4.1, but this will accommodate the additional libraries needed for the new analytics features:
     
    The following libraries must be added to your project:
    libcryptoMT.lib
    libsslMT.lib
    Rpcrt4.lib
    crypt32.lib
    libcurl.lib

     
    The following header search paths must be added to your project:
    $(LeadwerksHeaderPath)\Libraries\openssl\include

  14. Josh
    How do you like that clickbait title?
     
    I implemented analytics into Leadwerks Editor using GameAnalytics.com last month, in order to answer questions I had about user activity. Here's what I have learned.
     
    The number of active users is what I was hoping for. A LOT of people ran Leadwerks in the last month, but people don't usually use it every day, as the number of daily users is lower. The numbers we have are good though.
     
    A lot of people use the Workshop to install models and other items for their projects. Unfortunately, paid Workshop items cannot be purchased right now, as I am working with Valve to change some company financial information. i will have this running again as soon as possible.
     
    Boxes are the most common primitive created, by a huge margin, followed by cylinders, wedges, spheres, and cones, in that order. Maybe the list of available primitives should be rearranged based on this? Not a big deal, but it's interesting to see.
     
    There's definitely a disconnect between user activity and the community, so in the future I hope to encourage people using the program to register forum accounts and become active in the community.
     
    Overall, I am glad that analytics have allowed me to get a broad picture of collective user behavior so I am no longer working blindly. It's a blunt instrument, but it will be interesting to see how I can use it in the future to improve the user experience.
  15. 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.
  16. Josh
    Along with Leadwerks GUI, Leadwerks 4.4 adds an in-game menu that is available with the default Lua scripted game.  You can use this to allow your users to adjust settings in the game, or provide a more sophisticated way to quit the game than simply pressing the escape key.

    The default window size has been changed to 1280x720 when run from the editor.  Your game will now run in fullscreen mode by default when it is launched outside the editor.
    All of these changes are contained in the Main.lua and Menu.lua scripts, and can all be modified or removed to your heart's content.
    A full build is available now on the beta branch.
  17. Josh
    After working out a thread manager class that stores a stack of C++ command buffers, I've got a pretty nice proof of concept working. I can call functions in the game thread and the appropriate actions are pushed onto a command buffer that is then passed to the rendering thread when World::Render is called. The rendering thread is where all the (currently) OpenGL code is executed. When you create a context or load a shader, all it does is create the appropriate structure and send a request over to the rendering thread to finish the job:

    Consequently, there is currently no way of detecting if OpenGL initialization fails(!) and in fact the game will still run along just fine without any graphics rendering! We obviously need a mechanism to detect this, but it is interesting that you can now load a map and run your game without ever creating a window or graphics context. The following code is perfectly legitimate in Leawerks 5:
    #include "Leadwerks.h" using namespace Leadwerks int main(int argc, const char *argv[]) { auto world = CreateWorld() auto map = LoadMap(world,"Maps/start.map"); while (true) { world->Update(); } return 0; } The rendering thread is able to run at its own frame rate independently from the game thread and I have tested under some pretty extreme circumstances to make sure the threads never lock up. By default, I think the game loop will probably self-limit its speed to a maximum of 30 updates per second, giving you a whopping 33 milliseconds for your game logic, but this frequency can be changed to any value, or completely removed by setting it to zero (not recommended, as this can easily lock up the rendering thread with an infinite command buffer stack!). No matter the game frequency, the rendering thread runs at its own speed which is either limited by the window refresh rate, an internal clock, or it can just be let free to run as fast as possible for those triple-digit frame rates.
    Shaders are now loaded from multiple files instead of being packed into a single .shader file. When you load a shader, the file extension will be stripped off (if it is present) and the engine will look for .vert, .frag, .geom, .eval, and .ctrl files for the different shader stages:
    auto shader = LoadShader("Shaders/Model/diffuse"); The asynchronous shader compiling in the engine could make our shader editor a little bit more difficult to handle, except that I don't plan on making any built-in shader editor in the new editor! Instead I plan to rely on Visual Studio Code as the official IDE, and maybe add a plugin that tests to see if shaders compile and link on your current hardware. I found that a pragma statement can be used to indicate include files (not implemented yet) and it won't trigger any errors in the VSCode intellisense:

    Although restructuring the engine to work in this manner is a big task, I am making good progress. Smart pointers make this system really easy to work with. When the owning object in the game thread goes out of scope, its associated rendering object is also collected...unless it is still stored in a command buffer or otherwise in use! The relationships I have worked out work perfectly and I have not run into any problems deciding what the ownership hierarchy should be. For example, a context has a shared pointer to the window it belongs to, but the window only has a weak pointer to the context. If the context handle is lost it is deleted, but if the window handle is lost the context prevents it from being deleted. The capabilities of modern C++ and modern hardware are making this development process a dream come true.
    Of course with forward rendering I am getting about 2000 FPS with a blank screen and Intel graphics, but the real test will be to see what happens when we start adding lots of lights into the scene. The only reason it might be possible to write a good forward renderer now is because graphics hardware has gotten a lot more flexible. Using a variable-length for loop and using the results of a texture lookup for the coordinates of another lookup  were a big no-no when we first switched to deferred rendering, but it looks like that situation has improved.
    The increased restrictions on the renderer and the total separation of internal and user-exposed classes are actually making it a lot easier to write efficient code. Here is my code for the indice array buffer object that lives in the rendering thread:
    #include "../../Leadwerks.h" namespace Leadwerks { OpenGLIndiceArray::OpenGLIndiceArray() : buffer(0), buffersize(0), lockmode(GL_STATIC_DRAW) {} OpenGLIndiceArray::~OpenGLIndiceArray() { if (buffer != 0) { #ifdef DEBUG Assert(glIsBuffer(buffer),"Invalid indice buffer."); #endif glDeleteBuffers(1, &buffer); buffer = 0; } } bool OpenGLIndiceArray::Modify(shared_ptr<Bank> data) { //Error checks if (data == nullptr) return false; if (data->GetSize() == 0) return false; //Generate buffer if (buffer == 0) glGenBuffers(1, &buffer); if (buffer == 0) return false; //shouldn't ever happen //Bind buffer glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); //Set data if (buffersize == data->GetSize() and lockmode == GL_DYNAMIC_DRAW) { glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, data->GetSize(), data->buf); } else { if (buffersize == data->GetSize()) lockmode = GL_DYNAMIC_DRAW; glBufferData(GL_ELEMENT_ARRAY_BUFFER, data->GetSize(), data->buf, lockmode); } buffersize = data->GetSize(); return true; } bool OpenGLIndiceArray::Enable() { if (buffer == 0) return false; if (buffersize == 0) return false; glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); return true; } void OpenGLIndiceArray::Disable() { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } } From everything I have seen, my gut feeling tells me that the new engine is going to be ridiculously fast.
    If you would like to be notified when Leadwerks 5 becomes available, be sure to sign up for the mailing list here.
  18. Josh
    After three days of intense work, I am proud to show you this amazing screenshot:

    What is so special about this image? I am now successfully uploading voxel data to the GPU and writing lighting into another texture, using a texture buffer object to store the voxel positions as unsigned char uvec3s. The gray color is the ambient light term coming from the Blinn-Phong shading used in the GI direct light calculation. The next step is to create a light grid for the clustered forward renderer so that each light can be added to the calculation. Since voxel grids are cubic, I think I can just use the orthographic projection method to split lights up into different cells. In fact, the GI direct light shader actually includes the same lighting shader file that all the model shaders use. Once I have that done, that will be the direct lighting step, and then I can move on to calculating a bounce with cone step tracing.
    Clustered forward rendering, real-time global illumination, and physically-based rendering are all going to come together really nicely, but this is definitely one of the hardest features I have ever worked on!
    Here are a few wacky screenshots from the last few days.
    Why are half my voxels missing?!

    Why is only one texture layer being written to?!

    Ah, finally rendering to six texture layers simultaneously...

  19. Josh
    Here's a look at the new vehicle system that is being developed. The API has been simplified so you simply create a vehicle, add as many tires as you want, and start using it. The AddTire() command now accepts a model and the dimensions of the tire are calculated from the bounds of the mesh.
    class Vehicle { int AddTire(Model* model, bool steering=false, const float spring=500.0f, const float springrelaxation = 0.1f, const float springdamping = 10.0f); void SetGas(const float accel); void SetBrakes(const float brakes); void SetSteering(const float angle); static Vehicle* Create(Entity* entity); }; A script will be provided which turns any vehicle model into a ready-to-use playable vehicle. The script searches for limb names that start with "wheel" or "tire" and turns those limbs into wheels. If they are positioned towards the front of the car, the script assumes the wheels can be turned with steering. You can also reverse the orientation of the vehicle if the model was designed backwards.
    There is one big issue to solve still. When a vehicle drives on flat terrain the tires catch on the edges of the terrain triangles and the whole vehicle bounces around badly. I'm looking into how this can be solved with custom collision overrides. I do not know how long this will take, so it might or might not be ready by Christmas.
  20. Josh
    The new game engine needs to roll out with some top-notch examples showing off what it can do. Here's what I want:
    First-person shooter Offroad racing game Space shoot-em-up side-scroller. Side-scoller platformer similar to the Contra Playstation game. Now what I can use your help with is finding good example games on YouTube or Steam that I can start designing these samples around. Post your ideas below!
  21. Josh

    Articles
    I've actually been doing a lot of work to finalize the terrain system, but I got into tessellation, and another rabbit hole opened up. I've been thinking about detailed models in VR. Tessellation is a nice way to easily increase model detail. It does two things:
    Curved surfaces get smoother (using point-normal triangles or quads) A displacement map can be used to make small geometric detail to a surface. These are really nice features because they don't require a lot of memory or disk space, and they're automatic. However, tessellation also has a nasty tendency to create cracks in geometry, so it tends to work best with organic models like rocks that are carefully wrapped. I was able to mitigate some of these problems with a per-vertex displacement value, which dampens displacement wherever there is a mesh seam:

    However, this does not help round edges become rounder. With this cylinder, because the faces are not a continuous rounded surface, a crack appears at the sharp edges:

    What if there was a way to properly tessellate mechanical shapes like this? Wouldn't it be great if all your models could just automatically gain new detail that scales with the camera distance, with no need for extra Lod versions?
    Well, I had an idea how it might be possible, and a few hours later I came up with something. Here is the original model with no tessellation applied:


    Here is the same model with my new and improved tessellation shader, suitable for organic and mechanical shapes:


    A closeup view reveals perfectly aligned geometry with no gaps or cracks:

    The distribution of polygons can probably be made more uniform with additional work. This feature uses two additional bytes in the vertex structure to control a normal for tessellated curves. I think it will be possible to automatically detect seams and assign tessellation normals in the final editor. If no separate tessellation normals are assigned, then the default tessellation behavior occurs. This is a very promising technique because it could allow you to add a lot of detail to any model very easily with barely any effort.
  22. Josh
    In Leadwerks Engine 3, you can load a script and attach it to any entity. You can attach multiple scripts to any entity, and they will be called in the order they were attached. Right now, I am calling the script-side table "actor" because it is a little more descriptive than "object" but I'm not sure about all the syntax yet. Below is a sample script for a sliding door. When you attach this to a model, the script will control its behavior:

    ----------------------------- -- Sliding door script ----------------------------- --Attach this to any entity to turn it into a sliding door. --You can make the door move in any direction by adjusting the movement vector. --When the door opens or closes, a one-shot noise will play, along with looping --sound that will continue until the door comes to rest. --expose Sound opennoise --expose Sound closenoise --expose Sound movenoise --expose Sound stopnoise --expose Vec3 movement --expose function Open --expose function Close function actor:Start() if self.movement~=nil then self.openposition = self.entity.position + movement self.closeposition = self.entity.position end end function actor:Open() if self.openstate==0 then self.movestate=1 --Play one-shot noise, if it is set if self.opennoise~=nil then self.entity:EmitSound(self.opennoise) end --Play looping move noise if it is set if self.movenoise~=nil self.movesource = self.entity:EmitSound(self.movenoise,true) end end end function actor:Close() if self.openstate==1 then self.movestate=-1 --Play one-shot noise, if it is set if self.closenoise~=nil then self.entity:EmitSound(self.closenoise) end --Play looping move noise if it is set if self.movenoise~=nil self.movesource = self.entity:EmitSound(self.movenoise,true) end end end function actor:Update() local d local l if self.movestate~=0 --Calculate the difference between where we are and where we should be if self.openstate==1 d = self.openposition - self.entity.position else d = self.closeposition - self.entity.position end --Check to see if there is any difference l=d:Length() if l>0 then --Limit the difference if it is greater than the move speed of the door l = d:Length() if l>self.movespeed d = d:Normalize() * l end self.entity:Move(d,false) else self.movestate=0 --Disable looping noise source if it exists if self.movesource~=nil then self.movesource:Stop() --Play one-shot stop noise if it exists if self.stopnoise~=nil then self.entity:Emit(self.stopnoise) end end end
    Lua is pretty flexible, so I can make it work pretty much any way we want. When designing stuff like this, I find it's best to start with what the end user wants, and then work your way backwards to make it happen. What do you think?
  23. Josh
    Below is raw output from the Lua debugger. It displays all variables, tables, and functions in the Lua script call stack. This will be displayed in a nice treeview interface that looks much better, but I found this terribly exciting.
     
    You'll notice that tables don't get expanded, even though I have the ability to display all the values in a table. The reason they don't get expanded is because tables can contain tables, including tables that might be found elsewhere in the program. This can easily cause an infinite loop of tables leading to tables leading to tables. This is why the Lua debugger must be a networked program that talks to the running process. When the user opens a treeview node to view the contents of that table, the main program will return all the values in the table so you can view them, but not before.
     
    Here's what the Lua script looks like:

    print("Script is running...") local a = 2 local b = 3 someglobalvalue = "hello!" someglobaltable = {} local mytable={} mytable.color = "red" mytable.mood = "happy" mytable.subtable = {} mytable.subtable.n = 9 function dostuff() local test = "dog" RuntimeError("An error has occurred!") end dostuff()
     
    This will allow you to examine the entire contents of the virtual machine of any Leadwerks Engine 3 program built with debugging enabled, regardless of what language the main loop is coded in. The Lua implementation in Leadwerks Engine 2 was well-received, but we found in advanced programs we needed better tools to debug and analyze scripts. The script debugger in Leadwerks Engine 3 will make everything perfectly transparent so you can easily identity and fix problems. It also gave me a start on networking, because networking commands were needed to set this up.
     
    My plan for the networking API is to have commands for sending raw data with a message id:

    bool Send(const int& message, Bank* data=NULL, const int& channel=0, const int& flags=MESSAGE_SEQUENCED)
     
    As well as a few game-oriented commands to easily set up basic behavior:

    bool Say(const std::string& text) bool TeamSay(const std::string& text) bool Join(const int& team)
     
    The real magic is the entity syncing, which handles networked physics and makes it so any command you call on the server affects the corresponding entities on all clients. If you call entity->SetColor(1,0,0) to make an object red, it will turn red on all clients. I've tested an earlier prototype of this, and it worked well, even across continents. This makes network programming fairly easy, and a lot of fun.
     
    I'd really like to have a simple open-source tournament shooter game the whole community can play around with. Only by building a good networking base with a high-level entity syncing system does this become convenient and easy to modify.
     

    http://www.youtube.com/watch?v=7Vae_AkLb4Q
     
    ---------------------------------------------------------------------------------------
     
    And here's the debug output displayed in a tree view. The tables each get one blank child node, and when the user expands the table, the debugger will send a request for that table's data:

  24. Josh
    I was at a shopping center this afternoon wasting time, and came across a hobby shop. I can't quite articulate what it is about stuff like this that I like, but this is what I want game development with Leadwerks3D to be like. This is why I set up the Leadwerks Asset Store and make the effort to make nice thumbnails with transparency to show off items in 3D. I want more game development to be a process of producing reusable components, and then at the design level, of picking and choosing which components to utilize.
     
    This is the kind of stuff I used to do as a kid, which undoubtedly paved the way for my future work in 3D graphics. I particularly like the packaging on the box in the first image: "You can do it!" I should use that. B)
     
    Post your thoughts below.
     

     

     

     

  25. Josh
    An update is available on the beta branch which adds the new vegetation system. You can open the attached map in the editor to see the system in action. Be sure to create a new project, or update your existing one, in order to get the new shaders and models.
    vegetationsample.zip
     
    To get this update early you must opt in to the beta branch on Steam.
     
    The new vegetation system is special because it does not use persistent objects stored in memory. Rendering and physics are executed according to a distribution algorithm that dynamically generates instances each frame. This allows the system to manage an infinite number of instances, with much denser placement and faster performance than a conventional vegetation system would allow (such as what Leadwerks 2 used.)
     

     
    You can select the vegetation tool in the terrain tools dropdown box. Usage is pretty self-explanatory.
     
    Models that are to be used as vegetation layers much have a material with a vegetation shader applied. There are two new slots in shaders list in the material editor, for the vegetation and vegetation shadow shaders. These can be selected from the "Shaders\Vegetation" folder.
     
    Models with a default physics shape and collision enabled will be collideable.
     
    A new "Pick mode" setting has been added in the material editor. This allows you to disable picking on some materials (like leaves and grass). This allows bullets to pass through objects that should not stop them.
     
    At this time, vegetation will only appear when texture+lighting render mode is in use.
     
    The default models have been donated generously by Pure3D.de.
×
×
  • Create New...