Update 74

This week I have done more art for the game, and then packing the art into multiple sprite sheets. After that, I have spent multiple days trying to optimize the loading of the sprite sheet.

At first, I have been trying to implement a support for DXT texture, but with SDL_gpu using stb_image to load the texture into an SDL_Surface and then converting it to a GPU_Image. I have tried to decode the DXT textures with GLI, but after that SDL_gpu was not able to recognize the format.

Another problem with DXT texture is the artifacts produced by the compression so I have been trying to find a format lossless and fast. I have made a small benchmark for png with no compression and a lot of compression with stb_image and libpng.

compressed png (stb_image): 360.591 ms
uncompressed png (libpng): 543.351 ms
compressed png (libpng): 330.504 ms

I was expecting the png with no compression to be faster, the time to read the file seems to outweigh the decoding of the png. The small png are compressed with TruePNG and the zopflipng with the max compression settings. To make the game load faster I can first load all the asset for a level in the RAM and then for each map transfer the asset needed into the VRAM. The total memory needed to load the assets of the level is: 30 * 2048 *2048 * 4 = 503 MB. This is fine since most people have at least 4GB of RAM.

To make the game load faster I can first load all the asset for a level in the RAM and then for each map transfer the asset needed into the VRAM. The total memory needed to load the assets of the level is: 30 * 2048 *2048 * 4 = 503 MB. This is fine since most people have at least 4GB of RAM (steam survey).

To make the game load faster I can first load all the asset for a level in the RAM and then for each map transfer the asset needed into the VRAM. The total memory needed to load the assets of the level is: 30 * 2048 *2048 * 4 = 503 MB. This is fine since most people have at least 4GB of RAM.

For the moment, loading on the fly compressed png files seem efficient enough, the loading time is around 1 second for the map with the most sprites to load.

Update 73

The last level is progressing slowly because I have changed the story little bit at one point and there are a lot of art to redo, new dialogs, and even new shaders.

Most of my shaders are a modified version of some shaders found on shadertoy. This time I have combined two shaders to make one.
This one applies a glitchy effect on the image and also radial blur at the position of the uniform mouse.

varying vec4 color;
varying vec2 texCoord;

uniform sampler2D tex0;
uniform sampler2D tex1;
uniform float globalTime;
uniform vec2 resolution;
uniform float Strength;
uniform vec2 mouse;

#define AMPLITUDE 0.2 //0.2
#define SPEED 5 //0.05

float rand(float n){return fract(sin(n) * 43758.5453123);}

vec4 rgbShift( in vec2 p, in vec4 shift, in float Samples) {
    shift *= 2.0*shift.w - 1.0;
    vec2 rs = vec2(shift.x,-shift.y);
    vec2 gs = vec2(shift.y,-shift.z);
    vec2 bs = vec2(shift.z,-shift.x);
	
    //vec2 pos = vec2(960.0*(resolution.x/1920.0), 540.0*(resolution.y/1080.0));
    vec2 pos = vec2(mouse.x, mouse.y);
    vec2 dir = (gl_FragCoord.xy-pos.xy)/resolution.xy*vec2(-1.0,1.0);
	
    float r = 0;
    float g = 0;
    float b = 0;
    float a = 0;
	
    for (int i = 0; i < Samples; i += 2) {
       r += texture2D(tex0,p+rs+float(i)/float(Samples)*dir*Strength).x;
       g += texture2D(tex0,p+gs+float(i)/float(Samples)*dir*Strength).y;
       b += texture2D(tex0,p+bs+float(i)/float(Samples)*dir*Strength).z;
       a += texture2D(tex0,p+float(i)/float(Samples)*dir*Strength).w;
		
       r += texture2D(tex0,p+rs+float(i+1)/float(Samples)*dir*Strength).x;
       g += texture2D(tex0,p+gs+float(i+1)/float(Samples)*dir*Strength).y;
       b += texture2D(tex0,p+bs+float(i+1)/float(Samples)*dir*Strength).z;
       a += texture2D(tex0,p+float(i+1)/float(Samples)*dir*Strength).w;
    }
    
    return vec4(r,g,b,a);
}

vec4 noise( in vec2 p ) {
    return texture2D(tex1, p, 0.0);
}

vec4 vec4pow( in vec4 v, in float p ) {
    // Don't touch alpha (w), we use it to choose the direction of the shift
    // and we don't want it to go in one direction more often than the other
    return vec4(pow(v.x,p),pow(v.y,p),pow(v.z,p),v.w); 
}

void main() {
    vec2 p = texCoord;	
    vec4 c = vec4(0.0,0.0,0.0,1.0);
    vec4 shift = vec4pow(noise(vec2(SPEED*rand(globalTime), 2.0*SPEED*rand(globalTime)/25.0)),11.0)*vec4(AMPLITUDE,AMPLITUDE,AMPLITUDE,1.0);
    const int Samples = 64;
	
    c += rgbShift(p, shift, Samples);
	
    gl_FragColor = c/float(Samples);
}

