2009/09/30

Computer piracy: common myths, and how copyright laws should be working


Intro



Recently I saw some old thread on ign or gamespot, where someone told people that he uses pirated game. Immediately a flamewar erupted, with standard pro/anti-piracy argument :"you should be paying game developers!", "why should I be paying for something I can get free?", "piracy is theft!", "no it is not a theft", etc.

I'm sick of such arguments, because they are based on mistakes and misconceptions.
So I've decided to write a small list of "standard" arguments, explain why (I think) they are wrong, how I think copyright should be working, and why it is not going to happen.

Everything written here is my personal opinion.

Standard pro/anti-piracy arguments and why they are wrong




  • "Piracy is a theft!"

    This one is most often discussed. If you do a little google search about piracy theft, you'll probably find a lot of blog posts explaining why it is not a theft. Many of them will make sense(this one, for example), and some are even written by people that were interesting in things other than legalizing piracy.


    I have to disappoint moralists, saying that "piracy is theft, which is why it is bad" - piracy is not a theft, it is copyright infringement or copyright violation (read wikipedia, or your local laws). It was already explained one billion times, but let's explain it once again (to keep all argument within this article).


    Theft is when you take someone's property, and after that owner doesn't have access to that property anywhere. This is a critical part of "theft". I.e. if you take item from the shop without paying, and shop can't sell that item anymore, then it is theft. However, when you copy material (be it music, movie or game), owner still has access to original media, and still can sell endless number of copies. So, because owner doesn't lose access to the property, it is not a theft. However, it is still copyright violation.


    In case of theft, stolen object doesn't have to be material. If you steal someone's email password, or if you log into online game, and steal someone's item, it is stell theft (although laws most likely will classify that as hacking/unathorized access). Same thing happens if you take someone's serial number/registration info and delete all trace of that information on victim's computer.


    The reason why you keep hearing that "piracy is theft" is because someone wants you to feel guilty for pirating stuff. Although this is a fine goal (since people in general will feel less guilt about pirating than they will feel about stealing something), it is a lie.

  • "If it isn't theft, then it isn't bad!"

    This one is never said in the open, but is probably by at least half of people that keep saying that "piracy is not a theft". Theft or not, it is still illegal. It is much simpler to keep words "good" and "bad"(and "right"/"wrong") away, and simply concentrate on "legal" and "illegal". This is because everyone has slightly different definition of "good" and "bad" while legality of something is defined by your laws which are at least supposed to be impossible to misinterpret. So if you still want to pirate something, keep in mind, that no matter whether you think it is "right" or "wrong" thing to do, it is still illegal, which means you might get your punishment eventually.


    The sad thing about this is that sometimes people that already bought computer game or movie (this problem doesn't affect music) have also to get pirated copy because of some problem with the game. To my experience, normally publisher is responsible for that. Some examples:


    • If the game or movie is localized and original game/movie was not in your language, then publisher might remove original soundtrack and/or text. Which means (if you know original language of the game), you will have to either to pirate original (because translation is never perfect), or tolerate bad acting and/or bad translation. The one nice example of this situation is "Witcher" computer game. The game had 3 versions: Polish, Russian, and English. Polish version had best voice acting. Russian had best translation, and worst voice acting. And Englih had mediocre voice acting and worst english translation (translators simply cut 50..75% of original material). Great, isn't it? Why is it that difficult to keep original soundtrack is beyond me. After all, we have DVD9 (not to mention bluray( at the moment.
    • The game has some kind of copy protection mechanism that doesn't work on user's computer. In this case user might be forced to buy game and then pirate it in order to play it. I know at least a few publishers that remove SECUROM and replace it with Starforce during localization. While (non disk-based)securom is pretty tame copy-protection mechanism(never had a single problem with my Spore), the destiny of starforce is to chew your CD/DVD to death, so you will have to buy game again. Also it is very picky and I heard more than one story about it causing BSODs.
    • The game has serious disk-based copy-protection, so user is unable to create a backup. In this case user will probably have to bypass copy protection mechanism in order to keep disk playable. Online authorization (steam, securom) is much better than disk-based protection, however you have no warranty that servers will exist forever. Will steam servers still exist 50 years later? I don't know, but it looks unrealistic.

  • "If you pay for your game/movie, you give money to developers!"

    This one is the funniest from all arguments.

    I do not know how cash flows in music, industry, but I worked as a hired programmer on few games, so I have at least brief idea how cash works in game industry.

    The cold truth that whether original game developer gets any money you gratuitously paid for the game depends on how they manage royalties. There are no warranties.


    At least some people won't get a dime from your money - because they were hired, paid by hour and won't get additional payment once development is over. There always will be one person that won't get your cash. Perhaps lead designer or lead programmer gets a cut from all the cash. Fine. But what about all the testers? Tool programmers? All artists? Motion capture actors? The janitor (yeah, he/she is also responsible for the game development)? Do they all get a cut from profits? I seriously doubt that. Most of those folks probably won't get any extra cash once development is over.


    Indie developer probably will get good portion of money, minus commission paid to reseller - because they might be selling stuff nearly directly. As for larger companies, this needs investigation (see this thread for more info, for example). There are couple of ways how publisher could acquire game right. Publisher could buy all rights (so game developers won't get your extra money), some of them might pay royalties, but this is not warrantied. Also keep in mind, that sometimes games are still sold when developer is long gone (example: Fallout 2, old games in general). Who is getting your money? The publisher.

    Same is probably true for the movie industry. Can you imagine camera man getting royalties for new Hollywood blockbuster? I cannot. Perhaps in music industry situation is different, but I do not know that for sure.

    There is always creator/developer who creates stuff and publisher who sells you the stuff. If they are same person/company, then you are lucky. And if they are not - then it is unclear whether creator gets anything from cash you gave or not. However thinking that all your cash goes straight to the developer is lying to yourself.

    The situation might be better for companies that develop software (not games), because they might be selling it themselves. However, in this case some developers probably still won't get a dime from your money. Certain large companies are famous for buying right for piece of software from other companies, and then selling it to end users. In this case original developer not getting anything from your cash.

  • "More cash means better games"

    It is a bit unrelated to to piracy, but I had to mention it anyway. For some strange reason, when (game) developer starts its' journey to the top, they create classics (example: Doom 1), but once they are well-known, well-paid and have tons of cash, situation sometimes changes and instead of quality product, they start aiming at larger audiences. This result in good graphics and bad gameplay. This is how (I think) we got boxes with unlimited ammo in first-person shooters, regenerating health, and enemies that scream at you to indicate where they are. This is how games from being a challenge turned into popular entertainment, like TV. There are some exceptions, but in general when product becomes popular, it somehow might get nice graphics and bad gameplay. So you get a game where you can see how much money was thrown at it judging by graphical quality, but which loses to its' predecessor when it comes to gameplay. There are exceptions, of course (and there are games that have good graphics and solid gameplay), but in general, more money does not mean better games.

  • "Why should I pay for something I can get for free". This one is obvious, but I had to mention it for the sake of completeness. Original creator(s) should be praised for his/her/their job, or there will be no more games/movies for you. If no one pays - eventually creators obviously won't get paid. However, on other hand, there will be always overpriced low-quality products, and you really need to be sure who gets your money. Which makes situation not so obvious.


How copyright should work


Here is how I see ideal copyright laws:

  • By purchasing digital product (music, video game, software), you acquire right to download, use, view, copy, recompress (or convert into another format), upload it onto any network and download it again in another resolution/language.
  • This right is can be sold/transferred to another person. After the the transfer you no longer have the rights mentioned in part 1.
  • You cannot keep the right after you gave it to someone else.
  • Only publisher or original creator can sell/give those rights in unlimited quantites.


Why it makes sense


In this situation you would be able to download movie from any p2p network you like, pay for it, and live happily ever after. You will be able to continue seeding the movie without fear of getting sued - because you are reducing transfer costs for the publisher, and make material available for other people. In this case guy that downloaded movie without paying will be responsible, not you. You will be able to convert movie or music to any format you want, to be able to listen/use it on other device. And if you had a hardware failure, you will be able to download your material again with no additional fees. And you will be able to get same thing dubbed into another language.

..and why it is never going to happen



  • This set of rules doesn't mention broadcast/public performance rights.
  • Such scheme requires central registry of your rights.
  • Such scheme requires a way to identify what you are using on your PC.
  • And I cannot imagine any way to manage those rights and keep user to be able to convert material into any possible format.
  • This will mean heavy losses for publishers - user won't have to buy same movie/game again if disk was destroyed by accident. Which would mean either higher prices, or lower-quality material
  • To be implemented perfectly, this system should not be dependant on any external servers. Which makes it impossible to implement.
  • We are not living in perfect world, unfortunately.


What we have now instead.



Right now two closest things we have are Valve's Steam and any DRM.


Steam is good because it allows you to get required language pack for your game, but it doesn't qualify for the ideal copyright management system, because it doesn't allow you to upload (to p2p)/sell your games, and because your account can be stolen. Also, if server is offline, you won't be able to play your game.


And DRM doesn't qualify because of dependency on external server (server is down - no music for you), and because it forbids copying. Pity that inventors of DRM seems to be more interested in restricting copying than in making user's life easier.


Conclusion


And, this is it...
End of article. There are still imperfect laws and there is still piracy. What to do? Honestly, I don't know. Perhaps, this writing will give someone better ideas, and perhaps someday there will be better copyright management system. Maybe even ideal one. Or maybe nothing will ever change, and people will always equalize piracy to theft, or they will still thing that if it is not a theft, than it is good thing to do, not recognizing that "there is no black and white, only shades of gray", and piracy situation is not so simple.
Only time will tell.

2009/09/29

Example-based texture generation with SDL/OpenGL using bruteforce


Intro:

During last weekend I've decided to try implementing texture generation algorithm, where texture is being generated from example (photo or something else). I've got several interesting results, and a couple of problems. The attempt was inspired by this paper(PDF link), but I decided to try simple bruteforce before trying to use "jumpmaps".

Links:

  • Steve Zelinka's publications(includes couple of interesting material, like "Interactive Texture Synthesis on Surfaces Using Jump Maps.", "Mesh Modelling With Curve Analogies". Definitely worth checking out, however, I was only interested in texture generation at the moment.
  • Jump maps on surfaces (pdf, Steve Zelinka and Michael Garland)


Results:
Here is the example pattern I used:

And here is the result I got:


Algorithm:

  • Fill destination image with black, and make every pixel transparent.
  • Copy any pixel from pattern image into top-left corner of destination image.
  • For every transparent pixel of destination image (i.e. alpha == 0) with non-transparent neighbors within search distance, replace it with pixel from pattern image where non-transparent pixels in neighborhood most closely resemble non-transparent pixels in destination image's neighborhood of current pixel. Best matching pixel found by bruteforce search (yes, it is slow). Repeat until there are no more transparent pixels left.


How neighborhoods are compared:
There are several ways to do this:

  • Compute distance(within search distance) for every non-transparent pixel in current neighborhood, add distances up, divide sum by number of non-transparent pixels. Find pixel in pattern image with the smallest distance.
  • Add up (into rgb vector) all non-transparent pixel within search distance in destination surface into one vector, Add up up all non-transparent pixels within search distance from candidate pixel in pattern surface, compute distance between them. Find surface with smallest distance.

Things to keep in mind:

  • When calculating differences, watch out for transparency. DO not use pixels at offsets (from candidate) where source or pattern pixel are transparent.
  • Destination surface should be tileable, so pixel operations wrap around. Pattern is no tileable, so pixels near the border should not used.


Good things:

  • Tileable (well, you can see some repeating patterns, bot no obvious seams)
  • Looks great/realistic.


Problems:

  • It is incredibly slow. Example image took at least one hour (or more) to be finished. Cannot be used in realtime.
  • I've run into problems when I tried to do same thing using OpenGL/GLSL and DirectX/HLSL (to see if it will work faster):

    • In DirectX HLSL shader could not be compiled. D3DXCompileShaderFromFile simply hung during compilation, and I wasn't in the mood for assembly.
    • In OpenGL, it looks like there is no way to select mip level from within GLSL fragment shader. So, I can say farewell to cheap search optimization.
    • In OpenGL, I hit weird problem - entire system becomes unusable (stops responding, etc) when current frame is being rendered. And because one frame takes several seconds, this means, you can't do anything else on the system while application is running.



Perhaps it makes sense to try another algorithm or reimplement this thing on CUDA. Maybe I'll do it some other time, maybe not.

Code:
Code is free to use/redistribute for non-commercial purposes.
Code didn't completely fit into window, and I'm not in the mood for template hacking right now. If you want to see everything, select, copy and paste code into notepad (or kedit/jedit or whatever).

sdl version
main.cpp:


#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#include <common/timer.h>
#include <common/keyboard.h>
#include <wchar.h>
#include <math.h>

using Keyboard::keyPressed;

static Timer timer;
static int texPowX = 9;
static int texPowY = 9;
static int texWidth = 1 << texPowX;
static int texHeight = 1 << texPowY;
static int scrWidth = texWidth;
static int scrHeight = texHeight;
static int texMaskX = texWidth - 1;
static int texMaskY = texHeight - 1;
static int searchWidth = 3;
static int searchHeight = 3;
struct Dist{
unsigned long r, g, b;
};

size_t numPatternPixels = 0;
Dist* precomputedDist = 0;

struct Pixel{
unsigned char b, g, r, a;
};

void fillPixel(int x, int y, SDL_Surface* dst, SDL_Surface* src, int dstMaskX, int dstMaskY){
Pixel& dstPix = *((Pixel*)((char*)(dst->pixels) + sizeof(Pixel)*x + dst->pitch*y));

int xMin = x + texWidth - searchWidth;
int xMax = xMin + searchWidth*2;
int yMin = y + texHeight - searchHeight;
int yMax = yMin + searchHeight*2;


int numFilled = 0;
for (int curY = yMin; curY < yMax; curY++)
for (int curX = xMin; curX < xMax; curX++){
Pixel& cur = *((Pixel*)((char*)(dst->pixels) + sizeof(Pixel)*(curX & texMaskX) + dst->pitch*(curY & texMaskY)));
if (cur.a != 0)
numFilled++;
}

if (numFilled == 0){
int srcX = rand() % src->w;
int srcY = rand() % src->h;
dstPix = *((Pixel*)((char*)(src->pixels) + sizeof(Pixel)*srcX + src->pitch*srcY));
dstPix.a = 0xFF;
return;
}

int storedSrcX = rand() % src->w;
int storedSrcY = rand() % src->h;
float lastDifference = 3.40282347e+37F;

//unsigned char mask =

for (int srcY = searchHeight; srcY < (src->h - searchHeight); srcY++)
for (int srcX = searchWidth; srcX < (src->w - searchWidth); srcX++){
float curDifference = 0;
int numPixels = 0;
for (int tmpY = -searchHeight; tmpY < searchHeight; tmpY++)
for(int tmpX = -searchWidth; tmpX < searchWidth; tmpX++){
Pixel& tmpSrc = *((Pixel*)((char*)(src->pixels) + sizeof(Pixel)*(srcX+tmpX) + src->pitch*(srcY+tmpY)));
Pixel& tmpDst = *((Pixel*)((char*)(dst->pixels) + sizeof(Pixel)*((x + dst->w + tmpX) & dstMaskX) + dst->pitch*((y + dst->h + tmpY) & dstMaskY)));
if (tmpDst.a){
numPixels++;
int dr = tmpSrc.r - tmpDst.r;
int dg = tmpSrc.g - tmpDst.g;
int db = tmpSrc.g - tmpDst.g;
curDifference += dr*dr + dg*dg + db*db;
}
}
if (numPixels)
curDifference /= (float)numPixels;
if (curDifference < lastDifference){
lastDifference = curDifference;
storedSrcX = srcX;
storedSrcY = srcY;
}
}

dstPix = *((Pixel*)((char*)(src->pixels) + sizeof(Pixel)*storedSrcX + src->pitch*storedSrcY));
dstPix.a = 0xFF;
}

int main(int argc, char** argv){
SDL_Init(SDL_INIT_VIDEO);

SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

Keyboard::init();
timer.reset();
timer.setMaxFps(100);
timer.setMinFps(5);

SDL_Surface* screen = SDL_SetVideoMode(scrWidth, scrHeight, 32, SDL_SWSURFACE);

SDL_Surface *texture = SDL_CreateRGBSurface(SDL_SWSURFACE, scrWidth, scrHeight, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);

if (screen == 0){
fprintf(stderr, "couldn't set mode %dx%d!\n", 640, 480);
SDL_Quit();
return -1;
}

SDL_Surface *image = IMG_Load("example.png");
SDL_Surface *example = SDL_CreateRGBSurface(SDL_SWSURFACE, image->w, image->h, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
SDL_BlitSurface(image, 0, example, 0);

SDL_FreeSurface(image);
SDL_LockSurface(example);

numPatternPixels = example->w * example->h;
precomputedDist = new Dist[numPatternPixels * 256];
memset(precomputedDist, 0, sizeof(Dist)*numPatternPixels*256);
for (int mask = 0; mask < 256; mask++){
printf("processing mask %d", mask);
for (int y = 0; y < example->h; y++)
for (int x = 0; x < example->w; x++){
Dist& curDist = precomputedDist[x + y*example->h + mask*numPatternPixels];
}
}


size_t numPixels = scrWidth*scrHeight;
SDL_LockSurface(texture);
for (int y = 0; y <scrHeight; y++)
for (int x = 0; x < scrWidth; x++){
Pixel& cur = *((Pixel*)((char*)(texture->pixels) + sizeof(Pixel)*x + texture->pitch*y));
cur.r = cur.g = cur.b = 0xFF;
cur.a = 0;
}

SDL_UnlockSurface(texture);

int x = 0;
int y = 0;

bool running = true;
while (running){
SDL_Event event;
if (SDL_PollEvent(&event)){
switch(event.type){
case SDL_QUIT:
running = false;
break;
};
}
timer.update();
Keyboard::update();

SDL_LockSurface(texture);

for (int i = 0; (i < 100) && (y < scrHeight); i++){
/*Pixel& cur = *((Pixel*)((char*)(texture->pixels) + sizeof(Pixel)*x + texture->pitch*y));
cur.r = rand() & 0xFF;
cur.g = rand() & 0xFF;
cur.b = rand() & 0xFF;
cur.a = 0xFF;*/
fillPixel(x, y, texture, example, texMaskX, texMaskY);
x++;
if (x >= scrWidth){
x = 0;
y++;
}
}
SDL_UnlockSurface(texture);

static bool saved = false;
if ((y >= scrHeight) && !saved){
SDL_SaveBMP(texture, "result.bmp");
saved = true;
}

if (keyPressed(SDLK_ESCAPE))
running = false;

SDL_BlitSurface(texture, 0, screen, 0);
SDL_UpdateRect(screen, 0, 0, scrWidth, scrHeight);
}

delete[] precomputedDist;
SDL_UnlockSurface(example);
SDL_FreeSurface(example);
SDL_FreeSurface(texture);
SDL_Quit();
return 0;
}





OpenGL version:


#include <SDL/SDL.h>
#include <glee/glee.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <common/glutils.h>
#include <common/Framebuffer.h>
#include <common/textures.h>
#include <common/timer.h>
#include <common/keyboard.h>
#include <FTGL/FTGL.h>
#include <FTGL/FTGLPixmapFont.h>
#include <wchar.h>
#include <math.h>

using Keyboard::keyPressed;

static Timer timer;
static const int texSize = 128;
static int scrWidth = texSize;
static int scrHeight = texSize;
static const int searchSize = 3;

static const char* vsText =
"varying vec2 texCoords;\n"
" const float gridSize = 10.0;\n"
"void main(void){\n"
" gl_Position = ftransform();\n"
" texCoords = gl_MultiTexCoord0;\n"
"}\n";

static const char* fsText =
"varying vec2 texCoords;\n"
"uniform sampler2D srcTex;\n"
"uniform sampler2D patternTex;\n"
"uniform vec2 srcTextureSize;\n"
"uniform vec2 srcPixelSize;\n"
"uniform vec2 patternTextureSize;\n"
"uniform vec2 patternPixelSize;\n"
"uniform vec2 searchSize;\n"
"void main(void){\n"
" vec2 uv = texCoords;\n"
" vec4 thisColor = texture2D(srcTex, uv);\n"
" gl_FragColor = thisColor;\n"
" if (thisColor.a > 0.0)\n"
" return;\n"
" vec4 leftColor = texture2D(srcTex, uv - vec2(srcPixelSize.x, 0.0));\n"
" vec4 topColor = texture2D(srcTex, uv - vec2(0.0, srcPixelSize.y));\n"
/*" vec4 rightColor = texture2D(srcTex, uv + vec2(srcPixelSize.x, 0.0));\n"
" vec4 bottomColor = texture2D(srcTex, uv + vec2(0.0, srcPixelSize.y));\n"
" if ((leftColor.a == 0.0)&&(topColor.a == 0.0)&&(rightColor.a == 0.0)&&(bottomColor.a == 0.0))\n"*/
" if ((leftColor.a == 0.0)&&(topColor.a == 0.0))\n"
" return;\n"
" float lastDistance = 0.0;\n"
" bool first = true;\n"
" vec2 lastCoords = vec2(0.0);\n"
" vec2 patEndCoords = (patternTextureSize - searchSize - vec2(0.5))*patternPixelSize;\n"
" vec2 patStartCoords = (searchSize + vec2(0.5))*patternPixelSize;\n"
" vec2 patCoords = patStartCoords;\n"
" for(patCoords.y = patStartCoords.y; patCoords.y < patEndCoords.y; patCoords.y += patternPixelSize.y){\n"
" for(patCoords.x = patStartCoords.x; patCoords.x < patEndCoords.x; patCoords.x += patternPixelSize.x){\n"
" vec2 tmpCoords = vec2(0.0);\n"
" float distance = 0.0;\n"
" for(tmpCoords.y = -searchSize.y; tmpCoords.y <= searchSize.y; tmpCoords.y += 1.0){\n"
" for(tmpCoords.x = -searchSize.x; tmpCoords.x <= searchSize.x; tmpCoords.x += 1.0){\n"
" vec4 srcColor = texture2D(srcTex, (tmpCoords*srcPixelSize) + uv);\n"
" vec4 patternColor = texture2D(patternTex, (tmpCoords*patternPixelSize) + patCoords);\n"
" if (srcColor.a > 0.0){\n"
" vec3 dist = srcColor.xyz - patternColor.xyz;\n"
" distance += dot(dist, dist);\n"
" }\n"
" }\n"
" }\n"
" if (first||(distance < lastDistance)){\n"
" lastDistance = distance;\n"
" lastCoords = patCoords;\n"
" first = false;\n"
" }\n"
" }\n"
" }\n"
" gl_FragColor = texture2D(patternTex, lastCoords);\n"
" gl_FragColor.a = 1.0;\n"
"}\n";


void textureRect(float x, float y, float width, float height){
float x1 = x, y1 = y, x2 = x1 + width, y2 = y1 + height;
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(0, 0);
glVertex2f(x1, y1);
glTexCoord2f(1, 0);
glVertex2f(x2, y1);
glTexCoord2f(1, 1);
glVertex2f(x2, y2);
glTexCoord2f(0, 1);
glVertex2f(x1, y2);
glEnd();
}

int main(int argc, char** argv){
srand(GetTickCount());
SDL_Init(SDL_INIT_VIDEO);

SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 0);

Keyboard::init();
timer.reset();
/*timer.setMaxFps(100);
timer.setMinFps(5);*/

if (scrWidth <= 128){
scrWidth = texSize * 4;
scrHeight = texSize * 4;
}

if (SDL_SetVideoMode(scrWidth, scrHeight, 32, SDL_OPENGL) == 0){
fprintf(stderr, "couldn't set mode %dx%d!\n", scrWidth, scrHeight);
SDL_Quit();
return -1;
}

FTGLPixmapFont font("DejaVuSans.ttf");
font.CharMap(ft_encoding_unicode);
font.FaceSize(10);
FTGLPixmapFont largeFont("DejaVuSans.ttf");
largeFont.CharMap(ft_encoding_unicode);
largeFont.FaceSize(40);
SDL_ShowCursor(SDL_DISABLE);

glClearColor(0, 0, 0, 0);
glClearDepth(1.0);

Framebuffer *framebuffers[2] = {0, 0};
framebuffers[0] = new Framebuffer();
framebuffers[1] = new Framebuffer();
for (int i = 0; i < 2; i++)
framebuffers[i]->setSize(texSize, texSize);

int currentFramebuffer = 0;

Texture* texture = new Texture("example3.png", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR);

glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);

GLuint filterProgram = 0;

filterProgram = createProgram(vsText, fsText);
checkGlError();

GLuint srcSamplerUniform = glGetUniformLocation(filterProgram, "srcTex");
GLuint patternSamplerUniform = glGetUniformLocation(filterProgram, "patternTex");
GLuint srcTextureSizeUniform = glGetUniformLocation(filterProgram, "srcTextureSize");
GLuint srcPixelSizeUniform = glGetUniformLocation(filterProgram, "srcPixelSize");
GLuint patternTextureSizeUniform = glGetUniformLocation(filterProgram, "patternTextureSize");
GLuint patternPixelSizeUniform = glGetUniformLocation(filterProgram, "patternPixelSize");
GLuint searchSizeUniform = glGetUniformLocation(filterProgram, "searchSize");

bool running = true;
while (running){
SDL_Event event;
if (SDL_PollEvent(&event)){
switch(event.type){
case SDL_QUIT:
running = false;
break;
};
}
timer.update();
Keyboard::update();

currentFramebuffer = currentFramebuffer ^ 1;
Framebuffer* src = framebuffers[currentFramebuffer];
Framebuffer* dst = framebuffers[currentFramebuffer ^ 1];

if (keyPressed(SDLK_ESCAPE))
running = false;

glDisable(GL_DEPTH_TEST);

/*
framebuffer rendering
*/
dst->begin();
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, dst->width, 0, dst->height);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, src->renderTexture);

glEnable(GL_ALPHA_TEST);
glAlphaFunc(GL_GREATER, 0);
float f = 1.0f/ 9.1f;
/*glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE);*/
static bool first = true;
textureRect(0, 0, (float)(src->width), (float)(src->height));
bool justFinished = false;
if (first){
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture->tex);

float s = (float)(rand() % texture->width)/(float)texture->width;
float t = (float)(rand() % texture->height)/(float)texture->height;
glTexCoord2f(s, t);
glBegin(GL_POINTS);
glVertex2f(0, 0);
glEnd();

glRasterPos2i(10, 20);

//textureRect((float)(rand() % dst->width), (float)(rand() % dst->height), (float)(texture->width), (float)(texture->height));
//textureRect(0, 0, (float)(texture->width), (float)(texture->height));
first = false;
}
else{
textureRect(0, 0, (float)src->width, (float)src->height);
static int x = 0;
static int y = 0;
static const int tileSize = texSize;
static int xSize = texSize/tileSize;
static int ySize = texSize/tileSize;
static int counter = -tileSize;
if (y < ySize){
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture->tex);
glUseProgram(filterProgram);
if(filterProgram){
glUniform1i(srcSamplerUniform, 0);
glUniform1i(patternSamplerUniform, 1);
glUniform2f(srcTextureSizeUniform, (float)src->width, (float)src->height);
glUniform2f(srcPixelSizeUniform, 1.0f/(float)src->width, 1.0f/(float)src->height);
glUniform2f(patternTextureSizeUniform, (float)texture->width, (float)texture->height);
glUniform2f(patternPixelSizeUniform, 1.0f/(float)texture->width, 1.0f/(float)texture->height);
glUniform2f(searchSizeUniform, (float)searchSize, (float)searchSize);
}

float x1 = (float)(x * tileSize);
float s1 = x1/(float)(src->width);
float x2 = (float)((x+1) * tileSize);
float s2 = x2/(float)(src->width);
float y1 = (float)(y * tileSize);
float t1 = y1/(float)(src->height);
float y2 = (float)((y+1) * tileSize);
float t2 = y2/(float)(src->height);
glBegin(GL_TRIANGLE_FAN);
glTexCoord2f(s1, t1);
glVertex2f(x1, y1);
glTexCoord2f(s2, t1);
glVertex2f(x2, y1);
glTexCoord2f(s2, t2);
glVertex2f(x2, y2);
glTexCoord2f(s1, t2);
glVertex2f(x1, y2);
glEnd();

counter++;
if (counter >= tileSize){
counter = 0;
x++;
if (x >= xSize){
x = 0;
y++;
if (y >= ySize){
//save texture
justFinished = true;
}
}
}
}
//textureRect(0, 0, (float)src->width, (float)src->height);
}
glUseProgram(0);
glActiveTexture(GL_TEXTURE0);
dst->end();

