Jump to content

  • Log In with Google      Sign In   
  • Create Account

Leadwerks Developer Blog

Leadwerks 3: Editor features and workflow enhancements

Posted by , 22 May 2013 - - - - - - · 973 views

This update to Leadwerks 3 brings the addition of lightmapping across curved surfaces with smooth groups. The image below is a set of lightmapped CSG brushes, not mesh lighting. You can read a detailed account of our implementation of this feature here.

Posted Image

The project manager now includes an "Update" button, so you can easily update your project any time we modify files in the template folders. Although we tested with no problems, it is recommended you back up your project before using this feature. The editor will make a copy of any overwritten files, as an added precaution.

Posted Image

You've now got full control over all the features and settings in the Leadwerks editor, through the new Options dialog. This gives you control over various program behaviors and settings. You can toggle grid snapping, control the snap angle, and lots of other stuff.

Posted Image

As we use the editor more and hear about the community's experience, it allows us to refine our tools more. One of the more subtle but we made is in the properties editor. One of the annoyances I experienced was when setting a property like mass or position when an entire hierarchy of entities was selected. Obviously I didn't want to set the mass for every single bone in a character, but how to tell the editor that? I went through all the properties, and for ones that the user is unlikely to want set, I made the following rule: If the entity has a selected parent anywhere in the hierarchy, it gets ignored when properties are retrieved and applied. (Other things like color will still work uniformily.) Just try it, and you'll see. It speeds up editing dramatically.

In a similar vein, we finally solved the problem of "too many selection widgets", We only display the top-most control widget for each group of selected objects. Again, it's easier for you to just try it and see than for me to explain in detail. If we did our job right, you might not even notice because the editor will just do what you want without any thought.

You've also got control over the color scheme, and can use it to customize the look and feel of the 3D viewports and code editor.

Posted Image

On Windows we fixed an annoyance that triggered menu shortcuts when the user tried to copy and paste in text fields. This tended to happen in the properties editor. We're working to resolve the same issue in the Cocoa UI for Mac.

I'm a big fan of the 3ds max Max Script system, so in the output panel we've added a real-time Lua console:
Posted Image

You can type Lua commands in and interact with Leadwerks in real-time. Just for fun, try pasting in this line of code and see what happens:
for i=0,10 do a = Model:Box(); a:SetColor(math.random(0,1),math.random(0,1),math.random(0,1)); a:SetPosition(i*2,0,0); end
You can't create objects the editor will recognize (yet), but it's fun to play with and should give you an idea of where we're going with the editor.

This is an important update that includes new features and enhancements that improve usability and workflow. Thank you for your feedback. It's great to see all the activity that is taking place as people learn Leadwerks 3.


Lightmapping curved CSG surfaces

Posted by , 15 May 2013 - - - - - - · 655 views

I'm a big fan of constructive solid geometry because it allows people without advanced modeling skills to design a game level that looks great. In fact, I originally got my start in game development using the Quake and Half-Life modding tools, making game maps.

One of the criticisms of CSG has been that it only allowed creation of faceted objects. (Valve's Hammer Editor has a workaround for this that lets you set smooth groups, but you can't see the results until they are run in the game.) This was preventing me from making some game level features I wanted, like curved arches and rounded corners, so I decided to do something about it.

Leadwerks supports smooth groups for CSG objects. To access the controls, switch to face editing mode and then select the objects tab in the right-hand sidepanel:
Posted Image

It was fairly easy to calculate vertex normals from smooth group information. However, that information still has to be fed to the lightmapper or the lighting will appear faceted across a curved surface:
Posted Image

To solve this, I needed to calculate the interpolated normal across the surface, and use that for the lighting equation for each luxel (lightmap pixel). Initially, I thought I could use a simple weighted average. Vertices near the luxel would have a high influence, and vertices further away would have less influence. However, it quickly became apparent this would not produce anything close to accurate results! Gouraud Shading
The problem I was facing is actually a very common calculation that is done in real-time on the GPU. This was the first time I ever had to calculate it myself. It turns out the problem was first solved before I was born by a clever fellow by the last name of Gouraud, and thus we call it Gouraud Shading or Gouraud Interpolation.

