News

Update
- More than 20 custom shader effects are now available for download.
- Quick user guide on using custom shader effects.
- New tutorial on writing custom shader effects.

Tuesday 21 June 2011

kameraku 1.0

kameraku is a Symbian 3 application which delivers super fast hardware accelerated LIVE camera effects. It allows you to view and to capture unique and fun pictures.

Camera effects are generated in real-time using OpenGL ES 2.0 pixel shader which is available in Symbian 3 smart phones e.g. N8, C6-01, C7. It allows you to experience the true power of your Symbian 3 smart phone, thanks to its amazing processing power which allows these effects to be applied to the live camera view running at ~25 fps. Unlike many other apps which apply effects after you took a picture, kameraku gives you a unique WYSIWYG (what you see is what you get) experience. This is a must-have app to show off your powerful Symbian 3 smart phone to those fruit/robot-loving crowds :P

kameraku is fully functional and pre-loaded with seven built-in effects such as thermal imaging, night vision and toon shading. It also has extra feature that allows you to create your own visual effects. Custom effects are written in OpenGL ES 2.0 GLSL language which are stored as regular text files in phone memory and can be loaded or replaced at any time.

More than 20 examples of custom shader effects are made available for you to download and can be used as a starting point for writing your own effects (see this blog post).

Not only it will allow you to take unique pictures, this application can also be used as a tool for anyone who are interested in learning more about writing OpenGL ES 2.0 shader. With this application and mobilekoder app (see this blog post), your smart phone could become a useful device for writing and testing your shader. You can do it wherever and whenever you want as you can always carry it around in your pocket.

Tips: Please note that camera shutter key does not work with this application (see Nokia platform limitation). Pressing camera key will launch Nokia built-in camera application and may cause camera view to freeze. If that happens, simply exit and restart the application.

kameraku quick user guide

This is a step by step instruction on how to use custom shader effects example from this website.

1. Start kameraku application.








2. Tap kodemongki icon at the left corner of the screen to visit this website. Make sure WiFi or 3G Internet connection is available on your phone.








3. Browse to kameraku custom shader effect example page and tap "download shader code" link.








4. Go back to kameraku application and long press "My FX" button.








5. Go to browser default download folder (e.g. E:\download) and select custom shader file to use.








If the above steps does not work, you can also visit this website using Internet browser on your PC to dowload all shader code and then copy them to your phone via USB cable or bluetooth using Nokia Ovi Suite application.

kameraku built-in shader effects gallery

Sample pictures taken using built-in effects i.e. normal, thermal imaging, night-vision, outline, toon shading, negative and monochrome.











kameraku custom shader effects example

These are just a few examples of what you can create using your own custom shader code. The possibilities are endless!

To use these custom effects, simply download the code (it's a plain text file) into your phone memory and use it from kameraku application by long pressing "My FX" button.

To view the shader code, you can use your favourite text editor, but don't use Windows Notepad as the code all have Unix line ending.

If you've written cool effects and would like to share them, just let us know, we will add them to the gallery. We will also continue to add new effects whenever they are available, so watch this space.

Sepia toning
download shader code








Black and white
download shader code








Pop Art
Not quite like Warhol masterpiece but worth a try :)
download shader code







Miniature illusion
Faking tilt & shift technique to create miniature illusion. The blur is not perfect as the post-processing is limited to a single pass and the color is not saturated.
download shader code





Red isolation
This is an attempt to isolate specific color and set the rest to grayscale as seen in Sin City movie.
download shader code






Green isolation
download shader code








Blue isolation
As seen in KGB advert
download shader code







Yellow isolation
download shader code








Blur
download shader code








Sharpen
download shader code









Emboss
download shader code








Pixelation
download shader code








Billboard
Based on tutorial code from http://www.lighthouse3d.com/opengl/ledshader
download shader code






Outline
Another variation of outline effect, this time using Sobel algorithm.
download shader code






Glow
If you like Tron movie or Halo 3 ODST you might like this one :)
download shader code






Red-channel
download shader code








Green-channel (note: this is not night vision effect!)
download shader code








Blue-channel
download shader code








Vignette
download shader code









Vertical mirroring
download shader code








Horizontal mirroring
download shader code








4-way split
download shader code

How to write your own custom shader effect

Custom effect can be written in just a few lines of GLSL shader code. A typical kameraku shader code will have similar form to the following example,
precision mediump float;
uniform sampler2D vTex;
varying vec2 vCoord;

void main(void)
{
gl_FragColor.rgba = texture2D(vTex, vCoord).bgra;
}
To understand how the whole thing works, let's get into details on how kameraku application works. Every time camera image is received by the application, it forwards the image data to graphics processor. Image data is an array of pixels which represents of what the camera sees. This array of colors is delivered to graphics processor as a 2D texture together with information about its coordinate. From your shader code these two information are accessible via variable vTex and vCoord.

One important thing to note is that camera image data is in BGRA order, so you may need to reorder it into RGBA order before processing and setting it to the final color to be displayed on the screen, which is stored in gl_FragColor variable.

In the earlier example, the shader code uses built-in texture2D function to lookup color value in vTex texture using given vCoord coordinate and set it as the final color to gl_FragColor after re-ordering it from BGRA to RGBA (note the .rgba and .bgra notation used). Since there is no color modification involved, the shader code basically simply passing through camera image data, which will produce unmodified or normal output.

Now, let's move to another example
precision mediump float;
uniform sampler2D vTex;
varying vec2 vCoord;

void main(void)
{
vec4 color = texture2D(vTex, vCoord).bgra;
gl_FragColor.rgba = vec4(color.r, 0.0, 0.0, color.a);
}

