de_HiddenCityメモ

昨日のエントリーから移動。
思いつくまま書いたせいでわかりにくい文章になった。
しかしこのまま置いておく。


  • まず、前作で得た知見の中に間違ったものがあった。もともときっちり検証したものではないのでしょうがないことだが。
    ダイナミックシャドーがドア付近の影が落ちるはずのないところに現れるのは、ドアに使ったモデルとは関係ないようだ。今回ドアはまったく使わなかったのだが、それでも変な場所に影が現れている。影の生成判定にモデルではなくbounding boxを使っているような感じがするが、この辺の仕組みについては詳しくないのでよくわからない。
    調べてみると公式マップでも意味不明な場所に影が落ちることはあるが、実際に自分がプレーしているときにはそんなことにはほとんど気付かなかった。マップを作っている間はものすごく気になるが、自分なんかよりずっと無頓着な普通のプレーヤは当然気にするはずもない。要するにこの点について別に気にする必要はないし、ダイナミックシャドーの描画方法について何らかの手直しがされない限りどうにもならない。
    そもそもinfo_no_dynamic_shadowが用意されている理由を想像してみれば、この点にこだわっても仕方ないのだということがわかる。


    しかし、自分が求めている映像表現としては致命的で、容認しがたい気持ちがある。


    前回は時間帯を早朝に設定し太陽もそれにあわせて低い位置にあったため長い影が伸びてしまい、その影があまりにも不自然だったので室内は徹底的にinfo_no_dynamic_shadowでダイナミックシャドーが落ちないように細工した。このことがプレーヤの気付かないところで室内の"室内っぽさ"を演出したのは皮肉なことだと思う。室内なのに太陽の光を受けた際に出る影があるというのは実におかしな光景なのだが、ほぼすべてのマップでそういう表示になっていると、やがて慣れてしまい知性では「そういうもんなのだ」と理解していても、感性では違和感を感じ続けている。かつ、脳は通常、影を排除した光景を無意識のうちにに合成して判断している(このエントリー参照)ため影自体を意識することが少ない。そんなわけで、おかしな影を表示するくらいならいっそ無くしてしまったほうがリアルに感じるのだ。
    今回は太陽は高い位置にあり一部の建物では窓から室内に日光差し込んでいるので、プレーに重大な影響のある問題箇所にだけ使った。当然、より普通に、Sourceエンジンぽくなっている。
    自分の中では好ましいことではないのだが、エンジンの仕様については諦めるしかない。

  • func_detailの使い方について。
    SDKでは同様の機能を持ったエンティティがfunc_wallと呼ばれていた事からわかるように、これは広い面の上に置かれた小さなオブジェクトのせいでその広い面のポリゴンが複雑に細分化されるのを防ぐためのものだ。
    SDK Docsをみてみると、「func_detailは Non detail であるfaceをsplitすることはない」と書かれている。これが嘘であることには前作を作る過程で気付いていたが、今回偶然起こったミスからこれを避ける方法を思いついて多用した。
    嘘である、というのは、world brush のedge上にfunc_detailのvertexが重なってしまった場合、そのvertexを起点にworld brushのfaceがsplitされてしまう、という現象を念頭に言っている。
    こう書くとたいしたことがないようにも思えるかもしれないが、特に階段部分の polygon split をfunc_detailを使用することですっきりさせる場合等に大変困ったことになる。
    階段とその周りの polygon split と leaf division の簡素化を図るとき、三角柱を横倒しにしたものを斜めに並べることで作った一連の"段"をfunc_detailにし、その下に台形ないし平行四辺形の断面を持つblockを配し、このfunc_detailとblockの接面にnodrawを適用するのがもっとも効率的(合目的的かつ短時間で作成可能)な方法だと考えている。
    ところが、階段の側面が壁に接している場合にはこの方法でも壁のpolygonが階段の段数分切り刻まれてしまう。
    Hammerをいじり始めて以来これは仕様であってどうしようもないと思っていたのだが、今回ふとしたミスから、func_detail製の"段"をほんの少し壁にめり込ませ、world brush のedge上にfunc_detailのvertexが重なるのではなくedgeとedgeが交差するようにしてやればpolygon splitが生じないのを見つけて多用した。
    このとき、めり込みすぎると壁の影が段の上に表示されて真っ黒になってしまうので、めり込みは1ユニットでいいだろう。


    あと、func_detailにnodrawを適切に適用すると world brush の場合とほとんど同じ影になる。BETAでそのように変わった。(勘違いかも)

  • Lightmap scaleについて。
    Hammerをいじったことがあれば誰でも気付くことだとは思うが、brushworkでのグリッドとLightmap gridを比べると、圧倒的にLightmapのほうが粗い。
    こういうもんらしい。
    それでも可能な限りライティングにリアリティを持たせようとして細かな設定を施したのが、今回のマップのサイズが大きくなった主な原因だ。
    もちろん、開口部の多い建物が並んでいるせいでデフォルトのままでもCS:Sとしては相当大きな部類に入るが。
    Sourceエンジンがどのように働いているのか知らない自分には、Lightmap scale をいじるとなぜ細かいポリゴンに分ける必要があるのかが理解できない。
    が、とにかくライティングを詳細に表現しようとするとファイルサイズは増えるのであって、実写に迫るクオリティにしようとすると、ファイルサイズが実用的な範囲をはるかに超えてしまうのは間違いない。
    おまけに、いくらきめ細かに影の再現をしてみても、env_cubemapを使用する形式をとっている限り限界は知れている。理想をいえば、env_cubemapなしに滑らかに cubemap texture に相当する風景を変化させていくのがいい。しかしそれは目の前にある風景以外もレンダリングすることを意味するわけで、無理。
    しかしまあ、今回は、前回FPSの都合でできなかったLightmapまわりに力を入れることができ、いろんなノウハウを吸収することができた。
  • HDRについて。
    今回マップを作っている途中にHDR実装版のリリースがあったのだが、最初はかなり斜に構えていたにもかかわらず、実際に試してみると想像以上に効果的で自分のマップにも盛り込むことに。
    HDRといっても、ほとんどのテクスチャはLDRのままでよく、ゲーム内の明るさはエンジンが調節する。ただ、Skyboxはちょっと違った扱いになっているので、HDRテクスチャを用意すると格段に良くなる。
    Skyboxでは、LDR-SkyにHDR-Skyを重ねているようだ。HDR-Skyだけ差し替えても光の具合が変わるだけで風景は変わらない。
    HDR image は、LDR image から合成する場合Gamma2.2マッピングを使用するのが一般的で多くの場合これで事足りる、というのをHL2とは関係ないHDRの解説で読んだが、どうやらこの場合"一般的"でない場合にあたると考えたほうが良さそうだ。
    はっきりした数字は忘れてしまったが、このマップで使ったHDR-Skyは、Gamma3マッピングで生成したイメージを使った。(うろ覚え。3.2だったような気もするし3.5だったような気もする)ただしこの数字はどの場合にも適正なわけではなくて、使用する元LDRイメージやマップのシチュエーションによって加減する必要があるのは間違いない。ちなみにNukeで使われているHDR-SkyはGamma2.2マッピングで作られたように思える。
    HDRテクスチャもVTEXでコンパイルするわけだが、このときの元画像のフォーマットは.PFMで、texturename.txtにあらかじめ
    "pfm" "1"
    "pfmscale" "1"
    と記述しておかなければいけない。scaleが何のscaleなのかは知らない。
    normalmapや DU/DV map のように自動的に判別してくれるわけではないので一手間余計にかかる。
    .PFMのコンパイルはほぼ一瞬で終わる。
    LDRテクスチャはコンパイルするとサイズがかなり小さくなるが、HDRの場合変わらない。データの構造は.PFMそのままなんじゃないか、という気がする。
    そんなわけで、HDR-Skyboxは一組18ファイルで合計サイズは二十数メガになるのが普通であり、公式マテリアルでもそれくらいになっているはずだ。


    SDK Docsをみると、HDRではライトの明るさはLDRに比べて暗くてすむと書かれていて、事実その通りなのだが、LDRならば100前後にするところをHDRでは20〜30で設定することもあり、brightnessを1変えたときの変化割合が大きくなってしまい微調整は難しくなる。
    また、条件によってはライトのbrightnessを上げたのに実際に見てみるとさらに暗く描画されるということも起こりうるし、実際にそれで手間取った。


    HDRのExposureの切り替えは自動的に起こるが、このタイミングは結構遅い。これを逐一指定することもできるが、ものすごく面倒なので今回はやらなかった。これからもそんなことはしないだろうと思う。
    試してはいないが、Exopsureに変な値を設定すれば現実にはありえない狂った世界を表現できるかも。


    HDRをOnにすると、SwapBufferにものすごい負担がかかる。これが足かせとなってマップの構造をどんなにシンプルにしてもFPSは稼げない。新しいハードに期待。