Minko Weekly Roundup #2
What happened on the Minko planet in the past few days? It's time for a quick review!
Demos
Venus de Milo
This demo loads a 400k polygons statue 3D model and displays it with normal mapping. It was built in a few minutes using Minko Studio. Thanks to the MK file format and lossless compression, this status is only 6MB big (textures included) againt 50MB for the original model.
Mercedes E-500
You can watch the making of this demo on Youtube. It shows a very old version of Minko Studio, but you can see how easy it was to do this kind of things already!
Updates/Features
Pimped GitHub repository
We've put a lot of efforts into redacting a better README.md. This new version provides a lot of useful links to demos, tutorials and the plugins repositories. The default branch of the repository is now 2.0b to make sure people use it against the old deprecated version available on master.
Make sure you check the "Getting started with Minko" tutorial to get the sources from Minko's GitHub repository!
HDR Bloom
We've finally ported the HDR bloom post-processing effect used in BlackSun into Minko 2! This implementation is much cleaner and also faster. It uses the new multi-pass linear Gaussian blur implementation.
You can find the source code of this application in minko-examples.
CloneOptions
The CloneOptions are a very important addition: they let you control the way a scene tree is cloned. Cloning a scene tree is indeed often more complicated than simply duplicating each node. Those nodes have data providers and/or controllers attached to them. What should we do with all of those? The CloneOptions give you all the control you need to specify which controllers should be cloned, which should be left aside, etc...
More importantly, it solves a very old issue making it impossible to clone skins/skeletons without losing animations. You can now have two meshes sharing the same skin, or clone this skin to have a completely independent instance.
Software skinning
Hardware skinning is constrained by the Stage3D API. Indeed, it relies on the number of constants each vertex shader can handle (128 in the case of Stage3D). Dual quaternion skinning was already able to handle up to 51 bones with 8 influences per vertex. But in some cases it's not enough...
To handle the use cases where hardware skinning is not possible, we've added software skinning. It will perform the vertex transformation on the CPU instead of the GPU. It's slower but it can virtually handle an unlimited amount of bones/influences. So you should now be able to load any skinned 3D model!
This method is also very cool because we're one step closer from generating vertex morphing from skinning at runtime. It means we are now capable to bufferize the skinning data - with an unlimited number of bones/influences - and create keyframed data that will have virtually no cost neither on the CPU nor on the GPU! And all of this could happen transparently at runtime, giving you much better performances after a few seconds of playback.
Normals/Tangent Space Update
The Geometry.computeNormals() and Geometry.computeTangentSpace() method have been entirely refactored to be re-entrant. The direct consequence is the possibility to recompute the normals/tangents at anytime! It's very cool because it makes it easier to work with normals/tangents when you update the position of the vertices procedurally.
Those methods will also be more intelligent and avoid creating a new VertexStream when it's possible. They also accept a list of triangle IDs to specify which triangles have to be updated. It's very useful when you've edited only a fraction of the vertices and you just want to update only this part of the geometry.
Tutorials
- Your first mobile 3D app. with Minko
- Your first shader with Minko's ShaderLab (French) by Chloridrik
Fixes
- The Geometry.changed is now triggered when one of its vertex streams changes.
- "doubleSided" QuadGeometry will now have proper normals and catch light properly
- fixed Vector4::scale() not scaling the input Vector4.
- VertexStream.lock() and IndexStream.lock() will not assume the data hasn't changed anymore (because they actually don't have a clue...).
- VertexStream.lock() and IndexStream.lock() now take an optional hasChanged : Boolean argument to specify whether the locked data has actually changed or not and avoid dispatching the "changed" signal when it's not relevant.
Answers
- "Issues with setting TextureResource size" explains the current behavior of TextureResource's size.
- "GPU uploading speed" explains when the data is uploaded on the GPU and the futur internal changes on vertex/index streams.
Next week I'll introduce all the amazing changes we've made in Minko Studio.
Tutorial: your first mobile 3D application with Minko
As you already know I'm sure, you can build Android and iOS devices with the Flash platform. And Stage3D is also available on those devices! As a matter of fact, Stage3D was especially designed to work on mobiles. And so was Minko! We put a lot of efforts in building a robust and fast engine that will work on most mobile devices. This tutorial will start where the "Your first Minko application" tutorial stopped and explain what needs to be done to get it working on mobile.
Create your mobile project
The first thing to do is - of course - create a mobile project. With Flash Builder it is very simple: you just have to go into File > New > ActionScript Mobile Project. If you need a little reminder of how to bootstrap your project/development environment, you can read the "Getting started with Minko" tutorial. The only difference compared to creating a desktop/wepp application is to uncheck "BlackBerry Table OS" in the Mobile Settings panel: Stage3D is not yet available on BlackBerry devices. There is an issue opened on the BlackBerry tracker if you want to vote for it!
Configure the application
Now our project has been created we just have to make sure it can use the Stage3D API. It implies two little changes in the app.xml file (this file is named after your main class, most of the time it's Main-app.xml):
- renderMode has to be set to "direct"
- depthAndStencil has to be set to "true"
Here is a basic example of a properly setup app.xml file for AIR 3.2:
<?xml version="1.0" encoding="utf-8" standalone="no"?> <application xmlns="http://ns.adobe.com/air/application/3.2"> <id>Main</id> <filename>Main</filename> <name>Minko Mobile Example</name> <versionNumber>0.0.0</versionNumber> <initialWindow> <content>[This value will be overwritten by Flash Builder in the output app.xml]</content> <!-- Stage3D --> <renderMode>direct</renderMode> <depthAndStencil>true</depthAndStencil> <!-- /Stage3D --> <autoOrients>true</autoOrients> <fullScreen>false</fullScreen> <visible>true</visible> </initialWindow> <iPhone> <InfoAdditions><![CDATA[ <key>UIDeviceFamily</key> <array> <string>1</string> <string>2</string> </array> ]]></InfoAdditions> <requestedDisplayResolution>high</requestedDisplayResolution> </iPhone> <android> <manifestAdditions><![CDATA[ <manifest android:installLocation="auto"> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> </manifest> ]]></manifestAdditions> </android> </application> |
Bootstrap the Main class
That's the beauty of the Flash platform, Stage3D and Minko: the project boostrap aside, the code of the application is exactly the same whether you are working on a desktop, web or mobile application! Therefore, you can bootstrap your Main class by following the "Your first Minko application" tutorial!
Basically, you just have to copy/paste the MinkoApplication sample class...
public class MinkoApplication extends Sprite { private var _viewport : Viewport; private var _scene : Scene; protected function get scene() : Scene { return _scene; } protected function get viewport() : Viewport { return _viewport; } public function MinkoApplication() { super(); // make sure the stage is available if (stage) initialize(); else addEventListener(Event.ADDED_TO_STAGE, initialize); } private function initialize(event : Event = null) : void { removeEventListener(Event.ADDED_TO_STAGE, initialize); // create the viewport _viewport = new Viewport(); // add the viewport to the stage stage.addChild(_viewport); initializeScene(); addEventListener(Event.ENTER_FRAME, enterFrameHandler); } protected function initializeScene() : void { // create an empty scene _scene = new Scene(); } protected function enterFrameHandler(event : Event) : void { // render a frame _scene.render(_viewport); } } |
... and make your Main class extend it:
public class Main extends MinkoApplication { public function Main() { super(); } } |
Run your mobile application for the first time
If you use Flash Builder, it will display the Debug Configurations panel when you will try to run/debug your mobile application for the first time. This panel does not have anything special regarding Stage3D or Minko, but it's still a good thing to see the basics! There are two important fields on the panel:
- The "Target platform" field will specify what device you want to target for this debug session.
- The "Launch method" field will specify whether you want to run the application in the desktop device emulator or directly on the device. Of course, the "On device" method is better if you want to have a preview of the actual performances.
Display your first 3D object
Now that our project is setup and that we can launch it on the device or in the emulator, we will display our first 3D object. You just have to follow the "Display your first 3D object" tutorial for your mobile project. Here is what you'll get if you choose to run it on the desktop emulating the iPhone4 device:
You can also directly download the sources for this project!
If you have questions/suggestions regarding this tutorial, please post in the comments or on Aerys Answers, Minko's official support forum.
Minko Weekly Roundup #1
Updates are committed every day. Demos are starting to pop from third party developers. And I clearly don't have enough time to write an article about each of them! So I got the idea to write little summaries of what happened during the (past few) week(s). Here we go!
Demos
Smooth shadows
We've been working a lot to give the user more control on the shadow quality. One of the options now involves shadow smoothing. This features is available on all lights but the PointLight for now:
This new feature and the corresponding examples should be available in the public repository next week.
Points/particles rendering
minko-examples has been updated with a points/particles rendering example. The code includes both the geometry and the shader required to draw massive amounts of particles. It also demonstrates how one can built simple animations directly on the GPU:
Yellow Submarine
A little demo done by Jérémie Sellam (@chloridrik), developer at the "Les Chinois" interactive agency in Paris, France. The demo mixes my terrain generation example, texture splatting, points rendering and a custom displacement shader to simulate an underwater trip in control of a yellow submarine:
The submarine model was imported and customized using Minko Studio. In a few minutes, Jeremy was able import the original Collada asset, customize it with alpha blending and environment mapping and export an optimized compressed MK file.
Color Transition Shader
Another great work from Jérémie Sellam who implemented a very nice transition effect using nothing more but the public beta of the ShaderLab:
If you cannot run this demo, there is a video of this nice color transition shader on Youtube.
Answers
- A new category dedicated to Minko Studio.
- A new "Tutorial requests" thread for Minko Studio.
- "the big merge" thread explains what is going to happen on the repositories in a few weeks. Must read!
Tutorials
Features
- Support for multiple shadows in Minko Studio.
- New geometry primitives: ConeGeometry and TorusGeometry
- Normals flipping: you can now flip (= multiply by -1) the normals (and tangents) of a geometry by calling Geometry.flipNormals(). We will soon add an IndexStream.invertWinding() method to be able to fully turn any shape inside out without bugging the shaders that might rely on the normals/tangents.
- Merging geometries: you can now merge two Geometry objects. Used along with Geometry.applyTransform(), it makes it very easy to merge any static objects.
- Disposing local geometry data: you can now dispose the entire geometry data (IndexStream + all VertexStreams) with a single call to Geometry.disposeLocalData().
- New Matrix4x4 methods: Matrix4x4.setColumn(), Matrix4x4.getColumn(), Matrix4x4.getRow() and Matrix4x4.setRow().
Fixes
- Removed unused event listeners
- Fixed major performance issue caused by unnecessary "changed" signals listened on meshes removed from the scene in the RenderingController.
- VertexStream.usage is automatically set to StreamUsage.STATIC when the local data is disposed.
Tutorial: Display your first 3D object with Minko
Now that we've seen how to bootstrap an empty Minko application, it's time to learn how to display a simple 3D primitive.
Step 1: The Camera
In order to display anything 3D, we will need a camera. In Minko, cameras are represented by the Camera scene node class. The following code snippet creates a Camera object and adds it to the scene:
var camera : Camera = new Camera(); scene.addChild(camera); |
By default, the camera is in (0, 0, 0) and looks toward the Z axis. We must remember this when we will add our 3D object in the scene: we must make sure it's far enough on the Z axis to be visible!
Step 2: The Cube
A Mesh is a 3D object that can be rendered on the screen. It is somekind of 3D equivalent of the Shape class used by Flash for 2D vector graphics. But in 3D. As such, it is made of two main components:
- a Geometry object containing the triangles that will be rendered on the screen
- a Material object defining how that very geometry should be rendered
Creating a Mesh involves passing those two objects to the Mesh constructor:
var geometry : Geometry = new CubeGeometry(); var material : BasicMaterial = new BasicMaterial(); // set the RGBA color of the cube material.diffuseColor = 0x0000ffff; var cube : Mesh = new Mesh(geometry, material); scene.addChild(cube); |
There are many primitives available as pre-defined geometry classes in Minko: cube, sphere, cylinder, quad, torus... Those classes are in the aerys.minko.render.geometry.primitive package. You can easily swap the CubeGeometry with a SphereGeometry to create a sphere instead of cube for example.
The BasicMaterial is the material provided by default with Minko's core framework. It's a simple material that can render using a solid color or a texture. Here, we use it with a simple color. To do this, we simply set the BasicMaterial.diffuseColor property to the color we want to use with an RGBA format.
Remember: the camera is in (0, 0, 0) and - by default - so is our cube. Therefore, we have to slightly translate our cube on the Z axis to make sure it's in the field of view of the camera:
cube.transform.translationZ = 5.; |
We will introduce 3D transformations in details in the next tutorial.
Conclusion
To make it simple, our main class will extend the MinkoApplication class detailed at the end of the previous tutorial. We will simply override its initializeScene() method to create our cube, our camera and add both of them to the scene:
public class BlueCube extends MinkoApplication { override protected function initializeScene() : void { super.initializeScene(); var mat : BasicMaterial = new BasicMaterial(); mat.diffuseColor = 0x0000ffff; var cube : Mesh = new Mesh(new CubeGeometry(), mat); cube.transform.translationZ = 5.; scene.addChild(cube); var camera = new Camera(); scene.addChild(camera); } } |
And here is what you should get:

If you have questions or suggestions, you can post in the comments or on Aerys Answers!
Tutorial: Your first Minko application
In this tutorial we will see how to create your first scene with Minko. At the end of this tutorial, you will have nothing but a colored rectangle. Before you follow this tutorial it is recommended to read the "Getting started with Minko 2" article in order to learn how to setup your programming environment.
Creating the Viewport
Instanciating a new Viewport object
The first step before rendering anything is to have a rendering area. In Minko, this rendering area is called the "viewport" and is represented by a Viewport object. The viewport can be seen as the middle-man between the classic 2D rendering list and the hardware accelerated 3D rendering. Indeed, the Viewport class extends the Sprite class so it will behave like any other rendering element of the display list: it has a (x, y) position, a width, a height, etc...
Creating the viewport is really simple:
var viewport : Viewport = new Viewport(); |
The Viewport constructor accepts the following arguments:
- antiAliasing : uint, the anti-aliasing level to use when rendering in this viewport; this value can be 0, 2, 4 or 8 and the default value is 0
- width : uint, the width of the viewport; the default value is 0 to make the viewport fit its parent width automatically
- height : uint, the height of the viewport; the default value is 0 to make the viewport fit its parent height automatically
There a few things to remember about a viewport though:
- The viewport can only be behind or infront of all the other elements in the display list. This is because of a technical limitation of the Stage3D API. To make the viewport visible infront, you should set the Viewport.alwaysOnTop property to true.
- If the viewport is set to resized itself automatically according to its parent's size (ie. the Viewport constructor was built with width == height == 0), then you have to make sure its parent actually has a size different from 0
The following code snippet will create a 640x480 viewport with 4x anti-aliasing and move it in (100, 200):
var viewport : Viewport = new Viewport(4, 640, 480); |
Adding the viewport to the display list
Just like any DisplayObject, the Viewport must be added to the stage to be visible. As it behaves like any other DisplayObject, you can simply use the addChild() method to add it to the display list:
var viewport : Viewport = new Viewport(); stage.addChild(viewport); |
The viewport can be added to any DisplayObjectContainer, just make sure its parent has a proper width and height if you are working with an automatically resized Viewport.
Rendering into the viewport
As you can see, even with the viewport added to the Stage, there is no visual change. That's because the viewport is empty as long as we don't use it to render a scene. Now that we have a rendering area, we should render something in it! For now, we will just create an empty scene and render it in this viewport:
var scene : Scene = new Scene(); var viewport : Viewport = new Viewport(); stage.addChild(viewport); scene.render(viewport); |
This code snippet creates a new Viewport and a new Scene objects. Then, it adds the Viewport to the Stage and renders the Scene in that very Viewport. The immediate consequence is that our viewport will now be filled with black. Our viewport is completely black because we just rendered an empty scene and the default background color of the Viewport is black.
Manipulating the Viewport
Setting the background color
You can change the background color of the viewport by setting the Viewport.backgroundColor property. This property holds the background color of the viewport in the RGBA format:
// setting the background color to "blue" viewport.backgroundColor = 0x0000ffff; |
The alpha component of the background color is not used for now and is here only for forward compatibility.
Resizing the viewport
You can resize the viewport by setting the Viewport.width and Viewport.height properties:
// set the viewport width to 640 viewport.width = 640; |
Everytime you set the Viewport.width or the Viewport.height property, the Viewport.resized signal is executed. Thus, in order to avoid executing unnecessary signals when you want to set both the width and the height of the viewport, it is recommended to use the Viewport.resize() method:
viewport.resize(640, 480); |
This way, the Viewport.resized signal will be executed only once at the end of the Viewport.resize() method when the viewport has been successfully resized.
Moving the viewport
You can move the viewport using the Viewport.x and Viewport.y properties. It will behave just like any other DisplayObject element: the final position of the viewport is affected by the transformation applied by its parents. Thus, if you add the Viewport in a Sprite and if you move that Sprite, the viewport will move as well.
// move the viewport to the (100, 200) position viewport.x = 100; viewport.y = 200; |
Conclusion
The following code sample describe the basic structure of a main class used to create a new Minko application:
public class MinkoApplication extends Sprite { private var _viewport : Viewport; private var _scene : Scene; protected function get scene() : Scene { return _scene; } protected function get viewport() : Viewport { return _viewport; } public function MinkoApplication() { super(); // make sure the stage is available if (stage) initialize(); else addEventListener(Event.ADDED_TO_STAGE, initialize); } private function initialize(event : Event = null) : void { removeEventListener(Event.ADDED_TO_STAGE, initialize); // create the viewport _viewport = new Viewport(); // add the viewport to the stage stage.addChild(_viewport); initializeScene(); addEventListener(Event.ENTER_FRAME, enterFrameHandler); } protected function initializeScene() : void { // create an empty scene _scene = new Scene(); } protected function enterFrameHandler(event : Event) : void { // render a frame _scene.render(_viewport); } } |
You can re-use this class as you main class everytime you want to create a new 3D app!
Minko ShaderLab Beta
Try it now!
Click on the like below to run the ShaderLab beta directly in your browser:
Online ShaderLab Beta Wep ApplicationBut please remember...
Many people want to try the ShaderLab - our graphics shader programming environment. Yet, it seams we simply can't find the time to start an actual private beta. That's because we are focusing on Minko Studio for the public beta release.
I really think this early (buggy) release is still of some interest: you'll be able to test drive the UI, train yourself to shader programming in an easy and fun way but - most of all - you can provide feedback. But let's be honnest: this is an old release and it has many flaws.
- It works with Minko 1, which imply it uses the old shader compiler that procudes sometimes sub-optimal shader code.
- You can save and load shader source files, but you cannot publish them to test them in your live application.
- Parts of the UI might behave weirdly.
- You can't share your creations "à la YouTube".
There are other minor bugs. We know all of this. And we're fixing it as we are integrating the ShaderLab with Minko Studio. Those updates will likely be backported into the ShaderLab web app. But do not expect minor fixes every week: it will be a complete update. Thus, feel free to give us feedback but don't be to upset if it takes time to be fixed.

Samples
To help you getting started, here are a few samples you can load in the ShaderLab to start with:
French Flags.mks
Circular And Directional Waves v2.mks
Cel Shading.mks
Conclusion
I'm pretty confident this app can still be useful as it is today - especially to learn shader programming - and I hope you will like this first release despite all its flaws. If you have questions or suggestions regarding the ShaderLab, please feel free to post them on Answers.
Minko Workshop: Introduction to Minko Studio
The last workshop was a great success and I promised we would make it a regular thing if people were interested. So here we are again for a new workshop!
This new workshop will be an "Introduction to Minko Studio". This workshop will teach you the basics of Minko Studio:
- how the 3D assets workflow works
- how to import 3D assets
- what are the constraints: what is supported, what is not and why
- how to build you first 3D scene: move, rotate, scale objects, simple material edition
- how to load 3D scenes in your application
- how to script the loaded 3D scenes with ActionScript 3
This new workshop will take place the 26th of July in Paris and is free for professional services subscribers.
We need to have at least 10 people registered for this workshop to amke it happen! Make sure you register on the dedicated Aerys Answers thread.
I hope to see you there!
Get the Minko 2 Developers Reference
Most of Minko's source code is now documented in the 2.0b branch and you can download the developers reference with this link:
Minko 2.0b Developers Reference (28/06/2012)But this documentation evolves with the code. And the code is updated every day. Of course, most of the changes are minor bug fixes and do not affect the documentation. Yet, it might be the case so we needed a way to:
- be able to easily rebuild the updated developers reference when the ASDoc changes
- give others the possibility to rebuild the documentation from the latest sources in case we do not provide the latest compiled version (which will happen since we won't upload a new ZIP everyday)
This is why I've added all the required files to make it possible to build the developers reference with ANT:
- The build.xml file contains an "asdoc" task to build the developers reference.
- The build.properties file contains some customizable variables like the home directory of the Flex SDK to work with (you might need to customize this value in order to get the ANT tasks to work properly).
- The doc-templates directory contains a custom documentation template that will evolve with Minko's requirements.
If you have troubles working with the developers reference you can ask for help on Aerys Answers, Minko's official support forum.
New Minko 2 Features: Normal Mapping And Parallax Mapping
One of Aerys' engineers - Roman Giliotte - is the most active developer on Minko. He is the one behind the JIT shaders compiler, the Collada loader and the lighting engine. This last project received a special attention in the past few days with a lot of new features. Among them: normal mapping and parallax mapping.
The following sample shows the difference between (from left to right) classic lighting, normal mapping and parallax mapping:
The 3 objects are the exact same sphere mesh: they are just rendered with 3 different shaders. You can easily see that the sphere using parallax mapping (on the right) appears to have a lot more details and polygons. And yet it's just the same sphere rendered with a special shader that will mimic the volume effect and details on the GPU.
Parallax mapping can be used to add details and volumes on any mesh. This technique is used in many modern commercial games such as Crysis 2 or Battlefield 3. It makes it possible to load and display a lot less polygons but with a high-polygon level of details.
And of course, thanks to Minko and Flash 11/AIR 3, it works just as well on Android and iOS!
The only thing you need is a normal map and a heightmap. And those two assets are very easy to generate from any actual 3D asset. The technique we use is called "steep parallax mapping". And thanks to Minko's exclusive JIT AS3 shaders compiler, you can now use parallax mapping in any of your custom shaders! The code is available on github :
- the code for the parallax mapping is available as a shader part on github in minko-lighting
- the demo is available in the minko-examples repository
One of the future optimizations include storing the height in the w/alpha component of the normal map. This way, the memory usage will be the same than with normal mapping but with a much better rendering.
If you have questions or suggestions, you can leave a comment or post on Aerys Answers.
Procedural Terrain With Minko 2
Being able to create procedural geometry is very important in a 3D engine. Minko is special because it offers 2 ways to work with the 3D geometry:
- The streams API: low level but the fastest solution. You have to create and fill the buffers yourself which becomes rapidly annoying and hard to read.
- The vertex iterators: a high level dynamic API, slow but very very easy to work with.
In this post I will explain how you can create a 3D procedural terrain in just a few lines of code.
TL;DR
You can get the full source code for this example in minko-examples on github.
Read more...













Aerys