Sunday, December 8, 2013

3C Rules of Personal Development

Create
You know, do stuff. Experiment, hack, write programs, build houses. Creating means going against nature in some way: second law of thermodynamics rules out everything to go into chaos, while creation is about organizing matter or information. Creation is easy and natural behavior of children with their rich imagination, but keeping up with it when you get older requires dedication.

Collaborate
Working on something in isolation can be reasonable, but the potential of collaboration is greater. Discuss your ideas with friends, relatives, and even with random people on the Internet. Visit conferences to hear other peoples ideas, form work groups, and adjust your own goals. A well done argument may multiply each individual intellegence with regards to solving the target problem, when the idea is being ping-ponged between brains, evolving with each hit.

Complete
Creation process is an engine, and to keep working it needs to complete cycles. Finishing stuff gives you fuel to move to the next idea, and allows to draw right conclusions by analyzing the full cycle. Publish your work on the web, give other people a functioning product, not just a bunch of scrap and a github repo link. Receive recognition, push your goal bar higher, and move on.

Sunday, August 18, 2013

Quest for the best scene format

A graphics engine needs to know how to compose a scene from a given set of resources, such as: meshes, skeletons, and textures. This is what scene file is for - it's a document that describes relationship between basic resources, joining them into a system that can be effectively processed by the code. This file is composed either by hand (if the scene is small), or by the exporter script from a 3D modelling program. During the evolution of KRI engine the scene format changed several times. I'll try to review the development history and analyze various formats I used, based on the personal experience.

0. Composed in code: kri-1, kri-2

This is where we all start: just slapping entities on the screen directly.
Lang:    C++
Pros:
    -no export stage
    -no need to validate
    -no parsing
Cons:
    -non extensible

1. Custom binary: kri-3

All scene data and resources were stored in a single binary file of a custom format.
Lang:    Boo
Pros:
    -no external libs
    -fast parsing
Cons:
    -non human-readable -> difficult to debug
    -difficult to validate
    -resources are not separate

2. XML: kri-web

XML is a well-known document format, it has the greatest language/tool support. Besides, that's what we used at my former employer company.
Lang:    Dart, XML
Pros:
    -built-in validation with Schema
    -support for default values
Cons:
    -need to keep Schema synchronized with exporter/loader
    -too verbose
    -bloated loading code (no 1:1 data representation)
    -not clear what to put into attributes -> design ambiguity

3. JSON: claymore-engine

This is where I discovered JSON, and it immediately appealed to me because of the simple syntax and its 1:1 reflection with the data. Fortunately, this is the only format Rust had a built-in support for. However, it turned out to be a poor choice for the scene description due to the lack of heterogeneous structures.
Lang:    Rust, JSON
Pros:
Cons:
    -no heterogeneous structures -> difficult to read

From there I started looking for something like JSON but to describe the document instead of the data. I looked into YAML, which seemed nice, a bit more complex, and not supported by Rust. Then I found Candle Object Notation, which seemed like a non-ambiguous and compact version of XML, plus the 1:1 mapping to data. However, the format is not that well documented and supported... "It would be nice to have the same object initialization syntax as Rust" - I thought when this idea hit me like a train: why not use Rust then?

4. Rust: k-engine

Let's just export a rust source file, which will be compiled with the application.
Lang:    Rust
Pros:
    -free validation (your code is the spec)
    -no run-time parsing -> instant loading, no run-time errors
    -no need to learn new syntax
    -compact (no external file needed to run)
Cons:
    -need to compile the scene
    -bound to the language

This approach seems to be the perfect solution for my scene format. The only thing that worries me is that it depends on Rust compile times. Though, we can still parse Rust code at run time, if we want, while still verifying it at compile time. You can see an actual export result here. It is compact, easy to read, and elegant.

Saturday, January 5, 2013

My Internet