The algorithm works like this: draw a straight line in any direction from the point you want to interpolate. It doesn't matter what angle, as long as it's one straight line. Now find the two triangle edges the line intersects. Each of those edges is connected to two vertices, each with a normal. Use a linear interpolation to weight those two normals, for each point. Finally, use the distance of both these points from your original position to weight their interpolated normals:
Posted Image
More information on this technique can be found here. Implementation
Getting this to work on a CSG lightmapper was difficult for two reasons. First, CSG objects consist of n-sided polygons, not triangles. Although they can be broken down into triangles, I was worried that visual artifacts might arise. Second, lightmaps have a user-defined bleed border, and the luxels of a lightmap extend beyond the edges of the polygon being lit. Gauroud shading requires the point being interpolated actually be inside the triangle. Our luxel positions could be inside any of the triangles that make up a polygon face, or they might not be on the face at all!

I decided to start by only worrying about the luxels that fell inside one or another triangles on the face, and solve the outliers later. Fortunately, the transform and math classes built into Leadwerks 3 made it fairly easy to convert all the points into flat 2D space to solve the problem. As expected, my first attempt identified the luxels that fit inside a particular triangle, but the luxels along the edges could not be processed, and appear dark:
Posted Image

I added an error threshold for the triangle intersection routine, which got rid of the black borders, but turned out to be a bad idea. Some of my values were being interpolated in the wrong direction, as you can see in the following images:
Posted Image

Posted Image

Posted Image

In this image, it's almost working, but the error threshold is causing luxels along the center seam to get lit incorrectly. Additionally, a few luxels in the top right are forming a dark border:
Posted Image

The final piece of this puzzle was to deal with luxels that didn't fit into a particular triangle, This was a pretty puzzling problem, and for a while I thought there might not be a "correct" solution. However, if you think about it intuitively, a luxel that lies just outside a triangle should use the same lighting as a luxel just inside that triangle, right next to it.

For the remaining unsolved luxels, I tested each of their distances to each triangle in the face they belong to. I found a nearest triangle to each, then found the nearest point on that triangle, and calculated the normal from that point's position.
Results
This technique produces beautiful smooth lightmapping on curved surfaces:
Posted Image

The algorithm works with curves, arches, sphere, any CSG objects that use smooth groups. So now you can make those castles, arches, and towers you've always wanted to build:
Posted Image

This feature will be available in the next update to Leadwerks 3.


Leadwerks 3 Update Brings Rendering Enhancements to Mobile

Posted by , 07 May 2013 - - - - - - · 491 views
iphone, ipad, android, ios and 2 more...
An update for Leadwerks 3 has been released, bringing new graphical enhancements to mobile games. Building on the efficient art pipeline and user-friendly tools of Leadwerks 3, the engine now supports projected shadows for characters and other dynamic objects. This technique works by casting a shadow onto the surrounding world geometry, to provide real-time shadows that run fast on all platforms.

Posted Image

To enable dynamic shadows on a single object, just select it in the editor and choose the new "Dynamic" option in the "Cast Shadows" property. You can also do this in code by calling Entity::SetShadowMode(Light::Dynamic).

Posted Image

Leadwerks 3 has also gotten a visual upgrade with the addition of post-processing effects. In Leadwerks 2, all post-processing effects like volumetric light scattering, screen-space ambient occlusion, depth-of-field, and bloom were hard-coded. That is, they were written into the core engine and it was difficult to customize the renderer. Leadwerks 3 has added a new command, Camera::AddPostEffect(), which allows the user to attach a shader right to a camera, to automatically render post-processing effects.

Leadwerks is a fast and flexible development platform for building mobile games with native code. You can download a 30-day trial version on the website here.


Leadwerks 3 Gets Projected Shadows

Posted by , 28 April 2013 - - - - - - · 528 views

We've got a Leadwerks 3 update coming out this week, with miscellaneous fixes and some new features.