if (justFinished){
SDL_Surface* tmp = SDL_CreateRGBSurface(SDL_SWSURFACE, dst->width, dst->height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
SDL_LockSurface(tmp);
glBindTexture(GL_TEXTURE_2D, dst->renderTexture);
glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, tmp->pixels);

SDL_UnlockSurface(tmp);
SDL_SaveBMP(tmp, "result.bmp");
SDL_FreeSurface(tmp);
}


glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, scrWidth, scrHeight, 0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glClearColor(0, 0, 0.5f, 0);
glClear(GL_COLOR_BUFFER_BIT);

glBindTexture(GL_TEXTURE_2D, dst->renderTexture);

//textureRect(0, 0, (float)dst->width, (float)dst->height);
textureRect(0, 0, (float)scrWidth, (float)scrHeight);

glBindTexture(GL_TEXTURE_2D, 0);

wchar_t buf[256];
swprintf(buf, 256, L"fps: %.2f", timer.getFps());
glRasterPos2i(10, 20);

font.Render(buf);

glFlush();
SDL_GL_SwapBuffers();
}

if (glIsProgram(filterProgram))
glDeleteProgram(filterProgram);

delete texture;
for (int i = 0; i < 2; i++)
delete framebuffers[i];

SDL_Quit();
return 0;
}




