セカンドライフ

セカンドライフのテクスチャの秘密1

投稿日: 更新日:


はじめに

こんにちは!

久しぶりのブログです。

今日は、セカンドライフのテクスチャ、ノーマルマップ  の秘密について話します。
続かないかもしれませんが、とりあえず第1弾です。


ノーマルマップの色成分の基礎

ノーマルマップといえば、平面の凹凸を現した画像です。
通常グレースケールで高さを表した画像から、このノーマルマップを作成します。
おそらく、少し詳しzい方はこの辺までは、ご存知かと思います。

しかし、具体的に
赤色成分は、何をセカンドライフ上の何を示すのか、
青色成分は……?
といったことまで知っている方はそんなにいないのでは?

ということで、この色成分が何を表しているかの解説となります。

ノーマルマップの英語の解説を確認してみましょう。
これを見ると、次のような情報が分かります。
赤成分R = 方向成分X
緑成分G = 方向成分Y
青成分B = 方向成分Z

ただし、方向とは言ってもX+がR+に
対応しているのかといったことはテキストには書いてありません。
なぜ、それが重要かといいますと、ソフトによって色成分との対応が異なるためです。

>・ZBrush:(-X,+Y,+Z)
>・CrazyBump:(+X,+Y,+Z)
>・Blender 2.4x:(-X,-Y,+Z)
>・Blender 2.57以降:(+X,+Y,+Z)
Sandy Virtual City様のブログから引用
※XYZ軸がどちらに対応しているかも重要となるため、ブログ内の軸の解説も参照しましょう。
ブログでは、X軸のプラスをUV座標系のU方向、Y軸のプラスをUV座標系のV方向、Z軸のプラスを凸方向としています。

では、セカンドライフを調べてみましょう。
公式ページにあるノーマルマップの画像から、
凸に対して、画素の色が次のようになっています。
上が RGB(126,178,212)
右が RGB(169,124,210)
下が RGB(109, 75,206)
左が RGB( 69,124,212)

つまり、セカンドライフ(+X, -Y, +Z)
となることが分かります。

これは、NormalMap-Onlineでは、
Invert の R にチェックが入った場合と同様になります。

これらをおさらないすると、たとえば下記のようなバンプマップ/ハイトマップを用意したとすると、

次のような画像がセカンドライフ上でのノーマルマップとなります。

本日は、ここまで!

セカンドライフで自分の行動の色々な情報を取得する

投稿日: 更新日:


次のような自分の行動の情報を取得してみます。
・自分が喋った回数
・人から聞いた回数(アバターが話したものに限定)
・空を飛んでいる時間(ホバーは含めない)
・海の中を泳いでいる時間(ホバーは含めない)
・歩いている時間
・走った時間
・ジャンプ中の時間
・テレポートした回数
・SIMをまたいだ回数
・人や当たり判定がある物体と衝突した回数

以下、サンプルです。
このコードを適当なオブジェクトに入れた後、HUDとして装備してください。
drawStatusと発言すると、自分の情報が表示されます。

ログインした回数とかも取れるかなと思ったのですが、
装備した回数と見分けがつかないので諦めました。

integer count_attack		= 0;
integer count_speak			= 0;
integer count_listen		= 0;
integer count_flying		= 0;
integer count_swimming		= 0;
integer count_running		= 0;
integer count_walking		= 0;
integer count_teleport		= 0;
integer count_simtraversal	= 0;
integer count_jumping		= 0;

integer TYPE_ATTACK			= 0;
integer TYPE_SPEAK			= 1;
integer TYPE_LISTEN			= 2;
integer TYPE_FLYING			= 3;
integer TYPE_SWIMMING 		= 4;
integer TYPE_RUNNING		= 5;
integer TYPE_WALKING		= 6;
integer TYPE_TELEPORT		= 7;
integer TYPE_SIMTRAVERSAL	= 8;
integer TYPE_JUMPING		= 9;

integer show_dialog		= FALSE;
integer listen_handle	= -1;