The first are the addition of Import and Export buttons in the Project Manager. You can export an entire project to a zip file. You can import a project from either a Leadwerks project file (*.werk) or a zip file. This makes it easy to share projects and synchronize your work across different computers.
Posted Image

The second new feature is projected shadows. These allow characters and other objects to cast dynamic shadows on the scene around them. They run fast, even on mobile devices, and add an extra degree of depth to your scene:
Posted Image

You can expect these updates to become available later this week.


Leadwerks 3 Rendering Enhancements

Posted by , 21 April 2013 - - - - - - · 844 views

Shadows in 3D games are important. Not only do they look good, but they communicate information about the 3D geometry of the scene. Leadwerks pioneered dynamic deferred lighting, with one of the first deferred renderers in the world on PC. However, the reality of today's situation in computing hardware has to be considered when we are designing a platform for other people build commercial products on.

To support games that reach the widest audience possible, we launched Leadwerks 3 with a baseline renderer that runs across the board on all supported platforms. The engine has been designed in a modular fashion so we can add on a new high-end deferred renderer later on, and Leadwerks games will get an instant graphics upgrade with no code changes. I am looking forward to pushing graphics even further later on when I turn my attention to the OpenGL 3.2/4.0 renderer.

Projected Shadows
As for the baseline renderer, there are a few extra enhancements I'm finishing up that will make Leadwerks 3 games look good on a wide range of hardware. In my last blog I talked about light vector maps, which store normal mapping information in a second lightmap. We delivered the results to users last week, and are am working on projected shadows, a low-cost technique Source Engine uses to provide dynamic shadows on characters and other dynamic objects in the scene.

I started by just rendering an object and getting its rendered image to line up with the original object:

Attached Image

The next step was to color the shadow black and use alpha blending, to make it look like...a shadow!:

Attached Image

The hardest part of this process, which I am still working on, is the data management. It's easy to set up a simple one-time effect like this, but making it scalable so your games keep running fast takes much more work. We don't want to re-render shadows when they aren't visible on screen, and we only want to re-render them when the orientation of the shadow caster changes. We can't simply loop through all shadow-casting objects in the scene, because that approach will slow down when more objects are added. Instead we have to build the shadow system into the scene octree so that shadows only get updated when its absolutely needed.

Post-processing Effects
Thanks to our research for GDC 2013, we found that post-processing effects on mobile are completely doable. Consequently, we're adding a few post-processing steps to finish out the baseline renderer before we move on to OpenGL 4. Bloom and HDR iris adjustment are the two that make the biggest impact on visual quality, and will be approached first. Refraction effects are easy to add, and this time we're going to make them easier for the end user to set up. The end goal is for the baseline renderer to be on par with Valve's Source Engine, and have it run on mobile.

We think these features will provide a striking visual impact on a wide range of hardware, and provide a good fallback for systems that don't support full deferred rendering. Next, we'll be moving on to terrain and a new deferred renderer based on OpenGL 3.2 / 4.0.


Leadwerks 3 Brings Native Code to Mobile Games

Posted by , 17 April 2013 - - - - - - · 1,199 views

Leadwerks Software announced today the release of Leadwerks 3, their new development platform for building mobile games with native code. Based on the technology developed for their successful game engine for PC, Leadwerks 3 brings a totally new approach to mobile game development.

While environments such as Unity and MonoDevelop use managed code...that is, code that is designed to be easily run on multiple devices...Leadwerks uses an approach called native code. Applications built with native code are optimized to work with each platform. That means games written with Leadwerks will run faster and be more powerful than their managed code counterparts.

Mobile is growing rapidly, but there still exists a gap between mobile gaming and the larger game industry, which has traditionally focused on consoles. Professional game studios overwhelmingly favor native code because of its speed and flexibility. By focusing on the standard the game industry already uses, Leadwerks provides both professional studios and indie developers with an easy pathway into mobile. Games written in C++ can be ported to Leadwerks 3 without having to rewrite them in a new programming language.