I've been accustomed to the Internet as we know it: fire up a browser, read email, feeds, visit FB/G+/Twitter, buy something on Amazon with a Visa card. It is indeed convenient, especially if you don't care to look under the hood, or explore the limits of your freedom. And the fact is: there are big companies there (providers of "free" services) that gather all information about you.

One of the ways to use that information is to chose the advertising that you'll see. Honestly, I don't care about ads too much. Most of the time I block them anyway, and when I see them - I'll appreciate a featured anime figure more than some silly pills. But ads are just the tip of the iceberg, the only part of it we actually see. The real problem is the power you give them, the power that limits your potential, because no one cares about your weird habits until you become big.

In an ideal society, everyone can know everything about everyone. But we, as a species, are not ideal, thus making it a matter of protection to choose what information to share, and what to hide. Once your information can be bought, you never know who and when may turn it against you. Imagine a robber aware of your vacation schedule. The security question stands right near the privacy one. Your information is stored in a centralized manner: it could be denied of service, or it could be stolen - it's vulnerabile.

Now, how do we work around that, while still keeping it simple and convenient? There are several solutions for different sub-issues:

DNS. Generally provided by your ISP, thus may have some areas blocked (i.e. Wikileaks). They know wherever you go, and also redirect the "address not found" queries.
Solution: OpenNIC, any neutral DNS like Google DNS

File sharing. Exchanging music, books, and movies is prosecuted by RIAA & MPAA, even if you give it to your friend and delete it locally. They want you to rent things for an undefined period instead of owning them.
Solution: Torrent, private hosting if you can afford it.

Social network. This is where you expose the most of yourself. You need to preserve the rights to the content you create, and to share it only with those you care.
Solution: Disapora*.

Money transfer. Your Visa/AMEX/Mastercard knows everything you buy, everywhere you travel, and steals around 3% for each transaction. Also, you never know when your government decides to print more money, making whatever you have less valuable instantly.
Solution: Bitcoin.

Those solutions will only become valid once they gain a critical mass of users. I hope that my post aids this goal a little, making Internet a better place in the nearest future.

Sunday, November 18, 2012

What I know about Computer Graphics

I've been working closely with CG both professionally and as a hobby for the past 5-6 years. I've been making games and developing engine architectures. Latest developments can be tracked on Claymore Dev blog. I've seen different techniques, tried many others, even written articles about them in big books (GpuPro-3, OpenGL Insights). And the funny point is: I still don't know how to build engines... All I know is how bunch of known techniques may help or screw you up, based on personal experience.

Uber-shaders
Problems: Difficult to maintain due to bad granularity and monolithic approach. Unable to extend from the game side.
Alternative: Shader compositing. In OpenGL you can extend the functionality by either linking with different shader objects, swapping the subroutines, or by directly modifying the source code.

Deferred shading
Problems: Very limited BRDF support. High fill-rate and GPU memory bandwidth load. Difficult to properly support MSAA.
Alternative: Tiled lighting. You can work around the DX11 hardware requirements by separating lights into layers (to be described).

Matrices
Problems: Difficult to decompose into position/rotation/scale. Take at least 3 vectors to pass to GPU. Obligation to support non-uniform scale (e.g. no longer skipping invert-transpose on a 3x3 matrix to get a normal matrix).
Alternative: Quaternions and dual-quaternions. Both take 2 vectors to pass.

Context states
Problems: Bug-hunting is difficult because of bad problem locality. Assumptions over the context are easy to make, but if you decide to check it with assertions, why not just pass the whole state instead?
Alternative: Provide the whole state with each draw call. Let the caching work for you.

C++
Problems: Memory management and safety. Compiler-generated copy operators/constructors. Pain dealing with headers and optimizing the compile time. Many many lines of code.
Alternative: Rust. Other "safe" languages (.Net family, Java, Python) are not as low-level and often trade performance for safety (i.e. global GC phase causes an unacceptable frame rate interruption).