addAction(integer action) {
//	llOwnerSay("action : "+ (string)action);
	if(action == TYPE_ATTACK) {
		count_attack	= count_attack + 1;
	}
	else if(action == TYPE_SPEAK) {
		count_speak		= count_speak + 1;
	}
	else if(action == TYPE_LISTEN) {
		count_listen	= count_listen + 1;
	}
	else if(action == TYPE_FLYING) {
		count_flying	= count_flying + 1;
	}
	else if(action == TYPE_SWIMMING) {
		count_swimming	= count_swimming + 1;
	}
	else if(action == TYPE_RUNNING) {
		count_running	= count_running + 1;
	}
	else if(action == TYPE_WALKING) {
		count_walking	= count_walking + 1;
	}
	else if(action == TYPE_TELEPORT) {
		count_teleport	= count_teleport + 1;
	}
	else if(action == TYPE_SIMTRAVERSAL) {
		count_simtraversal	= count_simtraversal + 1;
	}
	else if(action == TYPE_JUMPING) {
		count_jumping	= count_jumping + 1;
	}
}

showStatus() {
	llWhisper(0,
		"attack\t:"			+ (string) count_attack			+ " times\n" +
		"speak\t:"			+ (string) count_speak			+ " times\n" +
		"listen\t:"			+ (string) count_listen			+ " times\n" +
		"teleport\t:"		+ (string) count_teleport		+ " times\n" +
		"simtraversal\t:"	+ (string) count_simtraversal	+ " times\n" +
		"flying\t\t:"		+ (string) count_flying			+ " sec\n" +
		"swimming\t\t:"		+ (string) count_swimming		+ " sec\n" +
		"running\t:"		+ (string) count_running		+ " sec\n" +
		"walking\t:"		+ (string) count_walking		+ " sec\n" +
		"jumping\t:"		+ (string) count_jumping		+ " sec"
	);
}

openDialog() {
	if(listen_handle != -1) {
		llListenRemove(listen_handle);
	}
	listen_handle = llListen(-100, "", llGetOwner(), "");
	llDialog( llGetOwner(), "Which operation?\nYou say \"drawStatus\"... or \"resetStatus\"", ["status", "reset", "cancel"], -100 );
	llSetTimerEvent(0.0);
	llSetTimerEvent(30.0);
	show_dialog = TRUE;
}

closeDialog() {
	if(listen_handle != -1) {
		llListenRemove(listen_handle);
	}
	show_dialog = FALSE;
	listen_handle = llListen(0, "", "", "");
	llSetTimerEvent(0.0);
	llSetTimerEvent(1.0);
}

default {
	state_entry() {
		llOwnerSay("Start Script !\nYou say \"drawStatus\"... or \"resetStatus\"");
		closeDialog();
	}
	
	touch_start(integer total_number) {
		openDialog();
	}
	
	timer() {
		if(show_dialog) {
			closeDialog();
		}
		else {
			string my_animatin = llGetAnimation(llGetOwner());
			if(my_animatin == "Flying") {
				vector v = llGetPos();
				if(llWater(v) > v.z) {
					addAction(TYPE_SWIMMING);
				}
				else {
					addAction(TYPE_FLYING);
				}
			}
			else if(my_animatin == "Running") {
				addAction(TYPE_RUNNING);
			}
			else if(my_animatin == "Walking") {
				addAction(TYPE_WALKING);
			}
			else if(my_animatin == "Jumping") {
				addAction(TYPE_JUMPING);
			}
		}
	}
	
	listen( integer channel, string name, key id, string message ) {
//		llOwnerSay(""+ (string)channel +" " + name + " " + (string)id + " " + message);
		if(show_dialog) {
			if(message == "status") {
				showStatus();
			}
			else if(message == "reset") {
				llResetScript();
			}
			else if(message == "cancel") {
			}
			closeDialog();
		}
		else {
			if(id == llGetOwner()) {
				if(message == "drawStatus") {
					showStatus();
				}
				else if(message == "resetStatus") {
					llResetScript();
				}
				else {
					addAction(TYPE_SPEAK);
				}
			}
			else if(llGetAgentSize(id)){
				addAction(TYPE_LISTEN);
			}
		}
	}
	
	changed(integer mask) {
		if(mask & CHANGED_OWNER) {
			llResetScript();
		}
		if((mask & CHANGED_TELEPORT) && (mask & CHANGED_REGION)) {
			addAction(TYPE_TELEPORT);
		}
		else if(mask & CHANGED_TELEPORT) {
			addAction(TYPE_TELEPORT);
		}
		else if(mask & CHANGED_REGION) {
			addAction(TYPE_SIMTRAVERSAL);
		}
	}
	
	collision_start(integer num) {
		if(llDetectedType(0) & ACTIVE) {
			vector my_velocity = llGetVel();
			vector velocity = llDetectedVel(0);
			float power = llVecMag(my_velocity - velocity);
			if(power >= 1.0) {
				addAction(TYPE_ATTACK);
			}
		}
	}
	
	on_rez(integer param) {
		// 1 ログイン、装備、rez
	}
	
	attach(key attached) {
		if(attached) {
			// 2 ログイン、装備
		}
	}
}

