Friday, February 28, 2014

The importance of global illumination

Every modern graphics engine needs a global illumination solution. Rage AFAIK uses some kind of path tracing + some static lighting baked into textures(kinda like the good old lightmapping) as they have "inlimited" amount of texture memory. Unreal and other big boys, as DICE use Enlighten, CryTek have their Light Propagation Volumes.
My solution isn't  that advanced, but can be tweaked to look OK. The main drawback of it is that the lighting is static.


Tuesday, February 25, 2014

3ds max - Office chair speed modeling.

I continue to play with 3ds max.
An attempt to model an office chair.



And here is the ingame test of the textured model.


Monday, February 24, 2014

Learning to crawl with 3ds max

For the needs of some of my hobby projects I often have a need for specific assets and level geometry.



Thursday, February 20, 2014

SSAO - Screen Space Ambient Occlusion

In computer graphics, ambient occlusion is used to represent how exposed each point in a scene is to ambient lighting. So the enclosed inside of a tube is typically more occluded (and hence darker) than the exposed outer surfaces; and deeper inside the tube, the more occluded (and darker) it becomes. The result is diffuse, non-directional lighting throughout the scene, casting no clear shadows, but with enclosed and sheltered areas darkened. In this way, it attempts to approximate the way light radiates in real life, especially off what are normally considered non-reflective surfaces.
Unlike local methods like Phong shading, ambient occlusion is a global method, meaning the illumination at each point is a function of other geometry in the scene. However, it is a very crude approximation to full global illumination. The soft appearance achieved by ambient occlusion alone is similar to the way an object appears on an overcast day.

I'm toying with the screen-space approximation of this technique in my Isle of marooned project.
It suffers some limitations and artifacts, that I will discuss and provide more info about in further posts.


Wednesday, February 19, 2014

Global Illumination - lifting the curtain

As promised, I will elaborate on the topic of global illumination and provide a bit of source code to illustrate the method, mentioned in a previous post.
Light probes are spread across critical areas, manually or automatically. Incoming lighting at these points in space is captured in cube maps which are then converted to spherical harmonics.
A short video shows these probes in action




The HLSL code for sampling the spherical harmonics coefficients looks like this :

You provide a normal direction and the function returns the illumination coming from that direction.
 
// 'lightingSH' is the lighting environment projected onto SH (3rd order in this case),

// and 'n' is the surface normal

float3 ProjectOntoSH9(in float3 lightingSH[9], in float3 n)

{

    float3 result = 0.0f;

   

    // Cosine kernel

    const float A0 = 1.0f;

    const float A1 = 2.0f / 3.0f;

    const float A2 = 0.25f;



    // Band 0

    result += lightingSH[0] * 0.282095f * A0;



    // Band 1

    result += lightingSH[1] * 0.488603f * n.y * A1;

    result += lightingSH[2] * 0.488603f * n.z * A1;

    result += lightingSH[3] * 0.488603f * n.x * A1;



    // Band 2

    result += lightingSH[4] * 1.092548f * n.x * n.y * A2;

    result += lightingSH[5] * 1.092548f * n.y * n.z * A2;

    result += lightingSH[6] * 0.315392f * (3.0f * n.z * n.z - 1.0f) * A2;

    result += lightingSH[7] * 1.092548f * n.x * n.z * A2;

    result += lightingSH[8] * 0.546274f * (n.x * n.x - n.y * n.y) * A2;



    return result;

}