All I actually know is that there is a thousand and one difficult architectural issues of the graphics engine, and there is no silver bullet to most of them. For the most common solutions I listed possible alternatives, but they are no near being flawless. I hope that one day the amount of experience I get will magically transfer into the quality of my decisions, and I will finally know the right answers.

Thursday, November 1, 2012

Rust

Today's early morning I woke up with a single thought reflecting loudly in my brain: "Dart was a mistake, it was not made for me. I should look for some statically typed practical language instead". Even though my KriWeb project (written in Dart) was not actively developed, I agreed (with my dreaming counterpart) that the instrument I choose for this project iteration is far from perfect. Suddenly, I felt the urge to look for something ideal, something that seemed so real as if I was reading its specification the other day... And I just needed to recall its name...

I started looking for it on the web. There were many interesting suspects among new languages. Ceylon, for example, features immutability by default (which highly encourages functional style), which seemed very familiar and close to what I looked for. It is a very nice language all in all, but it's currently running on Java VM, and was heavily inspired by it, what pushed me off. Go sounded attractive due to the strong support from Google, however disappointed me by its lack of user generics. Zimbu looked too original, while Haxe seemed to pretend covering too much use-cases. I've reached  the 5-th page in google search results, and there still wasn't any trace of it. Maybe it was a dream?..

One step away from stopping my search, I stumbled upon this Holy Grail of programming. Name is Rust, developed by Mozilla Foundation. Suddenly, I remembered this shining website interface, this clear language specification that I read a while ago. I found it, at last! Let me explain why I was so happy:
  • Strong static typing with inference, only explicit mutability. This is so right and so rare to see at the same time. Unlike Dart, most of my mistakes will be found at compile time.
  • No page faults while still compiling to native code. Memory model is protected and guaranteed to work without access violations under normal circumstances. It has a potential for C-like performance, hence being a better tool for various tasks.
  • User generics with constraints, pattern matching (Haskell-style). Yes, it took the best from my beloved purely functional language.
  • Less statements but more expressions and closures. This makes it even more sleek and functional.
  • Syntax extensions. Hello, Boo macros!
  • Structure compatibility with C. Using external API's (i.e. OpenGL) gets easier.
Overall, the language and its environment seem very nice. It is simple yet powerful, and feels very promising. I'm looking forward to work closely with this gem, and I'm very excited :)

Thursday, October 4, 2012

Mind shield

Travelling helps to get a clear view over the strange world we live in. Now I understand what Hollywood is, along with many other parties, as the idea hit me like a truck. And my position towards big names will never be the same again.

The ultimate goal of each corporation as well many organizations is to get your wallet. However, selling things and services directly may not be the best way to achieve it. Instead, they strike for your heart because it opens the doors to much more than just money. I'm talking about Hollywood, church, Apple, Google, governments and charity. They want you to like them, to consider them for your choice, to talk about them with your friends, to think about them at night. They want to be a part of your mind.

Humans are weird creatures. They consider themselves to be smart, but they barely understand how the environment shapes their minds. An average human does not even try to control the development of its brain, of its consciousness. And the brain just absorbs stuff chaotically, whatever happens to get in.

The story of Hollywood is simple. Long ago there was a cinema. Actors were servants, they didn't earn much, they were not recognized by random people, they were nothing at that point. And then a smart man came in and decided to change the role of the actors in the movie of life. From now on, he said, actors will be respected and well paid. He made people like them, love them and buy them. Clearly, he understood the "get into your heart" business model. As we see now, it turned out to be hugely successful. We have favourite actors, we know a lot of movies, and we pay insane amount of money to watch them at theatres. Movie business is blossoming, and every child now wants to be an actor in the future...

Let's figure out how we could protect our hearts. First off, don't watch too much of the TV. Try to evade any kind of advertising on TV, radio and on the Internet. Allocate a small part of your brain to be independent, to interrupt the flow of thoughts periodically with a simple question: "Do you really need to watch/listen/think about that?". Finally, pay more attention to stuff that really matters to you: science, art, family, philosophy, health, etc.