セカンドライフのプリムの当たり判定の検証

投稿日: 更新日:


こんにちは!

昨日から引き続き、「セカンドライフ技術系 Advent Calendar 2016」です!

すみません。
昨日の記事は、役に立つ情報もあったかもしれませんが、
今回は、テクニック系と違い、前々から気になっていたことを検証する……といった内容となります。
なんかすごいの来る!と期待していた方はスミマセン。(いないと思われますが)

というわけで、

あんまり面白いものではないかもしれませんが、
調査結果の報告というわけで、話していきます……。


はじめに

昨年に、当たり判定の記事を書きました。
セカンドライフでメッシュに物理形状を設定しよう1

今回は、その記事のさらに「実像の種類」について気になったことを確認していきたいと思います。
最初に少し解説しますが、より理解を深めたい方は前回の記事から読むことをお勧めします。

「実像の種類」というのはオブジェクトの設定から選べるものです。
実像というのは、当たり判定用に用いるオブジェクトです。

gui_jituzo_1 → gui_jituzo_2

ここで実像を「なし」「プリム」「凸状の外殻構造」の3種類選べます。
「なし」にした場合は、当たり判定用のオブジェクトを用意しないということになります。

ここで「プリム」「凸状の外殻構造」の違いについて説明するために、
3次元だと書きにくいので、2次元で考えたいと思います。

atari_hazimeni_1
2枚の壁が90度の垂直であることとします。

atari_hazimeni_2
実像の種類を「凸状の外殻構造」にすると、
黄色の囲んだ部分のように当たり判定が生まれます。
※中身すべてにすべて当たり判定を持つことになります。

atari_hazimeni_3
実像の種類を「プリム」にすると、
そのプリムそのものが1枚の壁のように当たり判定を持ちます。
※中身というものは存在しません。


実像の種類「プリム」の疑問

ここで、私の中では素朴な疑問が生まれました。
当たり判定の計算方法により、アバターが透けることがないのかということです。

たまーに、なぜかよくわからないですが、壁の中に入って閉じ込められることありませんか。
それが、このこの設定によるものなのかなーと、疑問に思ったわけです。

セカンドライフの実際の当たり判定のアルゴリズムについては知らないので少し、推測した話となります。
まず、当たり判定といえば、レイと3角ポリゴンとの衝突の検出※が有名です。
そこで、これをまず使用していると仮定します。
(※アルゴリズム、計算方法については、「はじめての3Dゲーム開発」)

そして、もしこのようなアルゴリズムを使って単純に実装している場合、
つまり、1本のレイを飛ばすような当たり判定を使っているのであれば、
次のような現象が起きるのでは……と思いつきます。

atari_nazo_1
壁1と壁2が90度で交わっているとします。

atari_nazo_2
ここで Ray1 を飛ばします。
つまりアバターが壁1に向かって斜めに突進した感じです。

atari_nazo_3
Ray1は、壁1と壁2の2種類に当たり判定チェックを行います。
その結果、壁1との衝突を検知することができます。
そして、めり込まないように、斜めの成分だけを抜き出します。

atari_nazo_4
次に、壁1との衝突点からRay2を飛ばします。
ここで、問題なのですが、Ray2が壁2との当たり判定を正しく行えるかという謎です。

普通は壁1と壁2は接続されているはずなので、
Ray2は壁2と衝突するはずですが、
実際は壁1と壁2は、別のポリゴンとして管理しており、
これらのポリゴンの位置は、実数による誤差の関係上、微妙に隙間が空いているはずなのです。