Here is the code for rendering the light probes (for debug purpose)
technique RenderSH
{
    pass p0
 {
  VertexShader = compile vs_3_0 SimpleVSTransformed();
  PixelShader = compile ps_3_0 psLightingRenderSH();
        CullMode = CCW;
  FillMode = solid;
  Zenable = true;
  StencilEnable = true;  
  AlphaBlendEnable = false;
  AlphaTestEnable = false; 
  ZWriteEnable = true; 
 }
};
void SimpleVSTransformed(in float4 inPos: POSITION, in float2 inTex: TEXCOORD0, 
out float4 outPos: POSITION, out float2 outTex: TEXCOORD0, out float4 wPos : TEXCOORD1)
{
outPos = inPos;
outTex = inTex;


outPos = mul(float4(inPos.xyz, 1), c_mViewProjection);
wPos = mul(float4(inPos.xyz, 1), c_mWorld); ; 


}
float4 psLightingRenderSH(PS_INPUT_LIGHT i, in float4 wPos : TEXCOORD1 ) : COLOR0
{

 
 
float4 color = 1.0 ;

  
    
 float3 vLightDir = normalize(   wPos.xyz - lightProbePos ) ;

   float4 probeCol = float4(ProjectOntoSH9(SHarmonicsCoefficients,-vLightDir) , 1.0) ; 
            return float4(probeCol.xyz  , 1.0);



}
As you can see, a sphere mesh is rendered and this is what is happening, briefly :
 Running through the vertex shader, world space vertex positions (yep, a sphere mesh has vertices spread around the center) are send to the pixel shader via TEXCOORD1 slot. Pixel shader then runs through every pixel, gets the light probe position we are currently rendering, gets the pixel position in world space, subtracts those to form direction and samples the spherical harmonics coefficients to obtain the pixel color.

Tuesday, February 18, 2014

Epic battery eater!

Android is designed (among other things) as a platform for gaming too, although probably not the ideal one.
Still development environments and especially emulators are not at a level sufficient to develop performance critical applications such as games. One way or another, you are forced to go through the slow and tedious process of building the application and uploading it to a a real device if you want to see it in action with more that 5 FPS.
In this regard libraries as libGDX are excellent tools to quickly prototype small games and multimedia applications, and why not a regular mobile application, rich of heavy GUI and graphics.
The framework provides an environment for rapid prototyping and fast iterations. Instead of deploying to Android/iOS/Javascript after each code change, you can run and debug your game on the desktop, natively. Desktop JVM features like code hotswapping reduce your iteration times considerably.
Yeah, for speeding things up, iterations need to be reduced and optimized for speed at code level, and at development cycle level as well. This does not mean that the iterations are the root of all evil.
Here's a quick peek of a small hill-climb racing game. It's meant to run on 

  • Windows
  • Linux
  • Max OS X
  • Android (+2.2)
  • BlackBerry
  • iOS
  • Java Applet (requires JVM to be installed)
  • Javascript/WebGL




Time to show some source code for people who would have been interested to see how the track is generated. It's not pretentious in any way - it's a quick and dirty solution. I actually switched to more natural, hand made "terrains" that are loaded from file and authored in a level editor-like application, where you can define points manually for better control.


    vertexCount = 500 ; 
    float fRoughness = 0.5f;
    
    float vert[] = new float [vertexCount] ; 
    
    for(int i = 0 ; i < vertexCount ; i++ )
    {
   
     vert[i] = i ;
     //if(i % 2 == 0) vert[i] *= scaleX ;
     
     if( i %  2 != 0) vert[i] =  (float) (Math.sin( Math.random()) * 0.9f) * fRoughness ;    
     
    }
Now, for every vertex, texture coordinates are assigned, and every second vertex is send to the bottom of the screen to form the track base.
Vector2 v2 [] = new Vector2[4] ;
  v2[0] = new Vector2(0.0f,0.0f) ; 
  v2[1] = new Vector2(0.5f,1.0f) ;
  v2[2] = new Vector2(1.0f,0.0f) ;
  v2[3] = new Vector2(1.0f,1.0f) ;
  
      
     float meshVertices [] =  new float [vertexCount  * 6 ] ;
     for(int  i = 0 ; i < vertexCount ; i++ )
     {

      meshVertices [ (i*6) + 0 ] = i * scaleX - scaleX  ; 
       
       
      if(i%2==0)
      {
       meshVertices [ (i*6) + 1 ] = -1.0f ;
      }
      else
      {
       meshVertices [ (i*6) + 1 ] = vert[i] ;
       
      }
       
      
      
      
      meshVertices [ (i*6) + 2 ] = 0.0f  ;
      meshVertices [ (i*6) + 3 ] = Color.toFloatBits(255, 255, 128, 255) ;
      
      int k = i % 4 ; 
      meshVertices [ (i*6) + 4 ] = v2[k].x ;
      meshVertices [ (i*6) + 5 ] = v2[k].y ;
            
      
      
     }