In the second example we modify the output color by only setting red channel and supressing the other color channels. The effect will produce output as shown in the left picture.

Well done! You have created your first custom shader effect. All you need to do is to save that code into a text file and store it in your phone memory.


Traps and pitfalls
One thing to remember when writing shader effects for kameraku is that OpenGL ES 2.0 shading language (also known as GLSL ES or ESSL) is based on desktop OpenGL GLSL version 1.20.

It is important to understand what the limitation are when porting shader code from desktop OpenGL. Make sure you read Appendix A from GLSL ES specification. One of them is the limitation when indexing samplers from within fragment shader code. Using index other than constant-index-expression is not guaranteed to work.

For example:
vec2 texPos = vCoord + vec2(0.5, 0.5);
vec4 col = texture2D(vTex, texPos); <= this may fail

Sunday 19 June 2011

More tutorial on custom shader effects

Color boosting
We can increase the contribution of a particular color by multiplying it with a scaling factor. For example, to increase red factor by 50% we can perform the following operations,

precision mediump float;
uniform sampler2D vTex;
varying vec2 vCoord;
void main(void)
{
vec3 col = texture2D(vTex, vCoord).bgr;
gl_FragColor = vec4(col.r * 1.5, col.g, col.b, 1.0);
}

The following example increase blue factor by 50%,

precision mediump float;
uniform sampler2D vTex;
varying vec2 vCoord;
void main(void)
{
vec3 col = texture2D(vTex, vCoord).bgr;
gl_FragColor = vec4(col.r, col.g, col.b * 1.5, 1.0);
}

And another example to increase yellow factor by 50%

precision mediump float;
uniform sampler2D vTex;
varying vec2 vCoord;
void main(void)
{
vec3 col = texture2D(vTex, vCoord).bgr;
gl_FragColor = vec4(col.r * 1.5, col.g * 1.5, col.b, 1.0);
}

They will produce output as follow,




















Color shifting

We can produce weird output by swapping RGB color channel. For example swapping red with green and green with blue as follow

precision mediump float;
uniform sampler2D vTex;
varying vec2 vCoord;
void main(void)
{
vec3 col = texture2D(vTex, vCoord).bgr;
gl_FragColor = vec4(col.g, col.b, col.r, 1.0);
}

or swapping red with blue and green with red,

precision mediump float;
uniform sampler2D vTex;
varying vec2 vCoord;
void main(void)
{
vec3 col = texture2D(vTex, vCoord).bgr;
gl_FragColor = vec4(col.b, col.r, col.g, 1.0);
}

will produce this output,











Grayscale

To convert RGB to grayscale we can use the following formula
float grayscale = 0.3 * red + 0.59 * green + 0.11 * blue

To reduce the number of grayscale tones, we can clamp the value to a specific threshold. For example to create 3 tones grayscale we can use the following code,

precision mediump float;
uniform sampler2D vTex;
varying vec2 vCoord;
void main(void)
{
vec3 col = texture2D(vTex, vCoord).bgr;
float y = 0.3 *col.r + 0.59 * col.g + 0.11 * col.b;
y = y < 0.3 ? 0.0 : (y < 0.6 ? 0.5 : 1.0);
col = vec3(y, y, y);
gl_FragColor = vec4(col, 1.0);
}

and another variation where only red-channel is used,

precision mediump float;
uniform sampler2D vTex;
varying vec2 vCoord;
void main(void)
{
vec3 col = texture2D(vTex, vCoord).bgr;
float y = 0.3 *col.r + 0.59 * col.g + 0.11 * col.b;
y = y < 0.3 ? 0.0 : (y < 0.6 ? 0.5 : 1.0);
col = vec3(y, 0.0, 0.0);
gl_FragColor = vec4(col, 1.0);
}

Those code will produce the following output,

Saturday 18 June 2011

Using kameraku and mobilekoder as a learning tool

It is not always about camera effects, kameraku and mobilekoder can also be used to learn more about OpenGL procedural texturing.

Here's an example shader code from 3Dlabs,

// Fragment shader for procedural bricks
// Authors: Dave Baldwin, Steve Koren, Randi Rost
// based on a shader by Darwyn Peachey
// Copyright (c) 2002-2004 3Dlabs Inc. Ltd.
// See 3Dlabs-License.txt for license information

// Modified by kodemongki for kameraku

precision mediump float;
uniform sampler2D vTex;
varying vec2 vCoord;
const vec2 bricksize = vec2(0.2, 0.1);
const vec3 brickcolor = vec3(0.8, 0.2, 0.1);
const vec2 brickpct = vec2(0.9, 0.85);
const vec3 mortarcolor = vec3(0.2125, 0.215, 0.21);

void main(void)
{
vec2 pos = vCoord / bricksize;
if (fract(pos.y * 0.5) > 0.5)
pos.x += 0.5;
pos = fract(pos);
vec2 usebrick = step(pos, brickpct);
vec3 col = mix(mortarcolor, brickcolor, usebrick.x * usebrick
.y);
gl_FragColor = vec4(col, 1.0);
}


which will produce the following output












And another example from OpenGL ES 2.0 Programming Guide book,

precision mediump float;
uniform sampler2D vTex;
varying vec2 vCoord;

const vec3 black = vec3(0.0, 0.0, 0.0);
const vec3 white = vec3(1.0, 1.0, 1.0);
float freq = 10.0;

void main(void)
{
vec2 pos = mod(ceil(vCoord * freq), 2.0);

float delta = abs(pos.x - pos.y);
vec3 col = mix(black, white, delta);
gl_FragColor = vec4(col, 1.0);
}

will generate this output


Recommended reading