1本のレイを使用した単純な当たり判定ならば、上記のような問題は起きるのですが、
もちろん、レイを複数とばす。あるいは、そもそも球とポリゴンとの当たり判定を使用するなど
いろいろな工夫を行っていれば、このようなことになりません。
なので、有名なセカンドライフであれば、すり抜けることはおそらくないはずですが。

というわけで、前置きがすごく長くはありましたが、
当たり判定用のプリム=壁のプリムを作成して、
衝突した場合どうなるか検証するのが、この記事の目的となります!


すり抜けの検証

次のような壁(1辺が10m)を作成して、
atari_test_1

下記のように10分間壁に向かって当たり続けて、すりぬけるか確認します。
atari_test2

ビューアは2種類で確認しました。
公式ビューア(v4.1.2.321518)
Catznipビューア(R10.0)の両方で確認しました。

元となるメッシュデータについては、頂点を共有しないメッシュと、
共有するメッシュの2種類について確認。

また、当たり判定のデータは、dae情報で直接設定する方法と、
表示用メッシュから自動生成する方法の2種類を試しました。

それで早速、結果なのですが、

.
..

なんと

.
..

なんとッ!

.
..

すり抜けませんでした!

まあ、そうですよねー。
期待していた方?はスミマセンでした。

ちなみにさらに検証していったのですが、
隙間がわずかにあってもすり抜けませんでした。

どの程度の隙間からすり抜けるようになるのか気になる点ではありますが、
まずは、接続された面であれば、当たり判定を「プリム」にしていても
問題ないということは確実ということが分かり、安心しました。

たまーにすり抜けるのは、
たぶん、幽霊の仕業か本当に実像的にスキマがあるのでしょう。きっと……


一応、これで2日間にわたる記事は終わりです。
ですが!まだまだ12月が始まったばかりです!

ではみなさま!
セカンドライフ技術系 Advent Calendar 2016」を楽しんでいきましょう!

.
..

.
..

.
..

オマケ

私は、Advent Calendar以外にも普段気が向いたときに、セカンドライフ系の記事をかいております。
その中で、私としてヨイデキな記事をいくつか紹介します。(宣伝デス)

2016年4月21日 セカンドライフのスカイボックスに太陽の光を!
シンプルながらも、知っておくと良いテクニック!

2014年12月29日 セカンドライフの関数逆引きメモ
セカンドライフにはどういった機能があるのか、逆引きをみて一通り覚えておこう!

2014年12月12日 セカンドライフでアニメーション
セカンドライフでアニメーションを作る方法!

セカンドライフのオブジェクトとの衝突音

投稿日: 更新日:


みなさん。お久しぶりです。

ついに今年も「Advent Calendar」の季節がやってきました!

イエーイ!

このようなイベントを開催していただいて、sabro様ありがとうございます!

私は去年から初参戦しているのですが、今年はナント1日目を予約してしまいました。
こんな私が1日目をとってしまってよかったのだろうか……といろいろありますが、
気にせずドンドン始めていきたいと思います!


衝突音

今回のテーマは、音関係の話、具体的には衝突音の話をしたいと思います。

みなさん、衝突音って気にしたことありますか……?

……

あんまり、気にしていない人多いかも。
でも、私はたまーに気になったりします。

例えばですが、プリムで階段を作ったとします。
kaidan

 

こういう階段にダッシュして登ってみましょう!

ゴツッ!

ほら!衝突音しましたよね。

なんとなくどんくさい感じがします。
他にも、柔らかなそうなソファーとかぶつかった時も、
ゴツッ!とか出るのも何だか不自然な感じがします。

実は、このような衝突音、簡単に消せるんです! \テテーン!/

プリムを選択して、スクリプトを追加。

gui_script_1 → gui_script_2
スクリプトでは次のように llCollisionSound で衝突音の設定をします。

default
{
	state_entry()
	{
		llCollisionSound("", 0.0);
	}
}

さあ、これで保存して、同じように階段を上ってみましょう!
衝突音がないため、スムーズに駆け上っている感じがでましたね。


簡単に衝突音設定しよう!

スクリプト面倒という方もいらっしゃると思います。
無音にする方法でなければ、実は手軽に衝突音を変えられるってご存知でしょうか?