Wednesday, September 5, 2012

First DirectX impressions


During the last half a year I had a great opportunity to work closely with DirectX on a production scale. From the very beginning, I had a suspicion that the technology is a big joke. It didn't start with little things, no, it started with a full-scale attack on my OpenGL-friendly brain. Let me name the offenders:

Render state. You are not in a full control of it. DX runtime may change it without your concern. In particular, this happens under DX10+ when you bind a texture resource that is also one of the render targets. Debug runtime will notify you in the log but the regular one will just do it silently. And then you wonder, where did the texture go? Unsurprisingly, PIX, the hammer of DX frame profiling, is not able to handle this behavior correctly, so debugging one of these little bugs may cost you a really long headache. In DX11 we can see a new flag that allows binding a depth-stencil texture as read-only, allowing to sample from it. As a result, you have to split the rendering paths: copy the depth for DX10, and use the flag for DX11.

In contrast, OpenGL gives you an undefined behaviour whenever you want to read and write at the same time. While it seems suspicious at first, in practice you don't sample from the texture being rendered to, so your program works as expected, and no state is corrupted. Moreover, your GL program doesn't need a new flag, or a depth texture duplicate: all you need is to disable depth/stencil writes, and you can read them. Concluding, while DX creates and fixes the problems of its own with new versions, OpenGL just works as expected.

Documentation. The official source of knowledge about DX is MSDN. Unfortunately, you are not able to track all changes that go there. I don't see any revision history. My co-worker was following the CHM documentation bundled with our DirectX SDK, and according to it, CopyResource() can not be used if one of the surfaces is multi-sampled. He ended up copying a surface using a full-screen quad with a designated shader... And only then I discovered that the online version is different: for DX 10.1 the function actually copies multi-sampled surfaces too.

Another example is D3D11_RASTERIZER_DESC structure. There is a MultisampleEnable member, which (surprise!) affects only line rendering under DX10+, while affecting all MSAA rendering under DX10 and below. Yes, I know there is also AntialiasedLineEnable flag, but how does this make it any less confusing?

The situation gets worse as you dig deeper. As an example, there is a texture object in HLSL. According to MSDN, you have to explicitly specify the number of samples in the template. Though, I'm not sure, maybe the page is fixed while I'm typing this. Anyway, in practice, under DX10.1+ you can skip it. That's where you end up scavenging all little details of these presentations, scanning the forums, and trying to guess logically. The DX knowledge is like a secret cave with treasures, where some companies (Epic,Crytek) know them better then others.

OpenGL, on the other hand, provides a strictly versioned document. You can download any version of it, see the changes highlighted, and find everything you are looking for. You don't need to scavenge the forums: if something works differently from the specification, it's most likely a bug, and not a feature.

Sloppiness. You can do many things incorrectly, and DX runtime will still try its best to let your application work. For example, you can sample from a multi-sampled texture bound as a regular one. DX will automatically resolve the pixel before sampling, if it's possible. Or you can assign a float3 to a float in HLSL, and it will still work (can probably be fixed by a strict flag in HLSL compiler). Such robust behaviour is very welcome on the end-user side, but developers need to be sure the code is valid. I would prefer it to crash hard on the first error encountered, or at least return some error code (hello, OpenGL). I understand that, again, one can use the debug runtime, see the error log, and figure this out. But the truth is, most development goes with a regular runtime, because the debug one is damn slow. And even on that you would have to trace through the suspicious instruction to see the new error in the log - that's not how exceptions should be handled.


All in all, DirectX makes an impression of being made by amateurs, who got the power to talk to hardware developers. It's not developer friendly, it's not blazing fast, it's not something to compete with OpenGL. I admit that's a bit of an emotional over-statement, and one could expect something like that from me. I will continue learning DX technology, and I hope to discover some real gems there, if they exist at all.