I think most of the shaders of the game are done by now. There is a total of 4 fragment shaders. After that, I have more art to do, maybe some animations and then the ending video of the game (I not sure what to include in the video).

Update 72

This week I have worked exclusively on the last level, adding new things, redoing old stuff. I am trying to add new effects such as this:

With this amount of particles, I doubt the particles system can handle it, I need to make some performance test. The solution good solution is to use shaders, there is this tutorial with WebGL.

In Obduction, the effect is used multiples times, so it needs to be available for multiple cases. I am only using this once in the game, so I can probably prerender this effect with adobe after effect in a video. This is probably the fastest solution if I can make the video fast enough. If I use shaders to make this effect it can add a lot of complexity in adding multiples effects at the same time. And another good thing with video is I don’t have to worry about the frame rate, the video will run at 30 fps

This is probably the fastest solution if making the video is fast. If I use shaders to make this effect it can add a lot of complexity in adding multiples effects at the same time. And another good thing with video is I don’t have to worry about the frame rate, the video will run at 30 fps. I don’t need to have input from the player for the effect, this makes the use of something prerendered possible.

Update 71

A lot of optimization and bug fixing this week, the level did not progress at all.I have optimized the text rendering with a small library

I have optimized the text rendering with a small library NFont developed by the creator of SDL_gpu. I have gained a more stable framerate 60 fps when a shader is used.

I have also improved the loading time of the game by generating sprite sheets for the objects. Doing that I have discovered the rendering of SDL_gpu (which use OpenGL) is not precise when the image is rotated, the image becomes blurry. So I add to replace SDL_gpu with a library specialized in image processing to have something precise. I have chosen a small, simple and header only library: CImg. The replacement is not finished yet, I need to redo the sprite sheets for the animations, maps, and menu.

There are so many unexpected bugs coming along, it became really difficult to have accurate estimations. The only thing I know is I have two months left before the job hunting. Hopefully, everything will be finished by then, if not I will continue working part-time on the game. I am not going to release something unfinished or not polished enough.

Update 70

A lot of profiling and refactoring have been done last week. I have also implemented some dialogs for the last level. I am trying to optimize the allocation of vectors using the function reserve. But first I have searched all over the internet to find the best free profiler. The profiler packed with visual studio 2015 seem to give the most readable result, microProfiler is also a nice one because you can profile in real time.  CodeXL doesn’t have support for intel processor and the interface is not so good.

The profiler packed with visual studio 2015 seem to give the most readable result, microProfiler is also a nice one because you can profile in real time.  CodeXL doesn’t have support for intel processor and the interface is not so good.

I am trying to optimize the text rendering in the game because sometimes when there is a shader applied the framerate drop from 60 fps to 15 fps. Maybe this is only due to the shader and I need to find a shader profiler.

For Christmas, I have received a new graphic tablet: Wacom Intuos medium pro since the small bamboo gives me wrist pain after working several hours on a piece. This tablet is better is every way possible, interface, precision, size, quality. The only downside is the price, like every other Wacom products you need to spend hundreds of dollars to have something good. I think this tablet have the best size and quality for the price since Cintiq are overpriced.

They are other brands like Huion, Ugee, Yiynova, the problem is Wacom have so many patents and years on experience on tablets it’s very difficult for new competitors to achieve the quality. Only maybe a very big corporation like Apple, Microsoft, Samsung can pull off a quality similar. And there are compatibilities problems with drivers of Wacom and other brands.

Only maybe a very big corporation like Apple, Microsoft, Samsung can pull off a quality similar. And there are compatibilities problems with drivers of Wacom and other brands. This tablet is also a best seller on amazon after the cheapest tablet of Wacom.

Update 69

The level 4 is finished, I am now working on the last level. This level is the ending of the game so it’s very short gameplay wise and they are a lot of dialogs.

Last week I have done an explosion with the particles system, this explosion has 100000 particles. At first, 100000 was too much to handle for the particle system.

After a lot of profiling, the engine I have found some interesting things:

rand() is too slow, so replace it with a xorshift generator, in the game engine I use xorshit128:

static uint32_t xor128x = 123456789;
static uint32_t xor128y = 362436069;
static uint32_t xor128z = 521288629;
static uint32_t xor128w = 88675123;
 
inline uint32_t xor128(void) {
	uint32_t t;
	t = xor128x ^ (xor128x << 11);
	xor128x = xor128y; 
	xor128y = xor128z; xor128z = xor128w;
	return xor128w = xor128w ^ (xor128w >> 19) ^ (t ^ (t >> 8));
}

Do not use std::vector to store the particles, push_back() and erase(iterator) are too slow. If you do you will see a lot CPU spent on memmove. A dynamically allocated array is way faster, only the initialization take time.

Use batching to reduce the number of draw call, with SDL_gpu the best way is to draw a lot of primitives is to use GPU_TriangleBatch. It adds a lot of code but you can’t have something faster than that.