具体的には、「オブジェクトの特徴」の設定で、
実像のタイプを選択することができます。

gui_sound_1 → gui_sound_2

デフォルトは「木」となっているのですが、
他にも、いくつか選べて、全部で7種類を選ぶことができます。
それぞれの設定の音は、次のようになります。

  • 石   … 低いゴツ!
  • 金属  … カン!(グレーチングを踏んだような音)
  • ガラス … カン!(氷をアイスピックでたたいたような音)
  • 木   … ゴツ!
  • 肌   … コツ!
  • プラスチック … ドン!
  • ゴム  … コツ!(硬くゴムを机に落としたような音)

※音の印象は個人差があります。

音は用意するの面倒だけど、衝突音を変えたいという方は
ここでGUI上でポチポチ触って変更することをオススメします!


他の音はないの?

先ほどは、簡単に音を設定する方法説明しましたが、
コツ、ゴツ系のみで種類がすくない~(><)と思う方もいると思います。

ただ llCollisionSound を使うにしても、
音を用意するのって結構面倒ですよね。

というわけで、
少し早いですがクリスマスプレゼント!
自由に使える音素材を収録して用意しました!

許可なしで有料/無料問わず自由に使える音のUUIDを公開します。
衝突音以外に使用してもらってもかまいません。

下記のスクリプトを入れれば、衝突音が変わります。
「1.0」と書いてある部分を小さな値にすれば、衝突音の音量を小さくもできます。

床1 … ドン!(低く、重たい音)

default{state_entry(){llCollisionSound("56fa194a-b894-043a-c1fe-04ab0ead663e", 1.0);}}

床2 … ドン!(普通の音1)

default{state_entry(){llCollisionSound("aab46478-b006-6fdb-1c2c-ac04dfa4c1ca", 1.0);}}

床3 … ドン!(普通の音2)

default{state_entry(){llCollisionSound("52dd9553-5c75-6fc8-5573-32df7b56d14d", 1.0);}}

床4 … ドン!(軽く、すこし硬い音)

default{state_entry(){llCollisionSound("88c0cae6-3c0d-6b6c-edee-85a3f1237828", 1.0);}}

アルミホイル … グシャ!

default{state_entry(){llCollisionSound("801f106b-d391-0214-cdd1-709b072b46aa", 1.0);}}

ビニール … グシャ!

default{state_entry(){llCollisionSound("e40d1ca7-d37f-1332-2513-37a8e209dbc6", 1.0);}}

金属音1 … コンッ!(すこし鈍い音)

default{state_entry(){llCollisionSound("b55200e1-b1bc-5302-ada4-ed559671225c", 1.0);}}

金属音2 … カッ!(軽い音)

default{state_entry(){llCollisionSound("739756e2-a4e1-7ab0-879e-118c458e545d", 1.0);}}

布1 … 軽く触れる音

default{state_entry(){llCollisionSound("a7451a80-e9f5-315a-92b2-f96253578077", 1.0);}}

布2 … バサ!

default{state_entry(){llCollisionSound("d64718b2-5923-ff14-c6d5-0ed9dda9d7c4", 1.0);}}

液体1 … ピトッ!

default{state_entry(){llCollisionSound("3bb0d4fc-d738-d04c-22f1-cd35ede613a4", 1.0);}}

液体2 … ペトッ!

default{state_entry(){llCollisionSound("75374bdf-c059-d568-bfe1-093cef58a0fd", 1.0);}}

というわけで、音の話……主に衝突音の話を終わります!

ありがとうございました!

イベントがあると、色々な人に知識を共有出来たり、
自分もさらに調べていこうと啓発もできて、とてもいいものです!
このような場を設けていただき、改めてありがとうございました!

セカンドライフのスクリプトのエラー処理について

投稿日: 更新日:


セカンドライフでは、スクリプトでエラーが起きるとどうなるかみなさん知っていますか。
何かエラーが出ること自体は知っていると思いますが、
そのエラーが発生後、どうなるのかはそんなに知らないと思います。

ためしに、次のようなスクリプトを実行してみましょう。

hoge() {
	integer x = 0;
	llOwnerSay("hoge_start");
	x = 1 / 0;
	llOwnerSay("hoge_end");
}