2009/09/03

The meaning of life and everything


Well, this time it isn't about programming or computers, but this was bothering me for a while. Warning: this text might be depressing, because I have no answer for that question.

Have you ever thought about this: everything you see around you eventually will disappear. Think about it. Many human-made object will be broken within 100 years. People last less than 200 years, so in a 200 years there probably will be no you (well unless you are lucky enough to find or invent immortality cure). Buildings last longer, but most of them won't survive even a few hundreds of years. In a few billions of years sun will explode and destroy the planet. And in a few more billions of years universe will collapse back to the single point it appeared from. So there will be nothing left at all.

"Daisy Owl" nicely illustrates the problem(here).

This makes me wonder - what is the point of everything? Every single thing that exists will eventually disappear. And in the end there will be no one left to tell the tale or remember anything. As if nothing ever existed at all.

I guess happiest people never run into that question.

The problem here is not that all matter will disappear. Some of the theories about the end of universe suggests that matter will remain (but temperature will drop to absolute zero). The problem is that every object or person (including yourself) around you already doesn't exist anymore - at some point in the future (or there is no longer any observer for this object), which is hard to accept simply because it doesn't feel "right".

Another problem is that human mind wants a meaning for everything (well, at least mine does). The most logical answer is that life has no meaning and is an accident. However, this idea is incredibly hard to accept. I guess that it is easier for religious people to face this question - after all, at least in some religions you are immortal (your soul, which is basically you), or you are reborn, and at the "end of times" you will meet all other people and you will live happily ever after. On other hand that eternal life in heaven/hell might not be that different from "end of time" in one of scientific theories - everything kind of "stops" and remains same forever.

If you think more about all of this, you can notice one interesting thing: the more advanced technology becomes, the less chances it has to exist for long time and less chances it has to be comprehensible for next civilization should humanity disappear. Think about it. As far as I know, writings on the stone can exist for a lot of time. Paper is more convenient, but requires extra care in order to persist for many years. And in order to make all information in your computer inaccessible, all you need is to cut the power. Also, the way information is stored is incredibly complicated, which means that should humanity disappear, the next civilization won't be able to get much from remains of our computers. Digital info is incredibly fragile itself, this article illustrates some problems. If you think about this, our civilization suddenly looks incredibly fragile, like a card house - just lose a few key technologies, and you are back in the medieval times.
This returns me to original problem:

  • Our world is fragile, and should something serious happen, many things we know will be lost forever.
  • In fact, nearly everything (on earth, at least) is going to disappear eventually hardly leaving the trace. Organic creatures die. Machinery rusts. Buildings are being destroyed by the elements. Eventually, Sun itself will "blow up" and burn the earth down, or it will eventually stop producing light.
  • Most of those events cannot be avoided.


Perhaps I'm missing something, but for me all this combined together doesn't make any sense.

So, what is the point of all this? What is the meaning of everything? The purpose?

Ideas, anyone?