アドベントカレンダー22日目は、ソフトウェア開発部の田川が担当します。
私は古参プログラマーなので、最新技術の話は若手に任せて今回は私とプログラムとの出会いについて書いてみたいと思います。
はじめに
私は現在、システム課に所属していながらプログラムコードは実務で書いていないのですが、中身的には生粋のプログラマーであると思っています。
経歴としても「潜水艦を探すシステム」から始まり「コンシューマーゲーム機でのゲーム開発」、「電子カルテ」、「データベースエンジン」など様々な開発経験をしてきました。
元々は高校生の時に学校にあったPC-8001mk2というパソコンを触ったことから、コンピューターに興味を持ち始め、次にレイトレーシングやフラクタル、マンデルブロートに興味を持ちBASICでそれらの描画プログラムを組み始めました。
しかし、当時自分で持っていたFM77-AVは4096色も発色できながら、CPUは超貧弱で1画像描画するのに8時間も掛かっていました。
そして、C言語ならもっと早いプログラムが組めるということを知ってX68000という一世を風靡したパソコンを購入しC言語を勉強し始めたのですが、この時からスピード狂だった自身の本能が目覚めてしまい更に高速に描画できる方法を模索し始めました。当時のCコンパイラはそこまで性能が良くなかったので、Cコンパイラは無駄なコードを吐いてしまい思ったように高速化できなかったのです。
それでもBASICよりは格段に速かったのですが・・・
そして、さらに高速なプログラムを書くためにアセンブラを覚え、徐々にその世界に魅了されていったのでした。
アセンブラ言語を勉強した話
アセンブラ言語はとてもシンプルで分かりやすい言語です。
アセンブラ言語をやるとわかるのですが、コンピューター(CPU)とは所詮「読取り(READ)」「書込み(WRITE)」「演算(CALCURATE)」「実行位置指定(JUMP)」しかできないのです。でも、それらを組み合わせて絵をかいたり、音を鳴らしたり、通信したり色々な機能を実現しているのです。
そしてアセンブラを理解することはハードウェアを理解することにもつながり、本当の意味でコンピューターがどのような原理で動いているかを理解することができるようになります。
コンピューターの仕組みがいろいろと解ってくると、その機能を堪能するために自分でいろいろなコードを書いて確かめたいと思うようになりました。
ラスタースクロールのプログラムやワイヤーフレームによる3D表示のプログラムは寝ることも忘れてプログラミングしていた記憶があります。
刺激を受けたアルゴリズム(ブレゼンハムの線分描画アルゴリズム)
画面描画に関心のあった私は、当時のOS標準ライブラリの描画性能の低さに落胆していたのですが、ある雑誌を読んで「自分で描画処理をアセンブラで書けば、さらに高速になる!」ということを知りました。
描画処理の一番基本となる2点間に線を引くという処理を考えると y=ax+bという公式を皆さん思い浮かべることと思います。
実際もその公式は使用するのですが、当時のCPUにこの公式を実行させるにはとても大きな問題がありました。
それは当時の安価なCPUでは「浮動小数点演算ができない。」という問題です。
(別売りの浮動小数点演算ユニットが必要。しかもウン万円!?)
浮動小数点という考え方は当然ありましたが、実際に計算するには浮動小数点表現から「整数値」「指数値」を抜き出し、それぞれ別計算して最終的にまた浮動小数点数に戻すという処理が必要でした。
つまり、y=ax+bでaが整数でない場合は、計算自体がとてつもなく遅く実用できないということです。
そこで登場するのがブレゼンハムの線分描画アルゴリズムです。
一切浮動小数点演算を使用せずに、しかも簡単なループ処理で記述できるため標準ライブラリの数倍の速度で描画してしまうという超優れモノでした。
このアルゴリズムは知ってしまえば「まぁ、そうだよな。」となるのですが、当時はそのシンプルさと発想に感動してしまい、何度もコードを見直してうっとりとしていました。
まぁ、普通の人からすればきっと変態ですね(笑)。
これをきっかけにプログラムの面白さに更に引き込まれてしまい、今の自分が出来上がったと言えます。(さらに変態になったのか?)
ブレゼンハムの線分描画アルゴリズム サンプル・コード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
// P0(x0,y0) – P1(x1,y1) に線を描画する関数 // ただし x0 < x1, y0 < y1 void Line (int x0, int y0, int x1, int y1) { int dx = x1 - x0; int dy = y1 - y0; int dx2 = 2 * dx; // 四捨五入の0.5を整数で処理したいため2倍する int dy2 = 2 * dy; // 同様に2倍してつじつま合わせ int d = -dx; // -0.5から開始することで四捨五入を省略 int y = y0; // 描画位置:Y for (int x = x0; x <= x1; x++) { // 描画位置:Xでループ if (d > 0) { // 0を超えたら y = y + 1; // Yをひとつ移動 d -= dx2; // 判断値を戻す(端数を残したままなのがポイント) } d += dy2; plot(x, y, color); // 描画関数 指定座標に点を打つ } } |
これからプログラマーを目指す人たちに
プログラムを組むということは、コンピューターと会話するということです。
ただし、PHPやJavaやPythonなど高級言語では間に通訳が入ってしまい、本当にコンピューターに伝えたいことが伝わりづらくなっています。そして、逆もまた然り。
本当の意味でプログラムを理解するということは、直接コンピューターと会話できるようになるということだと思います。英語を勉強することと同じ理由です。
簡易なツールや環境が用意され、開発速度はどんどん速まり、直接会話をすることのメリットなんて、なかなか見いだせないかもしれません。
でも、その直接会話をすることができる扉を開けたとき、プログラマーとしての世界が変わることを私のように体験できるかもしれません。
そしてこの技術は、この業界で生きる上でとても有用な武器となり得ます。
これからこの業界でプログラマーを目指すという人は、ぜひこの扉を開けてみてください。
そして、私と同じようにプログラミングの面白さに引き込まれる人が出てくれることを札幌の寒空の下から祈っています。