default {
	state_entry() {
		llSetTimerEvent(3.0);
	}
	
	touch_start(integer total_number) {
		llOwnerSay("touch_start");
		hoge();
		llOwnerSay("touch_end");
	}
	
	timer() {
		llOwnerSay("clock");
	}
}

このスクリプトは、3秒に1度、発言が行われて、
また、クリックすると0の割り算エラーを発生させるスクリプトです。

これでクリックするとどうなると思いますか。三択問題です。

A. hoge関数内でエラーが発生するので、例外で終了するため”hoge_end”は表示されずに、関数を抜ける
B. touch_startイベント関数内でエラーが発生するので、そこでtouch_startイベント関数が強制終了する
C. プログラム自体が強制終了し、タイマーイベントなど全てが止まる

さて、どうなるでしょう。

正解は・・・


 

 

テテテテテテテ

 

 

ジャン!

Cでした!

なんと、すべて止まってしまうのです。
無限ループもタイマーもすべて止まってしまうので、手動リセットさせるしかありません。
なお、エラーの種類は「LSL Errors」でまとまっていますので、一度見ておくといいかもしれません。
注意点として、メモリリークの「Script run-time error: Stack-Heap Collision」なのですが、
これも発生してしまうと、プログラムが止まってしまいます。
そこで、止まるよりはみずから llGetFreeMemory で定期チェックをして、
llResetScript でリセットさせたほうが安全です。


オマケ

次のスクリプトはエラーが発生するでしょうか……

default {
	state_entry() {
		llOwnerSay((string)((integer)"ABC"));
		llOwnerSay((string)((integer)"123ABC456"));
		llOwnerSay((string)((vector)"ABC"));
		llOwnerSay((string)((vector)"<1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0>"));
	}
}


正解はこんな感じでエラーは発生しません。
文字列の左からデータとして認識できる範囲で変換してくれるようですね。

Object: 0
Object: 123
Object: <0.00000, 0.00000, 0.00000>
Object: <1.00000, 2.00000, 3.00000>

セカンドライフのスカイボックスに太陽の光を!

投稿日: 更新日:


スカイボックスをご存知でしょうか。

セカンドライフでは地面の上に家をたてる場合と、
4000mまでの上空の間に家を浮かばせるスカイボックスがあります。

スカイボックスの最大のメリットとしては、
周りの情景に気にせず好きなものを建てられるということです。

通常、地面の上に建てる場合、お隣さんの家に気を使ったりして大きな建物を建てられなかったり、
あるいは雪の土地の上であれば、冬っぽい家を建てないと気分がでないなど
様々な制約があるのですが、スカイボックスは、自分で地面から作成して、
周りの風景まで画像を張ったりすることで楽しむこともできます。
中から外へのボックスが透過にし、解放感も味わうこともできます。

しかし1つ問題があります。
それは太陽の光をあびれないということ……。

スカイボックスは、プライバシーのために箱で包むことがよくあるのですが、
解放感を出すため内部から外へは透明にすることがよくあります。
一見、外の空が見えるので、解放感はあるのですが、なぜだか内部が暗くなってしまいます。
それは、影のせいです。

例えばですが、次のように立方体を設置すると影がでます。
secshadow1

ここで、影側のほうから壁を透明にした場合でも、やはり影ができてしまうのです。
secshadow2
スカイボックス内で内部から外を透過して解放感を出しても、
外からの光は残念ながら中に入らないのです。

 

 

実はテクニックがありまして・・・

 

 

テテーン!
secshadow3

さて、どのようにして影を出さないようにしたのでしょうか。

実は、外側のテクスチャを微妙に透過させることで、
影を出さないようにしたのです。
調査した結果、12%の透過度にすると影がでなくなるようです。

少しは透けてしまうようになるのですが、
大体中は見えないですし、二重にすることでより見づらくすることもできます。

こんな感じに
secshadow4

以上、スカイボックスの中に太陽の光を!でした。

セカンドライフのサードパーティビューア Black Dragon の紹介

投稿日: 更新日:


ビューア関係の前回の記事「セカンドライフのサードパーティビューア Catznip の紹介」では
土地の境界線表示機能付きのカラフルなミニマップ表示
自分のオブジェクト一覧表示機能
・容姿にフォルダ構造を持たせられる機能
など他のビューアにはない機能を持つ「Catznip Viewer」について紹介しました。