Leadwerks 3 brings some innovative new approaches to the table:
  • The editor features tools for building game levels using a technique called constructive solid geometry. This streamlines the process of creating games, and makes it easier for artists to see what their games will look like as they build them.
  • Leadwerks 3 uses automatic asset conversion. This means that images and objects can be reloaded on-the-fly, so an image file can be modified in Photoshop and the result will show up in the editor right away. This removes tedious steps from the game development workflow.
  • AI is supported out-of-the-box. The traversable areas AI can travel within are highlighted in the editor as you build your game level. Pathfinding is dynamic, meaning that if a door opens or a drawbridge lowers, the AI is smart enough to take the new routes that appear.
  • The script language Lua is also supported, and can be combined with games written in native code. Scripted objects can be linked together in a visual flowgraph editor. This makes it easy to set up game interactions, something that can be a challenge when working with development platforms based solely on code.
Leadwerks CEO Josh Klint said that “Leadwerks 3 is a big step forward for our company and our users. We’re bridging the gap between mobile gaming and the traditional game industry.” The product received a favorable response at the GDC 2013 expo. ”C++ is the game industry standard. Our market research at GDC 2013 revealed a huge demand for a cross-platform game engine built on native code. We found the design philosophy of Leadwerks resonates with a lot of developers.”

Leadwerks 3 can be purchased from the company’s website for $199, with add-ons for iOS and Android publishing available separately. A source code license is available for professional studios. A 30-day trial can be downloaded from the company’s website.

Leadwerks Software has provided game development tools to thousands of developers worldwide since 2006. It’s technology has been used in commercial games, education, training simulations, and military applications. To find out more, please visit http://www.leadwerks.com.


Using Light Vector Maps in Leadwerks 3

Posted by , 08 April 2013 - - - - - - · 1,062 views

After a wild week at GDC 2013, it's nice to be back doing what I do best...writing code!

A new build of Leadwerks 3 is now available. We've added light vector maps so that lightmapped surfaces can display normal mapping effects. This is a fantastic technique because it gives us high quality per-pixel lighting that requires very little processing, so it runs fast on mobile. Lightmapped materials with normal maps should use the texture "Common/lightvectormap.tex" in slot 4. (If you create a new lightmapped material, this will be done automatically.)
Attached Image

This technique works by calculating the average light vector that influences each luxel in the lightmap. Each vector is weighted by the light's intensity and range to get an overall vector representing the direction most light is coming from. The light vectors are encoded in a secondary light map that looks like this:
Attached Image

This effect will even work with specular reflection, as seen in this totally over-the-top screenshot:
Attached Image

We also made about a dozen small fixes to the engine and editor. For more detail on recent issues resolved, visit the bug reports forum. Like any new software, we've had some teething problems, but it's pretty easy to resolve those issues as they arise. Bugs can be fixed as they are identified, but bad design is forever. Fortunately, I think we've got a great design and a good and stable development system.


Post-GDC Wrapup

Posted by , 31 March 2013 - - - - - - · 917 views

I'm back home now, relaxing after a long week away. And what a week it was!

I got my lecture out of the way on Monday. I felt like I was pretty well prepared, but some acoustical problems in the hall really made it very difficult to concentrate, plus I was pretty nervous about talking in front of about 600 people. I did it though, and hope to do another one next year. The recorded lecture should be available in the GDC vault.

During my talk, I described my experience as a PC developer, moving into mobile, and making a renderer to be cross-platform and scalable. I also showed off a deferred renderer running on the iPad. A couple of interesting things came out of this research. FIrst, I figured out a few details on how to render to a texture. This forms the basis of project shadows and post-effects on mobile. More importantly, I discovered that mobile hardware is better than PC hardware at rendering to textures! This is what the performance of a deferred and forward renderer looks like on the PC:
Attached Image

A deferred renderer scales better, but takes an initial hit on performance, which is why Leadwerks 2 has such heavy hardware requirements, and the framerate never goes above 300 or so. It turns out, PowerVR graphics hardware for mobile can render to a texture at no cost. We get the scalability of a deferred renderer, without that initial hit on performance:
Attached Image

I talked to some engineers with Mali, and they told me their graphics chips work the same way. The implications of this are pretty staggering. It means that per unit processing horsepower, mobile graphics hardware is actually more capable than PC graphics hardware, and AAA graphics on mobile are right around the corner.