unsigned short indices[3] = {0, 1, 2};  // These are references to the vertex array's vertices, 3 for a triangle
float values[8 * 3];  // Each vertex will need x, y, s, t, r, g, b, a (8 floats per vertex)
values[0] = x1;  // Position
values[1] = y1;
values[2] = s1;  // Texture coordinates (normalized)
values[3] = t1;
values[4] = r1;  // Color (normalized)
values[5] = g1;
values[6] = b1;
values[7] = a1;
values[8] = x2;  // Position
values[9] = y2;
values[10] = s2;  // Texture coordinates (normalized)
values[11] = t2;
values[12] = r2;  // Color (normalized)
values[13] = g2;
values[14] = b2;
values[15] = a2;
values[16] = x3;  // Position
values[17] = y3;
values[18] = s3;  // Texture coordinates (normalized)
values[19] = t3;
values[20] = r3;  // Color (normalized)
values[21] = g3;
values[22] = b3;
values[23] = a3;

GPU_TriangleBatch(image, target, 3, values, num_indices, indices, GPU_BATCH_XY_ST_RGBA);

With SDL you will need to use OpenGL VBO to achieve efficient batching.

Update 68

This week I needed to make some smoke  for an important object in the game so I have implemented a simple particle system. I tried to find libraries for a system particle but surprisingly there is very little free libraries still alive.  There are expensive middlewares like popcornfx and fork particle. At first, I was creating a rendered compatible with SDL_gpu for the library spark engine but after multiples unsuccessful tries I decided to make one myself, something very simple and basic.

After this key item, I can start polishing the last level.

Update 67

Lately, I have been implementing the secrets in the game but testing became a pain because I need to go to multiple maps through the game. Basically, I need to go through the whole game just to test if every secret make sense. To help me with the testing I have been trying to add a GUI menu for debugging purpose, but there is no really good GUI it seems.

I have been testing :
CEGUI 0.8.7 : The tutorial are mostly written for the previous version 0.7, a lot of things are missing. I have failed to run the examples, the library is quite big. I need to waste a lot of time on forums or adapting examples just to get something simple basic working.  A lot of dependencies are required.

kiss_sdl : Very lightweight library where the rendering is performed by SDL and SDL_image. So I need to modify the library to use SDL_gpu, quite a bit of work. Developed by one person, so it could be buggy.

nanogui-sdl : The implementation have some problem on windows, static linking is creating conflict. This is a port of another library : nanogui.

After all these research I decided to simply do a small command line tool myself something very small, where I can warp, get an object and change a variable.

cmd2

Update 66

This week I have finished the small fake apps for the mobile phone in the game. I have discovered some bugs with the save file, where most of the thing on the mobile were not saved, and when you load the save you obtain old and new data mixed up (soft lock),

I have discovered some bugs with the save file, where most of the thing for the mobile were not saved, and when you load the save you obtain old and new data mixed up (soft lock). I am reimplementing that part correctly in XML because before it was done with some custom ugly formatting with many separators. The save file is bigger but this doesn’t have much importance. RapidXML is pretty fast so I can have a lot of data without having to worry about it.

I have some random disconnection from the internet which doesn’t help when I need to google some documentation or write an article on this blog for example. Nevertheless, the level 4 is progressing rapidly, each day new stuff is found and done. The save system took most of the weekend, so hopefully it’s finished tonight.

Sometimes I read some depressing stuff about indie games like that.

don’t go indie, 5 years of gamedev will kill you

Some people put everything on the line for one project, and at the end of the development : burnout and quit game development (or take a long break from it).

In my opinion, creating indie games are like writing novels or making paintings you are here for the long run. Success with the first game should not be considered the norm, but some people are lucky enough to have success for their first title : Undertale, Stardew Valley, Limbo, Fez, Dust: An elysian tale, and many others. And journalists create this myth, that anyone who works hard  can succeed, only hard work and quality matters.

Well, that’s weird why games should be more accessible than other media? They are some talented writer who works very hard on each of their books and they don’t necessarily became famous during their lifetime. It the same thing with starving artists, there are some other deciding external factors for success. There is no formula for success and all the unknown factors are called luck.

It makes me sad, when I see some people having a big hit (Minecraft, FEZ) and after that retiring from games development. It seems they don’t have enough love for their craft and take the easy path instead. I prefer to think of the courageous people who continue to make games no matter what.

Update 65

This week I have done a lot of programming with the game, I have implemented the SMS part correctly on the mobile phone in the game. Now you can use the phone to have a conversation with someone.

I have also integrated the video support with the library TheoraPlay. I need to integrate a video for one of the application in the phone :

The app is not finished yet, I need to work on the design, add buttons, etc…

The level 4 is almost finished but each time I think there are only small amount works something come and takes like a week. The only thing I can say for sure is : “It’s not done yet.”

It’s kind of preposterous to have a release with so many things changing on the fly. If you had asked me 3 days ago :

– “Do you need to have video support for that?”
– “No, why?”

3 days later 

– “Oh I see this is definitely the simplest solution ever