今回は、「Black Dragon」(ブラックドラゴン)を解説します。


Black Dragonはグラフィック設定がすごい!

Black Dragonの最大の特徴は、3DCGの表示機能設定が豊富な点です。
設定できる機能の一部を紹介します。
.

テクスチャのメモリの最大値の増加

ここのメモリの容量が大きいほど、テクスチャが汚くなりません。
しかし通常、テクスチャはグラボにグラフィックメモリが何GBもつんであっても、最大512MBしか設定できません。
Black Dragonでは、グラフィックメモリの最大値を8GBまで設定することができます。
.

FXAAのアンチエイリアスが有効

これを有効にすると、ジャギー(2D座標空間の標本化歪み)が目立たなくなります。
通常のビューアでは、アンチエイリアシングは FSAA 2x/4x/… などが利用できます。
このアルゴリズムは、SSAA(Super Sampling Anti-Aliasing, Full-Scene Anti-Aliasing)を使用しています。
SSAAは綺麗にはなるのですが、大きな画面として描写するため処理が重たくなります。
一方、ここでは使用できませんが、MSAAというものあり、
MSAAは、SSAAより軽いですが、テクスチャ自体にはアンチエイリアスをかけられない特徴があります。

今回、このビューアではFXAAが利用できます。
FXAAの最大の特徴は、3DCGを描写後に行うアンチエイリアスという点です。
品質は、SSAAより悪いですが、動作は非常に軽く、MSAAと違いテクスチャ自体のギザギザも抑えられます。
それぞれの特徴については、「4Gamerの記事」を参照。
.

影テクスチャを細かく設定できる