If you are interested to see how the ground track texture looks like, here it is. Use it on your own disk(risk?)

More macro Phun

Many believe syntax of C + + is weird, a bit unintuitive, ugly, cryptic and obfuscated. Some are pointing out the Pascal syntax as an opposite parallel.
Let’s note that the Pascal language was initially developed by N. Wirth as an educational language. This language demonstrates such conceptual peculiarities, like strict typing and availability of means of structured (procedural) programming. And, by N. Wirth, this language should facilitate forming of a good style of algorithmic thinking, and, thus, programming. In particular, the author tried to make its syntax intuitively clear even at the first acquaintance with the discipline “Programming”.
During long time Pascal was fairly considered one of the best programming languages for education purposes. Unfortunately, the versions of programming environments, which were used to teach the language (Turbo Pascal, Borland Pascal), have become outdated.
New programming systems, which are based on Pascal, for example, Delphi, are too expensive and industrially, not educationally, oriented. Particularly, the programming environment is poorly suitable to teach basic programming and algorithmization due to its complexity. Well..you can use C++ to write in whatever language you like.Well not exactly, but pretty much. Here's an example of a fun proggie I wrote.
It demonstrates nested procedures, which aren't present in the actual Pascal.



#include "Pascal.h"

Program Project1
begin

var
Integer(U) = 7;
Single(x) = Single(U / 1.51);
String(str) = "cool";
 
WriteLn(str);
WriteLn("Input a symbol : ");
Read(U); 

if U > 5 then 
begin 
 WriteLn("Pascal rulez !!");
 Exit(0); 
end 
else
 begin
   WriteLn("C rockz!");
 end;
 
 for U = 0 to U < 10 do  
 begin
    WriteLn("C++ powns all ");
    Inc(U,1); 
 end;
 
 procedure NestedProc 
 begin
   var 
   String(s); //4astna  promenliva
 
    Begin
        s = "Hello from a nested proc ";
        WriteLn(s);
    End; 

  end NestedProc; 

 NestedProc.exec();
 
 Exit(0);
 
end


Here's how the header Pascal.h looks like.
using namespace std;
#include 
#include 
#define Integer int
#define Single float
#define Pointer void*
#define begin {
#define end }
#define end; }
#define WriteLn(str) printf(str)
#define Program int main(int argc, char *argv[])
#define Project1 
#define if if(
#define then )
#define Exit return
#define Result(x) return x
#define Integer(x) int x
#define do ;)
#define for for(
#define Inc(x,y) x += y
#define to ;
#define Read(x) scanf("%u",&x)
#define String(name) char* name
#define Pointer(p) void* p
#define procedure struct
#define Begin void exec(){
#define End };                                   
#define var   
#define Addr(x) &x
#define deAddr(x) *x
                                  
                                       

Deferred irradiance light probes

For a real-time graphics simulation, global illumination has always been a very difficult problem to solve. Interaction of the surfaces in a scene based on the light sources, diffuse reflections of the surfaces and light energy bouncing off geometry according it's material properties is usually not a trivial task to solve in real time. Several approximation solution exists, but only a small handful of them are practically applicable for performance-critical applications, such as 3D games and simulations.
I always feel nostalgic for the beautiful views of the old indoor games, lit with performant and convincing technique called "light mapping". There are several issues and limitations with it as well, but at least it was fast, and looked great for static environments. Static regarding light properties (color, range, movement and light animation of any kind.) and the scene geometry.
They eat up a lot of texture memory as well, and do not combine well with normal mapping and other per-pixel effects. Lighting is also not per-pixel perfect, but rather per-texel. Anyways, I really needed a real-time solution for my game, so I decided to experiment with light probes, rendered as deferred lights, spread across critical areas. Those probes are generated using cubemaps, rendered at probe's positions that are further converted and stored as spherical harmonics coefficients. I basically spread light probes automatically across an area (or only on key areas) calculate the incoming light at those points, send this data and shade affected pixels
This is only one bounce of indirect light. It could be extended to several bounces, which would look much better on complex scenes, and the real-time cost (performance) should be the same.
The following screen shots show the famous Sponza model, lit with that technique with GI turned on and off for comparison.


I will describe the technique in more details and provide source snippets in further posts.