We set up our booth on Tuesday before the show. This was my first time going behind the scenes, so it was a totally different view of the conference. Before the expo floor opened, I asked the Oculus Rift guys if I could try their new toy out, and they let me demo it. I was only disappointed that they used a Mech-style game and the cockpit took up most of my peripheral vision, which eliminated any reason to look around and experience the full VR effect.

I had a lot of meetings with different graphics hardware manufacturers, got some good technical info, and scored some free hardware for development and testing.

The response we got from the attendees was really good. When we explained what Leadwerks 3 was, everyone got it right away, and were enthusiastic about what they saw. Here's some footage from the show:


It was a push to get Leadwerks 3 out in time for the GDC, but well worth it. We got the word out about Leadwerks 3, got a lot of positive feedback and a better idea of what our target market needs, and put Leadwerks on the radar of some very big companies in the industry.

Starting Monday, bug fixes have top priority, and I will start adding some graphical enhancements that will make a big enhancement to the renderer.


Unit Testing for Leadwerks 3

Posted by , 28 January 2013 - - - - - - · 860 views

I've spent the last few days writing simple examples for every single command in Leadwerks 3. Not only does this make the documentation more friendly, it also acts as a final test to make sure all the commands work the way they say they should. I make the C++ example and then Chris converts it to Lua (and tells me what I did wrong!).

I didn't realize it at first, but this really showcases the strength of API design of Leadwerks. Since you get full control over the execution and flow of a Leadwerks program, it's easy to learn from simple examples that demonstrate one idea. Below are a few examples for different commands in the API.

Get the device accellerometer reading:
#include "App.h"

using namespace Leadwerks;

Window* window = NULL;
Context* context = NULL;

bool App::Start()
{
    window = Window::Create();
    context = Context::Create(window);
    return true;
}

bool App::Continue()
{
    if (window->Closed() || window->KeyDown(Key::Escape)) return false;

    Draw::SetColor(0,0,0);
    context->Clear();

    //Display the device information on the screen
    Draw::SetBlendMode(Blend::Alpha);
    Draw::SetColor(1,1,1);
    Draw::Text("Orientation: "+String(Device::GetOrientation()),2,2);
    Draw::Text("Acceleration: "+Device::GetAcceleration().ToString(),2,22);
    Draw::SetBlendMode(Blend::Solid);

    context->Sync();        
    return true;
}
Create a physics shape from a model and use it on a scaled entity Posted Image :
#include "App.h"

using namespace Leadwerks;

Window* window = NULL;
Context* context = NULL;
World* world = NULL;
Camera* camera = NULL;

bool App::Start()
{
    window = Window::Create();
    context = Context::Create(window);
    world = World::Create();
    camera = Camera::Create();
    camera->SetRotation(35,0,0);
    camera->Move(0,0,-10);
    Light* light = DirectionalLight::Create();
    light->SetRotation(35,35,0);

    //Create the ground
    Model* ground = Model::Box(10,1,10);
    ground->SetPosition(0,-0.5,0);
    ground->SetColor(0,1,0);

    //Create a shape
    Shape* shape = Shape::Box(0,0,0, 0,0,0, 10,1,10);
    ground->SetShape(shape);
    shape->Release();

    //Load a model
    Model* model = Model::Load("Models/teapot.mdl");
    model->SetPosition(0,0,0);
    model->SetColor(0,0,1);
    model->SetScale(4,4,4);

    //Create a shape
    shape = Shape::PolyMesh(model->GetSurface(0));
    model->SetShape(shape);
    model->SetPosition(0,0,0);
    shape->Release();

    //Create some objects to fall
    model = Model::Sphere();
    shape = Shape::Sphere();
    model->SetShape(shape);
    shape->Release();
    model->SetMass(1);
    model->SetColor(Math::Rnd(0,1),Math::Rnd(0,1),Math::Rnd(0,1));
    model->SetPosition(Math::Rnd(-1,1),Math::Rnd(3,6),Math::Rnd(-1,1));

    for (int i=0; i<10; i++)
    {
        model = (Model*)model->Instance();
        model->SetCollisionType(Collision::Prop);
        model->SetColor(Math::Rnd(0,1),Math::Rnd(0,1),Math::Rnd(0,1));
        model->SetPosition(Math::Rnd(-1,1),5+i*2,Math::Rnd(-1,1));
    }

    return true;
}