通常のビューアでは、影の設定を「太陽/月・プロジェクタ」という1つの設定しかありません。
しかし、Black Dragonでは影の設定を細かく設定できるため、綺麗に影を落としこむこともできます。
例えば影を落とすために、シャドウマッピング用にテクスチャを用意するのですが、
このテクスチャの解像度によって、影の品質がきまります。
Black Dragonでは、このテクスチャの縦と横の大きさを自由に設定できます。
あまりに大きいと、グラフィックメモリを使用するので注意が必要です。
また、解像度以外にも、このテクスチャから
何点のポイントを使用して平均化し影をつけるかの設定ができます。(ソフトシャドウ技術
この設定を行うことで、はっきりした影や、ぼやけた影の表現もできます
.

SSAOの詳細設定ができる。

物をリアルに表示させるために明暗をつける
アンビエントオクルージョンというテクニックがあります。
例えば、近くに物があれば、その物の近くにあるオブジェクトを暗くする機能です。
通常のビューアでは「アンビエントオクルージョン」という1つのチェックボックスですが、
Black Dragonでは、Screen Space Ambient Occlusionの設定項目で、詳細設定が可能です。
ここの設定は重たくなる原因なので、チェックを外すのもアリだと思います。
.

DoFの詳細設定ができる。

DoF(Depth of Field)という技術があります。
これは、ある距離より遠いものや近いものをぼかして、被写界深度を再現します。
通常のビューアでは「フィールの遠近感」という1つのチェックボックスですが、
Black Dragonでは、Depth of Fieldの設定項目で、詳細設定が可能です。
なお、この中で「Enable Alphas in Depth of Field calculations」という設定があるのですが、
これは透明度を持つオブジェクトに対してもDoFを正しく行うという機能です。
この機能は、結構重たい処理のためFPS稼ぎに外しておくのがオススメです。
.

モーションブラーを設定できる。

カメラをぶらすと、映像の軌跡を残るように、
3DCG表示でもこれを再現させます。
モーションブラーを使用すると、アバターをアニメーションをさせたときに
滑らかに表示されるように感じたり、躍動感がうまれます。
.

レイトレーシングによる鏡面反射

「Render Screen Space Reflection」のオプションを有効にすることで、
より現実的な鏡面反射を実現できます。
鏡面反射光とは、光がものに当たり、その反射が目にはいる光のことです。
通常のSL上では、鏡面反射を設定した物質は、例えば光があったとして、その光の反射だけが画面に映ります。
しかし現実空間では、目で鏡面反射に映ったさきの物が見えます。(鏡とかがそれです。)
この「Screen Space Reflection」では、目で鏡面反射で映った先の物質が見えるようになります。
レイトレーシングを使用しているので画面全体で調べると処理時間が間に合わないことから
「SSR Resolution」という解像度の中でリアルタイムレイトレーシングを行います。
Screen Space Reflection の解説はhecomi様の「Unity で Screen Space Reflection の実装をしてみた」が詳しいです。
.

レンズフレア

太陽をみたときなどに、レンズフレアを表示させることができます。
ただ、太陽との間にオブジェクトで遮っている場合でも、
レンズフレアが見えてしまうことがあるので、この設定は一長一短。
.

トーンマッピング

3DCGのレンダリング後に、色に対してエフェクタを通すことができます。
色は、線形や非線形に変更したりできます。
具体的には、コントラストを上げたり、明るくしたり、赤みをおびさせたり、
好きな雰囲気にすることができます。


さて、使いたくなってきたところで、
インストール時によくやる設定について最後に紹介します。
.

キーボード操作の設定(Keybindings)の変更

スライド移動(Strafe)と回転(Rotate)とジャンプのキーボード操作が
デフォルトと異なるため、変更すると使いやすいです。

三人称視点時設定(Third Person Keybindings)と
一人称視点(マウスルック)時設定(First Person Keybindings)の
両方で設定をする必要があります。

Third Person Keybindings
・Move Forwards [W] -> [W]
・Move Backwards [S] -> [S]
Strafe Left [A] -> [A + [Shift]]
Strafe Right [D] -> [D + [Shift]]
Rotate Left [Q] -> [A]
Rotate Right [E] -> [D]
Jump [Space] -> [E]

First Person Keybindings
・Move Forwards [W] -> [W]
・Move Backwards [S] -> [S]
・Strafe Left [A] -> [A]
・Strafe Right [D] -> [D]
・Rotate Left [Q] -> [Q]
・Rotate Right [E] -> [E]
Jump [Space] -> [E]

.

カメラの設定(Camera)の変更

下記のチェックボックスを外しましょう。
「Enable ‘realistic’ Camera behavior in Mouselook」
この設定が有効になっていると、
マウスルック時のカメラが、アバターのアニメーションに
追従するようになると思います。酔う原因になります。
.
また、Smoothingを8.00->0.50にすると、
カメラが向いた方向へ瞬時に移動するので好みで設定。
.

グラフィックの変更

Black Dragonは、デレンダラ(非描写)機能があります。
Rendering Options -> Derender … と書いてある設定です。
この設定は、指定したファイルサイズより大きかったり、
表面の面積が大きかったりしたりすると表示しなくなります。
アバターやオブジェクトが表示されなくならないように、適切な値に調節するか、
あるいは全て 0 にして無効化するといいです。


グラボをつけている方や、
綺麗なスクリーンショットを撮りたい方は
一度 Black Dragon を試してみるといいかもしれません。

以上、紹介を終わります!


自分用の設定メモ

.

髪の毛などの影も綺麗に顔に落とす(太陽の光用)

☑Deferred Rendering
・Extended Shadow Distance 128 -> 16
・Closeup Shadowmap Size 2048 -> 4096
・Close Shadowmap Size 4096 -> 4096
※Shadowの設定で上と下があるのは、おそらく上が太陽の影、下がライトによる影設定です
※「Extended Shadow Distance」は小さくなるほど、影の精度があがりますが、遠い距離にある影がおちにくくなります。
.

全体をふんわりと明るくする

☑Windlight Options
・Warmth Red 1.00 -> 2.00
・Warmth Green 0.60 -> 2.00
・Warmth Blue 0.75 -> 2.00
☑Volumetric Lighting
・中はデフォルト
☑Post Processing Effects -> Lens Flare Effect
・中はデフォルト
☑Tone Mapping
☑Custom
Linear Strength 0.44 -> 0.25
Toe Strength 0.24 -> 0.87
Toe Numerator 0.02 -> 0.87
Toe Denominator 0.18 -> 0.66
Linear White 25.00 -> 13.22
Exposure Bias 3.00 -> 0.91
☑Color Correction Linear
・中はデフォルト