Monday, February 17, 2014

Back to the pre-wheel epoch

Ever thought why so many people adore C++, and so many execrate it at the same time ? Well, actually I don't know, but I guess it has something to do with it's elemental power, wild beasty nature and unpredictable manner.And no, I'm not going into that weird 'pro-grammers' humor like for example -
"In C++ it's harder to shoot yourself in the foot, but when you do, you blow off your whole leg." by the god-father Bjarne Stroustrup, or
"Writing in C or C++ is like running a chain saw with all the safety guards removed," , or
"C(++) is a write-only, high-level assembler language." or even this :
"C++ : Hard to learn and built to stay that way !!" , and this :
"How C++ is like teenage sex:

  • It is on everyone's mind all the time. 
  • Everyone talks about it all the time. 
  • Everyone thinks everyone else is doing it. 
  • Almost no one is really doing it. 
  • The few who are doing it are: A. Doing it poorly. B. Sure it will be better next time. C. Not practicing it safely."

Most people think that some of the coolest feature of C++ is it's templates.They are increasingly found to be powerful instruments for the development of cleaner, faster and smarter software. Indeed, templates have become the corner stone of several new C++ programming paradigms.Templates are very useful when implementing generic constructs like vectors, stacks, lists, queues which can be used with any arbitrary type. C++ templates provide a way to re-use source code as opposed to inheritance and composition which provide a way to re-use object code.
Ok , that's great, but i would say that actually the good'old C macros are just as cool as C++ templates. Generic programming and templates in C ? Yes it's pretty much possible, with a bit of macros involved :) Here's an example i wrote to test my wheel reinvention deduction.It's a basic attempt to replace the C++ STL vector<> container.
Sorry about the code formatting.

#define VECTOR(type) struct type##_Vector \
{  public :  type *pArray;  int len;  type illegal; \
  type##_Vector() {   len = 0;   pArray = NULL; }; \ 
 void ClearAll()  {    memset(pArray, 0, sizeof(type) * len); \
   len = 0;  };    void Erase()  {    if(pArray != NULL) \
     free(pArray);    len = 0;    pArray = NULL;  }; \
  int push_back(type Data)  {  \
    type* pTmp = (type*)malloc(sizeof(type) * len + sizeof(type) ); \
      if(pTmp == NULL)        return -1; \    
 memcpy(pTmp, pArray, sizeof(type) * len);      free(pArray); \
      pArray = pTmp;    pArray[len] = Data;    return len++;  }; \ 
   void SetItemAt(int pos, type data) \  
 {    if((pos > -1) && (pos <= len))  \
   {      pArray[pos] = data;    }  } \
   type GetItemAt(int pos)  {    if((pos > -1) && (pos <= len)) \
      return pArray[pos];    return illegal; \
 } \

} 


int main(int argc, char* argv[])
{
VECTOR(int) v;
v.push_back(14);
v.push_back(77);

class test {
public :
char name[64];
test(){strcpy(name ,"wtf"); };
void setName(char* Name){strcpy(name,Name);};
};

VECTOR(test) vtest;

test t;
vtest.push_back(t);
printf(vtest.GetItemAt(0).name);
vtest.Erase();
v.Erase();
return 0;
}

Sunday, February 16, 2014

Photoshop mouse rampage.

Sometimes school is forcing you do things, that you would never approach otherwise. I'm not entirely convinced that painting is critical to a software developer, but either way the task was assigned
"Use your imagination and draw a fictional character by using Photoshop".
The goal was to make us learn about layers and get used to working with them. After 4 hours approximately, here is what I came up with ( unfinished )
I'm seriously thinking about buying a graphic tablet, so at least my contours aren't that randomly curved. The basic skeleton for this quick sketch was made on paper and scanned into Photoshop. 



Thursday, February 13, 2014

Welcome!

Hello and welcome to my new blog. Follow me here to discover what I'm up to.
Things that I will eventually focus on using this blog are as follows :
  • game development (probably primary)
  • game reviews, comments and rant.
  • graphics and art development in general.  
  • 3D modeling and 2D image manipulation.
  • programing in general.
  • programing API's, IDE's and tools eventually.
  • and the last, but not least - ranting about things :)