bool App::Continue()
{
    if (window->Closed() || window->KeyDown(Key::Escape)) return false;

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

    return true;
}
Create a texture from scratch:
#include "App.h"

using namespace Leadwerks;

Window* window = NULL;
Context* context = NULL;
World* world = NULL;
Texture* texture = NULL;

bool App::Start()
{
    window = Window::Create();
    context = Context::Create(window);

    //Create a texture
    texture = Texture::Create(256,256);

    //Set the texture pixel data
    char* pixels = (char*)malloc(texture->GetMipmapSize(0));
    char r,g,b;
    for (int x=0; x<256; x++)
    {
        for (int y=0; y<256; y++)
        {
            int p = (x*texture->GetWidth() + y)*4;
            memcpy(&r,pixels + p + 0, 1);
            memcpy(&g,pixels + p + 1, 1);
            memcpy(&b,pixels + p + 2, 1);
            if (x<128)
            {
                if (y<128)
                {
                    r=0; g=0; b=255;
                }
                else
                {
                    r=255; g=0; b=0;
                }
            }
            else
            {
                if (y<128)
                {
                    r=255; g=0; b=0;
                }
                else
                {
                    r=0; g=0; b=255;
                }                
            }
            memcpy(pixels + p + 0, &r, 1);
            memcpy(pixels + p + 1, &g, 1);
            memcpy(pixels + p + 2, &b, 1);
        }
    }
    texture->SetPixels(pixels);

    return true;
}

bool App::Continue()
{
    if (window->Closed() || window->KeyDown(Key::Escape)) return false;

    Draw::SetColor(0,0,0);
    context->Clear();

    //Display the texture on screen
    Draw::SetColor(1,1,1);
    Draw::Image(texture,0,0);

    context->Sync();        
    return true;
}
http://www.leadwerks.com


Finishing up character physics in Leadwerks 3...

Posted by , 03 January 2013 - - - - - - · 1,006 views

In this blog I'm going to explain the evolution of the entity and physics system in Leadwerks 3.

In Leadwerks Engine 2, physics bodies and character controllers are both separate entity classes. If you want a model to be physically interactive, you parent it to a body entity. If you want a model to walk around with physics, you parent it to a character controller body.

In Leadwerks 3 I decided to give physics properties to all entities. This means all entities can use commands like GetVelocity(), AddForce(), SetMass(), etc. However, since character controllers are quite different, and they involve kind of a big chunk of code, I decided to keep the character controller as a separate entity. To make an enemy or NPC, you would create a character controller entity and then parent an animated model to that entity.

This was simple enough to do in the editor, but it started getting weird when we added scripts. Scripts for animation would need to be added to the child model, because the character controller would not return any animation lengths or the number of sequences. Scripts to control movement, on the other hand, would have to be attached to the parent character controller, for obvious reasons.

Next I tried creating a character controller script that attached to the model itself. This eliminated the extra entity in the hierarchy, and would automatically create a character controller when loaded in the engine, and parent the model to it. I didn't like that this was changing the hierarchy from what the user saw in the editor, and script accessing the character controller would still be based on some wonky assumptions.

Finally, I decided to just give the entity class a physicsmode member. This can be one of two values. By default, it is Entity::RigidBodyPhysics. However, you can set it to Entity::CharacterPhysics and the entity itself will act as a character controller! All the character controller functions are now available in the entity class, so you can just load a model, adjust some settings, and send him on his merry way around town:
Model* enemy = Model::Load("Models/Characters/barbarian.mdl");
enemy->SetMass(10);
enemy->SetPhysicsMode(Entity::CharacterPhysics);
enemy->GoToPoint(20,0,0);//model will walk to this position, using AI navigation

Pretty cool, eh?

http://www.leadwerks.com