SEGA TECH Blog 2024-03-28T10:00:00+09:00 sgtech Hatena::Blog hatenablog://blog/6653812171404886549 『PSO2ニュージェネシス』における雪原の跡付け表現について hatenablog://entry/6801883189093440004 2024-03-28T10:00:00+09:00 2024-03-28T10:00:01+09:00 1.はじめに 株式会社セガ 第3事業部 第3オンライン研究開発プログラム1部の釘田と申します。 連日の寒さも徐々に明け、春の訪れを感じる頃合いです。 今年の冬は何度か弊社オフィスのある大崎でも雪が降りました。 私はこれまで雪のあまり降らない地域で過ごしてきたこともあり、 雪が積もるとつい童心に帰り、雪の上を歩きたくなります。 この雪の上で跡が付く様子ですが、ゲームではどのように表現されているでしょうか? 今回の記事では『ファンタシースターオンライン2 ニュージェネシス』における 雪原の跡付け表現について紹介したいと思います。 2.目次 1.はじめに 2.目次 3.前置き 4.フィールドでの雪原… <h1 id="1はじめに">1.はじめに</h1> <p>株式会社セガ 第3事業部 第3オンライン研究開発プログラム1部の釘田と申します。<br> 連日の寒さも徐々に明け、春の訪れを感じる頃合いです。<br> 今年の冬は何度か弊社オフィスのある大崎でも雪が降りました。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112118.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>私はこれまで雪のあまり降らない地域で過ごしてきたこともあり、<br> 雪が積もるとつい童心に帰り、雪の上を歩きたくなります。<br> <br> この雪の上で跡が付く様子ですが、ゲームではどのように表現されているでしょうか?<br> 今回の記事では『ファンタシースターオンライン2 ニュージェネシス』における<br> 雪原の跡付け表現について紹介したいと思います。<br></p> <h1 id="2目次">2.目次</h1> <ul class="table-of-contents"> <li><a href="#1はじめに">1.はじめに</a></li> <li><a href="#2目次">2.目次</a></li> <li><a href="#3前置き">3.前置き</a></li> <li><a href="#4フィールドでの雪原の跡付け表現">4.フィールドでの雪原の跡付け表現</a><ul> <li><a href="#41キャラクターの足跡表現">4.1.キャラクターの足跡表現</a><ul> <li><a href="#411地形とキャラクターに対する深度撮影">4.1.1.地形とキャラクターに対する深度撮影</a></li> <li><a href="#412軌跡テクスチャの作成">4.1.2.軌跡テクスチャの作成</a><ul> <li><a href="#4121軌跡テクスチャのフィルタ処理">4.1.2.1.軌跡テクスチャのフィルタ処理</a></li> </ul> </li> <li><a href="#413雪面の変形">4.1.3.雪面の変形</a></li> </ul> </li> </ul> </li> <li><a href="#5ハウジングコンテンツでの雪原の跡付け表現">5.ハウジングコンテンツでの雪原の跡付け表現</a><ul> <li><a href="#51オブジェクトよる跡付け表現">5.1.オブジェクトよる跡付け表現</a><ul> <li><a href="#511オブジェクトに対する深度撮影">5.1.1.オブジェクトに対する深度撮影</a></li> <li><a href="#512オブジェクトの深度を考慮した軌跡テクスチャの作成">5.1.2.オブジェクトの深度を考慮した軌跡テクスチャの作成</a></li> <li><a href="#5121オブジェクトの深度撮影が表面のみの場合に起きる問題">5.1.2.1.オブジェクトの深度撮影が表面のみの場合に起きる問題</a></li> </ul> </li> </ul> </li> <li><a href="#6まとめ">6.まとめ</a></li> <li><a href="#7最後に">7.最後に</a></li> </ul> <h1 id="3前置き">3.前置き</h1> <p>記事内の画像は開発時のゲーム画面となります。<br> 実際にリリースされているゲーム画面とは異なる場合もありますので、あらかじめご了承ください。<br> また、以降『ファンタシースターオンライン2ニュージェネシス』のことを『NGS』と表記します。<br></p> <h1 id="4フィールドでの雪原の跡付け表現">4.フィールドでの雪原の跡付け表現</h1> <p>まず、『NGS』における雪と氷のフィールドである「クヴァリス」での雪原の跡付け表現について説明します。<br> 「クヴァリス」では一部の雪原において、キャラクターが歩いた場所に足跡が残ります。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112126.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h2 id="41キャラクターの足跡表現">4.1.キャラクターの足跡表現</h2> <p>足跡を雪原に残すにはどうすればいいでしょうか?<br> <br> まずは実際に現実世界で雪がどのようにしてへこむかについて考えてみましょう。<br> 冒頭の写真のような雪が積もった道を思い浮かべてみてください。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112136.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>雪は柔らかいため、足を踏み入れると雪が積もっていた高さから踏み込んだ深さまでへこみ、足跡として残ります。<br> <br> 『NGS』では、地面の高さを雪の厚みの分だけ上昇させ、キャラクターが歩いた場所をへこませています。 <br> これは以下のような処理で実現できそうです。<br></p> <ol> <li>地形とキャラクターに対する深度撮影</li> <li>軌跡テクスチャの作成</li> <li>雪面の変形</li> </ol> <p>それでは実際の処理について見ていきましょう。<br></p> <h3 id="411地形とキャラクターに対する深度撮影">4.1.1.地形とキャラクターに対する深度撮影</h3> <p>キャラクターの足によってどの位置でどの程度の深さまでへこませるかを決めるために、<br> カメラを地面の下から上方向に向けて地形とキャラクターに対して深度撮影を行います。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112140.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h3 id="412軌跡テクスチャの作成">4.1.2.軌跡テクスチャの作成</h3> <p>次に、跡を付ける深さの情報が格納された軌跡テクスチャを作成します。<br> 雪がへこむのは以下の図のように、キャラクターの足が地面と雪面の間にあるときです。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112144.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>条件式で表すと以下のようになります。<br></p> <pre class="code" data-lang="" data-unlink>地面の高さ &lt; キャラクターの高さ &lt; 雪面の高さ</pre> <p>ここでは説明のため、キャラクターの足の位置を「キャラクターの高さ」と表現します。<br> <br> 先ほどの深度撮影の結果を用いて<br> 「キャラクターの高さ」はキャラクター深度から、「地面の高さ」は地形深度から求まります。<br> また、「雪面の高さ」は「地面の高さ」と「雪の厚み」を合わせた値です。<br> 「雪の厚み」は内部的に設定されたパラメータで、場所によって厚みが異なります。<br> <br> 「雪をへこませる割合」は雪がへこんでいない状態を0.0、すべてへこんでいる状態を1.0として、 <br>以下のように計算します。<br></p> <pre class="code" data-lang="" data-unlink>雪をへこませる割合 = (地面の高さ + 雪の厚み - キャラクターの高さ) / 雪の厚み</pre> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112149.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>シェーダーで計算された値は軌跡テクスチャへと書き込まれます。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112154.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>地形深度を用いているため、傾斜のある地形などでもへこませることができます。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112158.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h4 id="4121軌跡テクスチャのフィルタ処理">4.1.2.1.軌跡テクスチャのフィルタ処理</h4> <p>次に作成した軌跡テクスチャに対して、より自然なへこみ跡を表現するため、フィルタ処理をかけています。<br> ここで冒頭の写真を再度見てみましょう。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112202.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>足跡と雪の縁の部分に着目してみると、足跡側ではへこみが緩やかに広がっています。<br> また、雪側では踏まれて押し出された雪によって盛り上がっていることがわかります。<br> <br> これらを表現するために、フィルタ処理では平滑化を行い、へこみを緩やかにしたうえで、<br> へこみ部分の縁の高さを調整し隆起させています。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112212.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>以下は実際のゲーム内でのフィルタ処理の有無の比較画像になります。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112216.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>フィルタ処理をかけることで、全体的に滑らかな跡になり、縁部分での雪の盛り上がりも表現できています。<br> <br> また、軌跡テクスチャにはプレイヤーキャラクターを中心として80m四方の範囲内の跡が記録されており、<br> プレイヤーキャラクターからの距離に応じて徐々に足跡が消えていく表現についてもフィルタ処理で行っています。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112222.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h3 id="413雪面の変形">4.1.3.雪面の変形</h3> <p>最後は雪面の描画時に、作成した軌跡テクスチャの情報を元に雪面を変形させます。<br> 雪面の変形にはテッセレーション処理を用います。<br> <br> テッセレーション処理では地形モデルのポリゴンを分割し、分割されたポリゴンの頂点の位置を変更します。<br> 頂点位置の変更の際に軌跡テクスチャを参照することで、跡付けを行う部分をへこませます。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112227.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>下記がテッセレーション処理の有無の比較画像になります。</p> <p><figure class="figure-image figure-image-fotolife" title="テッセレーションなし(左)とテッセレーションあり(右)の比較"><div class="images-row mceNonEditable"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112232.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112243.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></div><figcaption>テッセレーションなし(左)とテッセレーションあり(右)の比較</figcaption></figure></p> <p>ちなみに、テッセレーションに対応していない場合でも、軌跡テクスチャを用いた法線の調整やAOにより陰影をつけることで疑似的に表現しています。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112254.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h1 id="5ハウジングコンテンツでの雪原の跡付け表現">5.ハウジングコンテンツでの雪原の跡付け表現</h1> <p>ここまではフィールドにおける雪原の跡付け表現について説明しました。<br> <br> ここからは、『NGS』のハウジングコンテンツである、「クリエイティブスペース」の雪山風マップ<br> 「クヴァリステーマ」における雪原の跡付け表現について説明します。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112259.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>「クリエイティブスペース」内ではフィールドと同様のキャラクターによる雪への跡付けだけでなく、<br> プレイヤーが設置可能なオブジェクトである「ビルドパーツ」による跡付けにも対応しています。<br></p> <h2 id="51オブジェクトよる跡付け表現">5.1.オブジェクトよる跡付け表現</h2> <p>基本的な処理の流れについてはフィールドでの跡付けと同様です。<br> <br> 今回はオブジェクトによる跡付けを行うため、追加でオブジェクトに対する深度撮影を行い、<br> 軌跡テクスチャ作成時にオブジェクトの高さも考慮します。<br> <br> 処理の流れは以下の通りです。<br></p> <ol> <li>オブジェクトに対する深度撮影</li> <li>地形とキャラクターに対する深度撮影</li> <li>オブジェクトの深度を考慮した軌跡テクスチャの作成</li> <li>雪面の変形</li> </ol> <p>以降の説明では、1. と 3. について紹介します。<br></p> <h3 id="511オブジェクトに対する深度撮影">5.1.1.オブジェクトに対する深度撮影</h3> <p>まずは 「1. オブジェクトに対する深度撮影」についての説明です。<br> <br> オブジェクトを設置する際にカメラを地面の下から上方向に向け、<br> オブジェクトの表面と背面の深度を撮影します。<br> 描画結果は二枚のキャッシュテクスチャに格納されます。<br> 表面と背面の両方で深度を描画する理由については後述します。<br> <br> 「クリエイティブスペース」ではオブジェクトの設置だけでなく、地形の高さも編集することができます。<br> オブジェクトに対する深度撮影の際には地形の編集が可能な、高さ100m、256m四方の範囲が収まるように<br> キャッシュテクスチャへ深度が書き込まれます。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112308.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>これによって「クリエイティブスペース」内にいる間は、オブジェクトの跡が付いた場所から離れても跡が残ります。<br> <br> また、オブジェクトに対する深度撮影はオブジェクト設置時に一度だけ行うことで、<br> 深度撮影による負荷を抑えています。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112312.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h3 id="512オブジェクトの深度を考慮した軌跡テクスチャの作成">5.1.2.オブジェクトの深度を考慮した軌跡テクスチャの作成</h3> <p>次に「3. オブジェクトの深度を考慮した軌跡テクスチャの作成」について説明します。<br> <br> オブジェクト深度の使い方について、<br> まずはキャラクターの場合と同じように深度テクスチャを一つだけ使う場合を考えてみましょう。<br> <br> 次のようなオブジェクトを設置します。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112317.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>雪がへこむのは、オブジェクトの底面が地面と雪面の間にあるときです。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112324.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>条件式で表すと以下のようになります。<br></p> <pre class="code" data-lang="" data-unlink>地面の高さ &lt; オブジェクト底面の高さ &lt; 雪面の高さ</pre> <p>ここでオブジェクト底面の位置を、説明のため「オブジェクト底面の高さ」と表現します。<br> 「オブジェクト底面の高さ」はカメラを地面の下から上方向に向け、<br> オブジェクトに対して深度撮影した、オブジェクトの表面の深度から求まります。<br> <br> 「雪をへこませる割合」についてもキャラクターの場合と同様に計算します。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112328.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>ここまではキャラクターの場合と同様に、オブジェクト表面のみの深度撮影で問題なさそうです。<br> <br> では次のケースを見ていきましょう。<br> <br> 「クリエイティブスペース」ではプレイヤーが自由にオブジェクトを設置でき、<br> 地形の高さも編集できるため、オブジェクトが地形に埋まる場合があります。<br> 以下のようにオブジェクトを地形に埋めた状態で配置する場合はどうでしょうか?</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112332.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>地形に埋まった状態で設置した場合、オブジェクトの底面が地面よりも低くなってしまい、<br> 埋まった箇所で跡が付きません。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112339.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>そこで、地面の高さよりも低い位置にオブジェクト底面が来た場合は、<br> 「雪をへこませる割合」を1.0とし、雪をすべてへこませます。<br> <br> この場合は以下のように地形に埋まった箇所でも跡を付けることができます。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112343.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>しかし、上記の改善を加えた場合でも別の問題が二つ起きてしまいます。<br> 次で詳しく見ていきましょう。<br></p> <h3 id="5121オブジェクトの深度撮影が表面のみの場合に起きる問題">5.1.2.1.オブジェクトの深度撮影が表面のみの場合に起きる問題</h3> <p>まず一つ目はオブジェクトが完全に地中に埋まってしまった場合です。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112348.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>この場合だと「オブジェクト底面の高さ」だけではオブジェクトが完全に埋まったかの判定が取れず、<br> 以下のように不自然に跡が付いてしまいます。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112356.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>二つ目の問題はオブジェクトを回転させたときに起きます。<br> 先ほどのオブジェクトを次のように回転させ、一部地中に埋まった状態で設置する場合を考えてみましょう。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112400.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>この場合も完全に埋まった場合と同様に、地中に埋まって隠れってしまった部分で不自然に跡が付いてしまいます。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112408.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>これらの問題に対応するために、オブジェクトに関しては表面と裏面の両面で深度を描画しています。<br> 表面と裏面の深度の使い方について、先ほど回転させて設置した場合を例に見ていきます。<br> <br> まず、オブジェクトの上面が地面よりも上にくる領域に着目します。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112412.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>条件としては以下のようになります。<br></p> <pre class="code" data-lang="" data-unlink>地面の高さ &lt; オブジェクト上面の高さ</pre> <p>ここでも底面と同様に、オブジェクト上面の位置を、説明のため「オブジェクト上面の高さ」と表現します。<br> 「オブジェクト上面の高さ」はカメラを地面の下から上方向に向け、オブジェクトに対して深度撮影した、<br> オブジェクトの背面の深度から求まります。<br> <br> 次に、「オブジェクト底面の高さ」を用いて雪をへこませる部分を決めます。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112416.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>上図の①のように、オブジェクト底面が地面と雪面の間にくる場合は、先ほどの説明の通り、<br> キャラクターでの跡付けと同様の方法で「雪をへこませる割合」を計算します。<br> <br> また、上図の②のようにオブジェクトの底面が地面よりも下にくる場合は、<br> 「雪をへこませる割合」を1.0とし、雪をすべてへこませます。<br> <br> これにより、オブジェクトが完全に地中に埋まってしまう場合や、<br> 一部だけ埋まってしまう場合に対しても自然な跡付けを行うことができます。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112420.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>最終的に二枚のキャッシュテクスチャに保存されたオブジェクト深度、キャラクター深度、<br> 地形深度を用いて軌跡を描き、キャラクターの跡付けの際と同様のフィルタ処理を経て、<br> 「クリエイティブスペース」での軌跡テクスチャができます。</p> <p><figure class="figure-image figure-image-fotolife" title=""><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240325/20240325112428.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h1 id="6まとめ">6.まとめ</h1> <p>今回『NGS』における雪原表現について、フィールドとハウジングコンテンツにおける事例を紹介しました。<br> <br> フィールドではキャラクターの足跡による跡付け、<br> ハウジングコンテンツでは自由な配置を踏まえたオブジェクトによる跡付けについて説明させていただきました。<br> <br> 現実世界は目を引く景色、心を動かす風景、興味深い光学現象であふれています。<br> それらを注意深く観察し、ゲームに落とし込むことでさらに感動を与える表現が生まれると思っています。<br> <br> 今回紹介した手法は目新しいものではありませんが、何かの参考になりましたら幸いです。<br></p> <h1 id="7最後に">7.最後に</h1> <p>セガでは一緒に働く仲間を募集しています。<br> 共に感動体験を色々な人に提供できるようなゲームとそのグラフィックス表現を作りませんか?<br> もしご興味を持たれましたら下記のサイトにアクセスをお願いいたします。<br></p> <p><a href="https://www.sega.co.jp/recruit/index.html" onMouseDown="ga('HatenaBlogUserTracker.send', 'event', 'recruit', 'games_banner_clicked','recruit_games_out', true);">採用サイト</a></p> sgtech SIEM on Amazon OpenSearch Serviceによるセキュリティログの可視化について hatenablog://entry/6801883189073926057 2024-01-25T10:00:00+09:00 2024-01-25T10:00:00+09:00 はじめに 株式会社セガ ゲームコンテンツ&サービス事業本部技術本部開発IT支援部の長谷川と申します。今回はセキュリティログの活用法の一例としてSIEMを用いた可視化方法を紹介します。 目次 はじめに 目次 背景 Opensearch(Elasticsearch)とは SIEMとは Cognitoとは ユーザプールとは IDプールとは アーキテクチャ 設定方法 Cognitoによるログイン セキュリティログの可視化 補足 まとめ 参考 背景 昨今セキュリティ対策不足によるデータの抽出やサービス操作される被害が発生しており、ログからユーザの行動を抽出し、可視化するまでを一括管理できるものが求め… <h2 id="はじめに">はじめに</h2> <p>株式会社セガ ゲームコンテンツ&amp;サービス事業本部技術本部開発IT支援部の長谷川と申します。今回はセキュリティログの活用法の一例としてSIEMを用いた可視化方法を紹介します。</p> <h2 id="目次">目次</h2> <ul class="table-of-contents"> <li><a href="#はじめに">はじめに</a></li> <li><a href="#目次">目次</a></li> <li><a href="#背景">背景</a></li> <li><a href="#OpensearchElasticsearchとは">Opensearch(Elasticsearch)とは</a></li> <li><a href="#SIEMとは">SIEMとは</a></li> <li><a href="#Cognitoとは">Cognitoとは</a><ul> <li><a href="#ユーザプールとは">ユーザプールとは</a></li> <li><a href="#IDプールとは">IDプールとは</a></li> </ul> </li> <li><a href="#アーキテクチャ">アーキテクチャ</a></li> <li><a href="#設定方法">設定方法</a><ul> <li><a href="#Cognitoによるログイン">Cognitoによるログイン</a></li> </ul> </li> <li><a href="#セキュリティログの可視化">セキュリティログの可視化</a></li> <li><a href="#補足">補足</a></li> <li><a href="#まとめ">まとめ</a></li> <li><a href="#参考">参考</a></li> </ul> <h2 id="背景">背景</h2> <p>昨今セキュリティ対策不足によるデータの抽出やサービス操作される被害が発生しており、ログからユーザの行動を抽出し、可視化するまでを一括管理できるものが求められていました。さまざまなサービスの中でSIEM on Amazon OpenSearch Serviceにてログ情報からユーザの行動を可視化・検索により原因を改善するができるため、利用し始めました。 セキュリティログをgrepやAthena利用して調査を行ってきましたが、可視化を行うまでは進んでおらず全体的なセキュリティを確認するまで相当な時間がかかっていました。上記のサービスを利用することで、原因特定までの時間が軽減されました。</p> <h2 id="OpensearchElasticsearchとは">Opensearch(Elasticsearch)とは</h2> <ul> <li>大容量データを処理することを想定した全文検索エンジン</li> <li>複数のノードにデータ分散して保存する分散設計</li> <li>システムログの可視化・検知やユーザへのレコメンドや分析など多種多様な範囲で利用可能</li> </ul> <h2 id="SIEMとは">SIEMとは</h2> <ul> <li>SIEM は Security Information and Event Management の略で、セキュリティ機器、ネットワーク機器、その他のあらゆる機器のデータを収集及び一元管理をして、相関分析によって脅威検出とインシデントレスポンスをサポートするためのソリューションです。Amazon OpenSearch Service は、OpenSearch と OpenSearch Dashboards を大規模かつ簡単でコスト効率の良い方法を使用してデプロイ、保護、実行する完全マネージド型サービスです。Amazon OpenSearch Service の環境に SIEM として必要な機能を実装したのが SIEM on Amazon ES です。</li> </ul> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Faws-samples%2Fsiem-on-amazon-opensearch-service%2Fblob%2Fmain%2FREADME_ja.md" title="siem-on-amazon-opensearch-service/README_ja.md at main · aws-samples/siem-on-amazon-opensearch-service" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/README_ja.md">github.com</a></cite></p> <h2 id="Cognitoとは">Cognitoとは</h2> <p>大きくユーザプールとIDプールに分けて認証・認可を行うシステムです</p> <h4 id="ユーザプールとは">ユーザプールとは</h4> <ul> <li>ユーザの作成、管理及び認証を行うユーザディレクトリです</li> <li>アプリからの多数の承認フローが利用可能です</li> <li>サインイン後に発行されるトークンを用いて、認証されたサービスへアクセスを行います</li> </ul> <h4 id="IDプールとは">IDプールとは</h4> <ul> <li>ユーザプールにて認証されたユーザがどのリソースへのアクセスに対してユーザの権限を管理します</li> <li>未承認のユーザに対して、一時的なリソースへのアクセス権を付与することができます</li> <li>ユーザのアクセス権をルールベースおよびアクセスベースでの制御が可能です</li> </ul> <h2 id="アーキテクチャ">アーキテクチャ</h2> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240116/20240116160941.png" width="951" height="491" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></p> <h2 id="設定方法">設定方法</h2> <p> ※今回はセキュリティ面を考慮しまして、VPC内でOpenSearchを構築いたします</p> <ol> <li>SIEMの設定方法は下記より構築しています <a href="https://github.com/aws-samples/siem-on-amazon-opensearch-service/blob/main/docs/deployment_ja.md">SIEM構築</a></li> <li>ECS on Fargate,SecretsManager,Cognito,ELB,Route53サービスの作成します <ol> <li>terraformにより作成(作成方法については割愛します)</li> </ol> </li> <li>Cognito設定を一部抜粋して紹介します <ol> <li><p>ユーザプールの作成</p> <ol> <li>該当のユーザプールのサインインエクスペリエンス欄より、多機能認証を必須設定する <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240116/20240116160912.png" width="891" height="673" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></li> <li>アプリケーション総合よりアプリケーションクライアントの作成をします <ol> <li>認証フローについては該当の項目を選択します <blockquote><p>Note If you don't specify a value for ExplicitAuthFlows, your user client supports ALLOW_REFRESH_TOKEN_AUTH, ALLOW_USER_SRP_AUTH, and ALLOW_CUSTOM_AUTH. <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdocs.aws.amazon.com%2Fja_jp%2Fcognito-user-identity-pools%2Flatest%2FAPIReference%2FAPI_CreateUserPoolClient.html%23API_CreateUserPoolClient_RequestSyntax" title="CreateUserPoolClient - Amazon Cognito User Pools" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://docs.aws.amazon.com/ja_jp/cognito-user-identity-pools/latest/APIReference/API_CreateUserPoolClient.html#API_CreateUserPoolClient_RequestSyntax">docs.aws.amazon.com</a></cite></p></blockquote></li> <li>コールバックURL,サインアウトURLを記入します <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240116/20240116160904.png" width="806" height="534" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></li> </ol> </li> </ol> </li> <li><p>IDプールを作成します</p> <ol> <li>ユーザアクセス欄より認証されたユーザに対するロールを作成します <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240116/20240116160908.png" width="1376" height="327" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></li> </ol> </li> </ol> </li> <li>nginxプロキシによるCognitio認証設定します <ol> <li><a href="https://repost.aws/ja/knowledge-center/opensearch-outside-vpc-nginx">https://repost.aws/ja/knowledge-center/opensearch-outside-vpc-nginx</a></li> <li>セキュリティの観点より環境情報などをSecretsManagerより値を取得し、nginxに取得した環境変数を渡します ※下記はタスク定義の設定を抜粋して記載しています</li> </ol> </li> </ol> <pre class="code lang-json" data-lang="json" data-unlink><span class="synSpecial">{</span> &quot;<span class="synStatement">containerDefinitions</span>&quot;: <span class="synSpecial">[</span> <span class="synSpecial">{</span> ------ 中略 ------ &quot;<span class="synStatement">secrets</span>&quot;: <span class="synSpecial">[</span> <span class="synSpecial">{</span> &quot;<span class="synStatement">name</span>&quot;: &quot;<span class="synConstant">opensearch_domain</span>&quot;, &quot;<span class="synStatement">valueFrom</span>&quot;: &lt;secretsmanager_arn&gt;:&lt;opensearch_domain_key&gt;:: <span class="synSpecial">}</span>, <span class="synSpecial">{</span> &quot;<span class="synStatement">name</span>&quot;: &quot;<span class="synConstant">cognito_domain</span>&quot;, &quot;<span class="synStatement">valueFrom</span>&quot;: &lt;secretsmanager_arn&gt;:&lt;cognito_domain_key&gt;:: <span class="synSpecial">}</span> <span class="synSpecial">]</span> <span class="synSpecial">}</span> } </pre> <h3 id="Cognitoによるログイン">Cognitoによるログイン</h3> <ul> <li>SIEMのURLにアクセスすることでCognito認証によるログインを行います <section style="text-align: center;"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240116/20240116160945.png" width="455" height="369" loading="lazy" title="" class="hatena-fotolife" style="width:400px" itemprop="image"></span> </section></li> <li>MFA設定されている場合は次にTOTPよりコードを入力します <section style="text-align: center;"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240116/20240116160916.png" width="402" height="211" loading="lazy" title="" class="hatena-fotolife" style="width:400px" itemprop="image"></span> </section></li> </ul> <h2 id="セキュリティログの可視化">セキュリティログの可視化</h2> <ul> <li><p>Discover画面にて特定のインデックスで取り込んだログを表示が可能になります</p> <ul> <li>フィルターやSearch欄でクエリで絞り込むことで特定ログ・項目の絞り込みが可能になります <section style="text-align: center;"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240116/20240116160937.png" width="1579" height="500" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span> </section></li> </ul> </li> <li><p>DashBoardにおいても特定フィルター、特定アカウント、特定ACLの絞り込みにより必要なデータの可視化が可能になります <section style="text-align: center;"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240116/20240116160920.png" width="1727" height="809" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><br/> クロスアカウントのCloudTrailログの可視化 </section></p></li> </ul> <p><section style="text-align: center;"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240116/20240116160924.png" width="1295" height="668" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240116/20240116160928.png" width="1287" height="621" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20240116/20240116160932.png" width="1722" height="778" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><br/> WAFログの可視化 </section></p> <h2 id="補足">補足</h2> <p>※今回はアカウント間のデータを一括収集を行い、データの可視化を行う例となっております。</p> <ul> <li>特定の条件(特定のIP、国、UAからDDosアタック)が発生した場合にOpensearchのアラート通知を送るなどでシステム改善の気づきを与えます</li> <li>セキュリティログに限らずアクセスログも収集しているため、Athenaに頼らずに検索や可視化までが一括して可能になるため汎用的な調査が可能になります</li> <li>アクセスログ(CloudFront,ELB,WAF,VPCFlowログなど)の可視化により不要に開放しているセキュリティグループやパスを改善する手がかりを得られ、システム改善にも貢献します</li> <li>他のメンバーにも確認しやすいDashBoardになっているため、インフラ面の改善に限らずアプリケーション側の改善やBotなどの防ぐべき対象を可視化することができます</li> </ul> <h2 id="まとめ">まとめ</h2> <ul> <li>セキュリティログの一元管理および可視化としてSIEMを利用しました</li> <li>一括管理することで、情報が整理されて必要な条件下でのセキュリティの対策を包括的に行うことが可能になります</li> <li>S3のトリガー経由でログの取り込みが行われるため、同一アカウント・クロスアカウントに限らず様々なサービスログを取り込むことも可能になります</li> </ul> <p>※まずは、セキュリティに不安がある方や様々なサービスを用いて通知疲れになっている方はSIEMを用いて一元管理して可視化してみると効率的な監視の手がかりがつかめると思います。</p> <p>セガで働くことにご興味を持たれましたら下記サイトにアクセスお願いします。 <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sega.co.jp%2Frecruit%2Findex.html" title="採用サイト|株式会社セガ -【SEGA CORPORATION】" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html">www.sega.co.jp</a></cite> (C)SEGA</p> <h2 id="参考">参考</h2> <ul> <li>siem <ul> <li><a href="https://aws.amazon.com/jp/blogs/news/siem-on-amazon-elasticsearch-service/">https://aws.amazon.com/jp/blogs/news/siem-on-amazon-elasticsearch-service/</a></li> </ul> </li> <li>nginxプロキシ設定 <ul> <li><a href="https://repost.aws/ja/knowledge-center/opensearch-outside-vpc-nginx">https://repost.aws/ja/knowledge-center/opensearch-outside-vpc-nginx</a></li> </ul> </li> <li>Cognito <ul> <li><a href="https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/what-is-amazon-cognito.html">https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/what-is-amazon-cognito.html</a></li> <li><a href="https://dev.classmethod.jp/articles/get-aws-temporary-security-credentials-with-cognito-id-pool-by-aws-cli/">https://dev.classmethod.jp/articles/get-aws-temporary-security-credentials-with-cognito-id-pool-by-aws-cli/</a></li> </ul> </li> <li>TOTP: Time-based One-Time Password</li> <li>terraform <ul> <li><a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs">https://registry.terraform.io/providers/hashicorp/aws/latest/docs</a></li> </ul> </li> </ul> sgtech 『PSO2 ニュージェネシス』におけるトゥーン表示対応について hatenablog://entry/820878482956183122 2023-08-10T10:00:00+09:00 2023-08-10T16:55:45+09:00 1.はじめに 株式会社セガ 技術本部 技術統括室 ソフトシステムセクションの西濱 高志と申します。 今回の記事では『ファンタシースターオンライン2 ニュージェネシス』におけるトゥーン表示対応について紹介いたします。 2.目次 1.はじめに 2.目次 3.前置き 4.トゥーンレンダリングとは? 4.1.陰影のマルチトーン化 4.2.アウトライン表現 5.『NGS』におけるトゥーン表示対応について 5.1.『NGS』のレンダリングシステムについて 5.2.拡散反射光(陰影)のマルチトーン表現 5.3.鏡面反射光(スぺキュラ)のマルチトーン表現 5.4.アウトライン表現 5.4.3.輪郭線の抽出 6… <h1 id="1はじめに">1.はじめに</h1> <p>株式会社セガ 技術本部 技術統括室 ソフトシステムセクションの西濱 高志と申します。 今回の記事では『ファンタシースターオンライン2 ニュージェネシス』におけるトゥーン表示対応について紹介いたします。</p> <h1 id="2目次">2.目次</h1> <ul class="table-of-contents"> <li><a href="#1はじめに">1.はじめに</a></li> <li><a href="#2目次">2.目次</a></li> <li><a href="#3前置き">3.前置き</a></li> <li><a href="#4トゥーンレンダリングとは">4.トゥーンレンダリングとは?</a><ul> <li><a href="#41陰影のマルチトーン化">4.1.陰影のマルチトーン化</a></li> <li><a href="#42アウトライン表現">4.2.アウトライン表現</a></li> </ul> </li> <li><a href="#5NGSにおけるトゥーン表示対応について">5.『NGS』におけるトゥーン表示対応について</a><ul> <li><a href="#51NGSのレンダリングシステムについて">5.1.『NGS』のレンダリングシステムについて</a></li> <li><a href="#52拡散反射光陰影のマルチトーン表現">5.2.拡散反射光(陰影)のマルチトーン表現</a></li> <li><a href="#53鏡面反射光スぺキュラのマルチトーン表現">5.3.鏡面反射光(スぺキュラ)のマルチトーン表現</a></li> <li><a href="#54アウトライン表現">5.4.アウトライン表現</a><ul> <li><a href="#543輪郭線の抽出">5.4.3.輪郭線の抽出</a></li> </ul> </li> </ul> </li> <li><a href="#6トゥーン用の顔データの作成について">6.トゥーン用の顔データの作成について</a><ul> <li><a href="#61-法線の調整について">6.1 法線の調整について</a></li> <li><a href="#62-ラフネス値の調整について">6.2 ラフネス値の調整について</a></li> <li><a href="#63-目の影について">6.3 目の影について</a></li> </ul> </li> <li><a href="#7その他の対応">7.その他の対応</a><ul> <li><a href="#71カットイン画面のトゥーン表示対応">7.1.カットイン画面のトゥーン表示対応</a></li> <li><a href="#72半透明のアウトライン">7.2.半透明のアウトライン</a></li> </ul> </li> <li><a href="#8調整するパラメータについて">8.調整するパラメータについて</a></li> <li><a href="#9まとめ">9.まとめ</a></li> <li><a href="#10最後に">10.最後に</a></li> </ul> <h1 id="3前置き">3.前置き</h1> <p>記事内の画像は開発時のゲーム画面となります。実際にリリースされているゲーム画面とは異なるところもありますので、あらかじめご了承下さい。</p> <p>また、表記として『ファンタシースターオンライン2 ニュージェネシス』のことを『NGS』、『ファンタシースターオンライン2』のことを『PSO2』と呼称することにします。</p> <p>トゥーンレンダリングに関する最新技術の話はありませんが、何かしら参考になれば幸いです。</p> <h1 id="4トゥーンレンダリングとは">4.トゥーンレンダリングとは?</h1> <p>トゥーンレンダリングとは、コンピュータグラフィックスにおいてアニメ風、広くは漫画やイラスト風の作画でレンダリングする手法のことを言います。 セルシェーディングとも呼ばれ、ゲームの表現において個人、企業問わず採用する例が増えています。</p> <p><figure class="figure-image figure-image-fotolife" title="描画比較"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140538.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>トゥーンレンダリングを実現する上で、重要な要素となるのが「陰影のマルチトーン化」と「アウトライン表現」の2点になります。</p> <h2 id="41陰影のマルチトーン化">4.1.陰影のマルチトーン化</h2> <p>トゥーンレンダリングにおける陰影は、物理的な計算を解いて表現するフォトリアルな陰影とは違い、デザイナー(アーティスト)が指定、調整した色で陰影も表現されることが多いです。</p> <p>一般的な実装としては色の段階を設定したテクスチャ(ランプテクスチャ)を用意し、陰影の表現に使用する形が多いです。</p> <p><figure class="figure-image figure-image-fotolife" title="ランプテクスチャによる陰影付け"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140541.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>しかし陰影を段階的にする都合上、人間の顔など複雑な凹凸がある物体では陰影が綺麗にならないことが多いです。 このため、トゥーンレンダリングでは物体の法線を調整して陰影を綺麗にし、アニメのような表現に近づけるといった工夫がされています。</p> <p>この記事では、このようなトゥーンレンダリングにおける陰影の段階化を「陰影のマルチトーン化」と呼称することにします。</p> <h2 id="42アウトライン表現">4.2.アウトライン表現</h2> <p>イラストやアニメにおける、「線画」を表現するため、アウトラインの表示もトゥーンレンダリングでは重要な要素になります。</p> <p><figure class="figure-image figure-image-fotolife" title="アウトライン比較"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140545.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>実装方法としては、「背面法」と「輪郭線の抽出」の二つがあります。 「背面法」とは対象のモデルについて頂点を法線方向に拡大して裏面を描画した後、通常の描画を上塗りすることでアウトラインを表現する手法になります。<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p> <p><figure class="figure-image figure-image-fotolife" title="背面法によるアウトライン描画"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140549.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>「輪郭線の抽出」とは、レンダリング途中で生成した深度情報等をもとにフィルタ処理をすることで輪郭線の抽出を行い、アウトラインを描画する手法になります。 下記図は、出力された画像に対してSobelフィルタを用いてアウトラインを描画する例になります。</p> <p><figure class="figure-image figure-image-fotolife" title="輪郭線の抽出によるアウトライン描画"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140553.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>それぞれ特徴があり、まとめると下記のようになります。</p> <table> <thead> <tr> <th> 手法 </th> <th> クォリティ </th> <th> 処理負荷 </th> <th> モデルデータの改良 </th> </tr> </thead> <tbody> <tr> <td> 背面法 </td> <td> 高 </td> <td> 描画する物体が多くなるほど高くなる </td> <td> 必要 </td> </tr> <tr> <td> 輪郭線の抽出 </td> <td> 低 </td> <td> 描画する物体に関わらずほぼ一定 </td> <td> 不要 </td> </tr> </tbody> </table> <p>このため、プレイヤー等、描画する物体が少ない場合はクォリティが高い「背面法」、背景や小物など描画する物体が多い場合は処理負荷を抑えられる「輪郭線の抽出」と使い分けをすることが、最近のゲームでは多いです。</p> <h1 id="5NGSにおけるトゥーン表示対応について">5.『NGS』におけるトゥーン表示対応について</h1> <p>『NGS』では、元々トゥーンレンダリングを想定してモデルデータを作成していません。 このため、いくつか異なるアプローチで実装する必要がありました。 ここでは具体的にどのような実装をしたのかについて紹介いたします。</p> <h2 id="51NGSのレンダリングシステムについて">5.1.『NGS』のレンダリングシステムについて</h2> <p>『NGS』では、不透明の描画について「ディファードレンダリング」を行い、半透明、カットイン画面で「フォワードレンダリング」を行うという実装になっています。 通常のレンダリングパスを図にしたものが下記になります。</p> <p><figure class="figure-image figure-image-fotolife" title="通常のレンダリングパス"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140557.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>また、描画したGBufferの内容が下記になります。</p> <p><figure class="figure-image figure-image-fotolife" title="Gbufferの内容"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140601.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>前述したように、モデルデータがトゥーン表示用のものではないので必要な情報を適宜GBuffer等から取得して、活用していくことで実装しました。 最終的なトゥーン表示におけるレンダリングパスが下記になります。</p> <p><figure class="figure-image figure-image-fotolife" title="トゥーン表示時のレンダリングパス"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140605.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h2 id="52拡散反射光陰影のマルチトーン表現">5.2.拡散反射光(陰影)のマルチトーン表現</h2> <p>最初に拡散反射光(陰影)のマルチトーン表現について説明します。 前述したように、拡散反射光(陰影)のマルチトーン表現を行う際はランプテクスチャを用意して、陰影付けを行うのが一般的です。</p> <p>しかし、『NGS』の既存のモデルデータにランプテクスチャを追加するのは難しく、GBufferにモデル毎のランプテクスチャの値を入れるための容量もありません。 なので、一律のパラメータを用意し、計算で陰影付けを行いました。</p> <p>具体的なパラメータは下記になります。</p> <pre class="code c++" data-lang="c++" data-unlink>struct ToonDiffuseParameter { float brightness; //!&lt; 陰影の明るさ float subsurface; //!&lt; どの程度表面下散乱の色(血の色)を使用するか float threshold; //!&lt; どの段階から暗くするか float gradation; //!&lt; どの程度陰影をくっきりさせるか } ToonDiffuseParameter m_diffuse_bright; //!&lt; 明るい部分のパラメータ ToonDiffuseParameter m_diffuse_middle; //!&lt; 中間部分のパラメータ ToonDiffuseParameter m_diffuse_dark; //!&lt; 暗い部分のパラメータ</pre> <p>これらのパラメータを用いて、陰影を3段階に分けています。</p> <p><figure class="figure-image figure-image-fotolife" title="拡散反射光のマルチトーン化"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140609.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>『NGS』の拡散反射光は「Lambert BRDF」を使用しています。 このため、トゥーンレンダリングにおいてもモデルの法線とライトの内積値を元に、陰影を3段階に分けて陰影付けに使用しています。 実際にパラメータを調整すると下記のように陰影の調整ができます。</p> <p><figure class="figure-image figure-image-fotolife" title="拡散反射光のパラメータ調整"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140613.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>また、GBufferにどのシェーダを使用しているかの情報(ShaderID)を格納しているため、陰影をつけている物体の判別ができます。 これを用いて『NGS』では「毛髪用のパラメータ」と、「それ以外のパラメータ」の二つを用意して別々で調整ができるようにしています。<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup></p> <h2 id="53鏡面反射光スぺキュラのマルチトーン表現">5.3.鏡面反射光(スぺキュラ)のマルチトーン表現</h2> <p>次にスぺキュラのマルチトーン表現について説明します。 トゥーンレンダリングのスぺキュラ表現では、ワンポイントで表現することが多いかと思います。 実装方法としては、「スペキュラ自体をテクスチャに描きこむ」、或いは「スぺキュラマスクを用意して指定した箇所のみスペキュラを描く」等があります。</p> <p>しかし、『NGS』ではゲーム中に登場するNPCの「グレン」のように、顔の色がほぼ黒色のキャラクターを作ることができます。 このようなキャラクターは前述した、「拡散反射光(陰影)のマルチトーン化」をしても陰影ができず、真っ黒になってしまうといったことが発生しました。</p> <p><figure class="figure-image figure-image-fotolife" title="グレンのマルチトーン比較"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140617.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>このため、『NGS』でも「陰影のマルチトーン化」と同様に「スぺキュラのマルチトーン化」を行うことで、黒色のキャラクターでもアニメ調のような陰影が見えるように実装を行いました。 下記が調整するパラメータになります。</p> <pre class="code c++" data-lang="c++" data-unlink>struct ToonSpecularParameter { float brightness; //!&lt; スペキュラの明るさ float exponent; //!&lt; スペキュラの広がり float gradation; //!&lt; どの程度くっきりさせるか } ToonSpecularParameter m_specular_bright; //!&lt; 明るい部分のパラメータ ToonSpecularParameter m_specular_middle; //!&lt; 中間色のパラメータ ToonSpecularParameter m_specular_dark; //!&lt; 暗い部分のパラメータ</pre> <p>基本的には「拡散反射光(陰影)のマルチトーン化」とほぼ同じような処理でスぺキュラを3段階に分けて描画しています。</p> <p><figure class="figure-image figure-image-fotolife" title="鏡面反射のマルチトーン化"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140621.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>実際にパラメータを調整すると下記のような表示になります。</p> <p><figure class="figure-image figure-image-fotolife" title="鏡面反射のパラメータ調整"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140624.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>特にパラメータの調整では黒色のキャラクターでも真っ黒な顔にならないようにしつつ、キャスト(ロボット)等の金属の光沢がカッコよく表現できるように調整しました。</p> <p><figure class="figure-image figure-image-fotolife" title="鏡面反射のマルチトーン化の結果"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140628.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>また、スペキュラのマルチトーン化は「肌」、「毛髪」、「その他」で別のパラメータを調整しています。</p> <h2 id="54アウトライン表現">5.4.アウトライン表現</h2> <p>次に、「アウトライン表現」について説明します。 前述したように、トゥーンレンダリングのアウトライン表現では「背面法」と「輪郭線の抽出」の二つが手法としてあります。 『NGS』では、下記のような制約があり「背面法」を採用することができませんでした。</p> <ul> <li>モデルについて、片面しかないモデルやハードエッジを使用しているモデルがあり、法線方向に拡大した時にアウトラインがひび割れてしまう等、不自然な描画になってしまうことがある。</li> <li>多数のプレイヤー、NPCをトゥーン表示にする必要があり、「背面法」では処理負荷が高くなってしまう。</li> <li>半透明のアウトラインについて対応することが難しい。</li> </ul> <p>このため、「輪郭線の抽出」を用いてアウトライン表現を実装しました。</p> <h3 id="543輪郭線の抽出">5.4.3.輪郭線の抽出</h3> <p>『NGS』ではGBufferのうち「深度」、「法線」、「マテリアル」情報を用いて輪郭線の抽出を行いました。 処理としては、近傍の値と比較して一定以上の差異がある場合、アウトラインを描画するという内容になります。</p> <p>また、ShaderIDを用いて、「顔と毛髪以外は法線によるアウトラインを使用する」、「毛髪のみ、マテリアルによるアウトラインを使用する」と、カテゴリ毎に分けて使用することで、アウトラインを描画するようにしました。 下記が、それぞれの情報を用いて輪郭線の抽出を行った結果になります。</p> <p><figure class="figure-image figure-image-fotolife" title="アウトラインの合成"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140632.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>パラメータとしては、アウトラインの太さや色を調整できるようにしました。 特にアウトラインの色については、近傍の色を元に明度と彩度の調整をすることで色トレスができるようにしています。 また、これらのパラメータは「肌」、「毛髪」、「その他」で調整ができるように実装しています。</p> <pre class="code C" data-lang="C" data-unlink>struct ToonOutlineParameter { float brightness; // 明度 float saturation; // 彩度 } ToonOutlineParameter skin_outline_param; // 肌のアウトライン ToonOutlineParameter hair_outline_param; // 毛髪のアウトライン ToonOutlineParameter other_outline_param; // その他のアウトライン float outline_weight; // アウトラインの太さ </pre> <p><figure class="figure-image figure-image-fotolife" title="アウトラインのパラメータ調整"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140635.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h1 id="6トゥーン用の顔データの作成について">6.トゥーン用の顔データの作成について</h1> <p>ここまでの処理で、プログラム上の処理が一通り完了しました。 しかし、既存のモデルではやはり顔の陰影が綺麗になりにくいといった問題が発生しました。</p> <p>これに対処するには、顔モデルの法線を調整する等、データに対して調整を行う必要があります。 『NGS』では、トゥーン表示用に法線等を調整したモデルを新たに用意し、トゥーン表示に切り替えた際に顔モデルを切り替えることで対処するようにしました。<sup id="fnref:3"><a href="#fn:3" rel="footnote">3</a></sup></p> <p><figure class="figure-image figure-image-fotolife" title="顔モデルの差し替え"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140639.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>元々、『PSO2』から『NGS』にアップデートする際、顔のデータは『PSO2』で体のデータは『NGS』といったように、顔と体で別のデータを切り替えることができるシステムとデータを作っていました。 このため顔の切り替え処理については実装をスムーズに行うことができました。</p> <p>詳細な情報については、CEDEC2022の資料「『PSO2 ニュージェネシス』 長期運営タイトルにおける、大規模バージョンアップの開発事例の紹介」を参照してください。<sup id="fnref:4"><a href="#fn:4" rel="footnote">4</a></sup></p> <p>トゥーン用の顔データの作成では主に「法線の調整」、「目の陰影を追加」、「ラフネス値の調整」をデザイナー(アーティスト)の方に行っていただきました。 行った調整について簡単にご紹介させていただきます。</p> <h2 id="61-法線の調整について">6.1 法線の調整について</h2> <p>顔の法線については、モデルの頂点法線について下記のような調整を行っています。</p> <ul> <li>頬の陰影が綺麗になるように調整</li> <li>口元や、鼻の陰影がくっきりでるように調整</li> </ul> <p>下図が通常時との比較になります。</p> <p><figure class="figure-image figure-image-fotolife" title="顔の法線比較"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140643.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h2 id="62-ラフネス値の調整について">6.2 ラフネス値の調整について</h2> <p>一部の顔モデルについては、頬、鼻先、唇にスペキュラが出やすくするためにラフネスの調整をしています。 下記が通常時との比較になります。</p> <p><figure class="figure-image figure-image-fotolife" title="顔のラフネス比較"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140647.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h2 id="63-目の影について">6.3 目の影について</h2> <p>イラストの表現では、目に対してまぶたの影をつけることで立体感を表現することがあります。 『NGS』のトゥーン表示でも同様に目に影をつけることでイラスト特有の立体感のある目を表現しています。</p> <p><figure class="figure-image figure-image-fotolife" title="目の陰影比較"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140650.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h1 id="7その他の対応">7.その他の対応</h1> <p>以上がおおまかな、対応内容になります。 しかし、後付けの処理であるため様々な問題が発生しました。 ここでは、発生した問題や対処した方法について紹介したいと思います。</p> <h2 id="71カットイン画面のトゥーン表示対応">7.1.カットイン画面のトゥーン表示対応</h2> <p>『NGS』では、キャラクターの顔が小さいウインドウに表示される「カットイン描画」と呼ばれるものがあります。この機能は主に、チャット画面やショップでのプレビュー画面で使用されます。</p> <p><figure class="figure-image figure-image-fotolife" title="カットイン描画"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140654.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>このカットイン画面は、全てフォワードレンダリングで描画しています。 既存の処理ではGBufferの情報を出力しない設計になっていたので、新しくGBufferの情報を一部追加で出力するように改良する必要がありました。 最終的には下記のように、フォワードレンダリングの結果だけでなく法線、マテリアル情報も出力するように変更しました。</p> <p><figure class="figure-image figure-image-fotolife" title="カットイン描画の比較"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230810/20230810111316.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>後は、前述した処理と同様に「陰影のマルチトーン化」や「アウトラインの表示」を行っています。 下記がトゥーン表示時における、カットイン描画のパスになります。</p> <p><figure class="figure-image figure-image-fotolife" title="カットイン描画のパス"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140701.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h2 id="72半透明のアウトライン">7.2.半透明のアウトライン</h2> <p>『PSO2』では半透明を使用しているものが多くあります。例として、プレイヤーが身に着けられるアクセサリーである「フォトンマフラー」は、不透明と半透明の組み合わせで作られています。<sup id="fnref:5"><a href="#fn:5" rel="footnote">5</a></sup></p> <p>このデータでアウトラインを表示した場合、不透明部分だけ考慮されるため、半透明部分で不自然なアウトラインが描画される問題が発生しました。</p> <p><figure class="figure-image figure-image-fotolife" title="半透明アウトラインの問題"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140705.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <p>この問題に対処するため、新しく半透明部分を表すアルファマスク作成し、半透明部分にアウトラインが描画されない対応を行いました。 下図が対応後の結果になります。</p> <p><figure class="figure-image figure-image-fotolife" title="半透明アウトラインの対応"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140708.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h1 id="8調整するパラメータについて">8.調整するパラメータについて</h1> <p>内部で調整できるパラメータの合計は最終的に60個になりました。 実装当初、用意したパラメータは固定値とする予定でした。</p> <p>しかし、『NGS』では人間、キャスト(ロボット)、或いはその枠を超えた様々なキャラクターを作成することができます。</p> <p>システムの都合で個別にパラメータを設定することが難しいですがそれでも調整できる方が良いと判断し、上記のパラメータをシンプルな形で調整できるようにしました。</p> <p>製品では「影の濃度」と「輪郭の強調」の二つのパラメータを調整することで、見た目が変わるようにしています。</p> <p><figure class="figure-image figure-image-fotolife" title="パラメータの調整結果"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230807/20230807140712.jpg" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></figure></p> <h1 id="9まとめ">9.まとめ</h1> <p>これらの対応を行うことで事前にトゥーンレンダリングを想定していなくとも、ある程度のクォリティでキャラクターのトゥーン化を行うことができました。</p> <p>リリース前はプレイヤーの皆様に受け入れてもらえるか不安でしたが、「キャラクタークリエイトの幅が広がった」、「過去のコスチュームの見た目がよくなり使用する機会が増えた」といった好意的な意見があり、実装してよかったと感じました。</p> <h1 id="10最後に">10.最後に</h1> <p>汎用ゲームエンジンが流行りつつありますが、自社でゲームエンジンを開発することで、どういった処理が最適なのかを基礎から学び、ひいては独自の実装で特徴ある表現を可能にすることができます。特に今回のような「ゲームの表現を途中で変えるような大きな変更対応」は自社のゲームエンジンでしか実現ができないものだと思います。自社でゲームエンジンを「使う」だけでなく、「作る」ことができる環境。 セガで働くことにご興味を持たれましたら下記サイトにアクセスお願いします。</p> <p>(C) SEGA <iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sega.co.jp%2Frecruit%2Findex.html" title="採用サイト|株式会社セガ -【SEGA CORPORATION】" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html">www.sega.co.jp</a></cite></p> <div class="footnotes"> <hr/> <ol> <li id="fn:1"> 描画負荷としては裏面を後で描画する方が良いですが、わかりやすさのために上記の記載になっています。<a href="#fnref:1" rev="footnote">&#8617;</a></li> <li id="fn:2"> キャラクターの肌について、肌ではないけど肌と陰影を合わせたいアクセサリーがあり、パラメータを分けることはしませんでした。<a href="#fnref:2" rev="footnote">&#8617;</a></li> <li id="fn:3"> トゥーン用に用意してあるのは、『NGS』で新しく作成した顔モデルのみになります。<a href="#fnref:3" rev="footnote">&#8617;</a></li> <li id="fn:4"> <a href="https://cedil.cesa.or.jp/cedil_sessions/view/2614">https://cedil.cesa.or.jp/cedil_sessions/view/2614</a><a href="#fnref:4" rev="footnote">&#8617;</a></li> <li id="fn:5"> 『PSO2』における、髪型も半透明と不透明の組み合わせで作られています。<a href="#fnref:5" rev="footnote">&#8617;</a></li> </ol> </div> sgtech CEDEC 2023 セガサミーグループによるセッション紹介! hatenablog://entry/820878482953855273 2023-07-31T10:00:00+09:00 2023-07-31T10:00:02+09:00 今年も夏がはじまり、CEDECが近くなってまいりました。 今回はハイブリッド開催となったゲーム業界最大のカンファレンスに、 セガサミーグループからも登壇します! cedec.cesa.or.jp 会期:2023年8月23日(水)~8月25日(金) 今年で8回目となる、セッションと登壇者紹介に加え、ここでしか見られない当日の資料の抜粋チラ見せ付き(一部公募のみ)でブログ本文は株式会社セガ、第3事業部の麓がご紹介致します。 <p>今年も夏がはじまり、CEDECが近くなってまいりました。</p> <p>今回はハイブリッド開催となったゲーム業界最大のカンファレンスに、</p> <p>セガサミーグループからも登壇します!</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2023" title="CEDEC2023" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2023">cedec.cesa.or.jp</a></cite></p> <p><cite class="hatena-citation"><span style="font-size: 16px;">会期:2023年8月23日(水)~8月25日(金)</span></cite></p> <p>今年で8回目となる、セッションと登壇者紹介に加え、ここでしか見られない当日の資料の抜粋チラ見せ付き(一部公募のみ)でブログ本文は株式会社セガ、第3事業部の麓がご紹介致します。</p> <p><strong>目次</strong></p> <ul class="table-of-contents"> <li><a href="#Inertializationの問題点とその改善手法について---加算ブレンディングの悪影響を排除した改良型Inertial-Transitionアルゴリズムの提案--">“Inertialization”の問題点とその改善手法について - 加算ブレンディングの悪影響を排除した改良型Inertial Transitionアルゴリズムの提案 -</a><ul> <li><a href="#セッション内容">セッション内容</a></li> <li><a href="#講演者">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> </ul> </li> <li><a href="#運営が始まった後からでも自動テストを導入して自動化したい--実現する為に何を行ったのか導入までの工程と得られた効果ノウハウの共有-">運営が始まった後からでも自動テストを導入して自動化したい ~ 実現する為に何を行ったのか、導入までの工程と得られた効果・ノウハウの共有 ~</a><ul> <li><a href="#セッション内容-1">セッション内容</a></li> <li><a href="#講演者-1">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> </ul> </li> <li><a href="#VUCAの時代ワーキングペアレントの働き方と悩み上司経営者の立場での悩み">VUCAの時代:ワーキングペアレントの働き方と悩み/上司・経営者の立場での悩み</a><ul> <li><a href="#セッション内容-2">セッション内容</a></li> <li><a href="#講演者-2">講演者</a></li> <li><a href="#スナップショット-1">スナップショット</a></li> </ul> </li> <li><a href="#PSO2-ニュージェネシスアートワーク業務におけるCLIP-STUDIO-PAINTクリスタ活用事例">『PSO2 ニュージェネシス』アートワーク業務におけるCLIP STUDIO PAINT(クリスタ)活用事例</a><ul> <li><a href="#セッション内容-3">セッション内容</a></li> <li><a href="#講演者-3">講演者</a></li> </ul> </li> <li><a href="#CRI-ADXプロファイラー活用によるサウンドQAの自動化可視化に関する取り組みの紹介">CRI ADXプロファイラー活用によるサウンドQAの自動化・可視化に関する取り組みの紹介</a><ul> <li><a href="#セッション内容-4">セッション内容</a></li> <li><a href="#講演者-4">講演者</a></li> </ul> </li> </ul> <h3 id="Inertializationの問題点とその改善手法について---加算ブレンディングの悪影響を排除した改良型Inertial-Transitionアルゴリズムの提案--"><span style="color: #1464b3;">“Inertialization”の問題点とその改善手法について - 加算ブレンディングの悪影響を排除した改良型Inertial Transitionアルゴリズムの提案 -</span></h3> <h5 id="セッション内容"><strong>セッション内容</strong></h5> <p>“Inertialization”は、GDC2018で発表されたSmooth Transitionアルゴリズムで、遷移元モーションの変化速度に応じた慣性挙動を実現するInertial Transition(慣性遷移)の一種です。後にUnreal Engine 4に採用されたことでも話題になりました。</p> <p>Inertializationでは計算で作り出した慣性差分を遷移先モーションに加算ブレンディングすることで遷移時の滑らかな補間を実現していますが、この加算ブレンディングに起因した挙動上の問題点がいくつか確認されています。</p> <p>その中でも最大の問題点が、過大な慣性成分が生じた際に関節の可動域限界を容易に突破してしまうオーバーリミット問題です。本講演では、このオーバーリミットを始めとするInertializationの大小様々な挙動上の問題点について、それぞれの発生メカニズムと、その解決のために取った補正処理や設定項目について解説します。</p> <p>また、実際には加算ブレンディング起因の問題点は、Inertializationへの補正処理だけでは完全には解決しきれませんでした。しかしながら、それらの問題についてはInertializationの技術を転用した別のInertial Transitionアルゴリズムを作り出すことで問題解決に繋げることができたので、こちらについても詳しく解説します。</p> <p> </p> <h5 id="講演者">講演者</h5> <p><strong>株式会社セガ </strong><br /><strong>第3事業部 第3オンライン研究開発プログラム2部<br />松本 浩太<br /></strong></p> <p><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月24日(木) 11:20 〜 12:20 レギュラーセッション</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2023%2Fsession%2Fdetail%2Fs64115b421c17c" title="“Inertialization”の問題点とその改善手法について - 加算ブレンディングの悪影響を排除した改良型Inertial Transitionアルゴリズムの提案 - | CEDEC2023" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2023/session/detail/s64115b421c17c">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230724/20230724111428.png" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230719/20230719184606.png" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p> </p> <h3 id="運営が始まった後からでも自動テストを導入して自動化したい--実現する為に何を行ったのか導入までの工程と得られた効果ノウハウの共有-"><span style="color: #1464b3;">運営が始まった後からでも自動テストを導入して自動化したい ~ 実現する為に何を行ったのか、導入までの工程と得られた効果・ノウハウの共有 ~</span></h3> <h5 id="セッション内容-1"><strong>セッション内容</strong></h5> <p>本セッションでは、現在運営開発中のUnityを使用したスマートフォン向け対戦アクションゲームに対して運営を開始した後に自動テストを導入し、そのテストを自動化した事例について紹介をします。</p> <p>今回の取り組みはタイトルチームのメンバーではない、技術支援部門のメンバーが行いました。<br />タイトルチームに所属していないメンバーがタイトルチームとどのように協力して、この取り組みを行ったかについてタイトルチームと技術支援部門それぞれメンバーの視点から共有します。</p> <p>自動テストを行っていないが、今からでも始めたい<br />自動テストを実行する為の"仕込み"が出来ていない<br />今は自動テストを実行できないが、今後実装したい</p> <p>このような場合に、実際にタイトル運営が始まった後に自動テストを導入する際にはどのような仕組みが必要だったか、どのようなことが障害になったのか、どのようなことに注意して進めるべきだったかを事例にそって具体的に説明します。<br />実際に導入を進めた際には、自動テストの作成時や実行時、自動テストによるエラー検知時の報告フローに関しても運営中のタイトルならではの問題が発生しました。<br />これらの問題に対して、どのような解決策を講じたのかを具体的に説明します。</p> <p>運営が始まった後でも自動テストの導入が実現できたことを共有し、自分達もやってみようと思う人が少しでも増えれば幸いです。<br />また、現在開発中のタイトルであっても、自動テストを導入する障壁が下がるようなポイントを共有できればと思っています。</p> <h5 id="講演者-1">講演者</h5> <p><strong>株式会社セガ</strong><br /><strong>技術本部/開発技術部/技術開発課</strong><br /><strong>廣島 岳史<br />第4オンライン研究開発1部</strong><br /><strong>関 夏生</strong><br /><strong>渡部 将行</strong></p> <p>08月24日(木) 13:30 〜 14:30 <span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">レギュラーセッション</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2023%2Fsession%2Fdetail%2Fs641ad3f18b6df" title="運営が始まった後からでも自動テストを導入して自動化したい ~ 実現する為に何を行ったのか、導入までの工程と得られた効果・ノウハウの共有 ~ | CEDEC2023" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2023/session/detail/s641ad3f18b6df">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット" style="clear: both; margin: 1em 0px 0.5em; font-size: 14.3px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230719/20230719184527.png" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230719/20230719184534.png" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p> </p> <h3 id="VUCAの時代ワーキングペアレントの働き方と悩み上司経営者の立場での悩み"><span style="color: #1464b3;">VUCAの時代:ワーキングペアレントの働き方と悩み/上司・経営者の立場での悩み</span></h3> <h5 id="セッション内容-2"><strong>セッション内容</strong></h5> <p>職場や家庭における環境の変化も目まぐるしく、将来の予測が困難な状況の中、ワーキングペアレントの働き方と悩みは、どのように変わってきたでしょうか?上司、経営者の立場ではどうでしょうか?</p> <p>VUCAの時代を生きる、ワーキングペアレントの働き方と悩みに寄り添い、解決策を探ります。</p> <p><<4年振りの現地リアル開催です!>></p> <p>●ラウンドテーブル参加希望者(議題提出者はセッション開始時間前に優先入場できます)</p> <p>入室前に「悩み」「扱って欲しい議題」+「名前(ニックネーム可)」を付箋に書いて、入口前の専用ホワイトボードに貼ってください。(事前に書いて来たものを貼るのでもOKです/複数可)</p> <p>近似のジャンルでテーブル分けをし、参加者同士でディスカッションします。(差し支えない方は名刺をご持参ください)</p> <p>●見学希望者(セッション開始時間に入室可能となります)</p> <p>興味のある議題のテーブルに近づき、ディスカッションをご視聴ください。ご自由にテーブルを回っていただいてOKです。</p> <p>ディスカッションした内容は、テーブルごとに発表し、全員にシェアを行います。</p> <p>ゲーム業界全体が、多様な働き方について相談しやすい環境になることを願っており、その話題作りのキッカケとなることを目指しています。</p> <h5 id="講演者-2">講演者</h5> <p><strong>セガサミーホールディングス株式会社</strong><br /><strong>総務本部 コミュニケーションサービス部 コミュニケーション推進課<br />茂呂 真由美 ほか</strong></p> <p><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;"><span style="color: #000000; font-family: HiraKakuProN-W3, 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月23日(水) 11:20 〜 12:20</span> ラウンドテーブル</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2023%2Fsession%2Fdetail%2Fs642949e47ed5f" title="VUCAの時代:ワーキングペアレントの働き方と悩み/上司・経営者の立場での悩み | CEDEC2023" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2023/session/detail/s642949e47ed5f">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット-1"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20230727/20230727151058.jpg" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p> </p> <h3 id="PSO2-ニュージェネシスアートワーク業務におけるCLIP-STUDIO-PAINTクリスタ活用事例"><span style="color: #1464b3;">『PSO2 ニュージェネシス』アートワーク業務におけるCLIP STUDIO PAINT(クリスタ)活用事例</span></h3> <h5 id="セッション内容-3"><strong>セッション内容</strong></h5> <p>株式会社セガが開発・運営するオンラインゲーム</p> <p>『PSO2 ニュージェネシス』における2Dチームの体制とデザインする際に大切にしているオンラインゲームならではポイントを交えながらお話しします。</p> <p>また2Dアートワーク作業でCLIP STUDIO PAINTを使用するメリットと、設定画作成に役立つ機能を併せて紹介します。</p> <h5 id="講演者-3">講演者</h5> <p><strong>株式会社セガ<br /></strong><strong>第3事業部第3オンライン研究開発デザイン2部 第2デザインセクション</strong><br /><strong>デザイナー</strong><br /><strong>木村 大蔵 ほか</strong></p> <p>08月25日(金) 13:30 〜 14:30 <span style="color: #000000; font-family: HiraKakuProN-W3, 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">レギュラーセッション</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2023%2Fsession%2Fdetail%2Fs648c18dfa8ac4" title="『PSO2 ニュージェネシス』アートワーク業務におけるCLIP STUDIO PAINT(クリスタ)活用事例 | CEDEC2023" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2023/session/detail/s648c18dfa8ac4">cedec.cesa.or.jp</a></cite></p> <h3 id="CRI-ADXプロファイラー活用によるサウンドQAの自動化可視化に関する取り組みの紹介"><span style="color: #1464b3;">CRI ADXプロファイラー活用によるサウンドQAの自動化・可視化に関する取り組みの紹介</span></h3> <h5 id="セッション内容-4"><strong>セッション内容</strong></h5> <p>弊社では CRI 社様と協力して、CRI ADX2 プロファイラーの結果取得を自動化・可視化するツールを作成・運用しています。</p> <p>本講演では、当ツールを導入するに至った流れとその際に気を付けたことに加え、ツールを採用しているセガタイトルでの事例について紹介します。</p> <p>また、当ツールを活用しているサウンドクリエーターから、自動化・可視化のメリットについてもご紹介します。</p> <h5 id="講演者-4">講演者</h5> <p><strong>株式会社セガ</strong><br /><strong>開発技術部</strong><br /><strong>エンジニア</strong><br /><strong>竹原 涼</strong></p> <p><strong>株式会社セガ</strong><br /><strong>第2事業部サウンド開発部</strong><br /><strong>チーフサウンドエンジニア</strong><br /><strong>瀬津丸 勝</strong> <strong>ほか</strong></p> <p>08月23日(水) 17:50 〜 18:50 <span style="color: #000000; font-family: HiraKakuProN-W3, 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">レギュラーセッション</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2023%2Fsession%2Fdetail%2Fs648c0dde66a6d" title="CRI ADXプロファイラー活用によるサウンドQAの自動化・可視化に関する取り組みの紹介 | CEDEC2023" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2023/session/detail/s648c0dde66a6d">cedec.cesa.or.jp</a></cite></p> <p>いかがでしょうか?</p> <p style="margin: 0.5em 0px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">今回紹介したなかでぜひ聞きたい!!と思ったセッションはありましたか?<br />今年もCEDECを通して情報収集や交流をし、ゲーム業界の今を知り、業界の未来について語り合いませんか?</p> <p style="margin: 0.5em 0px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">私達は将来CEDECに登壇してみたいと思っている、やる気のある方を求めています。<br />そんなあなた、以下にアクセスおねがいします。</p> <p style="margin: 0.5em 0px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">それでは皆さんCEDECでお会いましょう!</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Frecruit.sega.jp%2F%23" title="セガ グループ 新卒採用サイト" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://recruit.sega.jp/#">recruit.sega.jp</a></cite></p> <p> </p> <p><span style="color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; background-color: #ffffff; float: none; display: inline !important;">※複数社登壇の場合でもセガの社員のみ表記しています </span><br style="color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; background-color: #ffffff;" /><span style="color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; background-color: #ffffff; float: none; display: inline !important;">©SEGA</span></p> sgtech 『PSO2 ニュージェネシス』におけるハイダイナミックレンジ対応について hatenablog://entry/4207112889936450194 2022-11-17T10:00:00+09:00 2022-11-17T11:56:49+09:00 1 はじめに 株式会社セガ ゲームコンテンツ&サービス事業本部 技術本部 技術統括室 ソフトシステムセクションの西濱 高志といいます。 現在グラフィックスプログラマとして株式会社セガが開発運営する『PSO2 ニュージェネシス(以下『NGS』)』に携わっています。 今回の記事では『NGS』におけるハイダイナミックレンジ(HDR)ディスプレイ対応について紹介いたします。 2 目次 1 はじめに 2 目次 3 注意事項 3.1 各ゲームにおけるHDRディスプレイ対応についての注意事項 3.2 掲載している画像についての注意事項 4 ハイダイナミックレンジ(HDR)とは? 4.1 明るさの違い 4.2… <h1 id="1-はじめに">1 はじめに</h1> <p>株式会社セガ ゲームコンテンツ&amp;サービス事業本部 技術本部 技術統括室 ソフトシステムセクションの西濱 高志といいます。 現在グラフィックスプログラマとして株式会社セガが開発運営する『PSO2 ニュージェネシス(以下『NGS』)』に携わっています。</p> <p>今回の記事では『NGS』におけるハイダイナミックレンジ(HDR)ディスプレイ対応について紹介いたします。</p> <h1 id="2-目次">2 目次</h1> <ul class="table-of-contents"> <li><a href="#1-はじめに">1 はじめに</a></li> <li><a href="#2-目次">2 目次</a></li> <li><a href="#3-注意事項">3 注意事項</a><ul> <li><a href="#31-各ゲームにおけるHDRディスプレイ対応についての注意事項">3.1 各ゲームにおけるHDRディスプレイ対応についての注意事項</a></li> <li><a href="#32-掲載している画像についての注意事項">3.2 掲載している画像についての注意事項</a></li> </ul> </li> <li><a href="#4-ハイダイナミックレンジHDRとは">4 ハイダイナミックレンジ(HDR)とは?</a><ul> <li><a href="#41-明るさの違い">4.1 明るさの違い</a></li> <li><a href="#42-色の違い">4.2 色の違い</a></li> </ul> </li> <li><a href="#5-HDRディスプレイ対応について">5 HDRディスプレイ対応について</a><ul> <li><a href="#51-SDR時におけるレンダリングパスについて">5.1 SDR時におけるレンダリングパスについて</a><ul> <li><a href="#511-HDRレンダリング処理について">5.1.1 HDRレンダリング処理について</a></li> <li><a href="#512-トーンマッピングとガンマ補正処理について">5.1.2 トーンマッピングとガンマ補正処理について</a><ul> <li><a href="#5121-トーンマッピング">5.1.2.1 トーンマッピング</a></li> <li><a href="#5122-ガンマ補正について">5.1.2.2 ガンマ補正について</a></li> </ul> </li> <li><a href="#513-カラーグレーディング処理について">5.1.3 カラーグレーディング処理について</a></li> </ul> </li> <li><a href="#52-HDR時におけるレンダリングパスについて">5.2 HDR時におけるレンダリングパスについて</a><ul> <li><a href="#521-HDR用のトーンマッピングについて">5.2.1 HDR用のトーンマッピングについて</a><ul> <li><a href="#5211-HDR用のトーンマッピングの問題点">5.2.1.1 HDR用のトーンマッピングの問題点</a></li> <li><a href="#5212-HDR時におけるレンダリングパスの改良">5.2.1.2 HDR時におけるレンダリングパスの改良</a></li> <li><a href="#5213-HDR用のトーンマッピングの改良">5.2.1.3 HDR用のトーンマッピングの改良</a></li> </ul> </li> <li><a href="#522-HDRにおけるOETFについて">5.2.2 HDRにおけるOETFについて</a><ul> <li><a href="#5221-色空間の変換について">5.2.2.1 色空間の変換について</a></li> <li><a href="#5222-色空間の変換における改善">5.2.2.2 色空間の変換における改善</a></li> <li><a href="#5223-輝度の補正">5.2.2.3 輝度の補正</a></li> <li><a href="#5224-PQ補正">5.2.2.4 PQ補正</a></li> </ul> </li> </ul> </li> </ul> </li> <li><a href="#6-調整するパラメータについて">6 調整するパラメータについて</a></li> <li><a href="#7-まとめ">7 まとめ</a></li> <li><a href="#8-最後に">8 最後に</a></li> </ul> <h1 id="3-注意事項">3 注意事項</h1> <p>この記事において、2点注意することがあります。</p> <h2 id="31-各ゲームにおけるHDRディスプレイ対応についての注意事項">3.1 各ゲームにおけるHDRディスプレイ対応についての注意事項</h2> <p>現在、様々なゲームにおいてHDRディスプレイ対応がされています。 しかし、対応方法については各ゲームで異なっている場合や、ユーザーが調整できるパラメータに違いがある場合があります。 この記事ではあくまで『NGS』におけるHDR対応の話になりますのでご注意ください。</p> <h2 id="32-掲載している画像についての注意事項">3.2 掲載している画像についての注意事項</h2> <p>この記事では随所にSDRディスプレイへの出力結果とHDRディスプレイへの出力結果の比較画像を掲載しています。 しかし、HDRで出力した画像はHDR出力に対応をしているディスプレイやデバイスでないと正しく表示することができません。</p> <p>そこで、SDRとHDRの違いがわかりやすくなるように加工したSDR画像を掲載しています。 実際の数値や実機上での見た目とは異なりますのでご注意ください。</p> <h1 id="4-ハイダイナミックレンジHDRとは">4 ハイダイナミックレンジ(HDR)とは?</h1> <p>それでは、本題に入っていきたいと思います。 HDRとは一言でいってしまうと「従来の標準ダイナミックレンジ(SDR)と比べて、より広い範囲の明るさを表現できる技術、或いはビデオ映像」のことを言います。</p> <p>SDRとの違いは表現できる「明るさの幅」、「色の幅」の2点になります。 この2つの幅についてHDRの方が圧倒的に広いため、今まで表現できなかった明るさや色を表現できるようになります。</p> <p>実際に、同じシーンでHDRとSDRを出力した結果を掲載します。 今回、比較に用いたのはゲームの拠点となる「セントラルシティ」と、ゲームプレイ時に発生する「ナーデレフのライブイベント」になります。 違いとしては、主にハイライト部分の箇所と全体的な色合いになります。</p> <p><figure class="figure-image figure-image-fotolife" title="SDR時のパイプライン"><div class="images-row mceNonEditable"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132524.jpg" alt="" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132531.jpg" alt="" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></div><figcaption>セントラルシティにおける比較(左:SDR出力、右:HDR出力)</figcaption></figure> <figure class="figure-image figure-image-fotolife" title="SDR時のパイプライン"><div class="images-row mceNonEditable"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132537.jpg" alt="" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132544.jpg" alt="" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></div><figcaption>ライブイベントにおける比較(左:SDR出力、右:HDR出力)</figcaption></figure></p> <p>セントラルシティにおいては、太陽の部分についてHDRの方が白飛びしておらず、色合いについても植物の緑色などが色濃くでているのがわかるかと思います。 ライブイベントにおいては、後ろにあるライトについてHDRでは白飛びせずライトの色が識別できるようになっているのがわかるかと思います。</p> <h2 id="41-明るさの違い">4.1 明るさの違い</h2> <p>ディスプレイにおける明るさはnit(ニット)という単位面積あたりの明るさ(カンデラ毎平方メートル)で表されます。 出力することが可能な明るさの範囲はディスプレイのスペックによって違いますが、SDRとHDRでおおよそ下記の範囲になります。</p> <ul> <li>SDR:0.1nit以下~数百nit</li> <li>HDR:0.1nit以下~数千nit</li> </ul> <p>あくまでイメージとなりますが表現できる白色について見た時、下記画像のような違いがあります。</p> <p><figure class="figure-image figure-image-fotolife" title="明るさの違い"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132551.jpg" width="654" height="346" loading="lazy" title="" class="hatena-fotolife" style="width:487px;height:255px" itemprop="image"></span><figcaption></figcaption></figure></p> <h2 id="42-色の違い">4.2 色の違い</h2> <p>HDRとSDRでは利用されている色空間が違うため、表現できる色の幅についても違いがあります。 具体的にはSDRではRec.709が利用され、HDRではRec.2020が利用されています。</p> <p>それぞれの色空間についてのグラフは下記になります。</p> <p><figure class="figure-image figure-image-fotolife" title="色空間の違い"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132557.jpg" width="1512" height="1890" loading="lazy" title="" class="hatena-fotolife" style="width:375px;height:473px" itemprop="image"></span><figcaption></figcaption></figure></p> <p>あくまでイメージとなりますが、実際の見た目としては赤色(R)、緑色(G)、青色(B)で下記画像のような違いがあります。</p> <p><figure class="figure-image figure-image-fotolife" title="色の違い"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132604.jpg" width="788" height="771" loading="lazy" title="" class="hatena-fotolife" style="width:395px;height:385px" itemprop="image"></span><figcaption></figcaption></figure></p> <p>このようにHDRディスプレイ対応を行うことで、明るさの幅と色の幅が広がり、今まで表現することができなかった色や、白飛びしてしまっていたライトの光等を精密に表示することができるようになります。</p> <h1 id="5-HDRディスプレイ対応について">5 HDRディスプレイ対応について</h1> <p>ここまでの内容でSDRとHDRでどういった所が違うのかについて、説明いたしました。 ここからは『NGS』における対応方法について説明いたします。</p> <h2 id="51-SDR時におけるレンダリングパスについて">5.1 SDR時におけるレンダリングパスについて</h2> <p>レンダリングパスとはグラフィックス処理の順序のことを言います。 『NGS』ではHDR時とSDR時でレンダリングパスは、ほぼ同じ構成になっており、SDR時の出力を基準としてパラメータでHDRへ拡張をするといった対応をしています。 このためSDR時の処理について先に説明します。</p> <p>下記がSDR時におけるレンダリングパスになります。 注目する点としては、それぞれの処理における「輝度の範囲」、「色空間」、「テクスチャフォーマット」になります。 またオレンジ色はHDRの区間、青色はSDRの区間を表しています。</p> <p><figure class="figure-image figure-image-fotolife" title="SDR時のレンダリングパス"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132612.jpg" width="2000" height="1125" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>SDR時のレンダリングパス</figcaption></figure></p> <p>今回はHDRディスプレイ対応と関連性がある、「Gbuffer描画からHDRポストプロセスにかけて行うHDRレンダリング処理」、「トーンマッピングとガンマ補正処理」、「カラーグレーディング処理」について簡単に説明いたします。<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup></p> <h3 id="511-HDRレンダリング処理について">5.1.1 HDRレンダリング処理について</h3> <p>HDRレンダリングとは十分な計算精度を保ったまま幅広い諧調を扱うレンダリング方法のことを言います。 SDRで出力する場合でもHDRの範囲で一旦描画を行い、この後の「トーンマッピングとガンマ補正処理」においてSDRに変換することで、幅広い諧調を持った画像を出力できるようになります。 HDRレンダリングの結果が下の画像となります。</p> <p><figure class="figure-image figure-image-fotolife" title="HDRレンダリングの結果"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132619.jpg" width="1307" height="735" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>HDRレンダリングの結果</figcaption></figure></p> <h3 id="512-トーンマッピングとガンマ補正処理について">5.1.2 トーンマッピングとガンマ補正処理について</h3> <p>トーンマッピングとガンマ補正処理においては、先ほどのHDRレンダリングの結果をSDRディスプレイにおいて適切な見た目となるように変換する処理を行っています。<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup></p> <h4 id="5121-トーンマッピング">5.1.2.1 トーンマッピング</h4> <p>ゲームでは生成したHDRレンダリング画像に対して、トーンカーブを用いることで出力するディスプレイで正確な表現ができるように変換します。 SDRディスプレイに出力する場合、0~1の範囲に変換します。 トーンカーブは様々な種類があるのですが、『NGS』ではACES Filmicを使用しています。</p> <pre class="code c++" data-lang="c++" data-unlink>// 使用している係数 // a = 3.0 // b = 0.03 // c = 2.43 // d = 0.59 // e = 0.14 float3 ACESFilmic(float3 x, float a, float b, float c, float d, float e){ return (x*(a*x+b))/(x*(c*x+d)+e); }</pre> <p>『NGS』において設定しているACES Filimicの係数を当てはめた結果が下記の画像となります。横軸が変換前の値で、縦軸が変換後の値です。</p> <p><figure class="figure-image figure-image-fotolife" title="SDR時のトーンカーブ"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132628.jpg" width="613" height="579" loading="lazy" title="" class="hatena-fotolife" style="width:305px;height:290px" itemprop="image"></span><figcaption>SDR時のトーンカーブ</figcaption></figure></p> <p>輝度値が低いところでは変化が大きくなり輝度値が高いところでは変化が緩やかになり、1.0に収束していることがわかるかと思います。 トーンマッピングを行った結果が下記になります。</p> <p><figure class="figure-image figure-image-fotolife" title="トーンカーブ適用後の結果"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132633.jpg" width="1307" height="735" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>トーンマッピング後の画像</figcaption></figure></p> <h4 id="5122-ガンマ補正について">5.1.2.2 ガンマ補正について</h4> <p>ガンマ補正の説明をする前に、まず電気光伝達関数(Electro-Optical Transfer Function)と光電伝達関数(Opto-Electronic Transfer Function)について説明します。 (以降、電気光伝達関数はEOTF、光電伝達関数はOETFとします。) EOTFは映像信号をディスプレイの光に変換するための関数、OETFはシーンの光を映像信号に変換するための関数を表しています。</p> <p>現実の世界でカメラを用いて説明しますと、被写体をカメラで撮影した時、カメラの内部でシーンの光を映像信号に変換するOETF処理が行われます。 次にこのカメラ内の映像信号はカメラに内蔵されているディスプレイ等に送られ、ディスプレイ側で映像信号をディスプレイの光に変換するEOTF処理が行われます。 カメラで撮られた画像はこのようにして、私たちの目に届くといった仕組みになっています。</p> <p><figure class="figure-image figure-image-fotolife" title="カメラにおけるEOTFとOETF"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132638.jpg" width="1890" height="567" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>カメラにおけるEOTFとOETF</figcaption></figure></p> <p>ゲーム等のCGでは、カメラにあたる部分がないため生成した画像をそのままディスプレイに渡してしまうと、ディスプレイ側でEOTF処理が行われてしまうため、想定と違う見た目になってしまいます。 このため、あらかじめOETF処理を行うことでディスプレイ側で行われるEOTFの効果を相殺します。</p> <p><figure class="figure-image figure-image-fotolife" title="ゲームにおけるEOTFとOETF"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132650.jpg" width="1890" height="567" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>ゲームにおけるEOTFとOETF</figcaption></figure></p> <p>SDRディスプレイにおけるEOTFは様々有り、ガンマ1.9、ガンマ2.2、ガンマ2.4等と呼ばれます。 これをOETFで相殺する処理を(特にSDRでは一般に)ガンマ補正と呼びます。 『NGS』ではsRGBのガンマ2.2として扱い、ガンマ補正として画素に対して1/2.2を累乗を行うことでSDRディスプレイにおいて適切な見た目で表示できるようにしています。</p> <p><figure class="figure-image figure-image-fotolife" title="ガンマ補正後の画像"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132655.jpg" width="1307" height="735" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>ガンマ補正後の画像</figcaption></figure></p> <h3 id="513-カラーグレーディング処理について">5.1.3 カラーグレーディング処理について</h3> <p>次にカラーグレーディング処理について説明いたします。 カラーグレーディング処理とは出来上がった画像に対して色味を変える処理のことを言います。 広義としては色調補正、カラーコレクション等と呼ばれたりします。</p> <p>ゲームではシチュエーションによっては赤味を強くしたいといった要望や、過去回想などにおいてセピア調にしたいといった要望があると思います。 これらの処理を行うのがカラーグレーディングの役目となります。 具体的にはPhotoshop等を用いて作成したルックアップテーブル(LUT)テクスチャを用いて色の調整を行います。</p> <p>下記画像がカラーグレーディングの比較画像になります。</p> <p><figure class="figure-image figure-image-fotolife" title="カラーグレーディングの比較画像(左:なし、右:あり)"><div class="images-row mceNonEditable"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132700.jpg" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132706.jpg" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></div><figcaption>カラーグレーディングの比較画像(左:なし、右:あり)</figcaption></figure></p> <p>見比べてみるとかなり色味が変わってることがわかるかと思います。 『NGS』では、地域、天候等によってLUTを複数用意しており、ライブイベントの場合4つのLUTを使用して、時間変化で切り替えています。</p> <p>長くなりましたが、以上がSDR時のレンダリングパスの説明となります。</p> <h2 id="52-HDR時におけるレンダリングパスについて">5.2 HDR時におけるレンダリングパスについて</h2> <p>次に、HDR時におけるレンダリングパスについて説明いたします。 基本的には先ほどのSDR時のレンダリングパスからの追加対応について説明していく形になります。 下記が初期に実装したHDR時のレンダリングパスになります。</p> <p><figure class="figure-image figure-image-fotolife" title="初期に実装したHDR時のレンダリングパス"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132711.jpg" width="2000" height="1125" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>初期に実装したHDR時のレンダリングパス</figcaption></figure></p> <p>違いとしては、SDR時にトーンマッピングとガンマ補正を掛けていた箇所がHDR用のトーンマッピングになり、出力の手前でOETF処理をしているところになります。 また、オレンジはHDR、赤色は最大輝度で変換したHDR、紫色はOETF処理をしたHDRを表しています。</p> <h3 id="521-HDR用のトーンマッピングについて">5.2.1 HDR用のトーンマッピングについて</h3> <p>HDR用のトーンマッピングの説明をする前に、まずHDRで表現できる数値について説明いたします。 SDRでは0~1の範囲に変換をしたと思うのですが、HDRでは1.0以上の値で表示が可能となります。</p> <p>ディスプレイのスペックによって変わってくるのですが例えば最大輝度(ピーク輝度)が350nitの場合、単純なケースでは3.5までの値が描画可能となります。<sup id="fnref:3"><a href="#fn:3" rel="footnote">3</a></sup> これは、HDRの規格上100nitが標準白レベル(1.0 = 100nit)として取り扱っているためです。 このため、1.0以上の範囲で変換できれば対応することができそうです。</p> <p>まず、最も簡単な方法としてACES Filimicの係数を変更してみることにします。 ACES Filimicの処理について、「x」が無限大に近づくときの値は「a / c」になります。 このため、「a / c」が最大輝度となるように係数を導出すれば表現できそうですね。 「a = 3.0」とすると、「c = 3.0 / 最大輝度」となるため、これを式に当てはめてみます。</p> <pre class="code c++" data-lang="c++" data-unlink>// a = 3.0 // b = 0.03 // c = a / L // L = 最大輝度 // d = 1.0 // e = 0.14 float3 ACESFilmic(float3 x, float a, float b, float c, float d, float e){ return (x*(a*x+b))/(x*(c*x+d)+e); }</pre> <p>係数を調整し、1.5に収束するようにした結果が下記になります。</p> <p><figure class="figure-image figure-image-fotolife" title="HDR時のトーンカーブ(青:HDR、緑:SDR)"><span itemscope itemtype="http://schema.org/Photograph"><a href="http://f.hatena.ne.jp/sgtech/20221114132719" class="hatena-fotolife" itemprop="url"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132719.jpg" width="613" height="579" loading="lazy" title="" class="hatena-fotolife" style="width:305px;height:290px" itemprop="image"></a></span><figcaption>HDR時のトーンカーブ(青:HDR、緑:SDR)</figcaption></figure></p> <p>また、この「最大輝度」はパラメータ「HDR設定:最大輝度レベル」としてユーザーが調整できるようにしています。 このカーブを用いれば、ディスプレイの最大輝度に合わせた画像を出力することができます。</p> <p>しかし、ここで問題が起きました。</p> <h4 id="5211-HDR用のトーンマッピングの問題点">5.2.1.1 HDR用のトーンマッピングの問題点</h4> <p>元々『NGS』ではトーンマッピング後はSDR前提で処理が組まれています。 このため、カラーグレーディングやSDRポストプロセス処理で問題が発生しました。</p> <p>特にカラーグレーディング処理では0.0~1.0の値を前提として作られているため工夫が必要でした。 対策として、最大輝度で除算を行いカラーグレーディング処理を行った後、元に戻すと対応を試してみましたが色合いが不自然になってしまう問題が発生しました。</p> <p>下の画像がSDR時の画像とHDR時の画像の比較になります。</p> <p><figure class="figure-image figure-image-fotolife" title="左:SDR出力、右:HDR出力"><div class="images-row mceNonEditable"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132724.jpg" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132730.jpg" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></div><figcaption>左:SDR出力、右:HDR出力</figcaption></figure></p> <p>今回の対応では「明るさの幅」を拡張したいのですが全体的に青みが強く出てしまっています。 この問題に対処するため、レンダリングパスについて再度見直す必要がありました。</p> <h4 id="5212-HDR時におけるレンダリングパスの改良">5.2.1.2 HDR時におけるレンダリングパスの改良</h4> <p>先ほどのレンダリングパスについて、改良を加えたものがこちらになります。</p> <p><figure class="figure-image figure-image-fotolife" title="改良したHDR時のレンダリングパス"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132745.jpg" width="2000" height="1125" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>改良したHDR時のレンダリングパス</figcaption></figure></p> <p>違いとしては、UI描画の手前までSDRで処理を通し、その後HDR用のトーンマッピングをかけているところです。 この対応を行うことでUI描画の手前までの区間はSDR時と同じ処理になるため、色味に不具合が発生しないようにしました。</p> <p>また、元々のSDR時のレンダリングパスでは8bit精度で処理を通していたのですが16bit精度にしています。 これはSDRに範囲を狭くして、後から引き延ばす都合上精度を落とさないようにするために行っています。</p> <h4 id="5213-HDR用のトーンマッピングの改良">5.2.1.3 HDR用のトーンマッピングの改良</h4> <p>それでは新しくUI描画の手前に移したHDR用のトーンマッピング処理について説明いたします。</p> <p>HDR用のトーンマッピングではこちらの3つを満たすものを独自実装しました。</p> <ul> <li>SDR用のトーンマッピング後の値を使用すること</li> <li>輝度の値が低いところについてはSDRと同じにすること</li> <li>輝度の値が高くなるにつれて既存のHDR用のトーンカーブの変化率に近づくようにすること</li> </ul> <p>これらを満たすトーンマッピングを実装したコードが下記になります。</p> <pre class="code c++" data-lang="c++" data-unlink>// ガンマ補正の効果を相殺するため、ガンマ2.2を処理 color.rgb = pow(color.rgb, 2.2f); // 係数を算出 float3 rate = color.rgb; rate = pow(rate, 10.0f); // HDR用のトーンマッピングをかける // max_nit_level:最大輝度 color.rgb = lerp(color.rgb, color.rgb * max_nit_level, saturate(rate)); // UI素材と色空間を揃えるため、再度ガンマ補正を処理 color.rgb = pow(color.rgb, 1.0f/2.2f);</pre> <p>下記がトーンマッピング適用時のグラフになります。</p> <p><figure class="figure-image figure-image-fotolife" title="青:既存のHDR用トーンカーブ、緑:SDR用トーンカーブ、灰:改良したHDR用トーンカーブ"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132751.jpg" width="613" height="579" loading="lazy" title="" class="hatena-fotolife" style="width:305px;height:290px" itemprop="image"></span><figcaption>青:既存のHDR用トーンカーブ、緑:SDR用トーンカーブ、灰:改良したHDR用トーンカーブ</figcaption></figure></p> <p>グラフを見ると、輝度の値が低いところはSDRと同じで、輝度が高くなるにつれてHDRに近づいているのがわかるかと思います。</p> <p>この改良したトーンマッピングを行った結果とSDR時の画像を比較したものが下記になります。</p> <p><figure class="figure-image figure-image-fotolife" title="左:SDR出力、右:改良したトーンマッピングによるHDR出力"><div class="images-row mceNonEditable"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132756.jpg" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132820.jpg" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span></div><figcaption>左:SDR出力、右:改良したトーンマッピングによるHDR出力</figcaption></figure></p> <p>改良前と比べ全体的な色見は変わらず、ライトの白飛びが改善していることがわかるかと思います。</p> <h3 id="522-HDRにおけるOETFについて">5.2.2 HDRにおけるOETFについて</h3> <p>次にHDRにおけるOETF処理について説明します。 HDRの場合はOETF処理と合わせて下記の処理を行っています。</p> <ul> <li>ガンマ2.2を処理</li> <li>色空間の変換処理</li> <li>輝度の補正</li> <li>PQ補正</li> </ul> <p>一番最初にガンマ2.2を処理しているのは、ここまでガンマ補正後の画像で処理されているためです。 SDRディスプレイとHDRディスプレイで使用されているEOTFは違うので、ここでガンマ補正前の画像にします。</p> <h4 id="5221-色空間の変換について">5.2.2.1 色空間の変換について</h4> <p>『NGS』ではRec.709で描画処理を行っているため、HDRディスプレイにそのまま値を出力すると下記画像のようにSDR時の画像と比べて鮮やかすぎる見た目になってしまいます。</p> <p><figure class="figure-image figure-image-fotolife" title="色変換せずに出力した画像"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132826.jpg" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>色変換せずに出力した画像</figcaption></figure></p> <p>HDRディスプレイではRec.2020で処理するため、Rec.709の値をそのまま渡してしまうと下記の画像のように座標変換で引き延ばされてしまい、想定と違う色味になってしまうのが原因です。</p> <p><figure class="figure-image figure-image-fotolife" title="座標変換による引き延ばし"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132831.jpg" width="1512" height="1890" loading="lazy" title="" class="hatena-fotolife" style="width:375px;height:473px" itemprop="image"></span><figcaption>座標変換による引き延ばし</figcaption></figure></p> <p>そこで、Rec.709からRec.2020への変換処理を行うことで元の画像と同じ色合いになるようにします。</p> <pre class="code c++" data-lang="c++" data-unlink>// Rec.709からRec.2020への変換 float3 ConvertRec709To2020(float3 value){ float3x3 matrix709to2020 = { { 0.627404f, 0.329282f, 0.043314f }, { 0.069097f, 0.919541f, 0.011362f }, { 0.016392f, 0.088013f, 0.895595f } }; return mul(matrix709to2020, value); }</pre> <p>これで、SDRディスプレイの時と同じ色合いの画像をHDRディスプレイで出力できるようになります。</p> <h4 id="5222-色空間の変換における改善">5.2.2.2 色空間の変換における改善</h4> <p>上述のように色空間の変換を行うことで元の画像と同じ色合いにしましたが、これはHDRなのにも関わらずRec.709の範囲の色しか扱えていないとも言えます。 本来であればゲームの素材をすべてHDR用に調整して、表示すればいいのですが運営しているタイトルですべての素材をHDR用に調整し直すのは現実的ではありません。 そこで、色の範囲を疑似的に拡張しました。</p> <p>先ほどRec.709の値をそのまま渡すと、色空間がRec.2020に引き伸ばされると言いました。 これはRec.2020の色の範囲を扱えているとも言えます。 なので、色空間の変更後と変更前で線形補間を行い調整できるようにしました。</p> <p>この「線形補間の係数」はパラメータ「HDR設定:彩度調整」としてユーザーが調整できるようにしています。</p> <pre class="code c++" data-lang="c++" data-unlink>float3 rec709 = color.rgb   // rec709の数値をrec2020に変換 float3 rec2020 = ConvertRec709To2020(rec709);   //rateはユーザーが調整できるようにする color.rgb = lerp(rec2020, rec709, rate);</pre> <p>これで、ユーザーの好みに合わせて色域の拡張を行い鮮やかさを調整できるようにしました。 「HDR設定:彩度調整」の値を50(計算上は0.5)にした結果が下記になります。</p> <p><figure class="figure-image figure-image-fotolife" title="係数を0.5にした時の画像"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132835.jpg" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>係数を0.5にした時の画像</figcaption></figure></p> <h4 id="5223-輝度の補正">5.2.2.3 輝度の補正</h4> <p>次に輝度の補正について説明します。 HDRでよく問題になるのが、SDRと比べて画像が暗くなるという問題です。</p> <p>これは、SDRとHDRで標準白レベルの明るさに相違があるため発生します。</p> <p>一般的なSDRディスプレイでは、1.0を100nitで表示しておらず、おおよそ200~300nitで表示されています。 このため、HDRで1.0を100nitとして表示を行うと暗くなるという問題が起きます。</p> <p>この問題については輝度の補正をすることで対処します。 具体的には標準白レベルをパラメータで制御することで、明るさを調整できるようにします。 HDRは規格上10000nitまで表現が可能ですので、「標準白レベル ÷ 10000」乗算することで補正します。</p> <p>この「標準白レベル」はパラメータ「HDR設定:標準白レベル」としてユーザーが調整できるようにしています。</p> <pre class="code c++" data-lang="c++" data-unlink>// 指定した輝度に補正する float3 NormalizeBaseNit(float3 value, float base_nit){ base_nit = max(base_nit, 1.0f); return value * base_nit / 10000.0f; }</pre> <h4 id="5224-PQ補正">5.2.2.4 PQ補正</h4> <p>次にPQ補正について説明します。</p> <p>HDRディスプレイのEOTFではPQ方式が使用されます。 これは、人間の視覚特性に基づいて新しく開発されたガンマカーブになります。 OETFではこの逆関数であるPQ補正を行います。</p> <pre class="code c++" data-lang="c++" data-unlink>// PQ補正 float3 LinearToPQ(float3 value){ float m1 = 2610.0f / 16384.f; float m2 = 2523.0f / 4096.0f * 128.0f; float c1 = 3424.0f / 4096.0f; float c2 = 2413.0f / 4096.0f * 32.0f; float c3 = 2392.0f / 4096.0f * 32.0f; float3 cp = pow(value, m1); float3 n = (c1 + c2 * cp); float3 d = (1 + c3 * cp); return pow(n / d, m2); }</pre> <p>以上の処理を行い、描画した結果をSDRディスプレイに表示した結果がこちらになります。</p> <p><figure class="figure-image figure-image-fotolife" title="OETF後の画像"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132840.jpg" width="1307" height="735" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>OETF後の画像</figcaption></figure></p> <p>SDRとHDRで使用しているEOTFが違うため、白っぽい見た目になりますがこちらの画像をHDRディスプレイで表示することで下の画像のように適切な見た目となります。</p> <p><figure class="figure-image figure-image-fotolife" title="ディスプレイに表示される画像"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132845.jpg" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>ディスプレイに表示される画像</figcaption></figure></p> <p>以上がHDR時におけるレンダリングパスの説明になります。</p> <h1 id="6-調整するパラメータについて">6 調整するパラメータについて</h1> <p>『NGS』で調整できるパラメータは下記3つになります。</p> <ul> <li>HDR設定:標準白レベル(輝度の補正で使用)</li> <li>HDR設定:最大輝度レベル(HDR用のトーンマッピングで使用)</li> <li>HDR設定:彩度調整(色域の拡張で使用)</li> </ul> <p>これらのパラメータを用意した理由はディスプレイによって、明るさや色味が違うためです。 『NGS』では調整しやすいように下記のような調整用の画像を用意しました。</p> <p><figure class="figure-image figure-image-fotolife" title="調整用の画像"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221114/20221114132851.jpg" width="1890" height="945" loading="lazy" title="" class="hatena-fotolife" itemprop="image"></span><figcaption>調整用の画像</figcaption></figure></p> <p>標準白レベルでは250nitが基準となるようにし、最大輝度レベルではそのディスプレイが表現できる明るさに調整できるようになっています。 しかし、ディスプレイの設定やスペックによっては眩しすぎたり、暗くなったりすることがあるため好みに合わせて調整してただくのが適切かと思います。</p> <h1 id="7-まとめ">7 まとめ</h1> <p>長くなってしまいましたが、『NGS』におけるHDR対応についてまとめに入ります。 HDR対応では下の3つのことを行い、SDRの見た目を維持しつつ明るさと色の拡張を行うことができるようにしました。</p> <ul> <li>HDR用のトーンマッピング処理</li> <li>色の範囲の拡張</li> <li>HDRにおけるOETF処理</li> </ul> <p>最初に記述したようにこれは『NGS』におけるHDRの対応方法になります。 ゲームによっては「SDRとは違った絵を出したい」といった要望や「HDR用に素材を調整したい」等の要望によって、対応方法に違いが出てくるかと思います。 この記事にかかれていることについては、あくまで参考として活用いただけると幸いです。</p> <h1 id="8-最後に">8 最後に</h1> <p>汎用ゲームエンジンが流行りつつありますが、自社でゲームエンジンを開発することで、どういった処理が最適なのかを基礎から学び、ひいては独自の実装で特徴ある表現を可能にすることができます。 自社でゲームエンジンを「使う」だけでなく、「作る」ことができる環境。 セガで働くことにご興味を持たれましたら下記サイトにアクセスお願いします。</p> <p>(C) SEGA</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sega.co.jp%2Frecruit%2Findex.html" title="採用サイト|株式会社セガ -【SEGA CORPORATION】" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html">www.sega.co.jp</a></cite></p> <div class="footnotes"> <hr/> <ol> <li id="fn:1"> Gbuffer描画からHDRポストプロセスの区間については処理を省略して掲載していますのでご注意ください。<a href="#fnref:1" rev="footnote">&#8617;</a></li> <li id="fn:2"> 実際の処理としては、トーンマッピング前に露出制御を行っていますが詳細説明は省略いたします。<a href="#fnref:2" rev="footnote">&#8617;</a></li> <li id="fn:3"> 表現できる最大値はディスプレイの表示モードによって変わることがあります。<a href="#fnref:3" rev="footnote">&#8617;</a></li> </ol> </div> sgtech Inverse Kinematics(IK)について hatenablog://entry/4207112889926840422 2022-10-17T10:00:00+09:00 2022-10-17T10:00:00+09:00 はじめに 株式会社セガ 第3事業部 オンライン研究開発プログラム2部の松本と申します。 今回はInverse Kinematics(IK)に関する基本的な考え方や手法についての記事となります。 ゲーム制作の仕事に携わっているとIKの名前くらいは聞いたことがあるのではないかと思いますが、実際の中身については何をやってるのか良く分からない謎の技術だと感じている人も多いのではないでしょうか。この記事を読んでInverse Kinematicsについての理解を深めたり、あるいは改めて学び直すための良い機会になればと思います。 特にゲーム制作者ではない方にとっては、前提知識が不足していて分かり辛い所もあ… <h3 id="はじめに">はじめに</h3> <p>株式会社セガ 第3事業部 オンライン研究開発プログラム2部の松本と申します。</p> <p>今回はInverse Kinematics(IK)に関する基本的な考え方や手法についての記事となります。</p> <p>ゲーム制作の仕事に携わっているとIKの名前くらいは聞いたことがあるのではないかと思いますが、実際の中身については何をやってるのか良く分からない謎の技術だと感じている人も多いのではないでしょうか。この記事を読んでInverse Kinematicsについての理解を深めたり、あるいは改めて学び直すための良い機会になればと思います。</p> <p>特にゲーム制作者ではない方にとっては、前提知識が不足していて分かり辛い所もあるかも知れませんが、本題であるIKそのものの概念や処理内容については、高校数学課程の知識 <a href="#f-e08301b4" name="fn-e08301b4" title="+α">*1</a> があれば十分に理解できそうな内容になっているので、そうした視点で数学の復習がてら読んでみるのも良いかと思います。SNS等で度々話題になるベクトルや三角関数と言った高校数学で習う項目の有用性を感じてもらうだけでも構いません。</p> <h3 id="目次">目次</h3> <ul class="table-of-contents"> <li><a href="#はじめに">はじめに</a></li> <li><a href="#目次">目次</a></li> <li><a href="#IKの正体">IKの正体</a><ul> <li><a href="#FKについて">FKについて</a></li> <li><a href="#FKの役割">FKの役割</a></li> <li><a href="#ようやくIKの登場">ようやくIKの登場</a></li> <li><a href="#IKは難しい">IKは難しい?</a></li> </ul> </li> <li><a href="#1ボーンIK">1ボーンIK</a><ul> <li><a href="#概要">概要</a><ul> <li><a href="#前提知識1X軸Y軸Z軸による姿勢表現について">前提知識1:X軸Y軸Z軸による姿勢表現について</a></li> </ul> </li> <li><a href="#手法">手法</a><ul> <li><a href="#前提知識2ヨー回転ピッチ回転について">前提知識2:ヨー回転・ピッチ回転について</a></li> <li><a href="#1ボーンIK手順">1ボーンIK手順</a></li> </ul> </li> <li><a href="#その他の手法もざっくり紹介">その他の手法もざっくり紹介</a></li> <li><a href="#Up-Vector-Constraint">Up Vector Constraint</a><ul> <li><a href="#Up-Vector-Constraintの手順">Up Vector Constraintの手順</a></li> </ul> </li> </ul> </li> <li><a href="#2ボーンIK">2ボーンIK</a><ul> <li><a href="#概要-1">概要</a></li> <li><a href="#手法-1">手法</a><ul> <li><a href="#理論背景を交えた手順説明">理論背景を交えた手順説明</a></li> <li><a href="#回転方向の設定について">回転方向の設定について</a></li> <li><a href="#2ボーンIKの手順まとめ">2ボーンIKの手順(まとめ)</a></li> </ul> </li> <li><a href="#Up-Vector-Constraint-1">Up Vector Constraint</a></li> <li><a href="#第2関節の回転角制限">第2関節の回転角制限</a><ul> <li><a href="#理論背景を交えた手順説明">理論背景を交えた手順説明</a></li> <li><a href="#回転角制限の副作用">回転角制限の副作用</a></li> <li><a href="#回転角制限が必要となる事例">回転角制限が必要となる事例</a></li> </ul> </li> </ul> </li> <li><a href="#2ボーンIKをキャラクターに適用する">2ボーンIKをキャラクターに適用する</a><ul> <li><a href="#エンドエフェクターについて">エンドエフェクターについて</a><ul> <li><a href="#エフェクターの目標位置の置き換え">エフェクターの目標位置の置き換え</a></li> </ul> </li> <li><a href="#疑似3ボーンIK">疑似3ボーンIK</a><ul> <li><a href="#疑似3ボーンIKの手順">疑似3ボーンIKの手順</a></li> <li><a href="#別バージョン">別バージョン</a></li> <li><a href="#特徴">特徴</a></li> </ul> </li> </ul> </li> <li><a href="#まとめ">まとめ</a></li> <li><a href="#終わりに">終わりに</a></li> </ul> <h3 id="IKの正体">IKの正体</h3> <p>まずはIKというのがどういう物なのかを説明したいのですが、いくつか前提となる知識も必要となるので、そちらから順番に説明します。</p> <h4 id="FKについて">FKについて</h4> <p>人体のように複数の関節が連なって構成される骨格構造の姿勢を決定していく際に、構造の開始位置となるルート(=根っこ)関節から始めて、構造の終端側にある関節に向かって順番に平行移動や回転変換による姿勢計算を繰り返すことで、全身の姿勢を決定していく手法が考えられます。</p> <p>この様な逐次的な手順で多関節連鎖構造の姿勢を解決する手法を、Forward Kinematics(フォワード・キネマティクス=順運動学)と呼びます。長いので今後はFK(エフ・ケー)と省略します。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="FKによる平行移動と回転のイメージ図"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183944.png" width="1200" height="330" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">FKによる平行移動と回転のイメージ図</figcaption> </figure> <h4 id="FKの役割">FKの役割</h4> <p>ゲームに登場する3Dキャラクターの動きは、あらかじめ用意されているモーションデータを再生することで表現されていることがほとんどですが、この処理はFKによって計算されています。つまりFKはモーション再生処理に欠かせない基盤技術という位置付けです。</p> <p>実際のFKモーションデータの大半は回転データの塊ですが、適切な全身のポーズや動きを作るために、どの関節にどのくらいの回転量を与えるのがいいのかというのは、FKでは決めることができません。計算で決めることができないのはもちろんのこと、人の手を使ったとしてもFK的な手続きによるデータ作成は、極めて非効率的な作業となります。ここで言うFK的手続きというのは、関節の回転角を1つずつ編集することで目的の全身ポーズや動作をつくることを指します。例えば関節が動くフィギュアやプラモで全身のポーズを付ける作業手順が、おおよそこれに該当するので、経験したことのある方は、あの作業で複雑で細かい動きを作るのがどれだけ大変か想像がつくのではないでしょうか?</p> <p>まとめると、FKは既に決まっている回転データを順番に処理して姿勢を作り上げるという基礎的な役割を担いますが、その回転量そのものを決めることができないため、モーションデータを作成するだけでなく、ゲーム中にモーションの再生結果を加工して別の動きを作り出すのも難しい、ということになります。</p> <h4 id="ようやくIKの登場">ようやくIKの登場</h4> <p>そこで、制御し易い情報を与えることで、FK処理に必要な回転量を決めるための機能が求められます。</p> <p><span style="text-decoration: underline;">特定の部位の位置や姿勢を指定することで、そこに到達するまでの中間の関節の姿勢(=回転量)を全て計算で決める手法</span>、すなわちInverse Kinematics(インバース・キネマティクス=逆運動学)と呼ばれる手法が、その役割を担います。こちらも今後はIK(アイ・ケー)と略します。</p> <p>IKには様々な手法があり、その手法や適用範囲にも寄りますが、例えば手先の位置を決めたら、そこに連結されている前腕や上腕、場合によっては肩や背骨、そこに連結された反対側の腕の姿勢までも一度に決めるようなことも可能です。これはモーションデータを作る際にも非常に効率的なので、モーションデザイナーが扱うツールには必須の機能となっていますし、ゲーム中で再生されたモーションの結果をゲーム側の都合に合わせて修正・加工したりするのにも使われています。</p> <h4 id="IKは難しい">IKは難しい?</h4> <p>計算でどのように回転量を決めるのかはパッとは思いつかないかも知れませんが、具体的なIKの手法そのものは、知ってしまえば超簡単な物から、理論背景を理解するだけでも難しい物まで様々です。今回紹介するのは基本的なアルゴリズムで、仕組みや理論は比較的簡単な部類に入るものですが、手法そのものの実用性や重要性は非常に高く、今でも多くのゲームで使われているので、学びのコストパフォーマンスはかなり良いはずです。</p> <h3 id="1ボーンIK">1ボーンIK</h3> <h4 id="概要">概要</h4> <p>多関節の連鎖で構成される骨格構造を1つ1つ分解すると、1つの関節とそれに対応する骨(ボーン)に相当する部位に分解できます。この単体骨に適用するIKが1ボーンIKです。1ボーンIKを組み合わせて多関節のNボーンIKとすることはできませんが、2ボーン以上のIK処理の多くが内部処理に利用している重要なIKです。</p> <p>下の図は1ボーンIKの動作概要を示した図です。このような図は今後も出てくるので、その見方と合わせて動作概要を説明します。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="1ボーンIKの概念図"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183839.png" width="380" height="231" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">1ボーンIKの概念図</figcaption> </figure> <p>図には、ちょっと太めの針のようなモデル表示が灰色と水色で2本分描かれています。これが制御対象の骨の初期配置(灰色)と、1ボーンIK適用後の配置(水色)を表しています。針の尖った方向がこの骨の進行方向になり、針の根本から先端までの長さはそのまま骨の長さを表します。水色の針モデルの延長線上にある白と青の四角いチェッカーマークがありますが、その中心がIKの目標位置を表しています。この図は1ボーンIKを適用したことで、骨の進行方向が目標位置の方向を向いているということを表したものです。</p> <p>このように、1ボーンIKが達成する処理内容は、ある目標位置が1点与えられたら、骨の進行方向をその点の方向に向けるというものになります。IKは一般的には、与えられた目標位置に骨の先端位置が到達するような姿勢を解として導き出しますが、1ボーンの場合はそれを達成できるのが、目標位置が骨の長さと同じ距離にある場合だけなので、進行方向が合えばOKとしています。</p> <p>骨の進行方向を目標位置に向けるというのは、単純に関節の位置から目標位置に向けたベクトルを計算して、骨の長さに合わせれば完了という訳にはいきません。骨の進行方向に関してはそれで解決するのですが、関節の姿勢がどのように変化したかは、それだけでは不十分だからです。</p> <p>具体的な手法の説明に移る前に、少しだけ関節の姿勢について説明します。</p> <h5 id="前提知識1X軸Y軸Z軸による姿勢表現について">前提知識1:X軸Y軸Z軸による姿勢表現について</h5> <p>各関節の姿勢は、それぞれのX軸、Y軸、Z軸の方向で与えることができます。CGなどの分野では、関節の進行方向をX軸に割り当てるのが主流となっているので、ここでもそれを前提に説明します。<br />先ほどのベクトル計算では、このX軸の方向を向けることはできていますが、Y軸、Z軸に関しては未解決です。X軸を回転させたのと同じ分だけY軸やZ軸も回転させることで、初めて関節の方向が変わったことになります。</p> <p>3次元の場合はXYZ全ての軸の方向を決める必要がありますが、XY座標だけを取り扱う2次元の場合は、Z軸に相当する軸の方向は常に手前側に固定されていると考えることができるので、X軸とY軸の方向だけを解決すればOKです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="XYZ軸の回転イメージ(X→X'、Y→Y'、Z→Z')"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012184045.png" width="380" height="348" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">XYZ軸の回転イメージ(X→X'、Y→Y'、Z→Z')</figcaption> </figure> <h4 id="手法">手法</h4> <p>1ボーンIKにはいくつかの手法がありますが、ここでは三角比を使ってヨー回転量とピッチ回転量を計算する手法を紹介します。</p> <h5 id="前提知識2ヨー回転ピッチ回転について">前提知識2:ヨー回転・ピッチ回転について</h5> <p>その前に、ヨー回転、ピッチ回転について簡単に説明しておきます。</p> <ul> <li>ヨー回転というのは進行方向に対して垂直上方向を回転軸とする回転です。<br />進行方向基準で姿勢の左右方向を規定します。</li> <li>ピッチ回転というのは進行方向に対して水平左方向を回転軸とする回転です。<br />進行方向基準で姿勢の上下方向を規定します。</li> </ul> <p>この他にロール回転というのもあって、これは進行方向軸を回転軸とし、進行方向基準で姿勢の捻じれ具合を規定しますが、ここでは一旦無視します。※あとでまた登場します。</p> <p>ここでは、ヨー回転軸をZ軸、ピッチ回転軸をY軸にとり、ヨー回転角をθz、ピッチ回転角をθyとして説明します。<a href="#f-86528c8e" name="fn-86528c8e" title="この場合は必然的にX軸がロール回転軸となります。">*2</a></p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="ヨー回転とピッチ回転"> <div class="images-row mceNonEditable"> <div class="images-row-item"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012184049.png" width="800" height="688" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></div> <div class="images-row-item"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012184041.png" width="801" height="688" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></div> </div> <figcaption class="mceEditable">ヨー回転とピッチ回転</figcaption> </figure> <p>ヨー回転軸がZ軸なのでヨー回転ではX軸とY軸だけを回転し、ピッチ回転軸がY軸なのでピッチ回転ではX軸とZ軸だけを回転します。必然的にロール回転軸はX軸となり、ロール回転ではY軸とZ軸だけを回転します。</p> <h5 id="1ボーンIK手順">1ボーンIK手順</h5> <ol> <li>IKの目標位置を関節のローカル座標に変換する</li> <li>ローカル座標から三角比を用いてcosθz, sinθz, cosθy, sinθyを計算する <br /> <ul> <li><img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Ccos%7B%CE%B8_z%7D%20%3D%20x%20%2F%20%5Csqrt%7Bx%5E2%20%2B%20y%5E2%7D%20%7D" alt="\displaystyle{ \cos{&theta;_z} = x / \sqrt{x^2 + y^2} }"/></li> <li><img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Csin%7B%CE%B8_z%7D%20%3D%20y%20%2F%20%5Csqrt%7Bx%5E2%20%2B%20y%5E2%7D%20%7D" alt="\displaystyle{ \sin{&theta;_z} = y / \sqrt{x^2 + y^2} }"/></li> <li><img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Ccos%7B%CE%B8_y%7D%20%3D%20%5Csqrt%7Bx%5E2%20%2B%20y%5E2%7D%20%2F%20%5Csqrt%7Bx%5E2%20%2B%20y%5E2%20%2B%20z%5E2%7D%20%7D" alt="\displaystyle{ \cos{&theta;_y} = \sqrt{x^2 + y^2} / \sqrt{x^2 + y^2 + z^2} }"/></li> <li><img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Csin%7B%CE%B8_y%7D%20%3D%20z%20%2F%20%5Csqrt%7Bx%5E2%20%2B%20y%5E2%20%2B%20z%5E2%7D%20%7D" alt="\displaystyle{ \sin{&theta;_y} = z / \sqrt{x^2 + y^2 + z^2} }"/></li> </ul> </li> <li>関節の姿勢をcosθz, sinθzでヨー軸回転、cosθy, sinθyでピッチ軸回転する <a href="#f-4e7b090c" name="fn-4e7b090c" title="回転の処理はX軸、Y軸、Z軸それぞれに対して計算する必要があります。1つずつ計算しても良いのですが、通常は行列などを使ってまとめて処理します。">*3</a></li> </ol> <figure class="figure-image figure-image-fotolife mceNonEditable" title="ヨー回転(Z軸)+ピッチ回転(Y軸)時の三角比"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183850.png" width="380" height="347" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">ヨー回転(Z軸)+ピッチ回転(Y軸)時の三角比</figcaption> </figure> <p>赤いライン(X軸)に沿っている灰色表示の骨がIK適用前の初期配置です。<br />そこからIK目標位置(白青のチェッカーマーク中心)の方向に向けてヨー軸(Z軸)回転させた状態が中央の灰色表示の骨となり、更にそこから目標位置の方向にピッチ軸(Y軸)回転させた最終状態が水色表示の骨となります。</p> <p>三角比の計算は、上の図を参考にしてください。<br />いきなり三角関数が出てきましたが、cos=底辺 / 斜辺、sin=高さ / 斜辺なので、手順2.のような式になります。<br />斜辺は三平方の定理 <a href="#f-83710894" name="fn-83710894" title="中学3年で習う「底辺の2乗+高さの2乗=斜辺の2乗」です。">*4</a> で求めます。</p> <p>この手法は3次元での1ボーンIKの一例ですが、ピッチ軸回転を無視することで、そのまま2次元でのIKにも使えるのが利点です。</p> <h4 id="その他の手法もざっくり紹介">その他の手法もざっくり紹介</h4> <p>1ボーンIKは他にも外積を用いる手法や、クォータニオンを用いる手法があるので、簡単に概要を紹介しておきます。</p> <p>外積を用いる手法は回転を用いずにXYZ各軸を生成する手法ですが、今回説明したヨー回転+ピッチ回転による手法と実質的に同じ結果が得られます。</p> <p>クォータニオンを用いる手法は、元の進行方向ベクトルと目標位置までの方向ベクトルから計算できる内積と外積の結果を利用してクォータニオンを生成し、このクォータニオンで姿勢を回転させる手法です。ヨー+ピッチ回転方式とは、進行方向となるX軸の方向は一致しますが、Y軸とZ軸の方向が異なる結果となります。</p> <h4 id="Up-Vector-Constraint">Up Vector Constraint</h4> <p>ヨー回転とピッチ回転の組み合わせで、目標位置の方向に関節の進行方向を向ける1ボーンIK手法を紹介しましたが、このままではロール回転については全く制御されていない状態です。<a href="#f-724ccef3" name="fn-724ccef3" title="これは外積版やクォータニオン版も同様です">*5</a></p> <p>Up Vector Constraint(アップ・ベクター・コンストレイント=上方ベクトル拘束)は、関節のロール回転軸に対して垂直な任意の軸を上方ベクトルとして設定し、この上方ベクトルが拘束用の目標位置を向くようにロール回転軸の回転量を拘束する手法です。これはロール回転を制御する1ボーンIKだとも言えます。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="Z軸に対するUp Vector Constraint(赤い矢印がロール回転、白赤チェッカーの中心が拘束用目標位置)"> <div class="images-row mceNonEditable"> <div class="images-row-item"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183843.png" width="864" height="767" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></div> <div class="images-row-item"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183847.png" width="864" height="767" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></div> </div> <figcaption class="mceEditable">Z軸に対するUp Vector Constraint(赤い矢印がロール回転、白赤チェッカーの中心が拘束用目標位置)</figcaption> </figure> <p>上方ベクトルはロール回転軸=X軸に垂直ならばどのような方向でも構いませんが、一般的にはY軸やZ軸、あるいはそれらの負方向を設定することが多いと思うので、ここではそれを前提に手順を紹介します。<br />以下の手順は、1ボーンIKを適用した後の追加処理となります。</p> <h5 id="Up-Vector-Constraintの手順">Up Vector Constraintの手順</h5> <ol> <li>拘束用の目標位置 <a href="#f-839beb56" name="fn-839beb56" title="1ボーンIK用の目標位置とは別に設定される">*6</a> を関節のローカル座標に変換する</li> <li>ローカル座標から三角比を用いてcosX, sinXを計算する<br /> <ul> <li><img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Ccos%7BX%7D%20%3D%20y%20%2F%20%5Csqrt%7By%5E2%20%2B%20z%5E2%7D%20%7D" alt="\displaystyle{ \cos{X} = y / \sqrt{y^2 + z^2} }"/></li> <li><img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Csin%7BX%7D%20%3D%20z%20%2F%20%5Csqrt%7By%5E2%20%2B%20z%5E2%7D%20%7D" alt="\displaystyle{ \sin{X} = z / \sqrt{y^2 + z^2} }"/></li> </ul> </li> <li>Up Vectorとして選択する軸の種類によってcosX, sinXを変換する <ul> <li>Y軸:変更しない <a href="#f-925f8cda" name="fn-925f8cda" title="手順2.で求めたcosX, sinXの式はY軸合せの場合の式なので">*7</a></li> <li>Z軸:cosX = sinX, sinX = - cosX</li> <li>各軸の負方向合わせの場合は、上記手順で求めたcosX, sinX両方を符号反転する</li> </ul> </li> <li>cosX, sinXで関節をロール回転する</li> </ol> <p>1ボーンIK本体の方で三角比を用いたヨー回転+ピッチ回転の手法で説明したので、こちらも三角比で計算する手法を紹介しましたが、クォータニオンを用いて計算する方法もあります。</p> <h3 id="2ボーンIK">2ボーンIK</h3> <h4 id="概要-1">概要</h4> <p>2ボーンIKとは、連結された2本の骨の先端位置が与えられた目標位置に到達するように、2本それぞれの骨の姿勢を同時に決定するIK処理です。<br />人間の手足の構造に適用するのに非常に適しているため、Limb IK(リム=肢)と呼ばれることも多いです。</p> <p>2ボーンIKはその基本アルゴリズムだけで、2本目の骨の関節の回転軸が1軸に限定されることや、その回転方向を1方向に限定できることがメリットです。 <a href="#f-a15ace7a" name="fn-a15ace7a" title="これは他のIKだと非常に面倒な追加処理を要求されます">*8</a></p> <h4 id="手法-1">手法</h4> <p>こちらもいくつかの手法が知られていますが、余弦定理を用いる手法が一般的です。骨が増えた分だけ少し複雑になるので理論背景を交えつつ順番に説明します。</p> <h5 id="理論背景を交えた手順説明">理論背景を交えた手順説明</h5> <p>まずは前項で説明した1ボーンIKを用いて第1関節を目標位置の方向に向けます。<a href="#f-bb25a214" name="fn-bb25a214" title="この図では第2関節も一緒に追従させていますが、計算上は第2関節は放置していて問題ありません。">*9</a></p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="第1関節の方向を1ボーンIKを用いて目標位置の方向に向ける"> <div class="images-row mceNonEditable"> <div class="images-row-item"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183835.png" width="837" height="574" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></div> <div class="images-row-item"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183854.png" width="837" height="574" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></div> </div> <figcaption class="mceEditable">第1関節の方向を1ボーンIKを用いて目標位置の方向に向ける</figcaption> </figure> <p>目標位置に向けた第1関節の進行方向軸を基準として、第2関節の回転軸を法線とする平面を想定します。この図では手前側に法線が向いた状態となっています。<br />第1関節も第2関節もこの法線方向を回転軸とした1軸回転を行うため、ここからは2次元での問題として扱います。<br />この平面上で、第2関節の先端が目標位置に到達するように、2本の関節を回転させて以下のような三角形を形成した状態を想定します。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="平面上に2本の骨が構成する三角形を想定した図"> <div class="images-row mceNonEditable"> <div class="images-row-item"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183905.png" width="837" height="574" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></div> <div class="images-row-item"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183910.png" width="837" height="574" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></div> </div> <figcaption class="mceEditable">平面上に2本の骨が構成する三角形を想定した図</figcaption> </figure> <p>辺a、辺bの長さは、それぞれ1本目と2本目の骨の長さに相当します。これは事前に分かっている既知の値です。また、辺cの長さは1本目の関節の位置と目標位置との距離に相当しており、これは2点間の距離を計算することで求まります。このように三角形の3辺の長さが既知なので、<strong>余弦定理</strong>を用いてcosB, cosCを求めることができます。</p> <ul> <li><img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Ccos%7BB%7D%20%3D%20%5Cbigl%28c%5E2%20%2B%20a%5E2%20-%20b%5E2%5Cbigr%29%20%2F%202ca%20%7D" alt="\displaystyle{ \cos{B} = \bigl(c^2 + a^2 - b^2\bigr) / 2ca }"/></li> <li><img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Ccos%7BC%7D%20%3D%20%5Cbigl%28a%5E2%20%2B%20b%5E2%20-%20c%5E2%5Cbigr%29%20%2F%202ab%20%7D" alt="\displaystyle{ \cos{C} = \bigl(a^2 + b^2 - c^2\bigr) / 2ab }"/></li> </ul> <p>cosが決まれば <img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Ccos%5E2%7B%CE%B8%7D%20%2B%20%5Csin%5E2%7B%CE%B8%7D%20%3D%201%20%7D" alt="\displaystyle{ \cos^2{&theta;} + \sin^2{&theta;} = 1 }"/> の関係からsinも計算できます。</p> <ul> <li><img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Csin%7BB%7D%20%3D%20%C2%B1%5Csqrt%7B1%20-%20%5Ccos%5E2%7BB%7D%7D%20%7D" alt="\displaystyle{ \sin{B} = &plusmn;\sqrt{1 - \cos^2{B}} }"/></li> <li><img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Csin%7BC%7D%20%3D%20%C2%B1%5Csqrt%7B1%20-%20%5Ccos%5E2%7BC%7D%7D%20%7D" alt="\displaystyle{ \sin{C} = &plusmn;\sqrt{1 - \cos^2{C}} }"/></li> </ul> <p>sinの符号は回転方向の符号と一致するため、ここでの決定は一旦保留して、回転方向がどうなっているのかを確認する必要があります。各関節の回転方向を表した図を以下に示してみました。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="各関節の回転方向を示した図"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183914.png" width="380" height="261" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">各関節の回転方向を示した図</figcaption> </figure> <p>回転方向について考える前に、第2関節の回転角が余弦定理で求めた三角形abcの内角Cではなく、実際には外角のπ-Cとなっている点について考慮しなければなりません。<br />といっても、ここは以下の公式にしたがってcosCの符号を反転するだけで構いません。sinCの値はそのままです。</p> <ul> <li><img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Ccos%7B%28%CF%80-C%29%7D%20%3D%20-%5Ccos%7BC%7D%20%7D" alt="\displaystyle{ \cos{(&pi;-C)} = -\cos{C} }"/></li> <li><img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Csin%7B%28%CF%80-C%29%7D%20%3D%20%5Csin%7BC%7D%20%7D" alt="\displaystyle{ \sin{(&pi;-C)} = \sin{C} }"/></li> </ul> <p>改めて回転方向について話を戻します。<br />回転方向が反時計回りの場合は正方向の回転で、時計回りの場合は負方向の回転となります。この図によると、第1関節の回転Bは負方向への回転で、第2関節の回転π-Cは正方向の回転ということになります。<br />回転方向の正負はsinθの正負だけで表現できるので、cosの符号は変化しません。<br />回転方向を考慮した最終的なcosとsinの組み合わせは以下のようになります。</p> <ul> <li>第1関節:<img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Ccos%7BB%7D%20%7D" alt="\displaystyle{ \cos{B} }"/>, <img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20-%5Csin%7BB%7D%20%7D" alt="\displaystyle{ -\sin{B} }"/></li> <li>第2関節:<img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20-%5Ccos%7BC%7D%20%7D" alt="\displaystyle{ -\cos{C} }"/>, <img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Csin%7BC%7D%20%7D" alt="\displaystyle{ \sin{C} }"/></li> </ul> <p>それぞれの関節についてcosとsinが決まったので、これらを使った回転変換で姿勢を作ることができるようになりましたが、2ボーンIKとしてはまだ考慮しなければならないことがあります。</p> <p>2ボーンIKの条件を満たす三角形は、辺cの反対側にも想定することができるからです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="回転方向が反対となる逆側の三角形"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183918.png" width="380" height="369" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">回転方向が反対となる逆側の三角形</figcaption> </figure> <p>もう1つの三角形はBとCの回転方向を正負逆にしたものなので、既に求めているsin値の符号変換だけで対応可能です。</p> <ul> <li>第1関節:<img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Ccos%7BB%7D%20%7D" alt="\displaystyle{ \cos{B} }"/>, <img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20%5Csin%7BB%7D%20%7D" alt="\displaystyle{ \sin{B} }"/></li> <li>第2関節:<img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20-%5Ccos%7BC%7D%20%7D" alt="\displaystyle{ -\cos{C} }"/>, <img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20-%5Csin%7BC%7D%20%7D" alt="\displaystyle{ -\sin{C} }"/></li> </ul> <p>2ボーンIKの計算をする場合に、どちらの三角形による結果を選択するのかは、第2関節の回転方向が正負どちらであるかという基準で決定することが一般的です。これらはあらかじめどちらか一方に決めたものを選択することもあれば、両方に回転可能な場合も考慮して、IKを適用する前にどちら側に関節が曲がっていたかを調べて、同じ方向に曲がるような選択をする場合もあります。<a href="#f-56fd4ee7" name="fn-56fd4ee7" title="適用前の角度が180°の場合は方向が決められないので、その場合に正負どちらを優先するかは決めておく必要があります。">*10</a> いずれにせよ、第2関節の回転方向が正なら下の三角形、負なら上の三角形を選択します。余弦定理で求めるcosの結果は一緒なので、単純にsinの符号の組み合わせの選択を行います。</p> <h5 id="回転方向の設定について">回転方向の設定について</h5> <p>第2関節の回転軸がどの軸になるかや、回転方向が正負どちらになるのかについては、2ボーンIKを適用する対象の構造に依存します。したがって、回転軸や回転方向を規定する設定項目を用意しておくのが良いでしょう。</p> <p>人体モデルに適用する場合、一般的な作り方だと腕に設定する場合と足に設定する場合では、回転方向は逆になることが多いようです。当てはめてみて逆に曲がってしまったらもう一方の設定にすれば良いだけなので、そんなに難しく考える必要はありません。</p> <h5 id="2ボーンIKの手順まとめ">2ボーンIKの手順(まとめ)</h5> <ol> <li>1ボーンIKを用いて目標位置の方向に第1関節を向ける</li> <li>余弦定理でcosB, cosCを求める(cosCは符号反転する)</li> <li>sinB, sinCを求める(符号は正とする)</li> <li>第2関節の回転方向設定によりsinB, sinCいずれかの符号反転を行う <ul> <li>正回転:-sinB</li> <li>負回転:-sinC</li> </ul> </li> <li>得られたcos, sinの組み合わせで、各関節を回転させる</li> </ol> <p> </p> <p>次項以降では、2ボーンIKに対するいくつかの基本的な機能拡張について説明します。</p> <h4 id="Up-Vector-Constraint-1">Up Vector Constraint</h4> <p>2ボーンIKは、1ボーンIK適用後に第2関節の回転軸を法線とする平面上での三角形を想定して計算するという基本アルゴリズムでした。2次元の場合はこれ以上のIK解は存在しませんが、3次元の場合はロール軸回転が存在するため、無限の解が存在することになります。これらの中から任意の平面上の三角形を選択したい場合は、1ボーンIKの計算後にUp Vector Constraintをかけることで対応します。 <a href="#f-b5d23c8f" name="fn-b5d23c8f" title="この処理自体は1ボーンIKにかかるものなので計算手順も同じです。">*11</a></p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="2ボーンIKへのUp Vector Constraint適用イメージ"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183902.png" width="380" height="281" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">2ボーンIKへのUp Vector Constraint適用イメージ</figcaption> </figure> <p>キャラクターモーションの補正目的で2ボーンIKを使う場合は、元のモーション姿勢から1ボーンIKを適用した状態での平面をそのまま使い、Up Vector Constraintをかけないことも多いですが、そこから手足の開き具合の調節が必要な場合などには、この機能に頼らなければなりません。</p> <h4 id="第2関節の回転角制限">第2関節の回転角制限</h4> <p>2ボーンIKでは第2関節の曲がる方向を選択することで、回転角の範囲が自動的に0~180°か-180~0°のいずれかに制限されますが、この曲がり具合の範囲を更に制限することができるので、その手法について説明します。</p> <h5 id="理論背景を交えた手順説明">理論背景を交えた手順説明</h5> <p>通常の2ボーンIK処理の工程で、cの長さを目標位置と第1関節の位置との距離として求めますが、ここでも余弦定理を使うことで角Cの角度制限の問題を、辺cの長さの範囲制限の問題に落とし込み、第2関節の回転角制限を実現します。</p> <p>ここでは実際の回転計算で考慮する三角形の外角(π-C)ではなく、余弦定理で求める対象となる三角形の内角Cの方で考えます。</p> <p>角Cの最小回転角をθmin、最大回転角をθmaxとします。(0 ≦ θmin ≦ θmax ≦180°)<br />設定は角度で与えておいたとしても、実際には事前処理でcosθmin, cosθmaxを求めておくのが効率的です。<br />辺a、辺bの長さと、それらがなす角Cに対するcosθmin, cosθmaxが既知なので、余弦定理で辺cの長さの最小値と最大値が決まります。 <a href="#f-6accdd4e" name="fn-6accdd4e" title="余弦定理の式が先程とは違いますが、cについて展開し直しただけです">*12</a></p> <ul> <li><img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20c_%7Bmin%7D%20%3D%20%5Csqrt%7B%20a%5E2%20%2B%20b%5E2%20-%202ab%20%5Ccos%7B%CE%B8_%7Bmin%7D%7D%7D%20%7D" alt="\displaystyle{ c_{min} = \sqrt{ a^2 + b^2 - 2ab \cos{&theta;_{min}}} }"/></li> <li><img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20c_%7Bmax%7D%20%3D%20%5Csqrt%7B%20a%5E2%20%2B%20b%5E2%20-%202ab%20%5Ccos%7B%CE%B8_%7Bmax%7D%7D%7D%20%7D" alt="\displaystyle{ c_{max} = \sqrt{ a^2 + b^2 - 2ab \cos{&theta;_{max}}} }"/></li> </ul> <p>実際の距離から求めた辺cの長さを、この<img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20c_%7Bmin%7D%20%7D" alt="\displaystyle{ c_{min} }"/>と<img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20c_%7Bmax%7D%20%7D" alt="\displaystyle{ c_{max} }"/>で範囲制限した結果を新たなcとして2ボーンIKを計算することで、第2関節の角度が範囲制限された状態で、対応する第1関節の角度と共に求まります。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="第2関節の角度制限適用例(最小角度:30°、最大角度:170°)"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183858.png" width="1428" height="487" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">第2関節の角度制限適用例(最小角度:30°、最大角度:170°)</figcaption> </figure> <p>最初からcの長さを規定するパラメーター(距離に対する比率など)で範囲制限することもありますが、その方法だとaとbの長さの比率がキャラによって異なる場合に、制限する角度を一定に保つことができないという問題があります。aとbの長さの比率が固定なら<img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20c_%7Bmin%7D%20%7D" alt="\displaystyle{ c_{min} }"/>と<img src="https://chart.apis.google.com/chart?cht=tx&chl=%5Cdisplaystyle%7B%20c_%7Bmax%7D%20%7D" alt="\displaystyle{ c_{max} }"/>は完全に事前計算可能なので、この方式を選択することにより2ボーンIKの処理負荷が余計に増えることはありません。</p> <h5 id="回転角制限の副作用">回転角制限の副作用</h5> <p>回転制限がかかると目標位置への到達という、IKが達成すべき本来の目的が達成できなくなってしまいます。しかしながら、目標位置への到達が多少阻害されたとしても、挙動の乱れや関節間の回転限界を超えた不自然な姿勢を見せないことの方が重視されるケースも多々あるため、そうしたメリット・デメリットを天秤にかけて、必要な場合には回転角制限をかけることを選択しなければなりません。</p> <h5 id="回転角制限が必要となる事例">回転角制限が必要となる事例</h5> <p>2ボーンIKを適用する事例では、実はそこまで回転角制限が必要になるケースはありません。これは2ボーンIK自体に最初から関節が逆側に曲がらないような回転制限が自動的にかかっているためで、これは2ボーンIKの大きなメリットと言えます。<br />ただ、目標位置の配置によっては2本の関節が伸びきったり曲がったりするような状態、すなわち第2関節の最大角度が180°まで振り切ったり少し戻ったりするようなギリギリの状態になることがあり、そのような状態では目標位置の僅かな移動量に対し角度の変化量が極端に大きくなることから、その急激な挙動変化が不自然な動きとして目立つようになります。このような急激な角度変化の影響を緩和し目立たなくする目的で、最大角度を180°よりも少し小さい値 <a href="#f-90bb8562" name="fn-90bb8562" title="例えば170~175°程度">*13</a> に設定することで関節が完全に伸びきらないように設定しておくことがあります。手足を限界まで伸ばさなくても支障がない、あるいは限界まで伸び切って欲しくない場面ではメリットしかないので試してみてください。</p> <h3 id="2ボーンIKをキャラクターに適用する">2ボーンIKをキャラクターに適用する</h3> <h4 id="エンドエフェクターについて">エンドエフェクターについて</h4> <p>2ボーンIKを人型キャラクターなどに適用する場合は、腕や足に設定することが多いですが、実際に当てはめてみると腕部だと上腕+前腕、脚部だと腿+脛という割り当てになり、手足や足先の関節が対象から外れてしまうので、1ボーン分足りないと感じるかもしれません。実際のゲーム中で位置や姿勢を合わせたいのは手の指先や足先だったり足の裏面だったりするのに、このままではIK処理が合わせるのは手首、足首の位置になってしまうからです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="2ボーンIKの人型キャラクターへの適用例"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183954.png" width="347" height="400" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">2ボーンIKの人型キャラクターへの適用例</figcaption> </figure> <p>IKの位置や姿勢を目標に合わせたい部位のことをエンドエフェクター、あるいは単にエフェクターと呼びます。これは末端効果器という意味で、IKを使って動作させるロボットアームなどの先端に接続されて実際に作業を行う装置を想定していることから、このような呼び方をしています。</p> <p>先程の人型キャラクターの例に話を戻すと、手先や足先の部位がエフェクターに相当することになりますが、このエフェクター部位はIKの計算対象には含まなくて良いのです。<br />あらかじめ何らかの手法で求められているエフェクターの姿勢や位置から逆算して、途中の関節の姿勢や位置を計算するのがIKなので、エフェクターの位置を目標位置として渡してしまえば、IK内ではエフェクターそのものの制御をする必要がないからです。<a href="#f-93401bcf" name="fn-93401bcf" title=" IKで決定した最終位置にエフェクター部位を接続する処理も、IK処理全体の枠組みの中には含まれますが、IKアルゴリズムそのものが解決する内容ではないという意味です。">*14</a></p> <h5 id="エフェクターの目標位置の置き換え">エフェクターの目標位置の置き換え</h5> <p>もう少し具体的に説明すると、もしエフェクターの姿勢があらかじめ固定されているのなら、実際にエフェクターが効果を作用させたい位置とエフェクターの関節位置との相対的な位置関係も固定されていることになります。であれば本来の目標位置から、この相対的な位置差分を引いた位置をIKの目標位置にすれば、エフェクターが作用する位置にも自動的に合うことになります</p> <p>人体で例えれば、手先エフェクターの実際の作用点が指先だった場合は、その時点での指先の位置と手先エフェクターの関節位置との相対的な位置関係を求めておけば良いのです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="エフェクターの作用位置を考慮した目標位置の平行移動"> <div class="images-row mceNonEditable"> <div class="images-row-item"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183922.png" width="721" height="521" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></div> <div class="images-row-item"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183925.png" width="721" height="521" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></div> </div> <figcaption class="mceEditable">エフェクターの作用位置を考慮した目標位置の平行移動</figcaption> </figure> <p>図で説明すると、エフェクターの先端部を本来の目標位置である白のチェッカーマーク位置に合わせたい場合に、エフェクターの位置差分を考慮して得られたピンクのチェッカーマーク位置を2ボーンIKの目標位置として計算することで、エフェクターの先端位置は自動的に白のチェッカーマークに到達するという仕掛けです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="エフェクターの関節位置が目標に到達すると実際の作用位置も自動的に目標に到達する"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183929.png" width="380" height="275" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">エフェクターの関節位置が目標に到達すると実際の作用位置も自動的に目標に到達する</figcaption> </figure> <p>この手法は多くのIKに応用可能で、IK制御が必要な連鎖数を1つ減らすことが可能となります。<a href="#f-0fe0b430" name="fn-0fe0b430" title="エフェクター部位の情報もIK計算に必要な場合は残す必要があります">*15</a></p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="2ボーンIK+エフェクター部位の制御イメージ"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183949.png" width="365" height="400" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">2ボーンIK+エフェクター部位の制御イメージ</figcaption> </figure> <h4 id="疑似3ボーンIK">疑似3ボーンIK</h4> <p>エフェクターの姿勢が固定されたままだと、IKによる姿勢変化が大きくなった時に、親となる第2関節とエフェクターとの間の回転角が極端な状態になることがあります。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="エフェクター部位の関節の角度が極端になった例(左手)"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012184002.png" width="1009" height="450" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">エフェクター部位の関節の角度が極端になった例(左手)</figcaption> </figure> <p>エフェクターの固定姿勢を決める際に、目標位置や対象の状態を見てある程度の変化を付けておいたり、目標位置への到達を多少犠牲にしてでも回転制限の範囲内になるようにエフェクターの姿勢を後から変更する方法も考えられますが、どうせならエフェクター部位もIKに計算させてしまいたいと考えるはずです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="エフェクターもIKに含めて解決した場合"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012184006.png" width="1009" height="450" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">エフェクターもIKに含めて解決した場合</figcaption> </figure> <p>人間の手足のケースならば3ボーンに対応したIKを適用することで解決できそうですが、ここでは2ボーンIKを使って疑似的に3ボーン分のIK処理を実現する手法について紹介します。</p> <h5 id="疑似3ボーンIKの手順">疑似3ボーンIKの手順</h5> <ol> <li>IK適用前の第2関節と第3関節間のローカル回転差分を計算する</li> <li>第3関節の関節位置と先端位置の移動差分を計算する</li> <li>手順2.で求めた移動差分を目標位置から差し引いた位置を新たな目標位置とする</li> <li>第1関節と第2関節に2ボーンIKを適用する</li> <li>手順1.で求めたローカル回転差分を用いて、第3関節の姿勢を再構成<br /> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183933.png" width="300" height="216" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> </li> <li>手順5.で求めた第3関節の姿勢と、第3関節の初期姿勢の中間姿勢を計算し、これを第3関節の姿勢とする <ul> <li>中間姿勢のブレンド率は追加パラメーターとして別途与える必要がある</li> <li>0%だとブレンドターゲット側、100%だと初期姿勢側としてブレンドする</li> </ul> </li> <li>手順6.のブレンド率が100%以外(未満)の場合は、手順2.~4.を再び実行する <a href="#f-d2db0d84" name="fn-d2db0d84" title="100%の場合は、そのままIK処理を終了する">*16</a><br /> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183937.png" width="300" height="216" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> </li> </ol> <p> </p> <p>細かく手順を書きましたが、ざっくり言うと、2ボーンIK計算後に第3関節の姿勢を初期姿勢を使って加工し、目標位置からずれた分を再度2ボーンIKを計算することで解消しています。手順2.~4.は、2ボーンIKで必要となる手順そのものなので、そのまま機能を呼び出せばOKです。</p> <p>ブレンド率の調整で出る結果の幅のサンプルが以下の画像となりますが、この幅は第3関節の初期姿勢だけでなく目標位置の場所によっても広がったり狭まったりします。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="ブレンド率による結果の幅"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183941.png" width="380" height="274" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">ブレンド率による結果の幅</figcaption> </figure> <p>人型キャラクターに適用する時の様にエフェクター部位を第3関節とする場合には、必要なら姿勢を外部から与えて拘束してもいいのですが、通常は元のモーションで得られるFK姿勢をそのまま使えば十分です。下の適用例は疑似3ボーンIKとUp Vector Constraintのみで、Tポーズの状態から1分くらいで適当にポーズ付けしたものです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="疑似3ボーンIK(+Up Vector Constraint)の人型キャラクターへの適用例"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012183958.png" width="312" height="400" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">疑似3ボーンIK(+Up Vector Constraint)の人型キャラクターへの適用例</figcaption> </figure> <h5 id="別バージョン">別バージョン</h5> <p>上の説明では回転差分を用いることで元のFK姿勢とのブレンドを行う方式について説明しましたが、回転差分を用いずに第2関節と同じ姿勢をそのままブレンド対象とするやり方もあるので、設定によって使い分けられるようにしておくと便利です。</p> <p>他にも2ボーンIKの適用後にエフェクター部位の回転制限をかけて目標位置からずれてしまった結果に対して、追加処理で手順2.~4.を適用することで、回転制限もある程度考慮しつつ目標位置に到達するといった簡易方式も考えられます。 <a href="#f-2bc4a19d" name="fn-2bc4a19d" title="その場合、結果として回転制限を突破する可能性もあります">*17</a></p> <h5 id="特徴">特徴</h5> <p>追加で第3関節のブレンド率の設定が必要となることや、2ボーンIKを2回計算することによる処理負荷増の問題はありますが、2ボーンIKの仕組みやメリットを生かしたまま3ボーン分のIK処理が実現できるという点で、導入し易いのではないかと思います。特にエフェクターの先端は目標位置に到達して欲しいけど、姿勢拘束はボチボチで良いという場合に最適です。</p> <p>また、一般的に四足歩行動物の四肢の制御は人間の手足よりも1ボーン多い関節制御が必要となるため、3ボーン以上に対応したIKアルゴリズム+エフェクター部位の制御を行う必要がありますが、この手法を用いることで2ボーンIKの機能しかなくても四足歩行動物の四肢の制御への対応が可能となります。以下は動作サンプルです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="疑似3ボーンIK+エフェクター制御の動作サンプル(前足→後ろ足→ブレンド率制御の様子)"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20221012/20221012184502.gif" width="853" height="480" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">疑似3ボーンIK+エフェクター制御の動作サンプル(前足→後ろ足→ブレンド率制御の様子)</figcaption> </figure> <h3 id="まとめ">まとめ</h3> <p>IKの基本的な概念、基本処理となる1ボーンIKと今でも広範囲で使われている2ボーンIKの具体的な処理内容について説明しました。数学の授業で習った時には何に使うのか今ひとつピンと来なかった余弦定理も、ここではしっかり役に立っています。</p> <p>IKアルゴリズムには他にも様々な手法があり、それぞれ適用できる範囲や得意分野が異なります。また今でも新しいIKアルゴリズムや既存のアルゴリズムの改善の提案が各所で発表されているので、そうした手法についても学ぶきっかけになればと思います。</p> <p>特に昨今は商用ゲームエンジンに標準機能として様々なIK処理が実装されるようになったので、自分でIK処理を新たに作成する機会は減っているかも知れません。それでも自社エンジンやタイトルにIK処理を組み込む事例はまだまだありますし、仮に既に用意されているIKの機能を使うだけであっても、その仕組みや特徴を理解しているのとそうでないのとでは、同じIK機能を使ってるにも関わらずゲーム上での挙動が大きく変わることがあったりするので、IK処理の知識は無駄になりません。</p> <p>今回はIK本体のアルゴリズムを中心に解説しましたが、実際のゲーム制作においては、IKに与える目標位置の取得方法や加工の仕方、各種パラメーターの設定にも工夫が必要となり、最終的な挙動に与える影響度としてはむしろそちらの方が重要だったりもします。今後機会があれば、そういった内容にも触れられれば良いなと思っています。</p> <h3 id="終わりに">終わりに</h3> <p>セガでは商用ゲームエンジンだけでなく自社開発エンジンによるゲーム開発も行われており、開発メンバーとして一緒に働ける仲間を幅広く募集しています。セガでのゲーム開発に興味がある方は、下記サイトにアクセスしてみてください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Frecruit.sega.jp%2F" title="セガ グループ 新卒採用サイト" class="embed-card embed-webcard" scrolling="no" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" loading="lazy" frameborder="0"></iframe><cite class="hatena-citation"><a href="https://recruit.sega.jp/">recruit.sega.jp</a></cite></p> <p>©SEGA</p> <p> </p><div class="footnote"> <p class="footnote"><a href="#fn-e08301b4" name="f-e08301b4" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">+α</span></p> <p class="footnote"><a href="#fn-86528c8e" name="f-86528c8e" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text">この場合は必然的にX軸がロール回転軸となります。</span></p> <p class="footnote"><a href="#fn-4e7b090c" name="f-4e7b090c" class="footnote-number">*3</a><span class="footnote-delimiter">:</span><span class="footnote-text">回転の処理はX軸、Y軸、Z軸それぞれに対して計算する必要があります。1つずつ計算しても良いのですが、通常は行列などを使ってまとめて処理します。</span></p> <p class="footnote"><a href="#fn-83710894" name="f-83710894" class="footnote-number">*4</a><span class="footnote-delimiter">:</span><span class="footnote-text">中学3年で習う「底辺の2乗+高さの2乗=斜辺の2乗」です。</span></p> <p class="footnote"><a href="#fn-724ccef3" name="f-724ccef3" class="footnote-number">*5</a><span class="footnote-delimiter">:</span><span class="footnote-text">これは外積版やクォータニオン版も同様です</span></p> <p class="footnote"><a href="#fn-839beb56" name="f-839beb56" class="footnote-number">*6</a><span class="footnote-delimiter">:</span><span class="footnote-text">1ボーンIK用の目標位置とは別に設定される</span></p> <p class="footnote"><a href="#fn-925f8cda" name="f-925f8cda" class="footnote-number">*7</a><span class="footnote-delimiter">:</span><span class="footnote-text">手順2.で求めたcosX, sinXの式はY軸合せの場合の式なので</span></p> <p class="footnote"><a href="#fn-a15ace7a" name="f-a15ace7a" class="footnote-number">*8</a><span class="footnote-delimiter">:</span><span class="footnote-text">これは他のIKだと非常に面倒な追加処理を要求されます</span></p> <p class="footnote"><a href="#fn-bb25a214" name="f-bb25a214" class="footnote-number">*9</a><span class="footnote-delimiter">:</span><span class="footnote-text">この図では第2関節も一緒に追従させていますが、計算上は第2関節は放置していて問題ありません。</span></p> <p class="footnote"><a href="#fn-56fd4ee7" name="f-56fd4ee7" class="footnote-number">*10</a><span class="footnote-delimiter">:</span><span class="footnote-text">適用前の角度が180°の場合は方向が決められないので、その場合に正負どちらを優先するかは決めておく必要があります。</span></p> <p class="footnote"><a href="#fn-b5d23c8f" name="f-b5d23c8f" class="footnote-number">*11</a><span class="footnote-delimiter">:</span><span class="footnote-text">この処理自体は1ボーンIKにかかるものなので計算手順も同じです。</span></p> <p class="footnote"><a href="#fn-6accdd4e" name="f-6accdd4e" class="footnote-number">*12</a><span class="footnote-delimiter">:</span><span class="footnote-text">余弦定理の式が先程とは違いますが、cについて展開し直しただけです</span></p> <p class="footnote"><a href="#fn-90bb8562" name="f-90bb8562" class="footnote-number">*13</a><span class="footnote-delimiter">:</span><span class="footnote-text">例えば170~175°程度</span></p> <p class="footnote"><a href="#fn-93401bcf" name="f-93401bcf" class="footnote-number">*14</a><span class="footnote-delimiter">:</span><span class="footnote-text"> IKで決定した最終位置にエフェクター部位を接続する処理も、IK処理全体の枠組みの中には含まれますが、IKアルゴリズムそのものが解決する内容ではないという意味です。</span></p> <p class="footnote"><a href="#fn-0fe0b430" name="f-0fe0b430" class="footnote-number">*15</a><span class="footnote-delimiter">:</span><span class="footnote-text">エフェクター部位の情報もIK計算に必要な場合は残す必要があります</span></p> <p class="footnote"><a href="#fn-d2db0d84" name="f-d2db0d84" class="footnote-number">*16</a><span class="footnote-delimiter">:</span><span class="footnote-text">100%の場合は、そのままIK処理を終了する</span></p> <p class="footnote"><a href="#fn-2bc4a19d" name="f-2bc4a19d" class="footnote-number">*17</a><span class="footnote-delimiter">:</span><span class="footnote-text">その場合、結果として回転制限を突破する可能性もあります</span></p> </div> sgtech CEDEC 2022 セガグループによるセッション紹介! hatenablog://entry/4207112889902404277 2022-07-27T10:00:00+09:00 2022-07-27T10:00:02+09:00 今年も日に日に暑さが増し、CEDECが近くなってまいりました。 昨年に続きオンラインで開催されるゲーム業界最大のカンファレンスに、 セガからも多くの社員が登壇します! CEDEC2022 cedec.cesa.or.jp 会期:2022年8月23日(火)~8月25日(木) 今回で7回目となる、セッションと登壇者紹介に加え、ここでしか見れない当日の資料の抜粋チラ見せ付きで株式会社セガ、第3事業部の麓からご紹介致します。 開発もQAも自動テスト!「LOST JUDGMENT:裁かれざる記憶」のQAテスター参加で進化した「テスト自動化チーム(仮)」の取り組みについて セッション内容 講演者 スナップ… <p>今年も日に日に暑さが増し、CEDECが近くなってまいりました。</p> <p>昨年に続きオンラインで開催されるゲーム業界最大のカンファレンスに、</p> <p>セガからも多くの社員が登壇します!</p> <p><strong>CEDEC2022</strong></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2022" title="CEDEC2022" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2022">cedec.cesa.or.jp</a></cite></p> <p>会期:2022年8月23日(火)~8月25日(木)</p> <p>今回で7回目となる、セッションと登壇者紹介に加え、ここでしか見れない当日の資料の抜粋チラ見せ付きで株式会社セガ、第3事業部の麓からご紹介致します。</p> <p> </p> <ul class="table-of-contents"> <li><a href="#開発もQAも自動テストLOST-JUDGMENT裁かれざる記憶のQAテスター参加で進化したテスト自動化チーム仮の取り組みについて">開発もQAも自動テスト!「LOST JUDGMENT:裁かれざる記憶」のQAテスター参加で進化した「テスト自動化チーム(仮)」の取り組みについて</a><ul> <li><a href="#セッション内容">セッション内容</a></li> <li><a href="#講演者">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> </ul> </li> <li><a href="#PSO2-ニュージェネシス長期運営タイトルにおける大規模バージョンアップを支えた開発手法の紹介">『PSO2 ニュージェネシス』長期運営タイトルにおける、大規模バージョンアップを支えた開発手法の紹介</a><ul> <li><a href="#セッション内容-1">セッション内容</a></li> <li><a href="#講演者-1">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> </ul> </li> <li><a href="#PSO2-ニュージェネシスアバターカスタマイズローンチ作業を振り返って">『PSO2 ニュージェネシス』アバターカスタマイズ ローンチ作業を振り返って</a><ul> <li><a href="#セッション内容-2">セッション内容</a></li> <li><a href="#講演者-2">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> </ul> </li> <li><a href="#PSO2-ニュージェネシス今更聞けない広大なフィールドの作り方">『PSO2 ニュージェネシス』今更聞けない!広大なフィールドの作り方</a><ul> <li><a href="#セッション内容-3">セッション内容</a></li> <li><a href="#講演者-3">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> </ul> </li> <li><a href="#PSO2-ニュージェネシスにおけるエフェクトエディタ制作事例">『PSO2 ニュージェネシス』におけるエフェクトエディタ制作事例</a><ul> <li><a href="#セッション内容-4">セッション内容</a></li> <li><a href="#講演者-4">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> </ul> </li> <li><a href="#withコロナ時代ワーキングペアレントの働き方と悩み上司経営者の立場での悩み">withコロナ時代:ワーキングペアレントの働き方と悩み/上司・経営者の立場での悩み</a><ul> <li><a href="#セッション内容-5">セッション内容</a></li> <li><a href="#講演者-5">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> </ul> </li> </ul> <h3 id="開発もQAも自動テストLOST-JUDGMENT裁かれざる記憶のQAテスター参加で進化したテスト自動化チーム仮の取り組みについて">開発もQAも自動テスト!「LOST JUDGMENT:裁かれざる記憶」のQAテスター参加で進化した「テスト自動化チーム(仮)」の取り組みについて</h3> <h5 id="セッション内容"><strong>セッション内容</strong></h5> <p>近年のゲーム開発では、開発規模が拡大するとともに、マルチプラットフォームや多言語対応、多拠点開発(海外・在宅勤務を含む)の必要性が増し、開発スピードや品質の維持のためにテスト自動化の重要性が日々高まっています。一方で、ゲーム開発におけるテスト自動化は、一般的には開発部門またはQA部門の片方が主体となって行われることが多く、どちらかが得意な切り口(単体テスト中心、画像認識によるプレイテスト中心など)に偏りがちです。<br />本講演では、開発部門とQA部門からそれぞれ参加して、一つの「テスト自動化チーム(仮)」を結成し、プログラマもQAテスターも各々の得意分野の自動テストを書くことで、より広範囲かつ効果的なテスト自動化を達成して、開発スピードと品質の向上に貢献した事例について、マルチプラットフォーム・多言語・多拠点開発となった「LOST JUDGMENT:裁かれざる記憶」の実例をもとに、開発部門とQA部門のそれぞれの視点を交えて紹介します。</p> <p> </p> <h5 id="講演者">講演者</h5> <p><strong>株式会社セガ </strong><br /><strong>第1事業部</strong><br /><strong>阪上 直樹</strong></p> <p><br /><strong>プロジェクト業務部<br />門脇 健造<br /><br />開発技術部<br />粉川 貴至<br /></strong></p> <p><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月24日(水) 14:50 〜 15:50 レギュラーセッション</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2022%2Fsession%2Fdetail%2F16" title="CEDEC2022" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2022/session/detail/16">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20220720/20220720185253.png" width="960" height="540" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20220720/20220720185258.png" width="960" height="540" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p> </p> <h3 id="PSO2-ニュージェネシス長期運営タイトルにおける大規模バージョンアップを支えた開発手法の紹介">『PSO2 ニュージェネシス』長期運営タイトルにおける、大規模バージョンアップを支えた開発手法の紹介</h3> <h5 id="セッション内容-1"><strong>セッション内容</strong></h5> <p>『ファンタシースターオンライン2(以下、PSO2)』を運営、開発しながら、『PSO2 ニュージェネシス(以下、PSO2:NGS)』へと大規模にバージョンアップする必要があり、そこで得られた知見、事例を紹介します。</p> <p>・開発環境やデータコンバート手法、自動化の取り組みの紹介<br />・オープンワールドの実装方法とデータ管理手法、最適化事例<br />・『PSO2:NGS』で採用されたグラフィック表現と、『PSO2』アセットに対する互換性の取り組み</p> <h5 id="講演者-1">講演者</h5> <p><strong>株式会社セガ</strong><br /><strong>第3事業部オンライン研究開発プログラム1部</strong><br /><strong>松波 進也</strong><br /><strong>志賀 直秀</strong><br /><strong>小西 一樹</strong></p> <p><span style="color: #000000; font-family: HiraKakuProN-W3, 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月23日(火) 17:30 〜 18:30</span> <span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">レギュラーセッション</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2022%2Fsession%2Fdetail%2F19" title="CEDEC2022" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2022/session/detail/19">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット" style="clear: both; margin: 1em 0px 0.5em; font-size: 14.3px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20220722/20220722180441.png" width="1922" height="1072" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20220722/20220722180456.png" width="1914" height="1070" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p> </p> <h3 id="PSO2-ニュージェネシスアバターカスタマイズローンチ作業を振り返って">『PSO2 ニュージェネシス』アバターカスタマイズ ローンチ作業を振り返って</h3> <h5 id="セッション内容-2"><strong>セッション内容</strong></h5> <p>運営がランニング状況下でのグラフィックエンジン更新に伴い、いかに既存アバターデータを対応させ、新要素を追加したか、そして今後について紹介します。</p> <h5 id="講演者-2">講演者</h5> <p><strong>株式会社セガ</strong><br /><strong>第3事業部オンライン研究開発デザイン1部</strong><br /><strong>池谷 章</strong></p> <p><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月24日(水) 11:20 〜 12:20 レギュラーセッション</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2022%2Fsession%2Fdetail%2F25" title="CEDEC2022" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2022/session/detail/25">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット" style="clear: both; margin: 1em 0px 0.5em; font-size: 14.3px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20220720/20220720190055.png" width="1187" height="670" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20220720/20220720190110.png" width="1191" height="672" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p> </p> <h3 id="PSO2-ニュージェネシス今更聞けない広大なフィールドの作り方">『PSO2 ニュージェネシス』今更聞けない!広大なフィールドの作り方</h3> <h5 id="セッション内容-3"><strong>セッション内容</strong></h5> <p>オンラインRPG『PSO2』が『超PSO2』をコンセプトに旧来のシステムを大幅改修する事で、『PSO2:NGS』として新たに広大なフィールドを実装しました。<br />その開発の中で得た広大なフィールド開発に必要な基本的な知識や概念、Terrainの編集、大量のアセット配置といった具体的手法と合わせて紹介します。</p> <h5 id="講演者-3">講演者</h5> <p><strong>株式会社セガ</strong><br /><strong>第3事業部オンライン研究開発デザイン1部<br />川瀧 智晴</strong></p> <p><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;"><span style="color: #000000; font-family: HiraKakuProN-W3, 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月25日(木) 11:20 〜 12:20</span> <span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">レギュラーセッション</span></span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2022%2Fsession%2Fdetail%2F35" title="CEDEC2022" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2022/session/detail/35">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット" style="clear: both; margin: 1em 0px 0.5em; font-size: 14.3px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20220720/20220720203209.jpg" width="800" height="450" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20220720/20220720203229.jpg" width="800" height="450" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p> </p> <h3 id="PSO2-ニュージェネシスにおけるエフェクトエディタ制作事例">『PSO2 ニュージェネシス』におけるエフェクトエディタ制作事例</h3> <h5 id="セッション内容-4"><strong>セッション内容</strong></h5> <p>『ファンタシースターオンライン2』は『PSO2 ニュージェネシス』へとグラフィックシステムを刷新する超大型アップデートを行いました。<br />それに伴い開発した内製のエフェクトエディタ「Hikari」について紹介します。<br />運営中のオンラインゲームのグラフィックアップデートとして、どのような機能を実装していったか、内製ツール制作によるメリットとデメリットは何だったかをお話できればと思います。</p> <h5 id="講演者-4">講演者</h5> <p><strong>株式会社セガ</strong><br /><strong>第3事業部オンライン研究開発デザイン1部<br />福留 竜介<br />第3事業部オンライン研究開発プログラム1部<br />篠原 広大<br /></strong></p> <p><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;"><span style="color: #000000; font-family: HiraKakuProN-W3, 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月24日(水) 10:00 〜 11:00</span> <span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;"><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">レギュラーセッション</span></span></span><br /><cite class="hatena-citation"></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2022%2Fsession%2Fdetail%2F73" title="CEDEC2022" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2022/session/detail/73">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット" style="clear: both; margin: 1em 0px 0.5em; font-size: 14.3px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20220721/20220721141704.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20220720/20220720210754.png" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p> </p> <h3 id="withコロナ時代ワーキングペアレントの働き方と悩み上司経営者の立場での悩み">withコロナ時代:ワーキングペアレントの働き方と悩み/上司・経営者の立場での悩み</h3> <h5 id="セッション内容-5"><strong>セッション内容</strong></h5> <p>withコロナでリモートワークも普及し、ワーキングペアレントの働き方と悩みは、どのように変わってきたでしょうか?<br />上司、経営者の立場ではどうでしょうか?<br />withコロナ時代を生きる、ワーキングペアレントの働き方と悩みに寄り添い、解決策を探ります。</p> <p>Zoom参加希望者は、事前に、「扱って欲しい議題」「悩み」「相談したいこと」を、CEDEC受講登録後のマイページの当セッション専用申込フォーム内リンクより提出してください。</p> <p>実際にコロナウイルス感染を経験した登壇者、及び経営者・管理職の立場の登壇者がファシリテーターとなり、ラウンドテーブルを進行。事前提出いただいた議題をジャンル分けし、参加者同士でディスカッションします。</p> <p>ゲーム業界全体が、多様な働き方について相談しやすい環境になることを願っており、その話題作りのキッカケとなることを目指しています。</p> <p> </p> <p>※本年はオンライン(ZOOM)でラウンドテーブルのディスカッションへ参加いただけます。<br />参加を希望する場合は、受講パスをご購入のうえマイページの専用申込フォーム(Googleフォーム)よりお申込みください。<br />なお、ディスカッションに参加せず視聴のみの場合、専用フォームからの登録は不要です。<br />ディスカッションへの参加申込みはマイページからお願いいたします。<br /><a href="https://cedec.cesa.or.jp/2022/mypage">https://cedec.cesa.or.jp/2022/mypage</a></p> <p> </p> <h5 id="講演者-5">講演者</h5> <p><strong>セガサミーホールディングス株式会社</strong><br /><strong>総務本部 コミュニケーションサービス部 コミュニケーション推進課</strong><br /><strong>茂呂 真由美<br />ほか</strong></p> <p><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;"><span style="color: #000000; font-family: HiraKakuProN-W3, 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月24日(水) 10:00 〜 11:00</span> <span style="color: #000000; font-family: HiraKakuProN-W3, 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">ラウンドテーブル</span></span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2022%2Fsession%2Fdetail%2F172" title="CEDEC2022" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2022/session/detail/172">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット" style="clear: both; margin: 1em 0px 0.5em; font-size: 14.3px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20220721/20220721100221.jpg" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20220721/20220721100231.jpg" width="1920" height="1080" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p> </p> <p><br /><br />いかがでしょうか?</p> <p style="margin: 0.5em 0px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">今回紹介したなかでぜひ聞きたい!!と思ったセッションはありましたか?<br />今年もCEDECを通して情報収集や交流をし、ゲーム業界の今を知り、業界の未来について語り合いませんか?</p> <p style="margin: 0.5em 0px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">私達は将来CEDECに登壇してみたいと思っている、やる気のある方を求めています。<br />そんなあなた、以下にアクセスおねがいします。</p> <p style="margin: 0.5em 0px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">それでは皆さんCEDECでお会いましょう!</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Frecruit.sega.jp%2F%23" title="セガ グループ 新卒採用サイト" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://recruit.sega.jp/#">recruit.sega.jp</a></cite></p> <p> </p> <p><span style="color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; background-color: #ffffff; float: none; display: inline !important;">※複数社登壇の場合でもセガの社員のみ表記しています </span><br style="color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; background-color: #ffffff;" /><span style="color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; background-color: #ffffff; float: none; display: inline !important;">©SEGA</span></p> sgtech CEDEC 2021 セガグループによるセッション紹介! hatenablog://entry/26006613791217964 2021-07-30T10:00:00+09:00 2021-07-30T10:45:07+09:00 今年もやってきました、毎年恒例のCEDECでのセガグループによるセッション紹介です!株式会社セガ、第3事業部の麓です。 昨年に続きオンラインで開催されるゲーム業界最大のカンファレンス CEDEC2021 cedec.cesa.or.jp https://cedec.cesa.or.jp/2021/ 会期:2021年8月24日(火)~8月26日(木)にグループ(および関連会社)から今年も登壇します!今回で6回目となる、セッションと登壇者紹介に加え、ここでしか見れない当日の資料からの抜粋付きでご紹介します。 プランナーもハックしよう ~業務効率化、ローコード開発とテクニカルプランナー~ セッション… <p>今年もやってきました、毎年恒例のCEDECでのセガグループによるセッション紹介です!<br />株式会社セガ、第3事業部の麓です。</p> <p>昨年に続きオンラインで開催されるゲーム業界最大のカンファレンス</p> <p><strong>CEDEC2021</strong></p> <p> </p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2021%2F" title="CEDEC2021" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2021/">cedec.cesa.or.jp</a></cite></p> <p><a href="https://cedec.cesa.or.jp/2021/">https://cedec.cesa.or.jp/2021/</a></p> <p>会期:2021年8月24日(火)~8月26日(木)<br />にグループ(および関連会社)から今年も登壇します!<br />今回で6回目となる、セッションと登壇者紹介に加え、ここでしか見れない当日の資料からの抜粋付きでご紹介します。</p> <p> </p> <ul class="table-of-contents"> <li><a href="#プランナーもハックしよう-業務効率化ローコード開発とテクニカルプランナー">プランナーもハックしよう ~業務効率化、ローコード開発とテクニカルプランナー~</a><ul> <li><a href="#セッション内容">セッション内容</a></li> <li><a href="#講演者">講演者</a></li> <li><a href="#スナップショット-1">スナップショット</a></li> </ul> </li> <li><a href="#AndroidiOS-実機上での自動テストをより楽に有意義にする為に-端末管理イメージ転送動画記録等の周辺情報のノウハウ共有">Android/iOS 実機上での自動テストをより楽に有意義にする為に ~端末管理・イメージ転送・動画記録等の周辺情報のノウハウ共有~</a><ul> <li><a href="#セッション内容-1">セッション内容</a></li> <li><a href="#講演者-1">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> </ul> </li> <li><a href="#進化したSympathyPSO2NGSが奏でるインタラクティブミュージック">進化したSympathy:『PSO2:NGS』が奏でるインタラクティブミュージック</a><ul> <li><a href="#セッション内容-2">セッション内容</a></li> <li><a href="#講演者-2">講演者</a></li> </ul> </li> <li><a href="#それどれだけ売れるのキャラクターIPソシャゲにおけるIP商品力の定量化と取り組み">「それ、どれだけ売れるの?」キャラクターIPソシャゲにおけるIP商品力の定量化と取り組み</a><ul> <li><a href="#セッション内容-3">セッション内容</a></li> <li><a href="#講演者-3">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> </ul> </li> <li><a href="#ダウンロード時間を大幅減大量のアセットをさばく高速な実装と運用事例の共有">ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~</a><ul> <li><a href="#セッション内容-4">セッション内容</a></li> <li><a href="#講演者-4">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> </ul> </li> <li><a href="#ゲーム業界の男性育児休業職場復帰の実態リモートワークでの育児両立の難しさと働き方3社事例紹介">ゲーム業界の男性育児休業~職場復帰の実態。リモートワークでの育児両立の難しさと働き方。3社事例紹介。</a><ul> <li><a href="#セッション内容-5">セッション内容</a></li> <li><a href="#講演者-5">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> </ul> </li> <li><a href="#リモートワークでどうなったワーキングペアレントの働き方と悩み">リモートワークでどうなった?!ワーキングペアレントの働き方と悩み</a><ul> <li><a href="#セッション内容-6">セッション内容</a></li> <li><a href="#講演者-6">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> </ul> </li> <li><a href="#メタバースにおける飲用体験システムの開発VRShaker">メタバースにおける飲用体験システムの開発:VRShaker</a><ul> <li><a href="#セッション内容-7">セッション内容</a></li> <li><a href="#講演者-7">講演者</a></li> </ul> </li> </ul> <h3 id="プランナーもハックしよう-業務効率化ローコード開発とテクニカルプランナー">プランナーもハックしよう ~業務効率化、ローコード開発とテクニカルプランナー~</h3> <h5 id="セッション内容"><strong>セッション内容</strong></h5> <p>本セッションでは実務においてプランナーが行った業務効率化の例をご紹介します。<br />その際に利用した、プランナーでもできる自動化としてローコード開発の紹介も行います。<br />これらの取り組みを通じて、雑務や人力の仕事が多いプランナー業の改革と、将来の新たなプランナー像であるテクニカルプランナーのキャリアパスを提起します。</p> <p> </p> <h5 id="講演者">講演者</h5> <p><strong>株式会社セガ </strong><br /><strong>ゲームコンテンツ&サービス事業本部 第4事業部開発2部</strong><br /><strong>瀧澤 翼</strong><br /><strong>リードプランナー</strong></p> <p><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月25日(水) 13:30 〜 13:55 ショートセッション</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2021%2Fsession%2Fdetail%2Fs605ab6ba8934c" title="プランナーもハックしよう ~業務効率化、ローコード開発とテクニカルプランナー~ " class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2021/session/detail/s605ab6ba8934c">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット-1"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210708/20210708131251.jpg" alt="f:id:sgtech:20210708131251j:plain" width="2000" height="1125" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210708/20210708131245.jpg" alt="f:id:sgtech:20210708131245j:plain" width="2000" height="1124" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p> </p> <h3 id="AndroidiOS-実機上での自動テストをより楽に有意義にする為に-端末管理イメージ転送動画記録等の周辺情報のノウハウ共有">Android/iOS 実機上での自動テストをより楽に有意義にする為に ~端末管理・イメージ転送・動画記録等の周辺情報のノウハウ共有~</h3> <h5 id="セッション内容-1"><strong>セッション内容</strong></h5> <p>当講演では、Android/iOS 向けタイトルにおける、オンプレミスで動作する実機上での自動テスト環境構築・運用時に得たノウハウについて共有します。<br />中でも一般的に言及が少ない、自動テスト環境を構築するのに必要な"周辺情報"にフォーカスして解説を行います。<br />"周辺情報"とは、テスト実行そのものやテストフレームワーク"以外"の以下の内容を指します。</p> <p>・端末の管理や情報の取得<br />iOS 端末の IP アドレスを取得するにはどうしたらいいか等。<br />・アプリケーションイメージの転送や起動<br />iOS のアプリケーションイメージをコマンドラインで実機に転送・起動するのはどうすればいいのか等。<br />・実機上の映像の動画撮影<br />Android/iOS 実機上でゲームの映像を録画する場合それにはどんな手段があってそれぞれのメリットデメリットは何があるか等。<br />・テスト結果の取得と整形、通知</p> <p>その他、環境構築後の運用時に発生した問題とその解決方法の共有も行います。<br />当講演を通じ、 Android/iOS 実機上で自動テストやってみようかな、と思う人が少しでも増えれば嬉しく思います。</p> <h5 id="講演者-1">講演者</h5> <p><strong>株式会社セガ</strong><br /><strong>開発技術部</strong><br /><strong>竹原 涼</strong><br /><strong>廣島 岳史</strong></p> <p>08月25日(水) 14:50 〜 15:50 <span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">レギュラーセッション</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2021%2Fsession%2Fdetail%2Fs605aefc9b1fd9" title="Android/iOS 実機上での自動テストをより楽に有意義にする為に ~端末管理・イメージ転送・動画記録等の周辺情報のノウハウ共有~ " class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2021/session/detail/s605aefc9b1fd9">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット" style="clear: both; margin: 1em 0px 0.5em; font-size: 14.3px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210720/20210720210755.png" alt="f:id:sgtech:20210720210755p:plain" width="2000" height="1125" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210720/20210720210814.png" alt="f:id:sgtech:20210720210814p:plain" width="2000" height="1125" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <h3 id="進化したSympathyPSO2NGSが奏でるインタラクティブミュージック">進化したSympathy:『PSO2:NGS』が奏でるインタラクティブミュージック</h3> <h5 id="セッション内容-2"><strong>セッション内容</strong></h5> <p>『ファンタシースター』シリーズの最新作『ファンタシースターオンライン2 ニュージェネシス』(通称:PSO2:NGS)では、『PSO2』で構築した既存のBGMシステム「Sympathy」をベースにして、新たな要素、機能を追加した新システム「Sympathy2.0」を制作致しました。そこに至る過程について、システム設計からツールのバージョンアップ、実装例までをご紹介できればと思います。</p> <h5 id="講演者-2">講演者</h5> <p><strong>株式会社セガ</strong><br /><strong>ゲームコンテンツ&サービス事業本部 第2事業部 サウンドセクション</strong><br /><strong>小林 秀聡</strong><br /><strong>サウンドディレクター・サウンドクリエイター</strong></p> <p><strong>ゲームコンテンツ&サービス事業本部 第3事業部 第3開発1部 第3プログラムセクション</strong><br /><strong>増田 亮</strong><br /><strong>リードプログラマー</strong></p> <p><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月26日(木) 14:50 〜 15:50 レギュラーセッション</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2021%2Fsession%2Fdetail%2Fs605878c150301" title="進化したSympathy:『PSO2:NGS』が奏でるインタラクティブミュージック " class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2021/session/detail/s605878c150301">cedec.cesa.or.jp</a></cite></p> <h3 id="それどれだけ売れるのキャラクターIPソシャゲにおけるIP商品力の定量化と取り組み">「それ、どれだけ売れるの?」キャラクターIPソシャゲにおけるIP商品力の定量化と取り組み</h3> <h5 id="セッション内容-3"><strong>セッション内容</strong></h5> <p>本セッションでは、キャラクターIPを使用したソーシャルゲームにおけるIP商品(=販売するキャラクター)の商品力を客観的に把握するための運営上の取り組みについてご紹介します。<br />キャラクターIPを使用したソーシャルゲームの運営には、事業上大きな課題があります。それは売上がその時々に販売するIP商品力に影響され適切な運営の弊害になるというリスクです。まずこの運営リスクについてご説明します。<br />次に、課題解決の取り組みとして、リスクを低減するため「商品力」を定量的に把握する試みについてご説明します。主に個人の売上データを用いた定量化するためのクリアすべき具体的な課題と統計的分析手法を用いた対策方法について解説します。<br />また、定量化した商品力指標の運営上の利用例を紹介します。</p> <h5 id="講演者-3">講演者</h5> <p><strong>株式会社セガ</strong></p> <p><strong>戦略支援部</strong><br /><strong>柴宮 朋和</strong><br /><strong>ビジネス&amp;データ分析1課 課長代行 / データアナリストスペシャリスト</strong></p> <p><strong>第4開発2部</strong><br /><strong>川上普史</strong><br /><strong>マネージャー/運営リーダー</strong></p> <p><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月25日(水) 11:50 〜 12:15 ショートセッション</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2021%2Fsession%2Fdetail%2Fs605aed6428e2e" title="「それ、どれだけ売れるの?」キャラクターIPソシャゲにおけるIP商品力の定量化と取り組み " class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2021/session/detail/s605aed6428e2e">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット" style="clear: both; margin: 1em 0px 0.5em; font-size: 14.3px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210720/20210720210551.png" alt="f:id:sgtech:20210720210551p:plain" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210720/20210720210603.png" alt="f:id:sgtech:20210720210603p:plain" width="1280" height="720" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <h3 id="ダウンロード時間を大幅減大量のアセットをさばく高速な実装と運用事例の共有">ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~</h3> <h5 id="セッション内容-4"><strong>セッション内容</strong></h5> <p>近年、モバイルゲームの規模も大規模化しており、そのアセットデータのダウンロードに掛かる時間も増大する傾向にあります。<br />弊社では、アセットデータのダウンロード待ち時間を HTTP/2 を採用することにより低減することに成功しました。<br />当講演では、この HTTP/2 の仕様のゲーム開発者向け解説とモバイル向けタイトルでの導入・運用事例を紹介します。<br />仕様の解説では、 HTTP/2 を採用すると何故ダウンロード時間の低減が可能なのかに加え、クライアントサーバ間の通信の効率化に寄与する点についても触れます。<br />導入事例では、具体的にアセットダウンロードがどれだけ高速になったかの実例も併せて紹介を行います。<br />運用事例については、HTTP/2 はゲーム業界においてはまだ事例紹介が少なく枯れ切っていない面も多くある為、採用したタイトルの運用中に実際に発生したトラブルとその解決方法について特に時間を掛けて紹介を行う予定です。</p> <h5 id="講演者-4">講演者</h5> <p><strong>株式会社セガ</strong><br /><strong>開発技術部</strong><br /><strong>竹原 涼</strong></p> <p><strong>山田 英伸</strong></p> <p><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月25日(水) 11:20 〜 12:20 レギュラーセッション</span><br /><cite class="hatena-citation"></cite></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2021%2Fsession%2Fdetail%2Fs605af068b50a2" title="ダウンロード時間を大幅減!~大量のアセットをさばく高速な実装と運用事例の共有~ " class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2021/session/detail/s605af068b50a2">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット" style="clear: both; margin: 1em 0px 0.5em; font-size: 14.3px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210720/20210720210850.png" alt="f:id:sgtech:20210720210850p:plain" width="2000" height="1125" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210720/20210720210905.png" alt="f:id:sgtech:20210720210905p:plain" width="2000" height="1125" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <h3 id="ゲーム業界の男性育児休業職場復帰の実態リモートワークでの育児両立の難しさと働き方3社事例紹介">ゲーム業界の男性育児休業~職場復帰の実態。リモートワークでの育児両立の難しさと働き方。3社事例紹介。</h3> <h5 id="セッション内容-5"><strong>セッション内容</strong></h5> <p>2020年より、ゲーム業界でもリモートワークが恒常化してきました。<br />その中で、ワーキングペアレントの働き方はどのように変わったでしょうか?<br />新たに生まれた課題は何でしょうか?</p> <p>「仕事への影響・不安」を持ちながらも、育児休業を取得し、職場復帰した登壇者たちが、「男性育児休業の実態」と、「リモートワークでの育児両立の難しさと働き方」をテーマに、3社の事例を紹介します。</p> <p>厚生労働省が発表している「男性の育児休業取得促進等に関する参考資料集」を元に、「制度の説明」「取得方法」を冒頭で紹介。<br />その後、本セッション用にゲーム業界各社で取った最新の「男性の育児休業~復帰後の働き方(リモート含む)アンケート」についての共有を行います。</p> <p><2021年版アンケートのご協力をお願いいたします><br />●【男性育休アンケート】対象者:「取得経験者」「取得しなかった方」「非該当者(性別問わず)」⇒それぞれのご意見をお聞かせください</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fdocs.google.com%2Fforms%2Fd%2Fe%2F1FAIpQLSffPzMyQ6hsNU9u84DSAuWzeWFRcPJFJoDzsjAHeS2YLmRAxA%2Fviewform" title="CEDEC2021「男性育休アンケート」  <8/8(日)〆切>" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://docs.google.com/forms/d/e/1FAIpQLSffPzMyQ6hsNU9u84DSAuWzeWFRcPJFJoDzsjAHeS2YLmRAxA/viewform">docs.google.com</a></cite></p> <p>・「上司」「経営者」の立場からの意見、考え方も、一例としてお伝えいたします。<br />・各社社内コミュニティの紹介や、オンライン環境での活動状況もお話しいたします。</p> <p> </p> <h5 id="講演者-5">講演者</h5> <p>セガサミーホールディングス株式会社</p> <p>総務本部 コミュニケーションサービス部 コミュニケーション推進課<br />茂呂 真由美</p> <p>株式会社セガ</p> <p>ゲームコンテンツ&サービス事業本部 第3事業部 第3開発1部 第3プログラムセクション<br />増田 亮<br />リードプログラマー</p> <p>ゲームコンテンツ&サービス事業本部第4事業部戦略支援部ビジネス&amp;データ分析2課<br />竹内 公紀<br />データアナリスト/課長代行</p> <p>ゲームコンテンツ&サービス事業本部第4事業部第4開発2部第一ソフト開発セクション<br />渡邉 吉治<br />リードプログラマー</p> <p>ほか</p> <p><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月24日(火) 11:20 〜 12:20 パネルディスカッション</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2021%2Fsession%2Fdetail%2Fs6064daaf0e1a7" title="ゲーム業界の男性育児休業~職場復帰の実態。リモートワークでの育児両立の難しさと働き方。3社事例紹介。 " class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2021/session/detail/s6064daaf0e1a7">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット" style="clear: both; margin: 1em 0px 0.5em; font-size: 14.3px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210720/20210720211123.png" alt="f:id:sgtech:20210720211123p:plain" width="2000" height="1125" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <h3 id="リモートワークでどうなったワーキングペアレントの働き方と悩み">リモートワークでどうなった?!ワーキングペアレントの働き方と悩み</h3> <h5 id="セッション内容-6"><strong>セッション内容</strong></h5> <p>Zoom参加者は、「扱って欲しい議題」「悩み」「相談したいこと」を、CEDEC受講登録後のマイページの当セッション専用申込フォーム内「アンケートリンク」より、事前提出してください。</p> <p>事前提出いただいた議題を取り上げ、「3つのパート」に分け、ディスカッションします。「リモートワーク下での悩み・議題」を優先して取り上げますが、それ以外でも、「課題感が大きい」「議論の必要性が高い」と判断したものは、議題に取り上げさせていただきます。</p> <p>●ディスカッション<1>(茂呂)<br />事前アンケートで「多かった悩み」「気になった悩み」をピックアップして進行</p> <p>●ディスカッション<2>(竹内)<br />「育児休業~復帰後に関して」「男性特有の悩み」をピックアップして進行</p> <p>●ディスカッション<3>(佐々木)<br />「当人以外の職場の仲間・管理職・人事総務・経営者等」の議題をピックアップして進行</p> <p>今回の受講をその場限りのものにせず、それぞれの職場に今回の知見を持ち帰り、共有していただけると嬉しいです。<br />ゲーム業界全体が、多様な働き方について相談しやすい環境になることを願っており、その話題作りのキッカケとなるセッションになることを目指しています。</p> <p> </p> <h5 id="講演者-6">講演者</h5> <p>セガサミーホールディングス株式会社</p> <p>総務本部 コミュニケーションサービス部 コミュニケーション推進課<br />茂呂 真由美</p> <p>株式会社セガ</p> <p><br />ゲームコンテンツ&サービス事業本部第4事業部戦略支援部ビジネス&amp;データ分析2課<br />竹内 公紀<br />データアナリスト/課長代行</p> <p>ほか</p> <p><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月24日(火) 13:30 〜 14:30 ラウンドテーブル</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2021%2Fsession%2Fdetail%2Fs6064ddcfc2bc6" title="リモートワークでどうなった?!ワーキングペアレントの働き方と悩み " class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2021/session/detail/s6064ddcfc2bc6">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット" style="clear: both; margin: 1em 0px 0.5em; font-size: 14.3px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210720/20210720211213.png" alt="f:id:sgtech:20210720211213p:plain" width="2000" height="1125" loading="lazy" title="" class="hatena-fotolife" itemprop="image" /></p> <p><br /><br /></p> <h3 id="メタバースにおける飲用体験システムの開発VRShaker">メタバースにおける飲用体験システムの開発:VRShaker</h3> <h5 id="セッション内容-7"><strong>セッション内容</strong></h5> <p>現実空間での飲用、喫食体験は人間関係を形成する上で重要な物の一つと言えるだろう。しかし、近年の社会状況からそれらの体験が難しい物となっている。<br />そこで、自宅にいながら、遠隔地の人と共にバーで他の人に作ってもらったカクテルを味わう体験ができるシステム:VRShakerを製作した。<br />バーテンダーのカクテルシェイク動作をトラッキングし、現実世界の遠隔地にあるVRShaker筐体がカクテルシェイカーをシェイクする。体験者は構築されたメタバース上で呑みながら会話をすることができる。<br />本セッションでは、コロナウィルスと共生しなければならない現代においてメタバースを用いた喫食体験とその可能性について議論する。</p> <h5 id="講演者-7">講演者</h5> <p>株式会社セガ</p> <p>アミューズメントコンテンツ開発生産本部 メダル研究開発部<br /> 鈴木 謙太</p> <p>ほか</p> <p><span style="color: #000000; font-family: '\ヒラギノ角ゴProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">08月26日(木) 11:20 〜 11:45</span></p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2021%2Fsession%2Fdetail%2Fs60645c7724553" title="メタバースにおける飲用体験システムの開発:VRShaker " class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2021/session/detail/s60645c7724553">cedec.cesa.or.jp</a></cite></p> <p> </p> <p style="margin: 0.5em 0px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">いかがでしょうか?</p> <p style="margin: 0.5em 0px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">今回紹介したセッションで聴講したい!と思ったセッションはありましたか?<br />CEDECを聴講して情報収集や交流をし、ゲーム業界の今を知り、業界の未来について語り合いませんか?<br />それでは皆さんCEDECでお会いましょう!</p> <p style="margin: 0.5em 0px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"> </p> <p style="margin: 0.5em 0px; color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">私達は将来CEDECに登壇してみたいと思っている、やる気のある方を求めています。<br />そんな貴方、以下にアクセスしてみませんか?</p> <p> </p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Frecruit.sega.jp%2F%23" title="セガ グループ 新卒採用サイト" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://recruit.sega.jp/#">recruit.sega.jp</a></cite></p> <p> </p> <p><span style="color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; background-color: #ffffff; float: none; display: inline !important;">※複数社登壇の場合でもセガの社員のみ表記しています </span><br style="color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; background-color: #ffffff;" /><span style="color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; background-color: #ffffff; float: none; display: inline !important;">©SEGA</span></p> sgtech クォータニオンとは何ぞや?:基礎線形代数講座 hatenablog://entry/26006613770903509 2021-06-15T10:00:00+09:00 2022-07-15T22:34:10+09:00 ---【追記:2022-04-01】--- 「基礎線形代数講座」のPDFファイルをこの記事から直接閲覧、ダウンロードできるようにしました。記事内後半の「公開先」に追記してあります。 --- 【追記ここまで】--- みなさん、はじめまして。技術本部 開発技術部のYです。 ひさびさの技術ブログ記事ですが、タイトルからお察しの通り、今回は数学のお話です。 #数学かよ って思った方、ごめんなさい(苦笑) 数学の勉強会 弊社では昨年、有志による隔週での数学の勉強会を行いました。ご多分に漏れず、コロナ禍の影響で会議室に集合しての勉強会は中断、再開の目処も立たず諸々の事情により残念ながら中止となり、用意した資料の配布および各自の自学ということになりました。 <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script> <script> MathJax = { chtml: { matchFontHeight: false }, tex: { inlineMath: [['$', '$']] } }; </script> <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script> <p>---【追記:2022-04-01】---</p> <p>「基礎線形代数講座」のPDFファイルをこの記事から直接閲覧、ダウンロードできるようにしました。記事内後半の「公開先」に追記してあります。</p> <p>--- 【追記ここまで】---</p> <p>みなさん、はじめまして。技術本部 開発技術部のYです。</p> <p>ひさびさの技術ブログ記事ですが、タイトルからお察しの通り、今回は数学のお話です。</p> <p>#数学かよ って思った方、ごめんなさい(苦笑)</p> <h4>数学の勉強会</h4> <p>弊社では昨年、有志による隔週での数学の勉強会を行いました。ご多分に漏れず、コロナ禍の影響で会議室に集合しての勉強会は中断、再開の目処も立たず諸々の事情により残念ながら中止となり、用意した資料の配布および各自の自学ということになりました。</p> <p>勉強会の内容は、高校数学の超駆け足での復習から始めて、主に大学初年度で学ぶ線形代数の基礎の学び直し 、および応用としての3次元回転の表現の基礎の理解といった感じです。</p> <p>「線形代数」とは、微積分と並び理工系の科学・技術の諸分野で基礎中の基礎として用いられる数学の分野で、ゲームでは主に3DCGの技術的基礎として応用されています。昨今のAIブームでも一時期話題になりました。 タイトルにある「クォータニオン」とは、日本語では「四元数」と訳され、ゲームではキャラや背景などを3次元回転させるときに応用されるもので、勉強会の中では最後に出てくるラスボスであり少し難しい数学の概念です。</p> <p>勉強会の趣旨は、この「クォータニオン」を数学的にきちんと理解することを <s>えさ</s> ゴールとして、そのために(実際はそれだけでなくさまざまな技術の基礎となっている)「線形代数」の基礎をきちんと学び直そうということでした。</p> <h4>なぜ数学?</h4> <p>ゲーム開発においても分業化・専業化の流れは著しく、ゲームアプリケーション(みなさんに遊んで頂いているゲームそのもの)を開発する際、いわゆるゲームエンジンや各種ライブラリを用いるのが当たり前になっています。これらエンジンやライブラリは、ゲーム開発者にさまざまな機能を提供し効率よく開発できるようにすることが役割であり、極端な話、三角関数を全く知らなくても3Dゲームを作れる時代になっています。 しかしながら例えばゲーム固有の表現のためにシェーダー(画面を描画する機能)をカスタマイズしたい場合や、当然のことながらエンジンやライブラリそのものの開発者は、ある程度のさまざまな数学の知識が必要となります。技術的に高度なことをしようと思うとなおさら深い理解が必要です。</p> <p>このように数学や物理学は、ゲーム業界のみならず理工系のさまざまな分野で、科学者・技術者を根元から支える基礎となり重要な武器となっています。</p> <h4>資料を公開します</h4> <p>今回、この勉強会用に用意した資料「基礎線形代数講座:線形代数 回転の表現」を一般に公開いたします。全8講、本文が全部で140ページのPDFで、各講は以下のような標題です。</p> <ul> <li>第1講 イントロダクション</li> <li>第2講 初等関数</li> <li>第3講 ベクトル</li> <li>第4講 行列 I:連立一次方程式</li> <li>第5講 行列 II:線形変換</li> <li>第6講 行列 III:固有値・対角化</li> <li>第7講 回転の表現 I</li> <li>第8講 回転の表現 II</li> </ul> <p>線形代数 基礎の本質的な部分をできるだけ簡潔に分かりやすく学べるように全体を組み立ててみました。各項目を学ぶ順番や手法、一部は定義すら一般的なものと違う(例:行列式)こともあります 。いわゆる「大人の学び直し」ではあるのですが、内容はガチの数学となっています。 記事の最後に公開先へのリンクを張っておきますので、興味のある方は参考にして頂ければと思います。</p> <p>特に学生の方で、この資料で線形代数を学んでみようと思われた奇特な方がいらっしゃれば、言うまでもないことですが読んだ後改めて講義で指定されている教科書を読んでみましょう。きっとこれまで以上に理解が深まることと思います。</p> <p>この記事では、その中から「クォータニオン」の導入部分である、第8講の第2節までをそのまま引用します。導入部なので内容は平易となっていますが、複素数・行列・三角関数に関するある程度の知識がないと理解は難しいと思われます。ぜひ紙と鉛筆を用意して、ご自身でも図や式を書いたり計算したりしながら、じっくり読んでみてください。</p> <h3>基礎線形代数講座からの引用</h3> <CENTER><B><BIG><U> 【第8講】回転の表現II </U></BIG></B></CENTER> <p> <br></p> <p><B>【8-1】はじめに </B></p> <p style="padding-left:1em"> 本講では、4種の3次元回転の表現の最後としてクォータニオンについて学ぶ。クォータニオンは日本語では四元数(しげんすう)と訳されるもので、1843年にハミルトンにより発見された複素数を拡張した代数体系であり、3次元の回転の表現としても多くの利点を備えている。<br> その性質から特に計算機を用いる場合にも他の表現手法に比べ優位な点が多く、近年 宇宙機を始め、3DCGやCV、ロボット工学等々さまざまな分野で応用されている。一方で他の表現手法に比べるとやや抽象的でその本質(<u>4次元空間に埋め込まれた3次元回転</u>)が捉えづらい面も否めない。本講では、拡張の元になった大きさ1の複素数の積による複素平面内での回転の復習から始め、ハミルトンによる発見に至るまでの過程<a href="#f-b9c42e97" name="fn-b9c42e97" title="あくまで筆者の想像(妄想)による過程であり、史実に基づいたものではありません。">*1</a>をたどる事でクォータニオンを導入し、その性質を分かりやすく解説する。<br> <BR> <br> ●おさらい <br> 任意の複素数 $ x+iy $ に大きさ $ 1 $ の複素数 $ \cos\theta+i \sin\theta $ を掛ける事は複素平面内での $ \theta $ 回転を表していた。実際 \[ (x'+iy')=(\cos\theta+i\sin\theta)(x+iy)=(x\cos\theta-y\sin\theta)+i(x\sin\theta+y\cos\theta ) \] この式で、$ 1 $ と $ i $ をベクトルの基底としてみると、 \[ x→x'=x\cos\theta-y\sin\theta,\ y→y'=x\sin\theta+y\cos\theta \] という線形変換と見ることができて、行列形式で書けば \[ \begin{eqnarray} \left[ \begin{array}{c} x' \\ y' \\ \end{array} \right]=\left[ \begin{array}{cc} \cos\theta & -\sin\theta\\ \sin\theta & \cos\theta\\ \end{array} \right] \left[ \begin{array}{c} x \\ y \\ \end{array} \right] \end{eqnarray} \] となり、すなわち複素平面である $ 1-i $ 平面での $ \theta $ 回転を表している事がわかる。<BR> <BR> これの本質は、$ i $を掛けるという事:基底 1 と $ i $ との閉じた代数が、$ 1-i $ 平面内で一回りする回転に相当していることにある。<BR> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210601/20210601193226.png" width="2000" height="669" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:160px" itemprop="image"></span> <BR> </p> <p><BR> <B>【8-2】クォータニオンの導入:ハミルトン劇場</B></p> <p style="padding-left:1em"> <B>[8-2-1] 拡張複素数で複素( 3次元)空間を回したい</B> </p> <p style="padding-left:2em"> ハミルトンは複素数を拡張して、虚数単位 $ i $ の他に独立な別の虚数単位 $ j $ を導入 $( i^2=-1,\ j^2=-1,\ \overline {i}=-i,\ \overline {j}=-j)$、$ 1,i,j $ の 3つの元で $ 1-i $平面、$ 1-j $平面、$ i-j $平面それぞれの回転を表現できないか?と考えた(つまり複素平面を複素空間に拡張できないか?ってこと) 。<BR> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210601/20210601193336.png" width="880" height="828" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:160px" itemprop="image"></span> <BR> </p> <p style="padding-left:3em"> 「独立な異なる虚数単位 $ i,j $」に違和感がある人もいると思う。新しい代数として拡張していっているので、うまく拡張できさえすればあとは「慣れ」ではあるのだが「複素数」を以下のように解釈することで別の虚数単位を導入するという拡張も違和感が減るかもしれない。<BR> おさらい<a href="#f-7b72a952" name="fn-7b72a952" title="詳細は第5講 付録2参照">*2</a>:2行 2列の行列 $ \begin{eqnarray} I= \left[ \begin{array}{cc} 0 & -1\\ 1 & 0\\ \end{array} \right] \end{eqnarray} $ を考えると(この行列は 上の おさらいで出てきた 2次の 回転行列で $ \theta=\pi/2 $ としたものでもあることに注意)、 $ \begin{eqnarray} I^2= \left[ \begin{array}{cc} -1 & 0\\ 0 & -1\\ \end{array} \right] = -E \end{eqnarray} $ ( $ E $ は単位行列 )となる(つまり 2乗して -1)。また行列 $ Z=xE+yI\ (x,y∈\Bbb R ) $ を考えると、 $ \begin{eqnarray} Z = \left[ \begin{array}{cc} x & -y\\ y & x\\ \end{array} \right] \end{eqnarray} $ なので、$ Z = O $ となるのは $ x=y=0 $ のときのみ(つまり $ E $ と $ I $ は線形独立)。この行列 $ Z=xE+yI $ に対し $ E $ を $ 1, I $ を $ i $ に対応させることで、複素数 $ z=x+iy $ に対応させる事が可能となる。<BR> ここでさらに別の行列 例えば $ \begin{eqnarray} J = \left[ \begin{array}{cc} 1 & -\sqrt{2}\\ \sqrt{2} & -1\\ \end{array} \right] \end{eqnarray} $ を考えると、$ J^2=-E $ を満たし、この $ J $ を含め $ E,I,J $ が線形独立であることは容易に確かめられる。このような「複素数の拡張」(上の $ J $ の事)がうまく行くかどうかは別にして「違和感」のない表現もやろうと思えば可能ではある。<BR> </p> <p><BR></p> <p style="padding-left:2em"> 以下、ハミルトンがクォータニオンを発見するまでの過程<a href="#f-7d099d6f" name="fn-7d099d6f" title="くどいですが、筆者による想像(妄想)です">*3</a>をたどってみよう。<BR> ハミルトン:$ 1-i $平面と $ 1-j $平面の回転は当然できた。<BR> <BR> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210601/20210601193421.png" width="2000" height="895" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:160px" itemprop="image"></span> <BR> でも $ i-j $平面がうまくいかない。<u> $ i\times j $ の扱いがどうにもこうにも…</u><BR> とりあえず $ i\times j $ を $ ij $ として回るようにはできたけど<a href="#f-f8d9aa91" name="fn-f8d9aa91" title=" $ 𝑖\times 𝑖𝑗=𝑖^2𝑗=−𝑗 $ ってこと">*4</a>、この $ ij $ って本来 $ i $ にならないと $ i-j $平面にはならない。でも $ ij = i $ としてしまうと $ i $ を掛けても $ -j $ にならずに $ -1 $ となってうまく回らない。どうしたものか・・・<BR> (ちなみに後に別の数学者により、このような $ 1,i,j $ による 「複素数の拡張」(三元数に相当)は、うまく行かない事が証明されている。)<BR> </p> <p><BR></p> <p style="padding-left:1em"> <B>[8-2-2] 4次元? マジか 4次元??</B> </p> <p style="padding-left:2em"> ある日運河のほとりを歩いている時(実話<a href="#f-13f18836" name="fn-13f18836" title="運河を渡る橋に $ 𝑖^2=𝑗^2=𝑘^2=𝑖𝑗𝑘=−1 $ と刻んだとの事">*5</a>)にひらめいた:<u> もう一つ虚数単位を導入して $ i\times j=k $ </u>としてみよう。実数単位 $ 1 $ と虚数単位 $ i,j,k $ で 4次元になるけど、うまくいくかも・・・<BR> 回転面は $ 1-i, 1-j, 1-k $平面, $ i-j, j-k, k-i $平面の6面になるのか。3次元回転をうまく取り出すには、$ i-j, j-k, k-i $平面の回転がこんな風になるといいのかな?<BR> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210601/20210601193503.png" width="707" height="725" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:160px" itemprop="image"></span> <BR><BR> ●$ i $ を掛けると?:想定図のように $ j-k $平面を回すため、$ ij=k $ としてみよう </p> <p style="padding-left:3em"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210601/20210601193724.png" width="2000" height="690" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:160px" itemprop="image"></span> <BR> お、$ j-k $平面だけでなく $ 1-i $平面も同時に回るんだ。そりゃそうか。しかもそれぞれの平面内で回りそうだ。<BR> 角度 $ \theta $ の場合として「大きさ」1の $ (\cos \theta+ i \sin \theta) $ を、4次元に拡張した「複素数」$ (w+ix+jy+kz) $ に( $ i^2=-1,\ ij=k, \ ik=-j $ に注意して)掛けてみよう:<BR> \[ \eqalign{ (w'+ix'+jy'+kz')=(\cos\theta&+i\sin\theta)(w+ix+jy+kz)\\<BR> =&w\cos\theta+ix\cos\theta+jy\cos\theta+kz\cos\theta\\ &+iw\sin\theta-x\sin\theta+ky\sin\theta-jz\sin\theta\\ =&(w\cos\theta-x\sin\theta)+i(w\sin\theta+x\cos\theta)\\ &+j(y\cos\theta-z\sin\theta)+k(y\sin\theta+z\cos\theta) \tag{8-2-1}\\ } \]<BR> 確かに $ w-x $平面( $ 1-i $平面:下から2行目)と $ y-z $平面( $ j-k $平面:下から1行目)がそれぞれの平面内 で同時に別々に回っている<a href="#f-095143a1" name="fn-095143a1" title="ちなみに 4次元では 2本の直交する基底で張られる (回転 )面を、基底を共有せずに 2面とることが できる( 3次元ではできない)。この場合 $ 1−𝑖 $平面 と $ 𝑗−𝑘 $平面 は原点のみで交わっている事に注意。">*6</a>。<BR> <center> <table border="1"> <tr> <th>つまりこういうこと</th> </tr> <tr><td> \begin{eqnarray} \left[ \begin{array}{c} w' \\ x' \\ y' \\ z' \\ \end{array} \right]=\left[ \begin{array}{cccc} \cos\theta & -\sin\theta & 0 & 0\\ \sin\theta & \cos\theta & 0 & 0\\ 0 & 0 & \cos\theta & -\sin\theta\\ 0 & 0 & \sin\theta & \cos\theta\\ \end{array} \right] \left[ \begin{array}{c} w \\ x \\ y \\ z \\ \end{array} \right] \end{eqnarray} </td></tr> </table> </center> </p> <p><BR></p> <p style="padding-left:2em"> ●$ j $ を掛けると?:想定図のように $ k-i $平面を回すため、$ jk=i $ としてみよう </p> <p style="padding-left:3em"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210601/20210601193756.png" width="2000" height="666" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:160px" itemprop="image"></span> <BR> およ。さっきの $ i $ を掛けて $ j-k $平面をうまく回せる条件:$ i\times j=k $ と合わせると、$ ij=k,\ ji=-k $ となって、なんと積は可換じゃなくなる! まあしょうがないか…。<BR> <BR> 角度 $\theta$ だと同様に:<BR> \[ \eqalign{ (\cos\theta&+j\sin\theta)(w+ix+jy+kz)\\ =&(w\cos\theta-y\sin\theta)+j(w\sin\theta+y\cos\theta)\\ &+k(z\cos\theta-x\sin\theta)+i(z\sin\theta+x\cos\theta) \tag{8-2-2}\\ } \]<BR> ん、これも別々に回っている。<BR> <BR> </p> <p style="padding-left:2em"> ●残り $ k $ を掛けると?:想定図のように $ i-j $平面を回すため、$ ki=j $ としてみよう </p> <p style="padding-left:3em"> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210601/20210601193844.png" width="2000" height="699" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:160px" itemprop="image"></span> <BR> これも角度 $\theta$ だと同様に:<BR> \[ \eqalign{ (\cos\theta&+k\sin\theta)(w+ix+jy+kz)\\ =&(w\cos\theta-z\sin\theta)+k(w\sin\theta+z\cos\theta)\\ &+i(x\cos\theta-y\sin\theta)+j(x\sin\theta+y\cos\theta) \tag{8-2-3}\\ } \]<BR> </p> <p style="padding-left:2em"> ●とりあえず分かったこと </p> <p style="padding-left:3em"> 虚数単位 $ i,j,k $ に対して積を $ ij=k, ji=-k, jk=i, kj=-i, ki=j, ik=-j $ として $ w+ix+jy+kz $ に左から $ \cos\theta+i\sin\theta $ を掛けると、$ 1-i $平面, $ j-k$平面が同時に $ \theta $ 回転 する。$ j,k $ で回しても同様。でもこのままだと$ 1-i $平面で余計な回転が発生し、最終的に実現したい純粋な 3次元の回転を切り出せない。何かうまい方法はないのだろうか?<BR> <center> <table border="1"> <tr> <th>つまりこうなって欲しい</th> </tr> <tr><td> \begin{eqnarray} \left[ \begin{array}{c} w' \\ x' \\ y' \\ z' \\ \end{array} \right]=\left[ \begin{array}{cccc} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & \cos\theta & -\sin\theta\\ 0 & 0 & \sin\theta & \cos\theta\\ \end{array} \right] \left[ \begin{array}{c} w \\ x \\ y \\ z \\ \end{array} \right] \end{eqnarray} </td></tr> </table> </center> </p> <p><BR></p> <p style="padding-left:2em"> ●そういえば非可換だった<a href="#f-bacdecd3" name="fn-bacdecd3" title="ハミルトン卿ご自身は、この積の非可換性(当時初?)あまりお気に召さなかったらしい">*7</a> </p> <p style="padding-left:3em"> 非可換なので、右から掛けたらどうなる?<BR> 右から $ i $ を掛けた場合:<BR> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210601/20210601193947.png" width="2000" height="742" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:160px" itemprop="image"></span> <BR> なんと $ 1-i $平面は同じ向きで、$ j-k $平面は逆向きに回る!じゃあ $ -i $ だとその逆になるだろう。<BR> <BR> 右から $ -i $ を掛けた場合:<BR> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210601/20210601194024.png" width="2000" height="627" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:160px" itemprop="image"></span> <BR> これなら、左から $ i $ を、右から $ (-i) $ を掛けることで $ 1-i $平面の回転だけを無くせそう。<BR> </p> <p><BR></p> <p style="padding-left:2em"> ●というわけで </p> <p style="padding-left:3em"> 左から $ i $ 右から $ -i $ を掛けた場合:<BR> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20210601/20210601194059.png" width="2000" height="618" loading="lazy" title="" class="hatena-fotolife hatena-fotolife-height-only" style="height:160px" itemprop="image"></span> <BR> $ j-k $平面は2倍回りそうだけどw やってみよう。<BR> \[ \eqalign{ (\cos\theta&+i\sin\theta)(w+ix+jy+kz)(\cos\theta-i\sin\theta)\\ =&(\cos\theta+i\sin\theta)\{(w\cos\theta+x\sin\theta)+i(-w\sin\theta+x\cos\theta)\\ &+j(y\cos\theta-z\sin\theta)+k(y\sin\theta+z\cos\theta)\}\\ =&w\cos^2\theta+x\sin\theta\cos\theta-(-w\sin^2\theta+x\sin\theta\cos\theta)\\ &+i(-w\sin\theta\cos\theta+x\cos^2\theta)+j(y\cos^2\theta-z\sin\theta\cos\theta)\\ &+k(y\sin\theta\cos\theta+z\cos^2\theta)+i(w\sin\theta\cos\theta+x\sin^2\theta)\\ &+k(y\sin\theta\cos\theta-z\sin^2\theta)-j(y\sin^2\theta+z\sin\theta\cos\theta)\\ =&w(\cos^2\theta+\sin^2\theta)+ix(\cos^2\theta+\sin^2\theta)\\ &+j\{y(\cos^2\theta-\sin^2\theta)-z(2\sin\theta\cos\theta)\}\\ &+k\{y(2\sin\theta\cos\theta)+z(\cos^2\theta-\sin^2\theta)\}\\ =&w+ix+j(y\cos2\theta-z\sin2\theta)+k(y\sin2\theta+z\cos2\theta)\tag{8-2-4} } \] <BR> 最後は倍角の公式を使った。これで $ j-k $平面 だけを回せた!<BR> めでたしめでたし。2倍回るけどw<BR> </p> <center> <table border="1"> <tr> <th>こうなった</th> </tr> <tr><td> \begin{eqnarray} \left[ \begin{array}{c} w' \\ x' \\ y' \\ z' \\ \end{array} \right]=\left[ \begin{array}{cccc} 1 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & \cos2\theta & -\sin2\theta\\ 0 & 0 & \sin2\theta & \cos2\theta\\ \end{array} \right] \left[ \begin{array}{c} w \\ x \\ y \\ z \\ \end{array} \right] \end{eqnarray} </td></tr> </table> </center> <p><BR></p> <p style="padding-left:3em"> ・・・ハミルトン劇場 終<BR> </p> <p><BR></p> <h3></h3> <p>このあと第8講は</p> <ul> <li>【8-3】クォータニオン:定義と諸性質</li> <li>【8-4】クォータニオン:3次元回転の表現</li> <li>【8-5】 [▼]付録 1:一般的な4次元の回転について</li> <li>【8-6】付録2:成分表示における4次元内積の不変性について</li> <li>【8-7】 [▼A]付録 3:オイラーの公式と代数的補間式 について</li> </ul> <p>と続きます・・・。</p> <h4>公開先</h4> <p>--- 【追記:2022-04-01】 ---</p> <p>PDFファイルは以下のリンク先でも閲覧、ダウンロードできます。</p> <p><a href="https://drive.google.com/file/d/1vU7BCI1arG_ZyUYkAEvLi1LH1ou0pULu/view?usp=sharing" target=top><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20220406/20220406024044.png" alt="f:id:sgtech:20220406024044p:plain" width="227" height="322" loading="lazy" title="" class="hatena-fotolife" itemprop="image"><figcaption>基礎線形代数講座20210615.pdf - Google ドライブ</figcaption></a></p> <p>--- 【追記ここまで】 ---</p> <p>--- 【更新:2022-07-15】---</p> <p>「基礎線形代数講座」は、開発技術部の技術資料一般公開先でもある、Speaker Deck サイトにて公開しています。</p> <p>#技術資料一般公開先サイトを Speaker Deck に引っ越しました</p> <iframe class="speakerdeck-iframe" style="border: 0px none; background: rgba(0, 0, 0, 0.1) none repeat scroll 0% 0% padding-box; margin: 0px; padding: 0px; border-radius: 6px; box-shadow: rgba(0, 0, 0, 0.2) 0px 5px 40px; width: 560px; height: 792px;" src="https://speakerdeck.com/player/943c3cc8f0674d489fc9255445efe647" title="基礎線形代数講座" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true" data-ratio="0.7070707070707071" frameborder="0"></iframe> <p>--- 【更新ここまで】 ---</p> <p>--- 各項目は以下のような内容となっています。</p> <p>【第1講】イントロダクション</p> <p> 【1-1】はじめに</p> <p> 【1-2】数学導入:数の拡張</p> <p>  [1-2-1] 自然数 ℕ:全てはここから</p> <p>  [1-2-2] 整数 ℤ:0の発見、負の数の導入</p> <p>  [1-2-3] 有理数 ℚ :分数・小数の導入</p> <p>  [1-2-4] 実数 ℝ:無理数の導入</p> <p>  [1-2-5] 複素数 ℂ:虚数の導入</p> <p>  [1-2-6] まとめ</p> <p> 【1-3】付録:ギリシャ文字一覧</p> <p>【第2講】初等関数</p> <p> 【2-1】はじめに</p> <p> 【2-2】指数・対数関数</p> <p>  [2-2-1] 指数関数の定義と性質</p> <p>  [2-2-2] 対数関数の定義と性質</p> <p>  [2-2-3] 自然対数と自然指数</p> <p>  [2-2-4] 応用例</p> <p> 【2-3】三角関数</p> <p>  [2-3-1] 三角関数の定義と性質</p> <p>  [2-3-2] 三角関数の主な公式</p> <p>  [2-3-3] ド・モアブルの定理</p> <p>  [2-3-4] 応用例</p> <p> 【2-4】指数関数の別定義</p> <p> 【2-5】[▼A] オイラーの公式</p> <p> 【2-6】付録1:二項定理(二項展開)</p> <p> 【2-7】付録2:総和記号</p> <p> 【2-8】付録3:sinθ/θ→ 1 (θ→ 0) の証明</p> <p> 【2-9】付録4:三角関数の各公式の証明</p> <p>【第3講】ベクトル</p> <p> 【3-1】はじめに</p> <p> 【3-2】ベクトルがもつ性質</p> <p>  [3-2-1] ベクトル自体がもつ性質</p> <p>  [3-2-2] ベクトルの組がもつ性質</p> <p> 【3-3】内積</p> <p>  [3-3-1] 定義</p> <p>  [3-3-2] 代数的性質</p> <p>  [3-3-3] 幾何学的意味</p> <p> 【3-4】抽象化されたベクトルの概念と例</p> <p> 【3-5】外積</p> <p>  [3-5-1] 定義</p> <p>  [3-5-2] 代数的性質</p> <p>  [3-5-3] 幾何学的意味</p> <p> 【3-6】n本のベクトルが張るn次元体積</p> <p>  [3-6-1] 2次元:2次元体積(面積)</p> <p>  [3-6-2] 3次元:3次元体積(体積)</p> <p>  [3-6-3] n次元:n次元体積</p> <p> 【3-7】付録1:Levi-Civita記号</p> <p>  [3-7-1] Levi-Civita記号 (3次の場合)</p> <p>  [3-7-2] 拡張Levi-Civita記号 (n次の場合)</p> <p> 【3-8】付録2:外積の公式の証明</p> <p> 【3-9】付録3:置換と転倒数の偶奇性</p> <p>【第4講】行列I:連立一次方程式</p> <p> 【4-1】はじめに</p> <p> 【4-2】掃き出し法</p> <p>  [4-2-1] 連立一次方程式の加減法による解法</p> <p>  [4-2-2] 掃き出し法と行基本変形</p> <p>  [4-2-3] 不定解、解なしとなる場合</p> <p>  [4-2-4] 連立一次方程式の違う見かた</p> <p> 【4-3】行列式の導入</p> <p>  [4-3-1] あらためて「関数」D(a,b,c) とは</p> <p>  [4-3-2] 行列式の定義</p> <p>  [4-3-3] 行列式の性質 I</p> <p> 【4-4】行列の導入</p> <p>  [4-3-1] 導入小話:もしかすると行列って・・・・</p> <p>  [4-4-2] 行列と演算の定義</p> <p>  [4-4-3] 行列の基本性質</p> <p>  [4-4-4] 連立一次方程式の行列による表示</p> <p> 【4-5】付録1:行列式の重要な性質</p> <p> 【4-6】付録2:簡約行列の構造</p> <p> 【4-7】付録3:補足説明</p> <p> 【4-8】付録4:行列式の定義について</p> <p>【第5講】行列II:線形変換</p> <p> 【5-1】はじめに</p> <p> 【5-2】線形変換(一次変換)</p> <p>  [5-2-1] 線形変換の例</p> <p> 【5-3】逆行列</p> <p>  [5-3-1] 行列式の性質II:余因子展開と積の行列式</p> <p>  [5-3-2] 逆行列の定義と余因子行列による表示</p> <p>  [5-3-3] 正則行列/逆行列の性質</p> <p> 【5-4】直交行列</p> <p>  [5-4-1] 転置行列の性質</p> <p>  [5-4-2] 直交行列の定義と性質</p> <p> 【5-5】線形変換の行列による表示</p> <p>  [5-5-1] この節のねらい</p> <p>  [5-5-2] 必要な諸定義</p> <p>  [5-5-2] ベクトルの列ベクトルによる表示</p> <p>  [5-5-3] ベクトルの組の行列による表示</p> <p>  [5-5-4] 線形変換の行列による表示</p> <p>  [5-5-5] 基底の変換と座標変換</p> <p>  [5-5-6] 線形変換に対する基底の変換と表示行列の変換</p> <p>  [5-5-7] 線形変換と座標変換(ActiveとPassive)</p> <p>  [5-5-8] 合成変換の行列による表示</p> <p> 【5-6】[▼C]付録1:Levi-Civita記号の積の性質</p> <p> 【5-7】付録2:複素数の行列による表現</p> <p>【第6講】行列III:固有値・対角化</p> <p> 【6-1】はじめに</p> <p> 【6-2】固有ベクトルと固有値</p> <p>  [6-2-1] 線形変換の点の「向きの流れ」</p> <p>  [6-2-2] 固有ベクトル・固有値と固有方程式</p> <p> 【6-3】行列の対角化</p> <p>  [6-3-1] 線形独立な固有ベクトルへの基底の変換</p> <p>  [6-3-2] 対角化可能な条件</p> <p>  [6-3-3] 相似変換</p> <p>  [6-3-4] 行列の三角化</p> <p>  [6-3-5] 固有値の諸性質</p> <p> 【6-4】実対称行列の対角化</p> <p>  [6-4-1] 実対称行列の固有値・固有ベクトル</p> <p>  [6-4-2] グラム・シュミットの正規直交化法</p> <p>  [6-4-3] 実対称行列の対角化</p> <p>  [6-4-4] 実二次形式</p> <p> 【6-5】応用例</p> <p>  [6-5-1] 剛体回転におけるオイラーの定理</p> <p>  [6-5-2] 漸化式と特性方程式</p> <p>  [6-5-3] [▼B] フーリエ級数展開</p> <p>  [6-5-4] 行列指数関数</p> <p> 【6-6】付録1:複素ベクトル空間・行列について</p> <p> 【6-7】付録2:各証明</p> <p> 【6-8】[▼A]付録3:オイラーの公式の行列表現</p> <p>【第7講】回転の表現I</p> <p> 【7-1】はじめに</p> <p> 【7-2】回転行列</p> <p>  [7-2-1] 考察の定式化</p> <p>  [7-2-2] 表示行列としての回転行列</p> <p> 【7-3】オイラー角と仲間たち</p> <p>  [7-3-1] 回転後の基底の姿勢を3つの回転角で表す</p> <p>  [7-3-2] オイラー角</p> <p>  [7-3-3] Tait-Bryan角</p> <p>  [7-3-4] ジンバルロック</p> <p> 【7-4】回転ベクトル</p> <p>  [7-4-1] 定義とロドリゲスの回転公式</p> <p>  [7-4-2] 回転行列による表示</p> <p>  [7-4-3] 回転行列の固有値・固有ベクトル</p> <p>  [7-4-4] 3次元回転の大域的な構造</p> <p> 【7-5】付録1:回転変換に関する2証明</p> <p> 【7-6】[▼A,C]付録2:3次回転行列となる行列指数関数</p> <p>【第8講】回転の表現II</p> <p> 【8-1】はじめに</p> <p> 【8-2】クォータニオンの導入:ハミルトン劇場</p> <p>  [8-2-1] 拡張複素数で複素(3次元)空間を回したい</p> <p>  [8-2-2] 4次元? マジか4次元??</p> <p> 【8-3】クォータニオン:定義と諸性質</p> <p>  [8-3-1] 定義</p> <p>  [8-3-2] スカラー+ベクトル表記</p> <p>  [8-3-3] ベクトル部の性質</p> <p>  [8-3-4] ノルム・逆元と積の性質</p> <p>  [8-3-5] 単位クォータニオンと極形式</p> <p>  [8-3-6] 4次元ベクトルとしての内積</p> <p> 【8-4】クォータニオン:3次元回転の表現</p> <p>  [8-4-1] 任意軸まわりの回転</p> <p>  [8-4-2] 3次元回転の合成</p> <p>  [8-4-3] 回転行列による表示</p> <p>  [8-4-4] 単位クォータニオンのパラメータ領域</p> <p>  [8-4-5] 球面線形補間</p> <p> 【8-5】[▼]付録1:一般的な4次元の回転について</p> <p> 【8-6】付録2:成分表示における4次元内積の不変性について</p> <p> 【8-7】[▼A]付録3:オイラーの公式と代数的補間式について</p> <p>--- </p> <p>セガでは共に技術力を高め合い研鑽していける方を募集しています。 興味がある方は下記サイトにアクセスして下さい。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Frecruit.sega.jp%2F" title="セガ グループ 新卒採用サイト" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://recruit.sega.jp/">recruit.sega.jp</a></cite></p> <div class="footnote"> <p class="footnote"><a href="#fn-b9c42e97" name="f-b9c42e97" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">あくまで筆者の想像(妄想)による過程であり、史実に基づいたものではありません。</span></p> <p class="footnote"><a href="#fn-7b72a952" name="f-7b72a952" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text">詳細は第5講 付録2参照</span></p> <p class="footnote"><a href="#fn-7d099d6f" name="f-7d099d6f" class="footnote-number">*3</a><span class="footnote-delimiter">:</span><span class="footnote-text">くどいですが、筆者による想像(妄想)です</span></p> <p class="footnote"><a href="#fn-f8d9aa91" name="f-f8d9aa91" class="footnote-number">*4</a><span class="footnote-delimiter">:</span><span class="footnote-text"> $ 𝑖\times 𝑖𝑗=𝑖^2𝑗=−𝑗 $ ってこと</span></p> <p class="footnote"><a href="#fn-13f18836" name="f-13f18836" class="footnote-number">*5</a><span class="footnote-delimiter">:</span><span class="footnote-text">運河を渡る橋に $ 𝑖^2=𝑗^2=𝑘^2=𝑖𝑗𝑘=−1 $ と刻んだとの事</span></p> <p class="footnote"><a href="#fn-095143a1" name="f-095143a1" class="footnote-number">*6</a><span class="footnote-delimiter">:</span><span class="footnote-text">ちなみに 4次元では 2本の直交する基底で張られる (回転 )面を、基底を共有せずに 2面とることが できる( 3次元ではできない)。この場合 $ 1−𝑖 $平面 と $ 𝑗−𝑘 $平面 は原点のみで交わっている事に注意。</span></p> <p class="footnote"><a href="#fn-bacdecd3" name="f-bacdecd3" class="footnote-number">*7</a><span class="footnote-delimiter">:</span><span class="footnote-text">ハミルトン卿ご自身は、この積の非可換性(当時初?)あまりお気に召さなかったらしい</span></p> </div> sgtech アーケードゲームを支えるデバッグ術 hatenablog://entry/26006613656523176 2020-11-25T10:00:00+09:00 2020-11-25T10:00:09+09:00 ブログ読者のみなさん、はじめまして。株式会社セガのベテランプログラマー阿部です。 このエントリーではデバッグ手法のあれこれについての体験談と、デバッグをテーマに一昨年に実施されたプログラマー向け新人研修の概要をお伝えしたいと思います。 EXE ファイルのデバッグ イーサネット絡みのデバッグ 周辺機器絡みのデバッグ デバッグスキルブートキャンプ 黒子に徹する、裏方系エンジニア EXE ファイルのデバッグ 同僚が作った EXE ファイルが手元にあり、あなたはこれを Windows で起動しようとしています。起動してみたところ何も反応がなく、しかもそれは想定外のことでした。「何コレ、動かないんだけど… <p>ブログ読者のみなさん、はじめまして。<br />株式会社セガのベテランプログラマー阿部です。</p> <p>このエントリーではデバッグ手法のあれこれについての体験談と、デバッグをテーマに一昨年に実施されたプログラマー向け新人研修の概要をお伝えしたいと思います。</p> <ul class="table-of-contents"> <li><a href="#EXE-ファイルのデバッグ">EXE ファイルのデバッグ</a></li> <li><a href="#イーサネット絡みのデバッグ">イーサネット絡みのデバッグ</a></li> <li><a href="#周辺機器絡みのデバッグ">周辺機器絡みのデバッグ</a></li> <li><a href="#デバッグスキルブートキャンプ">デバッグスキルブートキャンプ</a></li> <li><a href="#黒子に徹する裏方系エンジニア">黒子に徹する、裏方系エンジニア</a></li> </ul> <h3 id="EXE-ファイルのデバッグ">EXE ファイルのデバッグ</h3> <p>同僚が作った EXE ファイルが手元にあり、あなたはこれを Windows で起動しようとしています。<br />起動してみたところ何も反応がなく、しかもそれは想定外のことでした。<br />「何コレ、動かないんだけど」とあなたが同僚に文句を伝えると、同僚はあなたに返します。<br />「こっちでは動いてるよ」</p> <p> </p> <p>困りましたね。<br />あなたの手元には EXE のソースコードも無ければ、Visual Studio もありません。<br />こんな時、どうするのが正解でしょうか?</p> <p>実はこんな状況でもやれる事がいくつかあるんです。<br />わたしなら <strong>プロセスのメモリダンプ </strong>を取って、同僚に渡します。</p> <p> </p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="プロセスダンプの取得方法(Windows 10 / 8.1 / 8 / 7 / Windows Server 2008)" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fsupport.kaspersky.co.jp%2Fcommon%2Fdiagnostics%2F12401" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><br /></cite></p> <p>プロセスダンプがあれば、同僚はプログラムがどこまで進んだのかを Visual Studio で把握することができるようになるのです。<br />プロセスダンプの取得は <strong>ツール不要で Windows デスクトップから操作可能 </strong>なので、この方法は一番気軽に試せることでしょう。</p> <p> </p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="プロセスダンプの取得"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20201124/20201124210821.png" alt="f:id:sgtech:20201124210821p:plain" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">プロセスダンプの取得</figcaption> </figure> <p>あるいはその前に Sysinternals Suite に含まれる DebugView の出力を確認してみると、プログラムに埋め込まれた OutputDebugString() から 何らかの手掛かりが得られるかもしれません。<br />もし EXE ファイルと PDB ファイルが揃っていて 別の PC 開発環境があるなら、イーサネット経由でリモートデバッガをアタッチしても良いでしょう。<br />PDB ファイルが無いとしても 仮に EXE が .NET アセンブリなのであれば、ILSpy などの逆アセンブラーが使えるかもしれません。</p> <p> </p> <p><strong>こういう知識は「持っているかどうか」がとても重要 </strong>で、仕事の速いプログラマーほど よりたくさんの手段を自然と身に着けているような気がしています。<br />社内には SYS ファイル(デバイスドライバー)をデバッグできるプログラマーとかもいて、もうリスペクトしかないです。</p> <h3 id="イーサネット絡みのデバッグ">イーサネット絡みのデバッグ</h3> <p>ネットワーク上のゲームサーバーと通信するクライアントプログラムを書いて、これをアーケードゲーム機で起動させたとします。<br /><strong>ゲームサーバーとの通信が「たまに成功しないことがある」</strong>という場合は、どうデバッグしたら良いのでしようか?</p> <p>近年のアーケードゲーム機は PC アーキテクチャーをベースに設計されることも多く、セガでも Windows を搭載した機種が多数リリースされています。<br />コピーガードやリバースエンジニアリング防止を目的として、多くのアーケードゲーム機ではデスクトップ画面を開くことはできず、ネットワーク経由でのログインやプロセスへのアタッチもできません(外界からは <strong>ロックダウン </strong>されています)。</p> <p> </p> <p>「たまに失敗」という場合は、ソースコードレビューで判明するバグがあるとは考えにくいです。<br />そこでわたしなら、 <strong>イーサネットを流れるイーサフレームを Wireshark でパケットキャプチャーする </strong>ことから始めてみます。</p> <p> </p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="フレームの測定"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20201124/20201124210834.png" alt="f:id:sgtech:20201124210834p:plain" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">フレームの測定</figcaption> </figure> <p><br />イーサネットを観測することで、最初にまず以下を見極められると期待しています。</p> <ul> <li>ケース1: 想定通りにパケットが流れていない(送信失敗)</li> <li>ケース2: 想定外のパケットが流れている</li> <li>ケース3: 想定通りのパケットが流れている(送信成功)</li> </ul> <p>その結果、クライアントのコードが悪いのか、OS 側スタックのネットワーク設定が悪いのか、上流のネットワークが悪いのかを絞り込める、という算段です。</p> <p> </p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="問題を切り分ける"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20201124/20201124210838.png" alt="f:id:sgtech:20201124210838p:plain" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">問題を切り分ける</figcaption> </figure> <p><br />なお <strong>「上流のネットワークが悪い」という結果だった場合は、キャプチャーの測定範囲を変更して 問題の機器を特定</strong> していきます。<br />過去には、全国ゲームセンターにあるルーターが原因ということもありました。</p> <blockquote> <p>ルーターが IP パケットのチェックサムを再計算するときに、特定条件下で計算ミスが起こるため、<br />ルーターのさらに上位にあるネットワーク機器でパケットがドロップされていた</p> </blockquote> <p>というもので、本来ならばルーターファームウェアを修正し更新版を配信することになります。</p> <p> </p> <p>通信エラーだけではありません。<br />TCP 通信において <strong>「スループットが足りない」という場合、ここでもパケットキャプチャーから始めるのは良い選択の1つ</strong> です。<br />測定結果から、次に挙げるような点検箇所がいくつか見つかることでしょう。</p> <ul> <li>SYN パケットに時間が掛かっている<br />→ コネクションプールを導入するか、セッションクローズしないプロトコルを採用する</li> <li>リクエストからレスポンスまでの間隔が圧倒的に長い<br />→ サーバー処理でスワップアウトやスロークエリが発生していないか確認する</li> </ul> <h3 id="周辺機器絡みのデバッグ">周辺機器絡みのデバッグ</h3> <p>広く使われている <strong>キャラクター表示器 </strong>は、シリアルポートから送信されたアスキー文字や SJIS をドットマトリクスとして表示してくれます。</p> <p> </p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="キャラクター表示器(VFD)"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20201124/20201124210830.png" alt="f:id:sgtech:20201124210830p:plain" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">キャラクター表示器(VFD)</figcaption> </figure> <p>ある日「キャラクター表示器の表示がおかしい」という報告をもらって現地確認に行くと、見慣れない文字列が確かに表示されていました。<br />プログラムから制御しているというのに、 <strong>プログラム内に存在しない文字列が表示されてしまうのはおかしい</strong> ですね。<br />この表示器を含めて、多くは RS232C という低速でレガシーなシリアルポートを使って接続しています。<br />RS232C 通信は物理層での冗長性に乏しいため、ひょっとすると外的要因でポートに電気的なノイズが乗ってしまい、パケットが化けてしまったのかもしれません。</p> <p> </p> <p>ということで早速 RS232C を測定しました。<br />RS232C の測定には <strong>ロジックアナライザーという測定機器を使います</strong> 。<br />RS232C 接続を構成するラインをプローブすれば、各ラインの Hi/Lo をタイミングチャートとして確認できるようになります。</p> <p> </p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="研修で使用した ZEROPLUS 製 ロジックアナライザー"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20201124/20201124210826.png" alt="f:id:sgtech:20201124210826p:plain" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">研修で使用した ZEROPLUS 製 ロジックアナライザー</figcaption> </figure> <figure class="figure-image figure-image-fotolife mceNonEditable" title="測定結果のタイミングチャート"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20201124/20201124210842.png" alt="f:id:sgtech:20201124210842p:plain" title="" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">測定結果のタイミングチャート</figcaption> </figure> <p>実際測定してみると、タイミングチャート上はプログラムからの出力がそのまま反映されており、異常な部分は見つかりませんでした(結局その後の調査で 別の原因が見付かりました)。</p> <p> </p> <p>同じ手法は USB 機器にも使えます。<br />USB 機器の場合は USB 対応のプロトコルアナライザーを導入することもできます(実は USBPcap + Wireshark という別の選択肢もあります)。</p> <p>ゲームセンターに設置されるアーケードゲームは、ゲームパッドに縛られない、多彩なユーザーインターフェースが特徴の1つになっています。<br />さらにユーザーインターフェースだけでなく、キャビネット上の電飾や可動部のモーターなど さまざまな周辺機器がつながっており、それらをすべてプログラムで制御しています。<br />そういった周辺機器としては、既製品を採用することもあれば、新規に設計することもあります。<br />ここにもデバッグの機会が大いにあります。</p> <h3 id="デバッグスキルブートキャンプ">デバッグスキルブートキャンプ</h3> <p>ここまでいくつか紹介したように、「プログラムのデバッグに使えるもの」にはツール(ソフトウェア)だけでなく、測定機器(ハードウェア)も重要な一端を担っていることが理解いただけたかと思います。<br />また大学や専門学校などで <strong>「プログラミングをマスターする機会」はあっても、「デバッグをマスターする機会」は無いのが実情 </strong>です。</p> <p>わたしが所属する技術本部では、これらの背景を踏まえてプログラマー向け新人研修が実施されました。<br />デバッグスキルにフォーカスしたハンズオン研修、題して「デバッグスキルブートキャンプ」です。</p> <p>学生時代に触れる機会が少ないであろう測定機器にも触れながら <strong>バグを正しく観測する技術 </strong>を習得し、 <strong>printf デバッグ </strong>だけでは決して成し得ない、バグの根本原因に辿り着く <strong>貴重な体験を重視としたカリキュラム</strong> になっています。</p> <p> </p> <p>開催形態は以下の通り。<br />他の新人研修とは異なり、新人プログラマーが実務に少し馴染んだ年末年始に開催されています。</p> <ul> <li>ハンズオン重視: 当日フラっとやってきて学べればよい</li> <li>予習・宿題は原則ナシ: 「座学 20min、ハンズオン 75min」とか「座学 10min、ハンズオン 45min」とか</li> <li>開催時期はプロジェクト配属後6か月後から</li> <li>開催ペースは毎週1回、計9回(9ネタ)ほど</li> </ul> <p> </p> <p>本来なら社内に広く展開して必修化した方が社員みんなの為になるのですが、測定機材の都合もあって一部組織内での開催にとどまっているのが現状のようです。<br />各回資料は社内公開されていますが、そのうち一冊の本に体系化されたらイイなと密かに期待しています。</p> <p><br /><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20201124/20201124210850.jpg" alt="f:id:sgtech:20201124210850j:plain" title="" class="hatena-fotolife" itemprop="image" width="300" /><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20201124/20201124210854.jpg" alt="f:id:sgtech:20201124210854j:plain" title="" class="hatena-fotolife" itemprop="image" width="300" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20201124/20201124210845.jpg" alt="f:id:sgtech:20201124210845j:plain" title="" class="hatena-fotolife" itemprop="image" width="299" /></p> <p> </p> <h3 id="黒子に徹する裏方系エンジニア">黒子に徹する、裏方系エンジニア</h3> <p>デバッグの世界とデバッグスキルブートキャンプについて紹介しました。<br />最後にわたしが所属する技術本部について紹介します。</p> <p>技術本部にはいろいろなキャリアの開発者が在籍しており、 <strong>ゲーム体験・感動体験を下支えする何か</strong> を日々開発しています。<br />わたし自身を例に挙げると 以下のような感じです。</p> <ul> <li>ゲームを開発するためのライブラリを作ったり</li> <li>コンバーターとか自動化ツールを作ったり</li> <li>Windows Embedded を使いこなして、アーケードゲーム機向けの OS をビルドしたり</li> <li>開発者向けグループウェアを管理したり</li> </ul> <p>近隣のデスクには ちょっと違う種類の仕事をしている人がいますね。</p> <ul> <li>データベースとか VM をいじる人</li> <li>基板回路を設計する人</li> <li>Maya 上のメッシュモデルをあれこれする人</li> <li>ルーターとか「目新しいユーザーインターフェースデバイス」をいじめる人(w)など</li> </ul> <p>千人規模の社内開発者を支える技術本部にはいろいろな仕事があって、それぞれに奥が深そうです。<br />そして <strong>ゲーム自体のおもしろさを追求するのとは違った立ち位置で、ゲーム周辺にある様々な問題を解決</strong> しています。</p> <p> </p> <p>わたしもゲーム開発を後押しする裏方系エンジニアに転身したことで、結果的にはいろいろなテクノロジースキルを身に着けることができました。<br />「開発したゲームで世界をあっと言わせる!」という部分に自信を持てなくても、「技術のことなら何でも任せて!」という自信に満ちたプログラマー/ソフトウェアエンジニアなら、セガでキャリアを積むのも悪くないと思いますよ。</p> <p>ということで、現場で成長をつづけながら「縁の下の力持ち」として共に働ける仲間を求めています。</p> <p> </p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="セガ グループ 新卒採用サイト" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Frecruit.sega.jp%2F" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://recruit.sega.jp/">recruit.sega.jp</a></cite></p> <p><br /><cite class="hatena-citation"></cite></p> <p>-----</p> <p>©SEGA<br />記載されている会社名、製品名は、各社の登録商標または商標です。</p> <p> </p> sgtech ペルソナ5 ザ・ロイヤルの開発中、自動プレイでバグを検出してみた話 hatenablog://entry/26006613630904163 2020-09-25T10:00:00+09:00 2020-09-25T10:00:08+09:00 ごあいさつ 初めまして、株式会社アトラスのプログラマー埜渡です。Tech BLOGにお邪魔させていただきます。 今回は、弊社のタイトル「ペルソナ5 ザ・ロイヤル」(P5R)の開発中に、自動プレイを実装してバグの検出を行った経緯とその結果についてのお話をさせていただきます。ゲーム本編の実装についてのノウハウというよりは、デバッグ作業での工夫についての内容になります。 ただ、触れる内容といたしましてはP5Rのゲームの中身に関する事が多いため、未プレイの方はプレイしてから読んでいただけると、より理解が深められると思います。 p5r.jp 自動プレイ実装のきっかけ 自分が入社した頃の一昔前のバグの検出… <h3>ごあいさつ</h3> <p>初めまして、株式会社アトラスのプログラマー埜渡です。<br />Tech BLOGにお邪魔させていただきます。</p> <p>今回は、弊社のタイトル「ペルソナ5 ザ・ロイヤル」(P5R)の開発中に、自動プレイを実装してバグの検出を行った経緯とその結果についてのお話をさせていただきます。<br />ゲーム本編の実装についてのノウハウというよりは、デバッグ作業での工夫についての内容になります。</p> <p>ただ、触れる内容といたしましてはP5Rのゲームの中身に関する事が多いため、未プレイの方はプレイしてから読んでいただけると、より理解が深められると思います。</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="P5R - ペルソナ5 ザ・ロイヤル" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fp5r.jp%2F" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://p5r.jp/">p5r.jp</a></cite> </p> <h3>自動プレイ実装のきっかけ</h3> <p>自分が入社した頃の一昔前のバグの検出といえば(現象発生時の記録を残すために)開発機をビデオデッキに繋ぎながらプレイをして、発見したら詳細な手順をバグシート(紙)に書いて報告をしているような方法でした。</p> <p>最近では開発環境自体に録画機能が備えてあったり、バグ報告もWebベースでチケット管理したりとだいぶ環境が変わってきました。</p> <p>報告方法が変わってきただけでなく、検出方法も<strong>人が何時間も粘ってプレイ</strong>して出す方法から、<strong>機械的にテストできるものは自動化をする</strong>ような動きに変わってきています。</p> <p>弊社タイトルのP5Rは平均プレイ時間が<strong>およそ100時間</strong>ほどとなっており、勤勉に日々の業務時間フルにプレイしても、<strong>クリアまでに3週間近くかかってしまう</strong>計算になります。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200918/20200918095440.png" alt="f:id:sgtech:20200918095440p:plain" title="f:id:sgtech:20200918095440p:plain" class="hatena-fotolife" itemprop="image" width="182" /></p> <p>そんなことも背景にあったため、なんとかして<strong>少しでもプレイして確認する時間を増やしたい、できればエンディングまで通しで確認できる仕組みを作りたい</strong>という考えから人手を介さずともゲーム本編のテストをしてくれるような<strong>自動プレイ</strong>を実装しようと思い立ちました。</p> <h3>自動プレイを実装するにあたって</h3> <p>自動プレイを実装するにあたって、いくつか問題となる事がありました。</p> <ol> <li><strong>専用の作業時間を用意していなかったため、他の人に作業をお願いはできない</strong></li> <li><strong>同様の理由で自動プレイ自体の調整・修正作業に多くの時間は費やせない</strong></li> </ol> <p>1.についてですが、例えばプランナーやデザイナーに自動プレイ用に何かを対応作業をしてほしいというお願いをしようにも、そもそもの担当箇所の実装や調整作業で手一杯なため、追加の作業はお願いできないという状況にありました。</p> <p>2.についても、自分自身が日常・ダンジョンパート(プレイヤーを操作して自由に移動するパート)という担当箇所を持っていたため、自動プレイの実装をした後にプランナーやデザイナーの仕様変更に合わせた調整をするための時間が十分にあるわけではありませんでした。</p> <p> </p> <p>そんな事もあり、実装する仕組みとしては</p> <ul> <li><strong>データ作成の時間が無いため、自動プレイのための専用データはなるべく用意しない</strong></li> <li><strong>細かい対応する時間が無いため、仕様変更や調整に対応できるような仕組みでの実装を試みる</strong></li> </ul> <p>このようなコンセプトを持って、自動プレイの実装作業を開始しました。</p> <p>また、実装の目標として</p> <ul> <li><strong>人手を介さずとも、ゲーム開始からエンディングまで自動でプレイできる</strong></li> <li><strong>ランダム要素を増やしなるべく多くの箇所をチェックできるようにする</strong></li> </ul> <p>こちらを達成できるようなものを目指し作成を開始しました。</p> <h3>実装してみたもの</h3> <p>実装内容の説明の前にゲームのシステムを軽く説明させていただきます。</p> <p>ペルソナシリーズの特徴的なシステムとして、<strong>カレンダーシステム</strong>があります。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="カレンダーシステム"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200918/20200918095455.png" alt="f:id:sgtech:20200918095455p:plain" title="f:id:sgtech:20200918095455p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">カレンダーシステム</figcaption> </figure> <p>こちらはゲーム内1年間の日々を過ごす事でゲームが進行していく仕組みになっています。<br />極端な話ですと、毎日家に帰って寝るだけの自堕落な生活をしていても<strong>エンディングへ近づく事はできます</strong>。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="果報は寝て待つ"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200918/20200918095520.png" alt="f:id:sgtech:20200918095520p:plain" title="f:id:sgtech:20200918095520p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">果報は寝て待つ</figcaption> </figure> <p>・・・が、流石にそれだけでゲームが進行するはずもなく、一定期間に<strong>ダンジョンをクリアしてボス</strong>を倒すようなことはゲームクリアするために必要となります。<br />また、ただ寝るだけの生活ではバグの検出としては不十分なので<strong>なるべく色々なイベントを発生させる</strong>ようにもしたいという考えがありました。そのためには自室のベットへまっしぐら・・・ではなく様々な場所へ移動するための仕組みが必要となります。</p> <p> ここで問題となったのが、どのようにして<strong>プレイヤーキャラを目的地に移動させてゲームを進行させていくか</strong>です。</p> <p>ゲームを進行させるというのは、ダンジョンパートであればギミックを解除しボスの元までたどり着く、日常パートであればNPCに話しかけてイベントを発生させたり、バッティングセンターに通ったりすることになります。<br />こういったイベントをこなしていくことで、ゲームオーバーになることなく日付が進行しエンディングを迎えることができます。</p> <p>次に目的地へ移動する仕組みについてですが、真っ先に思いたものは<strong>人がプレイしたデータをリプレイ</strong>または<strong>そのような操作をツール上で指定するといったもの</strong>でした。<br />ただ、今回は先の「データ作成の時間が無いため、自動プレイのための専用データはなるべく用意しない」という事情もあり、実装することはできませんでした。<br /><br />そのため専用データを必要としない、<strong>ルールベースの移動システム</strong>を実装することにしました。</p> <p>ルールベースの実装基本方針として、<strong>付近のイベントヒットを探索し起動する</strong>という仕組みを実装しました。</p> <p>ここでいうイベントヒットとは、ゲーム中アクセスすることでイベントが発生するような範囲のことを指します。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="イベントヒット例"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200918/20200918095444.png" alt="f:id:sgtech:20200918095444p:plain" title="f:id:sgtech:20200918095444p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">イベントヒット例</figcaption> </figure> <ul> <li>NPCとのTalkヒット</li> <li>宝箱や扉のCheckヒット</li> <li>エリア移動を行うGotoヒット</li> <li>…etc</li> </ul> <p>こちらを目標地点として移動することで、闇雲に移動するのではなく先述の<strong>ゲームを進行させるイベントを発生するために移動する</strong>ことができます。</p> <p>本実装ではプレイヤーキャラクターの<strong>前方範囲を中心に、直線距離で障害物に阻まれることなくたどり着けるものをランダムで検索</strong>しそちらを目標地点として移動させました。(画面写真プレイヤー前方の扇形範囲)</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="イベントヒット探索"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200918/20200918095449.png" alt="f:id:sgtech:20200918095449p:plain" title="f:id:sgtech:20200918095449p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">イベントヒット探索</figcaption> </figure> <p>ただ、こちらだけでは付近にイベントヒットがない場合には移動に困ったためもう一つのルールを実装しました。</p> <p> もう一つのルールは<strong>ヒートマップ</strong>(時限制の徘徊履歴)になります。(画面写真の赤いラインのブロック)</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="ヒートマップ"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200918/20200918095500.png" alt="f:id:sgtech:20200918095500p:plain" title="f:id:sgtech:20200918095500p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">ヒートマップ</figcaption> </figure> <p>歩き回ったプレイヤーの周囲(本作では100cm立方のブロック)に時間経過でクリアされる徘徊履歴をつけることで、<strong>ヒートマップがない場所=(少なくとも直近では)あるきまわっていない場所</strong>というルールができました。</p> <p>こちらのルールを追加することで、イベントヒットが検索で見つからなかった場合には、<strong>付近のヒートマップが配置されていない場所(ブロック)を移動目標にすることで、未踏破部分を目指して歩き回ることができる</strong>ようになりました。 </p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="自動プレイの移動例"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200918/20200918095508.gif" alt="f:id:sgtech:20200918095508g:plain" title="f:id:sgtech:20200918095508g:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">自動プレイの移動例</figcaption> </figure> <p>蛇行した通路でも引っかかることなく、ヒートマップの存在しない未踏破部分へ移動し、イベントヒットを見つけた際には移動して調べる動作をしていることがわかると思います。</p> <p><strong>未踏破部分には今まで調べたことのないイベントヒットがある可能性が高く、そちらのイベントヒットにアクセスすることで、新たな未踏破エリアが増え、さらなる未踏破部分へと移動というループができ、より広く、より先の範囲を自動で移動できる</strong>ようになりました。</p> <p> その他にも細かい調整はしたものの、大きくは先の2つの移動ルールでエリア内の未踏破部分を歩き回り、発見したイベントヒットを調べることができたため<strong>最終的にはダンジョンのボスまで到達する</strong>ことができました。</p> <p>これまでの仕組みを実装したことで、日常パートではダンジョン最奥部のような目指す目的地は無いものの、同様のルールで<strong>様々なNPCや施設にアクセスするため、各種イベントを発生する</strong>ことができるようになりました。</p> <p>ここまで実装できれば、プレイヤーキャラの移動箇所以外(バトルパートやイベントパートなど)はランダム入力でもなんとかゲームが進行ができ、最終的には<strong>エンディングへ到達することができるようになりました</strong>。</p> <p>自動プレイで目的地として使用しているイベントヒットは、ゲーム内で使用するためのデータだったため追加のデータを必要とすることが(ほとんど)なく、ゲーム本編での調整による修正にも強いものとして実装することができました。</p> <p>そのため開発中盤~マスターの直前あたりからは手の空いた筐体(退社時など)を利用して自動プレイを回すようにしていましたが、各種の調整作業が有ったとしても自動プレイ自体の調整は殆どせずに稼働させておくことができました。</p> <h3>運用した結果</h3> <p>今回実装した自動プレイでは、主にハングアップや進行不能となるような不具合の検出に重点を置いてチェックを行いました。</p> <p>その結果として、上記のような<strong>最重要修正ランクバグの報告数のうち5%程は自動プレイで検出することができました</strong>。<br />割合としてはちょっと少ないかなという印象かもしれませんが、こちらはバグチケットとして記録が残っているものに限っているため、報告が残っていない開発中盤時から発見できた不具合などを含めるともう少し多い割合貢献できていたと思います。</p> <p>また自動プレイで検出できたバグは、人手で再現するのが難しいようなタイミングや方法でのものが多く、こちらが<strong>予想できないようなバグを発見することができた</strong>のも大きな収穫となりました。</p> <ul> <li>バトルの特定タイミングでラッシュをすると進行不能</li> <li>システムセーブ中にデータロードでハングアップ</li> <li>特定の手順とタイミングでペルソナ合体を行うとハングアップ</li> <li>etc...</li> </ul> <p>開発中盤から1台は自動プレイ用に常に稼働していた筐体がありましたが、そちらはほぼほぼ24時間フル稼働させていた結果、マスターアップ時点の累<strong>積プレイ時間は2000時間を超える</strong>ものとなっていました。(およそ250人日分の働き!!)</p> <h3>まとめ</h3> <p>今回の自動プレイの実装では、専用のデータを殆ど用意せずゲーム本編の調整があっても自動プレイの調整を行うことはあまりしないで済む方法として実装できました。</p> <p>実装方法としてメリットが多いように思えるかもしれませんが、もちろんデメリットもありました。</p> <ul> <li>ランダムでアクセスするためすべてのチェックを網羅できているわけではない</li> <li>同様の理由としてランダム操作が多く、複雑な条件のチェックができていない</li> <li>キャラクターの移動効率は良くないため1周あたり300時間かかってしまった</li> </ul> <p>これらは実際に運用してみて、今回の問題点・反省点と感じました。</p> <p> </p> <p>今後の課題として、これらの問題を解消し<strong>より効率よく細部までのチェックを行える仕組みを考えていきたい</strong>と思っています。</p> <p> </p> <p>アトラスではこのような取り組みに興味のある方を募集しています。もしご興味を持たれましたら下記サイトにアクセスしてみてください。</p> <p> </p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="リクルート | アトラス公式サイト" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.atlus.co.jp%2Frecruit%2F" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://www.atlus.co.jp/recruit/">www.atlus.co.jp</a></cite></p> <p> </p> <p>©SEGA/©ATLUS</p> sgtech CEDEC 2020 セガグループによるセッション紹介! hatenablog://entry/26006613619227054 2020-08-25T10:00:00+09:00 2020-08-25T10:57:16+09:00 皆さんこんにちは、毎年恒例のCEDECでのセガグループによるセッション紹介です!株式会社セガ、第3事業部の麓です。 来月に今年はオンラインで開催されるゲーム業界最大のカンファレンス CEDEC2020 https://cedec.cesa.or.jp/2020/ 会期:2020年9月2日(水)~9月4日(金)にセガグループ(および関連会社)から今年もいくつか登壇します!今回で5回目となる、セガグループ関係者によるセッションと登壇者紹介に加え、ここでしか見れない講演者からのメッセージや、当日の資料からの抜粋等、紹介します。 デフォルメとリアルの両立を目指して ~新サクラ大戦のキャラクター作成事例… <p>皆さんこんにちは、毎年恒例のCEDECでのセガグループによるセッション紹介です!<br />株式会社セガ、第3事業部の麓です。</p> <p>来月に今年はオンラインで開催されるゲーム業界最大のカンファレンス</p> <p><strong>CEDEC2020</strong></p> <p><a href="https://cedec.cesa.or.jp/2020/">https://cedec.cesa.or.jp/2020/</a></p> <p>会期:2020年9月2日(水)~9月4日(金)<br />にセガグループ(および関連会社)から今年もいくつか登壇します!<br />今回で5回目となる、セガグループ関係者によるセッションと登壇者紹介に加え、ここでしか見れない講演者からのメッセージや、当日の資料からの抜粋等、紹介します。</p> <p> </p> <ul class="table-of-contents"> <li><a href="#デフォルメとリアルの両立を目指して新サクラ大戦のキャラクター作成事例">デフォルメとリアルの両立を目指して ~新サクラ大戦のキャラクター作成事例~</a><ul> <li><a href="#セッション内容と講演者より">セッション内容と講演者より</a></li> <li><a href="#講演者">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> <li><a href="#セッションについて一言">セッションについて一言</a></li> </ul> </li> <li><a href="#歌い出すSympathyPSO2のボーカルBGM制作談">「歌い出すSympathy」、PSO2のボーカルBGM制作談</a><ul> <li><a href="#セッション内容と講演者より-1">セッション内容と講演者より</a></li> <li><a href="#講演者-1">講演者</a></li> <li><a href="#スナップショット-1">スナップショット</a></li> <li><a href="#セッションについて一言-1">セッションについて一言</a></li> </ul> </li> <li><a href="#在宅勤務でスクラム">在宅勤務でスクラム!</a><ul> <li><a href="#セッション内容と講演者より-2">セッション内容と講演者より</a></li> <li><a href="#講演者-2">講演者</a></li> <li><a href="#スナップショット-2">スナップショット </a></li> <li><a href="#セッションについて一言-2">セッションについて一言</a></li> </ul> </li> <li><a href="#龍が如くスタジオのQAエンジニアリング技術を結集した全自動バグ取りシステム">「龍が如くスタジオ」のQAエンジニアリング技術を結集した全自動バグ取りシステム</a><ul> <li><a href="#セッション内容と講演者より-3">セッション内容と講演者より</a></li> <li><a href="#講演者-3">講演者</a></li> <li><a href="#スナップショット-3">スナップショット </a></li> <li><a href="#セッションについて一言-3">セッションについて一言</a></li> </ul> </li> <li><a href="#ワーママワーパパたちの働き方って改革できていますか4社事例から道を探ってみよう">ワーママ・ワーパパたちの「働き方」って改革できていますか? 4社事例から道を探ってみよう!</a><ul> <li><a href="#セッション内容と講演者より-4">セッション内容と講演者より</a></li> <li><a href="#講演者-4">講演者</a></li> <li><a href="#スナップショット-4">スナップショット </a></li> <li><a href="#セッションについて一言-4">セッションについて一言</a></li> </ul> </li> <li><a href="#スケジュール作成をもっと楽にという動機から生まれた内製アプリケーション開発実例">スケジュール作成をもっと楽に!という動機から生まれた内製アプリケーション開発実例</a><ul> <li><a href="#セッション内容と講演者より-5">セッション内容と講演者より</a></li> <li><a href="#講演者-5">講演者</a></li> <li><a href="#スナップショット-5">スナップショット </a></li> <li><a href="#セッションについて一言-5">セッションについて一言</a></li> </ul> </li> <li><a href="#Technical-Artist-Bootcamp-2020-ToolDev-for-TA">Technical Artist Bootcamp 2020 :「ToolDev for TA」</a><ul> <li><a href="#セッション内容と講演者より-6">セッション内容と講演者より</a></li> <li><a href="#講演者-6">講演者</a></li> <li><a href="#スナップショット-6">スナップショット </a></li> <li><a href="#セッションについて一言-6">セッションについて一言</a></li> </ul> </li> <li><a href="#技術同人作家になろう-働き方改革時代におけるエンジニアのレベルアップの一例">技術同人作家になろう ~働き方改革時代におけるエンジニアのレベルアップの一例~</a><ul> <li><a href="#セッション内容と講演者より-7">セッション内容と講演者より</a></li> <li><a href="#講演者-7">講演者</a></li> <li><a href="#スナップショット-7">スナップショット </a></li> <li><a href="#セッションについて">セッションについて</a></li> </ul> </li> <li><a href="#リギングクロスオーバーゲームと映像それぞれのリグ制作事例">リギング・クロスオーバー ~ゲームと映像、それぞれのリグ制作事例</a><ul> <li><a href="#講演者-8">講演者</a></li> </ul> </li> </ul> <h3 id="デフォルメとリアルの両立を目指して新サクラ大戦のキャラクター作成事例"><span style="font-size: 150%;">デフォルメとリアルの両立を目指して ~新サクラ大戦のキャラクター作成事例~</span></h3> <h5 id="セッション内容と講演者より"><strong>セッション内容と講演者より</strong></h5> <p>「新サクラ大戦」のキャラクター表現では、トゥーン的諧調表現とPBRのリアル質感表現の双方を混在させて使用することで、アニメ・漫画的なデフォルメ感とリアリティのある質感・存在感を両立させることを目標としていました。一見すると相反する組み合わせのようにも見えますが、適切な使いどころを分けることによって双方の良さを引き出すことを試みています。<br />また、複数のキャラクターデザインが混在する今作で、全体の統一感を出しつつ、元デザインの個性を活かして調整するという点についても課題の一つとなっていました。<br />今回はその制作手法とプロセスを紹介し、更にそこから判明した課題点を共有したいと思います。</p> <h5 id="講演者">講演者</h5> <p><strong>株式会社セガ</strong></p> <p><strong>ジャパンアジアスタジオ統括本部 第2開発2部 第1デザインセクション</strong></p> <p><strong>デザイナー</strong></p> <p><strong>柳瀬 遼平</strong></p> <p><span style="color: #000000; font-family: 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">09月03日(木) 11:00 〜 12:00</span>(<span style="color: #000000; font-family: 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">レギュラーセッション</span>)</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="デフォルメとリアルの両立を目指して ~新サクラ大戦のキャラクター作成事例~ " src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2020%2Fsession%2Fdetail%2Fs5e5f58b640fc9" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2020/session/detail/s5e5f58b640fc9">cedec.cesa.or.jp</a></cite></p> <p><br /><cite class="hatena-citation"></cite></p> <h5 id="スナップショット"><strong>スナップショット</strong></h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200807/20200807164830.png" alt="f:id:sgtech:20200807164830p:plain" title="f:id:sgtech:20200807164830p:plain" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200807/20200807164842.png" alt="f:id:sgtech:20200807164842p:plain" title="f:id:sgtech:20200807164842p:plain" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200807/20200807164855.png" alt="f:id:sgtech:20200807164855p:plain" title="f:id:sgtech:20200807164855p:plain" class="hatena-fotolife" itemprop="image" /></p> <h5 id="セッションについて一言"><strong>セッションについて一言</strong></h5> <p>当セッションでは「新サクラ大戦」のキャラクターモデル表現のノウハウを紹介させて頂きます。</p> <p>細かい技術の積み重ねで出来ているタイトルですので、その中で少しでも制作のヒントになる発見があれば幸いです。</p> <p>よろしくお願いいたします。</p> <h3 id="歌い出すSympathyPSO2のボーカルBGM制作談"><span style="font-size: 150%;">「歌い出すSympathy」、PSO2のボーカルBGM制作談</span></h3> <h5 id="セッション内容と講演者より-1">セッション内容と講演者より</h5> <p>PSO2のBGMシステム「Sympathy」の仕組みやその使用例につきましてこれまでも講演を行ってまいりましたが、今回は各エピソードで制作した「ボーカル」を用いたBGMにつきまして制作事例をご紹介できればと思います。プロシージャルであり、インタラクティブである「ボーカル曲」は果たして作ることができるのか?そのためには作曲、編曲、作詞、レコーディングから、BGM制作ツール「MusicEditor」の改良まで、様々な要素についてチャレンジが必要でした。そのときの体験をご紹介できればと思います。</p> <h5 id="講演者-1">講演者</h5> <p><strong>株式会社セガ</strong></p> <p><strong>ジャパンアジアスタジオ統括本部 第2事業部 サウンドセクション</strong></p> <p><strong>サウンドディレクター・クリエイター</strong></p> <p><strong>小林 秀聡</strong></p> <p><span style="color: #000000; font-family: 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">09月03日(木) 11:00 〜 12:00(レギュラーセッション)</span></p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="「歌い出すSympathy」、PSO2のボーカルBGM制作談 " src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2020%2Fsession%2Fdetail%2Fs5e673208d9653" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2020/session/detail/s5e673208d9653">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット-1">スナップショット</h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200820/20200820152515.png" alt="f:id:sgtech:20200820152515p:plain" title="f:id:sgtech:20200820152515p:plain" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200820/20200820152511.png" alt="f:id:sgtech:20200820152511p:plain" title="f:id:sgtech:20200820152511p:plain" class="hatena-fotolife" itemprop="image" /></p> <h5 id="セッションについて一言-1">セッションについて一言</h5> <p>具体的な内容は多めですが、完成までの流れを追って説明を入れることでわかりやすさを目指しました。</p> <p>ご興味持って頂けましたら幸いです。</p> <p>また、BGMツール「MusicEditor」を使用した実演(楽曲再生)も予定しております。</p> <h3 id="在宅勤務でスクラム"><span style="font-size: 150%;"> 在宅勤務でスクラム!</span></h3> <h5 id="セッション内容と講演者より-2">セッション内容と講演者より</h5> <p>私達は、約半年前より新規プロダクトの開発を行っているスクラムチームです。<br />プロダクトの最初のリリースを目前に控えたある日、在宅勤務による開発を取り組む必要に迫られました。<br />セレモニーはどうするのか...スクラムを継続できるのか...<br />様々な不安がよぎりましたが、私達はスクラムを継続する選択をしました。<br />物理的に距離を乗り越えスクラムを継続した中での成果や気付き、そして失敗をお伝えできればと思います。</p> <h5 id="講演者-2">講演者</h5> <p> </p> <p><strong>株式会社セガ</strong></p> <p><strong>グローバルパブリッシング事業本部 DMS事業部 システム開発部 研究開発2課</strong></p> <p><strong>課長/シニアエンジニア</strong></p> <p><strong>横島 太志</strong></p> <p><span style="color: #000000; font-family: 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">09月03日(木) 18:00 〜 18:25(ショートセッション)</span></p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="在宅勤務でスクラム! " src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2020%2Fsession%2Fdetail%2Fs5e6735091c5eb" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2020/session/detail/s5e6735091c5eb">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット-2">スナップショット </h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200807/20200807163933.jpg" alt="f:id:sgtech:20200807163933j:plain" title="f:id:sgtech:20200807163933j:plain" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200807/20200807163937.jpg" alt="f:id:sgtech:20200807163937j:plain" title="f:id:sgtech:20200807163937j:plain" class="hatena-fotolife" itemprop="image" /></p> <h5 id="セッションについて一言-2">セッションについて一言</h5> <p>在宅勤務、オフィス勤務、それぞれの在り方を模索されている方も多くいらっしゃるかと思います。</p> <p>このセッションでは、どのようにリモートでスクラムを実践し、何が良く何につまずき、そしてどう改善していったのか発表させていただきます。</p> <p>私たちも挑戦の最中ではありますが、皆様にとって何かのキッカケになれば幸いです。</p> <p> </p> <h3 id="龍が如くスタジオのQAエンジニアリング技術を結集した全自動バグ取りシステム"><span style="font-size: 150%;">「龍が如くスタジオ」のQAエンジニアリング技術を結集した全自動バグ取りシステム</span></h3> <h5 id="セッション内容と講演者より-3">セッション内容と講演者より</h5> <p>近年のゲーム開発におけるバグは、大規模化や開発期間の長期化によって数が増大し、内容も複雑化する傾向にあります。また、バグは見つけて修正するだけではなく、様々な作業フローが必要です。本講演では、バグのワークフローを探索・報告・選別・修正・修正確認のフェーズに分けた上で、「龍が如くスタジオ」で取り組んできた自動テストや開発環境の自動化技術を活用し、バグにまつわる作業フローを最大限自動化した全自動バグ取りシステムについて、実際に運用した「龍が如く7 光と闇の行方」での事例を交えてご紹介いたします。</p> <h5 id="講演者-3">講演者</h5> <p><strong>株式会社セガ</strong></p> <p><strong>第1事業部</strong></p> <p><strong>QAエンジニア</strong></p> <p><strong>阪上 直樹</strong></p> <p> </p> <p><strong>開発技術部</strong></p> <p><strong>ビルドエンジニア</strong></p> <p><strong>粉川 貴至</strong></p> <p><span style="color: #000000; font-family: 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">09月02日(水) 18:00 〜 19:00(レギュラーセッション)</span></p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="「龍が如くスタジオ」のQAエンジニアリング技術を結集した全自動バグ取りシステム " src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2020%2Fsession%2Fdetail%2Fs5e71f52615726" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2020/session/detail/s5e71f52615726">cedec.cesa.or.jp</a></cite></p> <p><br /><cite class="hatena-citation"></cite></p> <h5 id="スナップショット-3">スナップショット </h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200818/20200818174259.png" alt="f:id:sgtech:20200818174259p:plain" title="f:id:sgtech:20200818174259p:plain" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200818/20200818174304.png" alt="f:id:sgtech:20200818174304p:plain" title="f:id:sgtech:20200818174304p:plain" class="hatena-fotolife" itemprop="image" /></p> <h5 id="セッションについて一言-3">セッションについて一言</h5> <div>本講演では、手動でのバグの作業フローを整理した上で、自動化に至る過程を丁寧に説明しますので、<br />エンジニア以外の方にも得られる知見があると思います。<br />また、チケット管理システム以外に、Jenkinsやテスト自動化にも触れる予定です。<br />龍が如くシリーズの自動化の集大成となる講演を目指します!是非ご視聴ください!</div> <div> </div> <div> <h3 id="ワーママワーパパたちの働き方って改革できていますか4社事例から道を探ってみよう"><span style="font-size: 150%;">ワーママ・ワーパパたちの「働き方」って改革できていますか? 4社事例から道を探ってみよう!</span></h3> <h5 id="セッション内容と講演者より-4">セッション内容と講演者より</h5> <p>2017年に始まったワーママ・ワーパパ(WM/WP)ラウンドテーブルから分離した、<br />企業規模を問わない4社合同の情報共有セッションです。以下内容を予定しています。<br />・各社の働き方情報共有<br /> (タイムテーブル実例、在宅勤務事情、男性育休の状況、勤務制度の活用状況など)<br />・各社WM/WPの働き方や悩みの紹介<br />・どうやったらより働きやすくなるかの試行錯誤状況の共有<br />・各社社内コミュニティの紹介や、その活動状況の共有<br />※例年ラウンドテーブルに続けて行われていた自費ランチ交流会は、後日改めての開催となりましたため、<br /> セッション内でご案内させていただきます。<br />※ワーキングペアレンツの働き方に関するアンケートへのご協力ありがとうございました。<br /> 結果は本講演内でのご紹介、及び、後日Cedilの資料に掲載させていただきますのでご参照くださいませ。</p> <h5 id="講演者-4">講演者</h5> <p><strong>株式会社セガ</strong></p> <p><strong>ジャパンアジアスタジオ統括本部 第5事業部 第5開発2部 プログラムセクション</strong></p> <p><strong>柳瀬 彩佳 <span style="font-size: 80%;">他</span></strong></p> <p><span style="color: #000000; font-family: 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">09月03日(木) 11:00 〜 12:00(レギュラーセッション)</span></p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="ワーママ・ワーパパたちの「働き方」って改革できていますか? 4社事例から道を探ってみよう! " src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2020%2Fsession%2Fdetail%2Fs5e78248f2a7cf" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2020/session/detail/s5e78248f2a7cf">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット-4">スナップショット </h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200817/20200817134258.jpg" alt="f:id:sgtech:20200817134258j:plain" title="f:id:sgtech:20200817134258j:plain" class="hatena-fotolife" itemprop="image" /></p> <h5 id="セッションについて一言-4">セッションについて一言</h5> <p>4社の様々な働き方を紹介します。<br />昨年までのCEDECワーママ・ワーパパラウンドテーブルにて多く聞かれた、「子育てしながら働いていけるのか不安」「子育て中の部下のことを知りたい」という疑問への回答の1つに、また、同じく子育てしながら働く人の参考になれると嬉しいです。</p> <p> </p> <h3 id="スケジュール作成をもっと楽にという動機から生まれた内製アプリケーション開発実例"><span style="font-size: 150%;">スケジュール作成をもっと楽に!という動機から生まれた内製アプリケーション開発実例</span></h3> <h5 id="セッション内容と講演者より-5">セッション内容と講演者より</h5> <p>スケジュール作成アプリケーション『ScheduleCanvas』を内製で開発する中で得られた知見を共有します。</p> <p>・必要な主な機能をピックアップし、何が重要だったかを説明。</p> <p>・ツールの運用と開発を同時進行するためのノウハウ。</p> <p>・アンケート結果と要望をまとめ、対応策やユーザー傾向を俯瞰。</p> <p>・アプリケーション実装からガントチャート描画に関して</p> <p>このツールはSEGA Techblogでも紹介していますが、ブログの内容を掘り下げて紹介します。</p> <h5 id="講演者-5">講演者</h5> <p><strong>株式会社セガ</strong></p> <p><strong>第3事業部 第3開発2部 テクニカルサポートセクション</strong></p> <p><strong>テクニカルアーティスト:マネージャー</strong></p> <p><strong>麓 一博</strong></p> <p><strong>テクニカルアーティスト</strong></p> <p><strong>清水 宣寿</strong></p> <p><span style="color: #000000; font-family: 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">09月03日(木) 13:30 〜 13:55(ショートセッション)</span></p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="スケジュール作成をもっと楽に!という動機から生まれた内製アプリケーション開発実例 " src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2020%2Fsession%2Fdetail%2Fs5e786d731fb67" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2020/session/detail/s5e786d731fb67">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット-5">スナップショット </h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200805/20200805141352.png" alt="f:id:sgtech:20200805141352p:plain" title="f:id:sgtech:20200805141352p:plain" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200805/20200805141356.png" alt="f:id:sgtech:20200805141356p:plain" title="f:id:sgtech:20200805141356p:plain" class="hatena-fotolife" itemprop="image" /></p> <h5 id="セッションについて一言-5">セッションについて一言</h5> <p>今回ご用意したセッションは『ScheduleCanvas』の紹介だけではなく、内製ツールを開発するためにどういった対応が必要なのかを実体験を元にまとめて発表させていただきます。皆様が内製ツールを開発する時にちらっと思い出していただけるような、そんなセッションになることを目指しています。よろしくお願い致します。</p> <p> </p> <h3 id="Technical-Artist-Bootcamp-2020-ToolDev-for-TA"><span style="font-size: 150%;">Technical Artist Bootcamp 2020 :「ToolDev for TA」</span></h3> <h5 id="セッション内容と講演者より-6">セッション内容と講演者より</h5> <p>前半:今野「新卒からのTA推移」</p> <p>「TAはベテランのアーティストやアートへの造詣が深いプログラマがなるもの」</p> <p>この言葉は僕がTAになるにあたって何度も聞かされた言葉です。本当にそうでしょうか。</p> <p>求めるTA像によりますが、決してそんなことはなく、むしろ経験の量に限らず技術面の知識はアーティストの武器になることを、実例を併せて紹介させていただきたいと思います。</p> <p>後半:清水「TAブートキャンプ ツールのGUIを作ろう」</p> <p>本セッションでは、C#とWindows Formsを使用してのツールのGUIの作り方を1から紹介します。</p> <p>Visual Studio上でのプロジェクト作成からシンプルなGUIを作成し、任意の処理を動かすところまでの流れを解説します。</p> <p>また、ツールにあって当然の機能として求められる「ドラッグ&ドロップ対応」「設定の保存」「プログレスバー実装」の実装方法の一例を紹介します。</p> <h5 id="講演者-6">講演者</h5> <p><strong>株式会社セガ</strong></p> <p><strong>第3事業部 第3開発2部 テクニカルサポートセクション</strong></p> <p><strong>テクニカルアーティスト:マネージャー</strong></p> <p><strong>麓 一博</strong></p> <p><strong>テクニカルアーティスト</strong></p> <p><strong>清水 宣寿 <span style="font-size: 80%;">他</span></strong></p> <p><span style="color: #000000; font-family: 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">09月04日(金) 09:45 〜 10:45(レギュラーセッション)</span></p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="Technical Artist Bootcamp 2020 :「ToolDev for TA」 " src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2020%2Fsession%2Fdetail%2Fs5e79f42ad5710" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2020/session/detail/s5e79f42ad5710">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット-6">スナップショット </h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200820/20200820093931.png" alt="f:id:sgtech:20200820093931p:plain" title="f:id:sgtech:20200820093931p:plain" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200820/20200820093925.png" alt="f:id:sgtech:20200820093925p:plain" title="f:id:sgtech:20200820093925p:plain" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200820/20200820093937.jpg" alt="f:id:sgtech:20200820093937j:plain" title="f:id:sgtech:20200820093937j:plain" class="hatena-fotolife" itemprop="image" /></p> <h5 id="セッションについて一言-6">セッションについて一言</h5> <p>テクニカルアーティストに必要なスキルをブートキャンプ(基礎訓練)と言う形で学び、日々の業務に活かしていこうという趣旨のセッションにて、今回は清水からツールの作り方を基本的なところからを1セッションの半分の時間を使って解説します。<br />この講演でTAも皆簡単なツールは作れるようになって開発環境をどんどん効率化していきましょう。よろしくお願い致します。</p> <p> </p> <h3 id="技術同人作家になろう-働き方改革時代におけるエンジニアのレベルアップの一例"><span style="font-size: 150%;">技術同人作家になろう ~働き方改革時代におけるエンジニアのレベルアップの一例~</span></h3> <h5 id="セッション内容と講演者より-7">セッション内容と講演者より</h5> <p>近年、「技術同人誌」がIT業界を中心として劇的な盛り上がりを見せています。</p> <p>「技術同人誌」は、IT技術だけに留まらず、科学や数学、工学系分野等非常に広範な技術内容を取り扱う同人誌の総称です。</p> <p>このセッションでは、「元々blogで積極的に情報を発信していたエンジニア」と「プライベートでは全く技術情報を発信してこなかったエンジニア」の二人が、それぞれの視点から「技術同人誌」の執筆を通じて得られたものについて紹介します。</p> <p>「技術同人誌」とblog・勉強会での講演・商業誌等の他の情報発信手段の比較についても実例を元に解説します。</p> <p>また、ゲームエンジニアが「技術同人誌」を書くことで技術以外の視野が広がり、より広い意味でのレベルアップを果たすことができる点についても紹介します。</p> <h5 id="講演者-7">講演者</h5> <p><strong>株式会社セガ</strong></p> <p><strong>エンジニア</strong></p> <p><strong>竹原 涼</strong></p> <p><strong>山田 英伸</strong></p> <p><span style="color: #000000; font-family: 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">09月03日(木) 18:30 〜 18:55(ショートセッション)</span></p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="技術同人作家になろう ~働き方改革時代におけるエンジニアのレベルアップの一例~ " src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2020%2Fsession%2Fdetail%2Fs5e80a512e26fc" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2020/session/detail/s5e80a512e26fc">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット-7">スナップショット </h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200817/20200817131827.png" alt="f:id:sgtech:20200817131827p:plain" title="f:id:sgtech:20200817131827p:plain" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200817/20200817131834.png" alt="f:id:sgtech:20200817131834p:plain" title="f:id:sgtech:20200817131834p:plain" class="hatena-fotolife" itemprop="image" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200817/20200817131843.png" alt="f:id:sgtech:20200817131843p:plain" title="f:id:sgtech:20200817131843p:plain" class="hatena-fotolife" itemprop="image" /></p> <h5 id="セッションについて">セッションについて</h5> </div> <p>「技術同人誌」という言葉を聞いたことはありますか?<br />「同人誌」なら聞いたことはあるけど「技術同人誌」って何だろう?と思う人の方が多いかもしれません<br />当講演では、この「技術同人誌」を通じて、私達がエンジニアとしてレベルアップした事例を共有します<br />気楽な形で聞ける内容にしようと思ってますので、「技術同人誌」って何だろうという方から、エンジニアとして行き詰まりを感じている方まで、お気軽にご視聴ください<br />そして、当講演を切っ掛けにゲーム業界にも「技術同人誌」が広がると嬉しく思います<br /> <br />※<br />・当講演は副業活動の一環です<br />・講演内容は個人の意見であり、株式会社セガの公式見解を示すものではありません</p> <p> </p> <h3 id="リギングクロスオーバーゲームと映像それぞれのリグ制作事例"><span style="font-size: 150%;">リギング・クロスオーバー ~ゲームと映像、それぞれのリグ制作事例</span></h3> <h5 id="講演者-8">講演者</h5> <p><strong>マーザ・アニメーションプラネット株式会社</strong></p> <p><strong>デジタル本部 映像制作課</strong></p> <p><strong>ショットワークチーム マネージャー</strong></p> <p><strong>赤木 達也 </strong><span style="font-size: 80%;"><strong>他</strong></span></p> <p><span style="color: #000000; font-family: 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">09月02日(水) 18:00 〜 19:00(レギュラーセッション)</span></p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="リギング・クロスオーバー ~ゲームと映像、それぞれのリグ制作事例 " src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2020%2Fsession%2Fdetail%2Fs5e817567ab8d7" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2020/session/detail/s5e817567ab8d7">cedec.cesa.or.jp</a></cite></p> <p> </p> <p>今回紹介したセッションで聴講したい!と思ったセッションはありましたか?<br />多くのゲーム開発者から注目が集まるCEDECは、今年はオンラインで 9月2日(水)~9月4日(金)の間、開催されます。</p> <p>CEDECに聴講して情報収集や交流をし、ゲーム業界の今を知り、業界の未来について語り合いませんか?<br />それでは皆さんCEDECでお会いましょう!</p> <p> </p> <p>私達は将来CEDECに登壇してみたいと思っている、技術に興味のある方を求めています。<br />そんな貴方、以下にアクセスしてみませんか?</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="セガ グループ 新卒採用サイト" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Frecruit.sega.jp%2F%23" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://recruit.sega.jp/#">recruit.sega.jp</a></cite></p> <p> </p> <p><span style="color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">※複数社登壇の場合でもセガの社員のみ表記しています </span><br style="color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;" /><span style="color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">©SEGA</span></p> sgtech 『D×2 真・女神転生リベレーション』でのビッグバナー画像制作事例 hatenablog://entry/26006613602972841 2020-07-27T10:00:00+09:00 2020-07-27T11:29:58+09:00 はじめまして。セガ 第4事業部・第4開発1部・TAセクションの村上です。 アーケード向けのゲーム開発におよそ10年間携わった後、現在ではスマートフォン用ゲーム『D×2 真・女神転生リベレーション』(以下、『D×2(ディーツー)』)に3D背景チームリーダー兼テクニカルアーティストとして参加しています。 『D×2』の3D背景制作に携わる一方で、制作工程における技術的なサポートも行っています。 『D×2』は悪魔召喚・交渉・悪魔合体・3Dダンジョンなど『真・女神転生』シリーズが持つ醍醐味を踏襲しつつ、スマートフォン向けとして最適化された戦略バトルRPGです。 2.5周年を記念した「超・感謝祭」キャンペ… <p>はじめまして。セガ 第4事業部・第4開発1部・TAセクションの村上です。</p> <p>アーケード向けのゲーム開発におよそ10年間携わった後、現在ではスマートフォン用ゲーム『D×2 真・女神転生リベレーション』(以下、『D×2(ディーツー)』)に3D背景チームリーダー兼テクニカルアーティストとして参加しています。</p> <p>『D×2』の3D背景制作に携わる一方で、制作工程における技術的なサポートも行っています。 </p> <p> </p> <p>『D×2』は悪魔召喚・交渉・悪魔合体・3Dダンジョンなど『真・女神転生』シリーズが持つ醍醐味を踏襲しつつ、スマートフォン向けとして最適化された戦略バトルRPGです。</p> <p>2.5周年を記念した「超・感謝祭」キャンペーンとイベントを開催中ですので、ご興味がありましたら公式サイトをご覧ください。</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="D×2 真・女神転生リベレーション 公式サイト" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fd2-megaten-l.sega.jp%2F" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://d2-megaten-l.sega.jp/">d2-megaten-l.sega.jp</a></cite></p> <p> </p> <p>『真・女神転生』シリーズとは皆様ご存知の通りアトラスさんが開発・販売されている25年以上の歴史を誇る「荒廃し、悪魔が跋扈する現実世界を舞台としたRPGシリーズ」です。</p> <p>「メガテン」の愛称のほうが馴染み深いかもしれませんね。弊社の家庭用ゲーム機でもいくつものタイトルが発売されてきました。</p> <p> </p> <p>つい最近「ゲームギア」が発売30周年になることを記念したミクロサイズの「ゲームギアミクロ」が発表されました。</p> <p>全4色のうちの「レッド」には、なんと『女神転生外伝 ラストバイブル』と『女神転生外伝 ラストバイブルスペシャル』が同梱されます。</p> <p>今まで上記タイトルをプレイする機会に恵まれなかったため、個人的に発売が待ち遠しいです!</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="ゲームギアミクロ | セガ | 収録タイトル" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2F60th.sega.com%2Fggmicro%2Ftitlelist.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://60th.sega.com/ggmicro/titlelist.html">60th.sega.com</a></cite></p> <p> </p> <p>さて少し時間を戻した2020年2月。『D×2』のファンミーティングが有楽町にて開催されました。</p> <p>新型コロナウイルス対策にスタッフ一同細心の注意を払った上で、ご応募をいただいた皆様の中から抽選により約100名様にご来場いただきました。</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="『D2メガテン』新コラボを始めとする新情報満載!2周年 真・感謝祭 ファンミーティングレポート [ファミ通App]" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fapp.famitsu.com%2F20200217_1589904%2F" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://app.famitsu.com/20200217_1589904/">app.famitsu.com</a></cite></p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="会場だけの極秘情報も飛び出した!「D×2 真・女神転生リベレーション」ファンミーティングレポート リリース2周年を迎えた、「D2メガテン」ファンのためのリアルイベントが開催!" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgame.watch.impress.co.jp%2Fdocs%2Fnews%2F1235443.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://game.watch.impress.co.jp/docs/news/1235443.html">game.watch.impress.co.jp</a></cite></p> <p> </p> <p>当日会場にサービス2周年記念悪魔である英雄 マサカドと天魔 アスラおうを撮影できるビッグバナー(フォトスポット)をご用意したところ、ファンの皆様には大盛況でした。</p> <p>この画像の制作工程を紹介したいとの依頼を受けまして、本記事では要点を絞り2部構成にしてお届けします。</p> <div class="confluence-information-macro confluence-information-macro-information conf-macro output-block" style="margin: 10px 0px 1em; padding: 10px 10px 10px 36px; background: #fcfcfc; border: 1px solid #aab8c6; border-radius: 5px; color: #333333; min-height: 20px; position: relative;" data-hasbody="true" data-macro-name="info"> <div class="confluence-information-macro-body" style="margin: 0px; padding: 0px;"> <p><strong>前半</strong></p> <ul> <li>画像の拡大変換ツールwaifu2x-caffeの使い方</li> <li>waifu2x-caffeとAdobe Senseiの拡大性能を比較検証</li> </ul> <p><strong>後半</strong></p> <ul> <li>拡大前の元素材画像のメイキング(UnityでのキャプチャーからPhotoshopでのレタッチまで紹介)</li> </ul> </div> </div> <p> </p> <p>うーん、少し地味ですかね。知っていてもすぐに役立たない情報もあるかもしれません。</p> <p>例えるなら弊社「メガドライブミニ」のヘッドホンボリュームは動かせますが、本体の音量は変わらないんです、ぐらい地味な話もあるかもしれません。</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="ヘッドホンボリュームを動かしても、本体の音量が変わりません。" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ffaq.sega.jp%2Fhc%2Fja%2Farticles%2F360036014433-%25E3%2583%2598%25E3%2583%2583%25E3%2583%2589%25E3%2583%259B%25E3%2583%25B3%25E3%2583%259C%25E3%2583%25AA%25E3%2583%25A5%25E3%2583%25BC%25E3%2583%25A0%25E3%2582%2592%25E5%258B%2595%25E3%2581%258B%25E3%2581%2597%25E3%2581%25A6%25E3%2582%2582-%25E6%259C%25AC%25E4%25BD%2593%25E3%2581%25AE%25E9%259F%25B3%25E9%2587%258F%25E3%2581%258C%25E5%25A4%2589%25E3%2582%258F%25E3%2582%258A%25E3%2581%25BE%25E3%2581%259B%25E3%2582%2593-" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://faq.sega.jp/hc/ja/articles/360036014433-%E3%83%98%E3%83%83%E3%83%89%E3%83%9B%E3%83%B3%E3%83%9C%E3%83%AA%E3%83%A5%E3%83%BC%E3%83%A0%E3%82%92%E5%8B%95%E3%81%8B%E3%81%97%E3%81%A6%E3%82%82-%E6%9C%AC%E4%BD%93%E3%81%AE%E9%9F%B3%E9%87%8F%E3%81%8C%E5%A4%89%E3%82%8F%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93-">faq.sega.jp</a></cite></p> <p> </p> <p>それでもお1人でも役に立ったと言っていただけるように、作業効率が変わりそうなコツを取り揃えてみました!</p> <p>前置きはほどほどに、地味~にお付き合いください。</p> <p> </p> <ul class="table-of-contents"> <li><a href="#フォトスポットってなに">フォトスポットってなに?</a><ul> <li><a href="#巨大なビッグバナーの前で撮影する場所">巨大なビッグバナーの前で撮影する場所</a></li> </ul> </li> <li><a href="#ビッグバナーの解像度はいくつなのか">ビッグバナーの解像度はいくつなのか?</a><ul> <li><a href="#高さ2m横幅4m">高さ2m、横幅4m</a></li> <li><a href="#出力する画像解像度は16K">出力する画像解像度は16K</a></li> <li><a href="#制作する画像解像度は8K">制作する画像解像度は8K</a></li> <li><a href="#拡大変換ってなに">拡大変換ってなに?</a></li> </ul> </li> <li><a href="#入稿前に拡大変換">入稿前に拡大変換</a><ul> <li><a href="#waifu2x-caffeとは">waifu2x-caffeとは?</a></li> <li><a href="#waifu2x-caffeのダウンロードからインストールまで">waifu2x-caffeのダウンロードからインストールまで</a></li> </ul> </li> <li><a href="#waifu2x-caffeの使い方">waifu2x-caffeの使い方</a><ul> <li><a href="#設定のポイントは2つだけ">設定のポイントは2つだけ</a></li> <li><a href="#ノイズ除去レベル">ノイズ除去レベル</a></li> <li><a href="#モデル">モデル</a></li> </ul> </li> <li><a href="#結局どれくらいキレイになるの">結局どれくらいキレイになるの?</a><ul> <li><a href="#オレの嫁waifu2x-caffeとアドビ先生Adobe-Senseiを比較">「オレの嫁(waifu2x-caffe)」と「アドビ先生(Adobe Sensei)」を比較</a></li> <li><a href="#前半まとめ">前半まとめ</a></li> </ul> </li> <li><a href="#メイキング拡大前の元素材の作成手法">メイキング:拡大前の元素材の作成手法</a><ul> <li><a href="#全体のワークフロー">全体のワークフロー</a></li> </ul> </li> <li><a href="#まずはUnityから">まずはUnityから</a><ul> <li><a href="#Unityのキャプチャー環境">Unityのキャプチャー環境</a></li> <li><a href="#キャプチャー">キャプチャー</a></li> <li><a href="#動きのあるポーズはTimeline機能を使う">動きのあるポーズはTimeline機能を使う</a></li> <li><a href="#撮影舞台の紹介">撮影舞台の紹介</a></li> </ul> </li> <li><a href="#ここからはPhotoshop">ここからはPhotoshop</a><ul> <li><a href="#レタッチの方向性は">レタッチの方向性は?</a></li> <li><a href="#空を高解像度化">空を高解像度化</a></li> <li><a href="#遠景と画像の切り抜き">遠景と画像の切り抜き</a></li> <li><a href="#近景と水面反射">近景と水面反射</a></li> <li><a href="#エフェクトと色調補正">エフェクトと色調補正</a></li> <li><a href="#リテイクに強いゴミを消す方法">リテイクに強いゴミを消す方法</a></li> <li><a href="#キャラクターのライティング">キャラクターのライティング</a></li> </ul> </li> <li><a href="#まとめ">まとめ</a></li> </ul> <p> </p> <h3 id="フォトスポットってなに">フォトスポットってなに?</h3> <h4 id="巨大なビッグバナーの前で撮影する場所">巨大なビッグバナーの前で撮影する場所</h4> <p>当日は『真・女神転生』シリーズの人気悪魔と一緒にファンミーティングの楽しい思い出を残せるフォトスポットができました。このフォトスポットに設置されている巨大な写真のことをビッグバナーと呼びます(スマートフォンでさっと撮影した写真で失礼いたします)。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="英雄 マサカド"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200211.png" alt="f:id:sgtech:20200723200211p:plain" title="f:id:sgtech:20200723200211p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">英雄 マサカド</figcaption> </figure> <figure class="figure-image figure-image-fotolife mceNonEditable" title="天魔 アスラおう"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200204.png" alt="f:id:sgtech:20200723200204p:plain" title="f:id:sgtech:20200723200204p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">天魔 アスラおう</figcaption> </figure> <p> <script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </p> <h3 id="ビッグバナーの解像度はいくつなのか">ビッグバナーの解像度はいくつなのか?</h3> <h4 id="高さ2m横幅4m">高さ2m、横幅4m</h4> <p><span style="color: #000000;">「えっ? 高さ2m? 横は4mもあるの!?」</span></p> <p><span style="color: #000000;">最初にビッグバナーの大きさを聞いた時はビックリしました。</span></p> <p><span style="color: #000000;">会場で見た実物は床から天井まで届く、文字通り「ビッグバナー」でした</span>。</p> <div> </div> <div class="confluence-information-macro confluence-information-macro-information conf-macro output-block" style="margin: 10px 0px 1em; padding: 10px 10px 10px 36px; background: #fcfcfc; border: 1px solid #aab8c6; border-radius: 5px; color: #333333; min-height: 20px; position: relative;" data-hasbody="true" data-macro-name="info"> <div class="confluence-information-macro-body" style="margin: 0px; padding: 0px;"><span style="color: #333333;"><strong>ビッグバナーのスペック</strong><br /></span> <ul style="color: #333333;"> <li>2m x 4m(高さ x 横幅)</li> <li>布地に印刷 ※ベルクロ(マジックテープ)で箱に貼り付け</li> <li>入稿はIllustratorフォーマット</li> </ul> </div> </div> <p> </p> <p>「画像解像度いくつだろう・・・」と不安が頭をよぎりましたが、問題なく作業するには8K~16K解像度が限界ではないか?と予想しました。</p> <p>※8K=7,680×4,320ピクセル</p> <p>※16K=15,360 x 8,460ピクセル</p> <p> </p> <p>印刷の密度表現としてはdpiが一般的ですが、ここではピクセルで考えてみます。</p> <p>タイミング良くPhotoshopを起動していたので、数値入力欄で計算してみましょう。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="Photoshopの入力欄で数値の計算"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200002.gif" alt="f:id:sgtech:20200723200002g:plain" title="f:id:sgtech:20200723200002g:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">Photoshopの入力欄で数値の計算</figcaption> </figure> <p><span style="font-weight: 400;">例えば横幅を</span><span style="color: #000000;">約</span>16,000ピクセルで作るとします。</p> <p>横幅1m辺り約4,000ピクセル、横幅1mmだと約4ピクセルの面積となるでしょうか。</p> <p> </p> <p>撮影対象となる悪魔モデルはビッグバナー画像の中央に大写しに立たせることになっていますので、撮影時のカメラまでの距離を考えるとなんとかなりそうです。</p> <p>「きっと16Kでも大丈夫!」と自分を納得させることにしました・・・(ドキドキ)。</p> <p> </p> <h4 id="出力する画像解像度は16K">出力する画像解像度は16K</h4> <p><span style="color: #000000;">少し適当に決めた解像度に聞こえてしまいますが、それにしても</span>16K<span style="font-weight: 400;">・・・</span><span style="font-weight: 400;">本当に大きいです。</span></p> <p><span style="font-weight: 400;">拡大しても、拡大してもピクセルが見えない!</span></p> <p><span style="font-weight: 400;">ちょっと大げさですが、普段はスマートフォン向けゲーム開発をしているだけにこんな気持ちになりました。</span></p> <blockquote> <p>後でdpiを計算すると約100dpiでした。※一般的な印刷物は300〜400dpi。</p> <p> </p> <p>PC用モニターは標準で72dpiなので、標準的なPC用モニターよりは細かくできました(Retinaディスプレイは除く)。16K解像度は結構妥当だったようです。</p> </blockquote> <p> </p> <h4 id="制作する画像解像度は8K">制作する画像解像度は8K</h4> <p>私の普段の業務は『D×2』の3D背景制作と技術サポートです。開発業務と平行してのビッグバナー制作のため、入稿締め切りギリギリのスケジュールでした。</p> <div>『D×2』はアトラスさんの監修を経てリリースされていますので、監修に必要な営業日と修正にかかる時間も考慮する必要があります。</div> <div> </div> <div>スピーディーなワークフローが求められるため「<span style="color: #000000;">制作自体は8K解像度で作業し、</span>入稿直前に16K解像度に拡大変換する」方法を選択しました。 </div> <div> <div> </div> <div>印刷される画像解像度を最終的に2倍に拡大することができれば、レタッチ面積を節約できるだろうと考えました。</div> <div>また作業するPSDファイルサイズは8K解像度で経験上1GB~2GBになります。16K解像度で作業するよりも軽くできますね。</div> </div> <div> </div> <h4 id="拡大変換ってなに">拡大変換ってなに?</h4> <div>例えばPhotoshopで画像の解像度を2倍に拡大してみます。おそらく拡大する前よりもボヤ~っとしていませんか?</div> <div> </div> <div>数年前まではPhotoshopで拡大してもそれほど良い結果は得られませんでした。それはバイキュービック法やバイリニア法という簡単な補完方法による変換だったからです。</div> <div> </div> <div>でも当時はそれが当たり前でした。</div> <div> </div> <div>――――当たり前だったのですが、ここ数年のAdobe社の画像テクノロジーへの取り組みは目覚ましく、ついにはAdobe Senseiという新技術が生まれました。</div> <div> </div> <div>現在はPhotoshopでもAIと機械学習によるキレイな拡大変換が可能となっています。</div> <div>※拡大変換=アップスケーリングとも呼ばれます。</div> <div> </div> <blockquote> <div>AI/機械学習による拡大変換は、縮小画像と解像度の高い元画像のペア(教師データ)を大量に学習した成果を生かして、ただ引き延ばすのではなく、不足情報を補っています。</div> <div> </div> <div>機械学習の説明は、こちらの記事が大変参考になりました。</div> <div> <p><iframe class="embed-card embed-blogcard" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" title="Are you readyyy to Deep Learning!? - SEGA TECH Blog" src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Ftechblog.sega.jp%2Fentry%2F2019%2F01%2F25%2F100000" frameborder="0" scrolling="no"></iframe></p> <p><cite class="hatena-citation"><a href="http://techblog.sega.jp/entry/2019/01/25/100000">techblog.sega.jp</a></cite></p> </div> </blockquote> <p> </p> <h3 id="入稿前に拡大変換">入稿前に拡大変換</h3> <h4 id="waifu2x-caffeとは">waifu2x-caffeとは?</h4> <div>それではビッグバナー制作においては、どのように画像を拡大させたのでしょうか?</div> <div> </div> <div>この流れだとAdobe Senseiを――――Photoshopを使う流れに見えますが・・・違うんです。</div> <div>これからご紹介するツールwaifu2x-caffeを使用すると簡単に、かつキレイに拡大変換できます!</div> <div class="confluence-information-macro confluence-information-macro-tip conf-macro output-block" style="margin: 10px 0px 1em; padding: 10px 10px 10px 36px; background: #f3f9f4; border: 1px solid #91c89c; border-radius: 5px; color: #333333; min-height: 20px; position: relative; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-hasbody="true" data-macro-name="tip"><strong>waifu2x-caffe</strong> <ul> <li>画像変換ソフトウェア「waifu2x」のWindows用ツール</li> <li>「waifu2x」の変換機能のみをCaffeを用いて書き直した</li> </ul> </div> <div> <p>「オレの嫁ね!」と、愛称で呼ばれて既に利用されている方もいらっしゃるかと思います。最近だとスマートフォン向けアプリにリリースされていたり、市販の画像最適化ツールにも搭載されていますね。</p> <p> </p> <p>ゲーム開発の立場で考えると、Windows上で実行できるスタンドアローンツールというのが大変に嬉しいです(外部サーバーに開発データをアップロードするのは問題ありますから)。</p> <p> </p> <p>この素敵なツールは下記からダウンロードして使うことができます。</p> </div> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="lltcggie/waifu2x-caffe" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fgithub.com%2Flltcggie%2Fwaifu2x-caffe" frameborder="0" scrolling="no"></iframe></p> <p><cite class="hatena-citation"><a href="https://github.com/lltcggie/waifu2x-caffe">github.com</a></cite></p> <p> </p> <h4 id="waifu2x-caffeのダウンロードからインストールまで">waifu2x-caffeのダウンロードからインストールまで</h4> <p>Windowsへのインストールもとっても簡単です。</p> <div class="confluence-information-macro confluence-information-macro-information conf-macro output-block" style="margin: 10px 0px 1em; padding: 10px 10px 10px 36px; background: #fcfcfc; border: 1px solid #aab8c6; border-radius: 5px; color: #333333; min-height: 20px; position: relative; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-hasbody="true" data-macro-name="info"><span style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;"><span style="font-size: 14px;"><strong>インストール方法</strong><br /></span></span> <ol style="font-weight: 400;"> <li>lltcggie/waifu2x-caffeの<strong><a href="https://github.com/lltcggie/waifu2x-caffe/releases">ダウンロードページ</a></strong>を開きます。</li> <li> <p><strong>waifu2x-caffe.zip</strong>をクリックして保存します。 ※最新版を選びます</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203707.png" alt="f:id:sgtech:20200723203707p:plain" title="f:id:sgtech:20200723203707p:plain" class="hatena-fotolife" itemprop="image" /><br /><br /></p> </li> <li>ダウンロードしたZIPファイルを右クリック→「<strong>すべて展開</strong>」します。</li> <li><span style="color: #000000;">waifu2x-caffeフォルダ内の<strong>waifu2x-caffe.exe</strong></span>を実行します。<br />※今回はGUI版を使用しますが、コマンドライン版も用意されています(waifu2x-caffe-cui.exe)。 <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203710.png" alt="f:id:sgtech:20200723203710p:plain" title="f:id:sgtech:20200723203710p:plain" class="hatena-fotolife" itemprop="image" /><br /><br /></p> </li> <li>「WindowsによってPCが保護されました」と警告が表示される場合は、「<strong>詳細情報</strong>」をクリックすると「<strong>実行</strong>」ボタンが押せるようになります。 <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203715.png" alt="f:id:sgtech:20200723203715p:plain" title="f:id:sgtech:20200723203715p:plain" class="hatena-fotolife" itemprop="image" /><br /><br /></p> </li> <li>ウインドウが立ち上がったら、「<strong>cuDNNチェック</strong>」ボタンを押します。<br />特にエラーがなければ、準備完了です。 <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203727.png" alt="f:id:sgtech:20200723203727p:plain" title="f:id:sgtech:20200723203727p:plain" class="hatena-fotolife" itemprop="image" /></p> </li> </ol> <blockquote> <p> <strong>cuDNNについて</strong></p> <ul> <li>GPUを使って変換を行う(※Compute Capability 3.0 以上のNVIDIA製GPU)</li> <li>高速に画像変換できる</li> <li>VRAM使用量を減らせる</li> </ul> 以前のバージョンでは別途NVIDIAのサイトからdllをダウンロードする必要がありましたが、ver 1.2.0.3より同梱されることになりました。とっても便利になりましたね。</blockquote> </div> <div data-hasbody="true" data-macro-name="info"> <p> </p> <div id="main-content" class="wiki-content" style="margin: 0px; padding: 0px; color: #172b4d; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"> <div class="confluence-information-macro has-no-icon confluence-information-macro-note conf-macro output-block" style="margin: 10px 0px 1em; padding: 10px; background: #fffdf6; border: 1px solid #ffeaae; border-radius: 5px; color: #333333; min-height: 20px; position: relative;" data-hasbody="true" data-macro-name="note"> <div class="confluence-information-macro-body" style="margin: 0px; padding: 0px;"> <p style="margin: 0px; padding: 0px;"><span style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;"><span style="font-size: 14px;"><strong>エラーが出たら?</strong><br /></span></span></p> もし「cuDNNチェック」で「GPUで変換できません」等のエラーが出た場合は、通常は指示に従いますが、ここではCPU変換にすることで解決してみます。</div> <div class="confluence-information-macro-body" style="margin: 0px; padding: 0px;"><br /> <ol style="font-weight: 400;"> <li>「<strong>動作設定</strong>」ボタンを押します。<br /> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203722.png" alt="f:id:sgtech:20200723203722p:plain" title="f:id:sgtech:20200723203722p:plain" class="hatena-fotolife" itemprop="image" /><br /><br /></p> </li> <li>「使用プロセッサー」を「<span style="color: #000000;"><strong>CPU</strong></span>」へ変更します。<br />※CPUは変換時間が遅くなりますが、確実に動作します。 <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203719.png" alt="f:id:sgtech:20200723203719p:plain" title="f:id:sgtech:20200723203719p:plain" class="hatena-fotolife" itemprop="image" /></p> </li> </ol> <p> </p> <blockquote> <p style="font-weight: 400;"><strong>便利なカスタマイズ</strong></p> <p style="font-weight: 400;">同じ「動作設定」にある「<strong>入力参照時固定フォルダ</strong>」 で入力パスを設定できます。起動のたびにデフォルトフォルダから変更するのが面倒になったら、カスタマイズしてみましょう。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="「入力参照時固定フォルダ」で入力パスをカスタマイズ"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203943.png" alt="f:id:sgtech:20200723203943p:plain" title="f:id:sgtech:20200723203943p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">「入力参照時固定フォルダ」で入力パスをカスタマイズ</figcaption> </figure> </blockquote> </div> </div> </div> </div> <p> </p> <h3 id="waifu2x-caffeの使い方">waifu2x-caffeの使い方</h3> <h4 id="設定のポイントは2つだけ">設定のポイントは2つだけ</h4> <p>詳しい使い方はフォルダ内の「README」ファイルを読んでいただくとして、今回のビッグバナー制作における設定をご紹介します。</p> <blockquote> <figure class="figure-image figure-image-fotolife mceNonEditable" title="『D×2』ビッグバナー画像の変換設定"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203733.png" alt="f:id:sgtech:20200723203733p:plain" title="f:id:sgtech:20200723203733p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">『D×2』ビッグバナー画像の変換設定</figcaption> </figure> </blockquote> <div class="confluence-information-macro confluence-information-macro-information conf-macro output-block" style="margin: 10px 0px 1em; padding: 10px 10px 10px 36px; background: #fcfcfc; border: 1px solid #aab8c6; border-radius: 5px; color: #333333; min-height: 20px; position: relative; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-hasbody="true" data-macro-name="info"> <div class="confluence-information-macro-body" style="margin: 0px; padding: 0px;"> <p style="margin: 10px 0px 0px; padding: 0px;"><strong>使い方</strong></p> <ol> <li>入力パスの「参照」ボタンを押して、変換する画像を選択します。<br />※出力パスは自動で設定されます。</li> <li>「変換モード」はそのままにします。※「ノイズ除去と拡大」</li> <li>「<strong>ノイズ除去レベル</strong>」を選びます。※今回は「レベル2」</li> <li>「拡大サイズ」を選びます。</li> <li>「<strong>モデル</strong>」を選びます。※今回は「写真・アニメ(UpPhotoモデル)」</li> <li>「実行」ボタンを選んで、変換開始です。  <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203738.png" alt="f:id:sgtech:20200723203738p:plain" title="f:id:sgtech:20200723203738p:plain" class="hatena-fotolife" itemprop="image" /></p> </li> </ol> </div> </div> <p> </p> <p>このように数クリックで変換できてしまうこともwaifu2x-caffeの魅力ですね。</p> <p>「実行」ボタンを押してしばらく待つと拡大された画像が作成されます。8Kから16K解像度への拡大もGPU変換なら短い時間で終了します。</p> <p> </p> <h4 id="ノイズ除去レベル">ノイズ除去レベル</h4> <p>ノイズの具合が、質感に大きく影響している印象があります。ここはしっかり設定したほうが良いですね。</p> <p>まずは「レベル1」を選んで一度変換し、結果を確認することをオススメします。</p> <div class="confluence-information-macro confluence-information-macro-information conf-macro output-block" style="margin: 10px 0px 1em; padding: 10px 10px 10px 36px; background: #fcfcfc; border: 1px solid #aab8c6; border-radius: 5px; color: #333333; min-height: 20px; position: relative; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-hasbody="true" data-macro-name="info"> <div class="confluence-information-macro-body" style="margin: 0px; padding: 0px;"><span style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;"><span style="font-size: 14px;">「レベル1」の結果を見た上で<br /></span></span> <ul style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"> <li>質感が失われ過ぎていれば「レベル0」で変換する。</li> <li>ノイズが強ければ「レベル2」で変換する。</li> </ul> <p><span style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;"><span style="font-size: 14px;">適切なレベルを設定することで、さらに良い結果を得られると思います。</span></span></p> </div> </div> <p> </p> <h4 id="モデル">モデル</h4> <p>ビッグバナー画像では「<strong>写真・アニメ(UpPhotoモデル)</strong>」を選んでいます。<br />※「写真・アニメ(Photoモデル)」より高速かつ同等以上の画質で変換できます。</p> <p>アニメやイラスト系の画像では「2次元イラスト」モデルを選びますが、目的に合わせて「UpRGBモデル」「Yモデル」など最適なモデルを選べると良いですね。</p> <p> </p> <h3 id="結局どれくらいキレイになるの">結局どれくらいキレイになるの?</h3> <h4 id="オレの嫁waifu2x-caffeとアドビ先生Adobe-Senseiを比較">「オレの嫁(waifu2x-caffe)」と「アドビ先生(Adobe Sensei)」を比較</h4> <p>ところでどれくらいキレイに拡大変換できるのか、気になりませんか?</p> <p>そこでwaifu2x-caffeとAdobe Senseiをビッグバナー画像を使って比較してみました。いったいどちらの拡大変換がよりキレイな画像になるのでしょうか? 私も楽しみになってきました。</p> <div class="confluence-information-macro confluence-information-macro-tip conf-macro output-block" style="margin: 10px 0px 1em; padding: 10px 10px 10px 36px; background: #f3f9f4; border: 1px solid #91c89c; border-radius: 5px; color: #333333; min-height: 20px; position: relative; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-hasbody="true" data-macro-name="tip"><strong> Adobe Sensei (Photoshop)</strong><br /> <ul> <li>人工知能(AI)とマシンラーニング(機械学習)</li> <li>「イメージ」→「画像解像度」のダイアログにある再サンプルから「<strong>ディテールを保持 2.0</strong>」を選ぶ <br />※Photoshop CC 2018からの新機能</li> </ul> </div> <p> </p> <div class="confluence-information-macro confluence-information-macro-information conf-macro output-block" style="margin: 10px 0px 1em; padding: 10px 10px 10px 36px; background: #fcfcfc; border: 1px solid #aab8c6; border-radius: 5px; color: #333333; min-height: 20px; position: relative; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-hasbody="true" data-macro-name="info"> <div class="confluence-information-macro-body" style="margin: 0px; padding: 0px;"> <p><strong>waifu2x-caffeとAdobe Senseiの検証</strong></p> <p>ベース画像(8K解像度)はそのままの大きさ、100%表示です。</p> <p>比較画像(16K解像度)は見やすくするため実際よりも200%拡大表示しています。</p> <p>それでは英雄 マサカドの口元から比較してみましょう。 </p> <table class="confluenceTable wrapped"><colgroup><col /><col /></colgroup> <tbody> <tr> <th class="confluenceTh"> <p>ベース画像</p> </th> <th class="confluenceTh" colspan="1"> <figure class="figure-image figure-image-fotolife mceNonEditable" title="100%表示"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200040.png" alt="f:id:sgtech:20200723200040p:plain" title="f:id:sgtech:20200723200040p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">100%表示</figcaption> </figure> </th> </tr> <tr> <td class="confluenceTd"> <p><strong>Adobe Sensei</strong></p> <p>ディテールを保持 2.0</p> <p>(ノイズを軽減0%)</p> </td> <td class="confluenceTd" colspan="1"> <figure class="figure-image figure-image-fotolife mceNonEditable" title="化粧の質感は残っているが、エッジ処理に問題があり 200%表示"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200044.png" alt="f:id:sgtech:20200723200044p:plain" title="f:id:sgtech:20200723200044p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable"> <p>化粧の質感は残っているが、エッジ処理に問題があり</p> <p>200%表示</p> </figcaption> </figure> </td> </tr> <tr> <td class="confluenceTd"> <p><strong>Adobe Sensei</strong></p> <p>ディテールを保持 2.0</p> <p>(ノイズを軽減50%)</p> </td> <td class="confluenceTd" colspan="1"> <figure class="figure-image figure-image-fotolife mceNonEditable" title="エッジはスムーズ、化粧の質感はノッペリ 200%表示"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200049.png" alt="f:id:sgtech:20200723200049p:plain" title="f:id:sgtech:20200723200049p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable"> <p>エッジはスムーズ、化粧の質感はノッペリ</p> <p>200%表示</p> </figcaption> </figure> </td> </tr> <tr> <td class="confluenceTd"> <p><span style="color: #d32f2f;"><strong>waifu2x-caffe</strong></span></p> <p>写真・アニメ<br />(UpPhotoモデル)</p> <p>ノイズ除去レベル2</p> </td> <td class="confluenceTd" colspan="1"> <figure class="figure-image figure-image-fotolife mceNonEditable" title="化粧の質感を保ちつつ、エッジをスムーズにするバランスが良い 200%表示"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200052.png" alt="f:id:sgtech:20200723200052p:plain" title="f:id:sgtech:20200723200052p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable"> <p>化粧の質感を保ちつつ、エッジをスムーズにするバランスが良い</p> <p>200%表示</p> </figcaption> </figure> </td> </tr> </tbody> </table> waifu2x-caffeの結果が一番良いですね。Adobe Senseiの挽回なるか?</div> <div class="confluence-information-macro-body" style="margin: 0px; padding: 0px;"><br /> <p>次は天魔 アスラおうの鎧装飾を比較してみましょう。</p> <table class="confluenceTable wrapped"><colgroup><col /><col /></colgroup> <tbody> <tr> <th class="confluenceTh">ベース画像</th> <th class="confluenceTh" colspan="1"> <figure class="figure-image figure-image-fotolife mceNonEditable" title="100%表示"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200008.png" alt="f:id:sgtech:20200723200008p:plain" title="f:id:sgtech:20200723200008p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">100%表示</figcaption> </figure> </th> </tr> <tr> <td class="confluenceTd"> <p><strong>Adobe Sensei</strong></p> <p>ディテールを保持 2.0</p> <p>(ノイズを軽減0%)</p> </td> <td class="confluenceTd" colspan="1"> <figure class="figure-image figure-image-fotolife mceNonEditable" title="四角いドットが残ったまま 200%表示"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200012.png" alt="f:id:sgtech:20200723200012p:plain" title="f:id:sgtech:20200723200012p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable"> <p>四角いドットが残ったまま</p> <p>200%表示</p> </figcaption> </figure> </td> </tr> <tr> <td class="confluenceTd"> <p><strong>Adobe Sensei</strong></p> <p>ディテールを保持 2.0</p> <p>(ノイズを軽減50%)</p> </td> <td class="confluenceTd" colspan="1"> <figure class="figure-image figure-image-fotolife mceNonEditable" title="エッジはスムーズ、質感は若干失われた 200%表示"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200016.png" alt="f:id:sgtech:20200723200016p:plain" title="f:id:sgtech:20200723200016p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable"> <p>エッジはスムーズ、質感は若干失われた</p> <p>200%表示</p> </figcaption> </figure> </td> </tr> <tr> <td class="confluenceTd"> <p><span style="color: #d32f2f;"><strong>waifu2x-caffe</strong></span></p> <p>写真・アニメ<br />(UpPhotoモデル)</p> <p>ノイズ除去レベル2</p> </td> <td class="confluenceTd" colspan="1"> <figure class="figure-image figure-image-fotolife mceNonEditable" title="エッジはスムーズ、質感は若干失われた 200%表示"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200019.png" alt="f:id:sgtech:20200723200019p:plain" title="f:id:sgtech:20200723200019p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable"> <p>エッジはスムーズ、質感も問題なし</p> <p>200%表示</p> </figcaption> </figure> </td> </tr> </tbody> </table> <p style="margin: 10px 0px 0px; padding: 0px;">ここでもwaifu2x-caffeの結果が一番妥当ですね。Adobe Sensei頑張って!</p> <p> </p> <p>最後は天魔 アスラおうの背景です。段差のエッジとピンク色の背景との境界を比較してみましょう。</p> <table class="confluenceTable wrapped"><colgroup><col /><col /></colgroup> <tbody> <tr> <th class="confluenceTh">ベース画像</th> <th class="confluenceTh" colspan="1"> <figure class="figure-image figure-image-fotolife mceNonEditable" title="1"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200023.png" alt="f:id:sgtech:20200723200023p:plain" title="f:id:sgtech:20200723200023p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">100%表示</figcaption> </figure> </th> </tr> <tr> <td class="confluenceTd"> <p><strong>Adobe Sensei</strong></p> <p>ディテールを保持 2.0</p> <p>(ノイズを軽減0%)</p> </td> <td class="confluenceTd" colspan="1"> <figure class="figure-image figure-image-fotolife mceNonEditable" title="4"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200028.png" alt="f:id:sgtech:20200723200028p:plain" title="f:id:sgtech:20200723200028p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable"> <p>エッジの輪郭がにじむ</p> <p>200%表示</p> </figcaption> </figure> </td> </tr> <tr> <td class="confluenceTd"> <p><strong>Adobe Sensei</strong></p> <p>ディテールを保持 2.0</p> <p>(ノイズを軽減50%)</p> </td> <td class="confluenceTd" colspan="1"> <figure class="figure-image figure-image-fotolife mceNonEditable" title="7"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200031.png" alt="f:id:sgtech:20200723200031p:plain" title="f:id:sgtech:20200723200031p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable"> <p>エッジのにじみは改善、あと一歩</p> <p>200%表示</p> </figcaption> </figure> </td> </tr> <tr> <td class="confluenceTd"> <p><span style="color: #d32f2f;"><strong>waifu2x-caffe</strong></span></p> <p>写真・アニメ<br />(UpPhotoモデル)</p> <p>ノイズ除去レベル2</p> </td> <td class="confluenceTd" colspan="1"> <figure class="figure-image figure-image-fotolife mceNonEditable" title="4"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200036.png" alt="f:id:sgtech:20200723200036p:plain" title="f:id:sgtech:20200723200036p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable"> <p>エッジのにじみが一番抑えられている</p> <p>200%表示</p> </figcaption> </figure> </td> </tr> </tbody> </table> <p>最後もwaifu2x-caffeの結果が一番でした。</p> <p> </p> <p>以上で「口元」「鎧装飾」「背景」の3つの比較が終了しましたが、ビッグバナー画像を元に検証した拡大性能に関しては「オレの嫁」――――waifu2x-caffeとの相性が良い結果となりましたね!</p> <p>※検証を行ったバージョン:waifu2x-caffe (1.1.8.3)、Adobe Sensei (Photoshop CC 2019)</p> </div> </div> <p> </p> <p>上記検証ではwaifu2x-caffe一択ですが、Adobe Senseiの「ディテールを保持 2.0」が活かせるケースもあります。</p> <p>例えば「テクスチャーデータを簡単に拡大できる」ところですね。数世代前のゲームを移植する際にテクスチャーがHD化されていないこともあります。</p> <p>この機能をバッチ処理することで、テクスチャーのHD化を低コストで量産できるかもしれません(弊社内で事例があると聞きました)。</p> <p> </p> <div id="main-content" class="wiki-content" style="margin: 0px; padding: 0px; color: #172b4d; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;"> <div class="confluence-information-macro has-no-icon confluence-information-macro-note conf-macro output-block" style="margin: 10px 0px 1em; padding: 10px; background: #fffdf6; border: 1px solid #ffeaae; border-radius: 5px; color: #333333; min-height: 20px; position: relative;" data-hasbody="true" data-macro-name="note"> <div class="confluence-information-macro-body" style="margin: 0px; padding: 0px;"> <p style="margin: 0px; padding: 0px;"><span style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: bold; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #fffdf6; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">「ディテールを保持 2.0」が使えない場合は?</span></p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="おかしいぞ? 本来はここにあるはずなのに、選べない場合は・・・"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723204004.png" alt="f:id:sgtech:20200723204004p:plain" title="f:id:sgtech:20200723204004p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">おかしいぞ? 本来はここにあるはずなのに、選べない場合は・・・</figcaption> </figure> <figure class="figure-image figure-image-fotolife mceNonEditable" title="「ディテールを保持 2.0 アップスケールを有効にする」をオン"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203959.png" alt="f:id:sgtech:20200723203959p:plain" title="f:id:sgtech:20200723203959p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">「ディテールを保持 2.0 アップスケールを有効にする」をオン</figcaption> </figure> <p>(Photoshop CC2018以降であれば)環境設定→「テクノロジープレビュー」の「<strong>ディテールを保持 2.0 アップスケールを有効にする</strong>」をオンにします。</p> </div> </div> </div> <p> </p> <h4 id="前半まとめ">前半まとめ</h4> <p>というわけで前半はビッグバナーの解像度、拡大変換ツールwaifu2x-caffeの紹介、Adobe Senseiとの比較を行いました。ここからは画像を拡大変換する前の「元素材ができあがるまで」のメイキングについてご紹介していきます。</p> <p> </p> <h3 id="メイキング拡大前の元素材の作成手法">メイキング:拡大前の元素材の作成手法</h3> <h4 id="全体のワークフロー">全体のワークフロー</h4> <p>それでは全体の工程を確認していきましょう。 1~5までの工程がありますが、このメイキングでは「1. Unity~」と「2. Photoshop~」にフォーカスした内容となります。</p> <div class="confluence-information-macro confluence-information-macro-information conf-macro output-block" style="margin: 10px 0px 1em; padding: 10px 10px 10px 36px; background: #fcfcfc; border: 1px solid #aab8c6; border-radius: 5px; color: #333333; min-height: 20px; position: relative; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-hasbody="true" data-macro-name="info"><strong>ビッグバナー制作全体ワークフロー</strong>  <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200218.png" alt="f:id:sgtech:20200723200218p:plain" title="f:id:sgtech:20200723200218p:plain" class="hatena-fotolife" itemprop="image" /></p> <ol> <li><strong>Unity</strong>でキャプチャーする<br />・8K解像度</li> <li><strong>Photoshop</strong>で作業をする<br />・合成<br />・レタッチ</li> <li><span style="color: #000000;"><strong>waifu2x-caffe</strong></span>で画像を拡大する<br />・8K→16Kに拡大変換</li> <li><strong>Photoshop</strong>で入稿用画像を作成する<br />・RGB→CMYK変換<br />・色調補正</li> <li><strong>Illustrator</strong>で入稿データを作成する<br />・印刷業者側から提供されたテンプレートファイルに入稿用画像を読み込む<br />・側面デザインや権利表記等など<strong>Illustrator</strong>上の作業を行う</li> </ol> </div> <div> </div> <h3 id="まずはUnityから">まずはUnityから</h3> <h4 id="Unityのキャプチャー環境">Unityのキャプチャー環境</h4> <p>『D×2』はUnityをゲームエンジンとして採用し、開発が行われています。</p> <p>悪魔モデルと背景シーンは3Dで作成されているため、Unityでカメラを作成することで色々な角度から悪魔モデルと背景シーンをキャプチャーすることができます。</p> <p> </p> <p>用意するデータは</p> <ol> <li>悪魔モデル</li> <li>バトルステージ用の背景シーン ※ゲーム中にロードされる</li> <li>キャプチャー用のシーン ※ゲームには含まれない</li> </ol> <p>です。</p> <p>シーン内にどのデータが入っているのかは、リストにして下記にまとめました。</p> <div class="confluence-information-macro confluence-information-macro-information conf-macro output-block" style="margin: 10px 0px 1em; padding: 10px 10px 10px 36px; background: #fcfcfc; border: 1px solid #aab8c6; border-radius: 5px; color: #333333; min-height: 20px; position: relative; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-hasbody="true" data-macro-name="info"> <p class="confluence-information-macro-body" style="margin: 0px; padding: 0px;"><strong>背景シーン(バトルステージ用)</strong></p> <ul style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"> <li>背景モデル</li> <li>(背景内の)バトル開始位置</li> <li>バトル開始位置に付随するフォグやライト等の環境設定</li> <li>悪魔モデルの質感調整等パラメーター</li> </ul> <p class="confluence-information-macro-body" style="margin: 0px; padding: 0px;"><span style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;"><span style="font-size: 14px;"><br /><strong> </strong></span></span><strong>キャプチャー用シーン</strong></p> <ul style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"> <li>悪魔モデル</li> <li>キャプチャー用バトル開始位置</li> <li>キャプチャー用カメラ</li> <li>キャプチャー用ライト</li> </ul> </div> <p> </p> <p>シーン内のバトル開始位置と連動して背景環境を変更させる仕組みとなっています。そのため同じ背景シーンでも、バトル開始位置によってはガラリと雰囲気が変化します。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="バトル開始位置を切り替えるとシーンの雰囲気や見た目も変わる"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200426.gif" alt="f:id:sgtech:20200723200426g:plain" title="f:id:sgtech:20200723200426g:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">バトル開始位置を切り替えるとシーンの雰囲気や見た目も変わる</figcaption> </figure> <p>この仕組みを流用してキャプチャーのためのカメラのポジションやライティング環境を作り、キャプチャー用シーン内に保存しています。</p> <p>マメなセーブデータが大切だ!ということを『真・女神転生』シリーズのザコ敵に全滅させられた経験から学んでいますので、うっかりミスで「あの背景をキャプチャーし忘れた!」と問題が発生しても、すぐ同じ環境を復帰できるように備えています(ああ、当時のトラウマが・・・)。</p> <p> </p> <h4 id="キャプチャー">キャプチャー</h4> <p>キャプチャー用カメラのベースはバトル時のカメラと同じなのですが、画面をキャプチャーするコンポーネント(スクリプト)がアタッチされています。</p> <div> <div> <p>画面のキャプチャーはフリーツールが多数ありますが、『D×2』では独自の描画方式を用いているのでフリーツールや標準機能では正しくキャプチャーできません。そのためキャプチャーツールは独自実装となっています。</p> <p> </p> </div> <p>カメラの背景色ですが「Background」をPhotoshopで抜きやすい色に変更しているだけです・・・横着ですね。背景エフェクトをキャプチャーする場合は「Background」を黒色でキャプチャーしています。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="「Background」カラーを抜きやすい色に変更"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203647.png" alt="f:id:sgtech:20200723203647p:plain" title="f:id:sgtech:20200723203647p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">「Background」カラーを抜きやすい色に変更</figcaption> </figure> <p> </p> </div> <h4 id="動きのあるポーズはTimeline機能を使う">動きのあるポーズはTimeline機能を使う</h4> <p>特定のポーズでキャプチャーしたい場合では、Timeline機能を使っています。</p> <p>※Timeline機能=シネマティクスやカットシーンを作ることができる</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="Timelineを利用したキャプチャー"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203953.png" alt="f:id:sgtech:20200723203953p:plain" title="f:id:sgtech:20200723203953p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">Timelineを利用したキャプチャー</figcaption> </figure> <p>Timeline機能を使うとライティング、パーティクルエフェクト発動のタイミングも自由に組み合わせることができます。</p> <p>「再生開始から◯◯フレーム目のアニメーション」をキャプチャーすることで、同じポーズとカメラアングルを再現しています。 </p> <p> </p> <p>猛将 マサカドのレタッチ画像の制作では、「カメラ」「猛将 マサカドのモデル」「攻撃のアニメーション」をTimeline機能で読み込んでキャプチャーしました。この猛将 マサカドの攻撃アニメーションは何度見ても迫力があってカッコイイですね!</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="猛将 マサカド「マサカドチャレンジ」 ※クリックすると大きい画像で表示"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200224.png" alt="f:id:sgtech:20200723200224p:plain" title="f:id:sgtech:20200723200224p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">猛将 マサカド「マサカドチャレンジ」 ※クリックすると大きい画像で表示</figcaption> </figure> <p> </p> <h4 id="撮影舞台の紹介">撮影舞台の紹介</h4> <p>英雄 マサカドのビッグバナー撮影の舞台は専用の「チャレンジクエスト」ステージ(いわゆるボス戦)です。</p> <p>海上の歌舞伎舞台をイメージしていて、奥には三重塔が英雄 マサカドを見守るように佇んでいます。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="英雄 マサカド専用の「チャレンジクエスト」ステージ"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200153.png" alt="f:id:sgtech:20200723200153p:plain" title="f:id:sgtech:20200723200153p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">英雄 マサカド専用の「チャレンジクエスト」ステージ</figcaption> </figure> <p>『真・女神転生Ⅲ-NOCTURNE』にマサカド公が登場する場面がありますが、アトラスさんからの提案により篝火と鳥居の要素をオマージュとして取り入れています。</p> <p> </p> <h3 id="ここからはPhotoshop">ここからはPhotoshop</h3> <h4 id="レタッチの方向性は">レタッチの方向性は?</h4> <p>Photoshop上にて、以下のように作業を進めていきます。</p> <div class="confluence-information-macro confluence-information-macro-information conf-macro output-block" style="margin: 10px 0px 1em; padding: 10px 10px 10px 36px; background: #fcfcfc; border: 1px solid #aab8c6; border-radius: 5px; color: #333333; min-height: 20px; position: relative; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-hasbody="true" data-macro-name="info"> <div class="confluence-information-macro-body" style="margin: 0px; padding: 0px;"><span style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;"><span style="font-size: 14px;"><strong>背景</strong><br /></span></span> <ol style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"> <li>空、遠景、近景、エフェクトの合成</li> <li>レタッチ</li> <li><span style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px;">色調補正</span></li> </ol> <span style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;"><span style="font-size: 14px;"><strong>キャラクター</strong><br /></span></span> <ol style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;"> <li>影とライティングの合成</li> <li>レタッチ</li> <li><span style="color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px;">色調補正</span></li> </ol> </div> </div> <p> </p> <p>英雄 マサカドは「格式の高さ」、そして天魔 アスラおうは「壮麗さ」をキーワードとして写真に収めた際に格好よく見えるような、写真映えするような方向性となっています。</p> <p> </p> <p>記事ボリュームの都合上、ここでは英雄 マサカドのレタッチ工程を中心に進めていきます。</p> <p>まずはゲーム画面の背景だけのスクリーンショットを確認してみましょう。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="ゲーム画面の背景スクリーンショット(参考用)"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200158.png" alt="f:id:sgtech:20200723200158p:plain" title="f:id:sgtech:20200723200158p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">ゲーム画面の背景スクリーンショット(参考用)</figcaption> </figure> <p>ゲーム中は迫力ある背景だと思ったのですが、スマートフォンのカメラで撮影するにはやや物足りないですね。</p> <p> </p> <h4 id="空を高解像度化">空を高解像度化</h4> <p>屋外の背景で空が見えているようであれば、空から作業を始めます。</p> <p>画像全体のトーンを空を見ながら決めやすいですし、光がどのように射し込むかイメージできます。</p> <p>また、単純に絵としてのクオリティーが上がりやすい印象もあります。</p> <blockquote> <p>実は空の元画像素材は8K解像度には足りていませんでした。</p> <p>先程Photoshopでの作業と書きましたが、この空だけは先にwaifu2x-caffeを使って4倍に拡大します。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="異なるノイズ除去レベルで4倍拡大した画像を2枚用意"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723204013.png" alt="f:id:sgtech:20200723204013p:plain" title="f:id:sgtech:20200723204013p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">異なるノイズ除去レベルで4倍拡大した画像を2枚用意</figcaption> </figure> <figure class="figure-image figure-image-fotolife mceNonEditable" title="異なるノイズ除去レベルで4倍拡大した画像を2枚用意"></figure> <p>変換してみるとノイズ除去レベル2ではノイズが残り過ぎ、3だと完全にノッペリしていましたので、この2枚を合成して画質をコントロールすることにしました。</p> </blockquote> <p> </p> <blockquote> <p>もし元画像の地平線が傾いていれば「切り抜きツール」の「<strong>画像上に線を引いて画像を角度補正</strong>」を使います。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="余白を自動的に補正する設定"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203619.png" alt="f:id:sgtech:20200723203619p:plain" title="f:id:sgtech:20200723203619p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">余白を自動的に補正する設定</figcaption> </figure> <p>自動で傾きを修正してくれるので便利ですね。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="「画像上に線を引いて画像を角度補正」で水平線に沿って線を引く"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203623.png" alt="f:id:sgtech:20200723203623p:plain" title="f:id:sgtech:20200723203623p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">「画像上に線を引いて画像を角度補正」で水平線に沿って線を引く</figcaption> </figure> <p>この時に「<strong>切り抜いたピクセルを削除</strong>」オフ、「<strong>コンテンツに応じる</strong>」オンに設定します。</p> <p>本来であれば傾きを修正すると空白が生まれてしまいますが、Photoshopがいい感じに埋めてくれます。</p> <p>ポイントになるのは「コンテンツに応じる」という機能です。</p> </blockquote> <p> </p> <p>こうして拡大された空をレイヤーマスクを使ってゲーム中の空に合成していきます。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="ゲーム中の空"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200057.png" alt="f:id:sgtech:20200723200057p:plain" title="f:id:sgtech:20200723200057p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">ゲーム中の空</figcaption> </figure> <figure class="figure-image figure-image-fotolife mceNonEditable" title="合成した空"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200101.png" alt="f:id:sgtech:20200723200101p:plain" title="f:id:sgtech:20200723200101p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">合成した空</figcaption> </figure> <p>空を変えただけですが、ずいぶんと雰囲気が変わります。</p> <p> </p> <h4 id="遠景と画像の切り抜き">遠景と画像の切り抜き</h4> <p>ここからは三重塔と橋を合成していきます。</p> <blockquote> <p>三重塔の画像をPhotoshopで読み込み、塔の形状で抜く作業をしていきます。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="選択範囲から「色域指定」"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203703.png" alt="f:id:sgtech:20200723203703p:plain" title="f:id:sgtech:20200723203703p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">選択範囲から「色域指定」</figcaption> </figure> <p> </p> <p>選択範囲メニューから「<strong>色域指定</strong>」を選んで、抜きたい色を削除するのが一番簡単な方法ですが、フチに1ピクセルほど微妙に色が残る場合がありますので注意が必要です。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="フチに色が残ったケース(極端な例)"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203654.png" alt="f:id:sgtech:20200723203654p:plain" title="f:id:sgtech:20200723203654p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">フチに色が残ったケース(極端な例)</figcaption> </figure> <figure class="figure-image figure-image-fotolife mceNonEditable" title="フリンジ削除でフチを削除"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203650.png" alt="f:id:sgtech:20200723203650p:plain" title="f:id:sgtech:20200723203650p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">フリンジ削除でフチを削除</figcaption> </figure> <p>レイヤーメニューから「マッティング」→「<strong>フリンジ削除</strong>」で1ピクセル削ってしまうと安心です。</p> </blockquote> <p> </p> <p>背景だと上記で大抵は問題ないのですが、木々のある背景や複雑な形状のキャラクターでは繰り返し調整可能な「レイヤーマスク」を使う方がより良い結果を得られます。</p> <blockquote> <p>選択レイヤーに「<strong>レイヤーマスク</strong>」を追加し、マスクの「<strong>属性</strong>」にある「<strong>色域指定</strong>」を使います(「反転ボタン」を押すと選択を逆転できます)。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="レイヤーマスク「属性」の「色域指定」と「選択とマスク」"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203658.png" alt="f:id:sgtech:20200723203658p:plain" title="f:id:sgtech:20200723203658p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">レイヤーマスク「属性」の「色域指定」と「選択とマスク」</figcaption> </figure> <p>次に「<strong>選択とマスク</strong>」を使いながらエッジの処理を調整することができます。※以前のバージョンでは「マスクの境界線」</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="「選択とマスク」を使用してエッジを微調整"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203743.png" alt="f:id:sgtech:20200723203743p:plain" title="f:id:sgtech:20200723203743p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">「選択とマスク」を使用してエッジを微調整</figcaption> </figure> </blockquote> <p> </p> <p>空気感の演出として、レイヤースタイルや修正を加えていきます。</p> <blockquote> <p>「カラーオーバーレイ」は空気感を演出できる便利な機能ですね。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="三重塔を追加"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200318.png" alt="f:id:sgtech:20200723200318p:plain" title="f:id:sgtech:20200723200318p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">三重塔を追加</figcaption> </figure> <figure class="figure-image figure-image-fotolife mceNonEditable" title="レイヤースタイルの「カラーオーバーレイ」を選んで、三重塔に空気感を追加"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723204034.png" alt="f:id:sgtech:20200723204034p:plain" title="f:id:sgtech:20200723204034p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">レイヤースタイルの「<strong>カラーオーバーレイ</strong>」を選んで、三重塔に空気感を追加</figcaption> </figure> </blockquote> <figure class="figure-image figure-image-fotolife mceNonEditable" title="フォグと橋を追加して遠景の完成"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200323.png" alt="f:id:sgtech:20200723200323p:plain" title="f:id:sgtech:20200723200323p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">フォグと橋を追加して遠景の完成</figcaption> </figure> <p>ゲームからキャプチャーした素材だけでは足りなかったので、雲ブラシでフォグを描き足しました。</p> <p> </p> <h4 id="近景と水面反射">近景と水面反射</h4> <p>歌舞伎舞台、鳥居を合成していきます。</p> <p>遠景のレタッチによって鳥居のシルエットがハッキリしました。この状態であればキャラクターを追加しても背景に埋没する心配はいらなさそうです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="歌舞伎舞台と鳥居を追加"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200328.png" alt="f:id:sgtech:20200723200328p:plain" title="f:id:sgtech:20200723200328p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">歌舞伎舞台と鳥居を追加</figcaption> </figure> <p>8K解像度ではライトマップの精度が荒い箇所がいくつも見つかりました。またアンビエント・オクルージョンも物足りないと感じたため、地味な作業ですが修正します。</p> <p> </p> <p>歌舞伎舞台中央には水面があります。映り込むと美しさが増しますので、三重塔と空の水面反射を追加していきます。</p> <blockquote> <p>レイヤーを選択して、フィルターメニューから「<strong>スマートフィルター用に変換</strong>」します。これでフィルター効果を何度でも修正できるようになりました。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="フィルター→「スマートフィルター用に変換」"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203630.png" alt="f:id:sgtech:20200723203630p:plain" title="f:id:sgtech:20200723203630p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">フィルター→「スマートフィルター用に変換」</figcaption> </figure> <p> </p> <p>編集の「自由変形」→「垂直方向に反転」で上下反転させますが、若干タテに伸びるように変形させた後に、フィルター→「ぼかし」→「<strong>ぼかし(移動)</strong>」を実行します。ぼかし表現をタテ方向(90度)に加えていきます(「距離」はケースバイケースで調整します)。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="フィルター→「ぼかし」→「ぼかし(移動)」で90度のぼかし"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203626.png" alt="f:id:sgtech:20200723203626p:plain" title="f:id:sgtech:20200723203626p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">フィルター→「ぼかし」→「ぼかし(移動)」で90度のぼかし</figcaption> </figure> <figure class="figure-image figure-image-fotolife mceNonEditable" title="水面反射として三重塔を追加"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203441.png" alt="f:id:sgtech:20200723203441p:plain" title="f:id:sgtech:20200723203441p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">水面反射として三重塔を追加</figcaption> </figure> <p>水面への映り込みは若干暗くなるように「トーンカーブ」で暗めに調整します。</p> </blockquote> <p> </p> <blockquote> <p>次に空の反射を追加しますが、水面がツルッとしてしまいました。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="空の反射も追加"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203445.png" alt="f:id:sgtech:20200723203445p:plain" title="f:id:sgtech:20200723203445p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">空の反射も追加</figcaption> </figure> <p> </p> <p>手っ取り早く調整する方法として、レイヤースタイルの「<strong>ブレンド条件</strong>」を使っていきます。</p> <p>「<strong>下になっているレイヤー</strong>」のスライダーを左右に動かして、ピクセルの明るさを基準にしながら、選択中のレイヤーより下になっているレイヤーを合成します。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="「ブレンド条件」で明るい部分だけの反射を残す"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203450.gif" alt="f:id:sgtech:20200723203450g:plain" title="f:id:sgtech:20200723203450g:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">「ブレンド条件」で明るい部分だけの反射を残す</figcaption> </figure> <p>このままだと合成が荒いままなので、一度「<strong>Alt(Windows)/Option(Mac)</strong>」キーを押しながらスライダーをクリックします。</p> <p>1つだったスライダーが2つに分割されます。隙間を空けるようにスライダーを移動させると、スムーズに境界が合成されます。</p> <p>※スライダーは左右両端にありますので、目的に応じて使い分けます。</p> </blockquote> <p> </p> <p>さらにレイヤーマスクを追加して、合成する範囲をコントロールしても良いかもしれません。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="近景の完成"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200340.png" alt="f:id:sgtech:20200723200340p:plain" title="f:id:sgtech:20200723200340p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">近景の完成</figcaption> </figure> <p> </p> <h4 id="エフェクトと色調補正">エフェクトと色調補正</h4> <p>Unityでエフェクトごとにキャプチャーした画像を基本的には描画モードを「スクリーン」で合成していきます。炎だけ、煙だけと要素に分けてキャプチャーするため、キャプチャー枚数は背景よりもずっと多くなります。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="エフェクトは描画モードを「スクリーン」で合成"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200149.png" alt="f:id:sgtech:20200723200149p:plain" title="f:id:sgtech:20200723200149p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">エフェクトは描画モードを「スクリーン」で合成</figcaption> </figure> <figure class="figure-image figure-image-fotolife mceNonEditable" title="背景の完成 ※クリックすると大きい画像で表示"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200249.png" alt="f:id:sgtech:20200723200249p:plain" title="f:id:sgtech:20200723200249p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">背景の完成<br />※クリックすると大きい画像で表示</figcaption> </figure> <p>それでも足りないエフェクトはブラシで描き足します。色調補正を重ねて背景の完成です。</p> <p> </p> <h4 id="リテイクに強いゴミを消す方法">リテイクに強いゴミを消す方法</h4> <p>少し脱線しますが、フォトバッシュやレタッチ作業をしていると画像から不必要なゴミを消したい場合もあります。</p> <p>定番というと「スポット修復ブラシツール(修復ブラシツール)」「コピースタンプツール」が思い浮かびますが、今回はCC 2019から追加されたマイナー(?)だけど便利な方法をご紹介したいと思います。</p> <blockquote> <p>スマートフォンで撮影した実物のビッグバナー写真からエフェクトやシミなどを削除してみます。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="火の粉や鳥、印刷のシミを削除するには・・・"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203530.png" alt="f:id:sgtech:20200723203530p:plain" title="f:id:sgtech:20200723203530p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">火の粉や鳥、印刷のシミを削除するには・・・</figcaption> </figure> <figure class="figure-image figure-image-fotolife mceNonEditable" title="削除したい範囲を囲み・・・"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203536.png" alt="f:id:sgtech:20200723203536p:plain" title="f:id:sgtech:20200723203536p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">削除したい範囲を囲み・・・</figcaption> </figure> <p> </p> <p>メニューから編集→「<strong>コンテンツに応じた塗りつぶし</strong>」を選びます。<br />※CC 2019より以前のバージョンでは編集→塗りつぶし→「コンテンツに応じる」ですが、新規レイヤー作成はできません。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="「新規レイヤー」を選ぶと、修正箇所を別レイヤー化できて便利"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203543.png" alt="f:id:sgtech:20200723203543p:plain" title="f:id:sgtech:20200723203543p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">「新規レイヤー」を選ぶと、修正箇所を別レイヤー化できて便利</figcaption> </figure> <p> </p> <p>CC 2019からはプレビューで確認しながら調整できるようになり、出力先として「新規レイヤー」が選べるようになりました。このままデフォルト設定で適用します。※意図した結果にならないケースでは、「サンプリング領域」をブラシで塗り直します。</p> <p>「サンプリング領域」と選択範囲を調節するだけで結果が変わるため、一気に修正できてリテイクに強い便利な機能となりました。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="囲った箇所を一気に修正"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203547.png" alt="f:id:sgtech:20200723203547p:plain" title="f:id:sgtech:20200723203547p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">囲った箇所を一気に修正</figcaption> </figure> </blockquote> <p> </p> <p>一方でブラシのストロークで修正できる「スポット修復ブラシツール」も捨てがたいです。</p> <p>ああ、元画像を直接修正しない方法があれば・・・スマートオブジェクトでも修正できれば・・・。分かります。</p> <blockquote> <p>実は「<strong>スポット修復ブラシツール</strong>」の「<strong>コンテンツに応じる</strong>」を選んでから「<strong>全レイヤーを対象</strong>」にチェックを入れることで解決できます。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="「スポット修復ブラシツール」の「全レイヤーを対象」を選ぶ"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723203616.png" alt="f:id:sgtech:20200723203616p:plain" title="f:id:sgtech:20200723203616p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">「スポット修復ブラシツール」の「全レイヤーを対象」を選ぶ</figcaption> </figure> <p>新規レイヤーを作成すれば、ストロークした修正箇所のみ新しいレイヤーに分けることができます。</p> </blockquote> <p> </p> <p>ここまでポイントなっているのは「コンテンツに応じて◯◯」という機能です。Photoshop CS4からバージョンが上がるごとに対応が増えている機能ですが、こちらで詳しく使い方をフォローされています。</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="ベテランほど知らずに損してるPhotoshopの新常識(10)Photoshopマジックの奥義「コンじる」の進化 | Adobe Blog" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fblogs.adobe.com%2Fjapan%2Fdtp-photoshop-kihon-tips-10%2F" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://blogs.adobe.com/japan/dtp-photoshop-kihon-tips-10/">blogs.adobe.com</a></cite></p> <p> </p> <h4 id="キャラクターのライティング">キャラクターのライティング</h4> <p>ここからは背景に英雄 マサカドを立たせて、基本的にはキャラクターのライティング調整を優先していきます。</p> <p>その理由として悪魔モデルはモデリングと質感のクオリティーが非常に高いレベルにあるため、大きい修正をする必要性を感じられないからです(アトラスさんの監修も通っていますし)。</p> <p>ちなみに下記画像のポーズは元のイラストのマサカド公を再現しています。イラストと見比べても再現性バッチリで、モデリングチームとアニメーションチームの熱意が伝わってくるかのようです。</p> <blockquote> <p>向かって左側に立っている英雄 マサカドがゲーム中のリアルタイムライトでキャプチャーした画像です</p> <p> </p> <p>まずは影の調整をしてみましょう。</p> <p>左側の画像をベースにブラシを使用してアンビエント・オクルージョンを追加していきます。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="ベースのキャプチャー画像(左側) アンビエント・オクルージョン追加後(右側)"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200304.png" alt="f:id:sgtech:20200723200304p:plain" title="f:id:sgtech:20200723200304p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable"> <p>ベースのキャプチャー画像(左側)</p> <p>アンビエント・オクルージョン追加後(右側)</p> </figcaption> </figure> <p>夕日のバックライトに合わせて手のひら、袖の下、洋服の重なり部分、足首周りにしっかりと影を落とします。</p>   <p>ここからはラィティングの調整をしていきます。作り込んだモデルの立体感とPBRマテリアルによる繊細な質感をさらに引き出すことを目標とします。</p> <p>基本はキーライト、フィルライト、バックライト(リムライト)があれば対応できます。顔周りが暗かったり、余計な影が顔に落ちているケースではフェイス用ライトを何個か追加してキャプチャーしておきます。</p> <p> </p> <p>最終的にPhotoshop上で合成するため、Unity上でのライト調整はそこそこで大丈夫です。</p> <p>1ライトにつき1枚キャプチャーしておくと、調整がしやすくなります。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="フロントライト(左側)、フィルライト(右側)"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200308.png" alt="f:id:sgtech:20200723200308p:plain" title="f:id:sgtech:20200723200308p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">フロントライト(左側)、フィルライト(右側)</figcaption> </figure> <p>ベースの画像を1枚目として数えると、フロントライト、フィルライトの追加を行ったので合計3枚キャプチャーしたことになります。</p> <p> </p> <p>意外と少ないキャプチャー枚数なのは屋外だったからかもしれません。もし屋内であれば光源が多数あるケースが多いため、キャプチャー枚数も増えていたでしょう。</p> <p>以前はMayaでディフューズ、スペキュラーなどレンダリング要素別に出力していたことに比べると、とってもシンプルな手法ですね。</p> <p> </p> <p>英雄 マサカドを取り囲むように篝火が配置してありますので、照り返しを感じられるように「トーンカーブ」を使って色調補正します。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="ベース(左側)、レタッチ完了後(右側)"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200313.png" alt="f:id:sgtech:20200723200313p:plain" title="f:id:sgtech:20200723200313p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">ベース(左側)、レタッチ完了後(右側)</figcaption> </figure> <p>足元には水面反射と影を追加し、注目される箇所を優先して修正します。</p> <p>顔は注目度が高いので、瞳や歯の辺りは丁寧に手を入れています(口の中までクッキリと映る解像度なんです)。</p> </blockquote> <p> </p> <p>最後に背景とキャラクターをなじませ、全体のバランスを調整をしてレタッチの完成です。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="英雄 マサカドのビッグバナー完成画像 ※クリックすると大きい画像で表示"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200238.png" alt="f:id:sgtech:20200723200238p:plain" title="f:id:sgtech:20200723200238p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">英雄 マサカドのビッグバナー完成画像<br />※クリックすると大きい画像で表示</figcaption> </figure> <p>新生ホーム画面背景にそびえ立つ天魔 アスラおうのビッグバナー画像も上記と似たような工程を経ています。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="天魔 アスラおうのビッグバナー完成画像 ※クリックすると大きい画像で表示"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200723/20200723200138.png" alt="f:id:sgtech:20200723200138p:plain" title="f:id:sgtech:20200723200138p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">天魔 アスラおうのビッグバナー完成画像<br />※クリックすると大きい画像で表示</figcaption> </figure> <p>この後の作業工程ですが、記事前半でご紹介したwaifu2x-caffeを使った拡大変換へとつながっていきます。ここまで長かったですね・・・長文にお付き合いいただきまして、ありがとうございました!</p> <p> </p> <h3 id="まとめ">まとめ</h3> <p>というわけで『D×2』ビッグバナー制作事例いかがでしたでしょうか?</p> <ul> <li>waifu2x-caffeを使って入稿用画像を拡大変換する。</li> <li>waifu2x-caffeの方がPhotoshop (Adobe Sensei)よりもキレイな拡大結果を得られる可能性がある。</li> <li>Photoshopの「コンテンツに応じる」機能はどんどん使ってみる。</li> </ul> <p>辺りがポイントでした。</p> <p>ちょっとしたツールの使い方の違いで作業効率が地味に変わることもあります。今回の記事が皆様にご活用いただける内容でしたら幸いです。</p> <p> </p> <p>セガではこのような取り組みに興味のある方を募集しています。もしご興味を持たれましたら下記サイトにアクセスしてみてください。</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="採用サイト|株式会社セガ -【SEGA Co., Ltd.】" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sega.co.jp%2Frecruit%2Findex.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html">www.sega.co.jp</a></cite></p> <p> </p> <p>最後は『真・女神転生』シリーズ定番のセリフでしめたいと思います。</p> <p>『コンゴトモヨロシク』お願いいたします。</p> <p> </p> <p>©SEGA/©ATLUS</p> <p>セガ・セガロゴ、ゲームギア、ゲームギアミクロ、メガドライブミニは株式会社セガまたはその関連会社の登録商標または商標です。</p> <p>記載されている会社名、製品名は、各社の登録商標または商標です。</p> sgtech 在宅でチームの働き方改革!! hatenablog://entry/26006613585145195 2020-06-15T10:00:00+09:00 2020-06-15T10:28:49+09:00 ごあいさつ 初めまして、株式会社セガ開発技術部の廣島です。 今回のBlogでは新型コロナウィルスの感染拡大防止のために弊社で実施されたリモートワークに関して、私達のチームで起きた問題やその問題に対してどう対応したのかを紹介します。 リモートワークをしてみて、私たちのチームに発生した問題は、コミュニケーションが上手くいかず、チームとしての機能が低下していくことでした。 そして、その原因は距離でした。 チームの間に物理的な距離ができてしまったことで、雑談のような気軽なコミュニケーションが減り、心の距離までもが遠くなってしまったのです。そしてこれまで何事もなく回っていたチームの歯車が、少しずつ噛み合… <h3>ごあいさつ</h3> <p><span class="md-plain">初めまして、株式会社セガ開発技術部の廣島です。</span></p> <p> </p> <p>今回のBlogでは新型コロナウィルスの感染拡大防止のために弊社で実施されたリモートワークに関して、私達のチームで起きた問題やその問題に対してどう対応したのかを紹介します。 </p> <p>リモートワークをしてみて、私たちのチームに発生した問題は、コミュニケーションが上手くいかず、チームとしての機能が低下していくことでした。</p> <p> </p> <p>そして、その原因は<strong>距離</strong>でした。</p> <p> </p> <p>チームの間に物理的な距離ができてしまったことで、雑談のような気軽なコミュニケーションが減り、心の距離までもが遠くなってしまったのです。そしてこれまで何事もなく回っていたチームの歯車が、少しずつ噛み合わなくなっていきました。</p> <p> </p> <p class="md-end-block md-p">しかし、リモートワークなので当然、物理的な距離を近づけることはできません。</p> <p>どうすれば良いのか?何をすればこれまでと同じように上手くチームが回るのか?</p> <p>そういった試行錯誤をした記録とそこから得た知見を共有したいと思います。</p> <p> </p> <p>どうぞ宜しくお願いします。</p> <h3>対象となる読者</h3> <ul> <li> <p>リモート環境でチームとして何かに取り組んでいる</p> </li> <li> <p>リモート環境でこれからチームとしての作業に取り組もうとしている </p> </li> </ul> <p class="md-end-block md-p"><span class="md-plain">そういった方たちの活動の参考になれば幸いです。</span></p> <h3><span class="inline-comment-marker" data-ref="b468afc7-d4dd-457b-ae70-3460aa889e76">仕事の内容</span></h3> <p><span class="md-plain">前置きになりますが、私達が所属する開発技術部はゲームを開発している部署ではありません。</span></p> <p> <span class="md-plain">Windows上で動作する開発支援ツールの作成や、UnityのPlugin開発などを行い、開発現場を支援しています。</span></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200614/20200614231029.png" alt="f:id:sgtech:20200614231029p:plain" title="f:id:sgtech:20200614231029p:plain" class="hatena-fotolife" itemprop="image" /></p> <p class="md-end-block md-p"><span class="md-plain">これは私達が制作している、<span style="color: #172b4d;">企画さんやデザイナさん向けのGit のクライアントツール「Pengit」です。過去には</span><span style="color: #172b4d;">「<a class="external-link" style="text-decoration: none;" href="https://www.macnica.net/github/usersgroup2018_p2.html/" rel="nofollow">第1回 GitHub Enterprise ユーザ会</a></span><span style="color: #172b4d;">」などでも紹介させていただきました。</span></span></p> <p> </p> <p class="md-end-block md-p"><span class="md-plain md-expand">私達のチームにはエンジニアが4人いて、それぞれがツールを作ったりプラグインの開発をしたりと、2人から4人のチームを組んで仕事をしていました。</span></p> <p> <span class="md-plain">4人が関わっているツール作成のプロジェクトに関しては2週間単位で業務の計画を立て振り返りを行うスタイルで開発をしていました。</span></p> <p> <span class="md-plain">それ以外のプロジェクトではやり方はバラバラで必要になったときに都度情報を共有するスタイルで仕事をしていました。</span></p> <p> <span class="md-plain">ビックリするかもしれませんが会社ではお互い席も近く振り向けばそこにチームメンバーがいる環境だったので、このような進め方でも問題ありませんでした。</span></p> <p> </p> <p class="md-end-block md-p md-focus"><span class="md-plain">しかしリモートワークではそう上手くはいかなくなります。が、その話はもう少しあとで紹介します。</span></p> <p> </p> <h4 class="md-end-block md-heading"><span class="md-plain md-expand"><span class="inline-comment-marker" data-ref="d21128e8-b8e2-4896-ad70-d103eda725f0">リモートワーク開始準備  </span></span><span class="md-plain">2月の中頃から</span></h4> <p class="md-end-block md-p"><span class="md-plain">リモートワークを始めるにあたって、在宅で何をするのかを上司とすり合わせました。</span></p> <p class="md-end-block md-p"><span class="md-plain">まず、基礎研究や調査と言った案件は比較的個人でも進めやすいので、これを機に新しい技術を勉強することになりました。</span></p> <p> </p> <p class="md-end-block md-p"><span class="md-plain">リモートワーク期間が短期で終われば新技術の勉強だけで良いですが、問題が長期化することも考え、その場合は在宅でも通常業務を回すという方針を立てました。</span></p> <p> <span class="md-plain">まだこの時点では、出社をする必要があるツールのサポート業務が続いていたため、チーム内で順番に出社する人を決めて週に2日ほど出社する半リモートワーク生活からスタートしました。</span> </p> <p class="md-end-block md-p"><span class="md-plain">当時はまだ緊急事態宣言も発令されていなかったので、出社している人が数多くいたのを覚えています。</span></p> <p> </p> <h4 class="md-end-block md-heading"><span class="md-plain">リモートワーク開始  </span><span class="md-plain">3月</span></h4> <p class="md-end-block md-p"><span class="md-plain md-expand">リモートワークが始まるといくつか困ることが出てきました。</span> </p> <p class="md-end-block md-p">毎日チャットで朝会を行っていたのですが、当初は文字のみでコミュニケーションをとっていたため、あまりにも効率が悪かったのです。</p> <ul> <li>一つの議論に多くの時間が掛かる</li> <li>情報が流れてしまうので、あとから情報を追うのが大変</li> </ul> <p class="md-end-block md-p">そこで、文字のみのチャットは止めて音声チャットを導入しました。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="文字のみで行っていた朝会"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200614/20200614231035.png" alt="f:id:sgtech:20200614231035p:plain" title="f:id:sgtech:20200614231035p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">文字のみで行っていた朝会</figcaption> </figure> <p class="md-end-block md-p"><span class="md-plain">しかしサポートのために出社しているメンバーは周りにも人が居るため音声によるチャットがしにくいなど、環境の不一致による問題が起こりました。</span></p> <p class="md-end-block md-p"><span class="md-plain">機材調達もまだだったのでマイクが無い人、音声チャットそのものに抵抗感がある人もいて、全員が気軽に使える状態ではありませんでした。</span></p> <p class="md-end-block md-p"><span class="md-plain">すると、音声チャットが気軽に使えないことから、あまり大きな問題が無い場合は朝会を短縮もしくは中止してしまうようになりました。それが重なり、徐々にそれぞれのプロジェクトが何をやっているかが見えづらくなっていきました。</span></p> <p class="md-end-block md-p"><span class="md-plain">これはちょっとマズい状態ですが、この当時はまだ基礎研究や調査が中心だったのでそこまで大きな問題にはなりませんでした。</span></p> <p class="md-end-block md-p md-focus"><span class="md-plain">そうしている間にも、新型コロナウィルスの情勢は一向に良くならず長期化が見込まれたため、4月からは完全にリモートワークへ移行することになりました。</span></p> <h4 class="md-end-block md-heading"><span class="md-plain">完全リモートワークへ  </span><span class="md-plain">4月</span></h4> <p class="md-end-block md-p"><span class="md-plain">私たちのチームは4月から完全なリモートワークに移行したのですが、振り返って以下のような問題がありました。</span></p> <ul class="ul-list"> <li class="md-list-item"> <p class="md-end-block md-p"><span class="md-plain">長期間一人で作業をすることで、孤立感が高まっていく</span></p> </li> <li class="md-list-item"> <p class="md-end-block md-p"><span class="md-plain">行き詰まったときに解決に以前より時間が掛かる</span></p> </li> </ul> <p> </p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200614/20200614231047.png" alt="f:id:sgtech:20200614231047p:plain" title="f:id:sgtech:20200614231047p:plain" class="hatena-fotolife" itemprop="image" /></p> <p class="md-end-block md-p"><span class="md-plain">これは「チーム」としてあまり機能していないことが原因だと考えました。マズいと思い進め方を見直しました。</span></p> <p>具体的には以下のように変えました</p> <ol class="ol-list"> <li class="md-list-item"> <p class="md-end-block md-p"><span class="md-plain">リモート朝会を毎日やる!</span></p> </li> <li class="md-list-item"> <p class="md-end-block md-p"><span class="md-plain">時間が掛かっても全プロジェクトを対象に行う</span></p> </li> <li class="md-list-item"> <p class="md-end-block md-p"><span class="md-plain">計画、振り返りを1週間単位に見直す、これも全プロジェクトでやる</span></p> </li> <li class="md-list-item"> <p class="md-end-block md-p"><span class="md-plain">雑談も積極的にする</span></p> </li> <li class="md-list-item"> <p class="md-end-block md-p"><span class="md-plain">小さいことでも皆で褒めよう!</span></p> </li> </ol> <p class="md-end-block md-p"><span class="md-plain">不定期になっていた朝会でしたが、全員がリモートワークに移行しマイクも無事到着したので、全プロジェクトを対象に音声チャットでやることにしました。</span></p> <p class="md-end-block md-p"><span class="md-plain">ダラダラしないようにルールを決めて進めることがポイントです。</span></p> <p class="md-end-block md-p"><span class="md-plain">朝会で設けたルールは以下のようなものです。</span></p> <ul class="ul-list"> <li class="md-list-item"> <p class="md-end-block md-p"><span class="md-plain">前日の作業内容と今日の予定を事前にチャットに書き込んでおく</span></p> </li> <li class="md-list-item"> <p class="md-end-block md-p"><span class="md-plain">共有したいことなども事前にチャットに書き込む</span></p> </li> <li class="md-list-item"> <p class="md-end-block md-p"><span class="md-plain">書いた内容を読み上げるのではなく気になったことのみを報告する</span></p> </li> <li class="md-list-item"> <p class="md-end-block md-p"><span class="md-plain">司会が順番に発言者を指名する</span></p> </li> <li class="md-list-item"> <p class="md-end-block md-p"><span class="md-plain">プロジェクトごとの詳細な議論は朝会の終了後にそれぞれ行う</span></p> </li> </ul> <p class="md-end-block md-p"><span class="md-plain">このあたりのルールやWeb会議のノウハウは今や色々なところで紹介されているので、自分達の状況に合ったものを見つけてくると良いと思います。</span></p> <p class="md-end-block md-p"><span class="md-plain">また情報の共有が終わったあとはそれとなく雑談をするようにしました。時事ネタから技術ネタまで自由に話してOK。もちろん強制ではないので忙しい人は自由に抜けてOKです。</span></p> <p class="md-end-block md-p"><span class="md-plain">こういう空気はとても大事です、雑談を強制されてもツラいだけですしね。</span></p> <p class="md-end-block md-p"><span class="md-plain">あまり長時間にならないように、時間に気を付けながら進めることも大切です。</span></p> <p class="md-end-block md-p"><span class="md-plain">また褒められると嬉しいしハッピーに仕事ができるよね。というわけで、些細なことでも褒めるスタンスで進めていくというルールになりました。</span> </p> <p class="md-end-block md-p"><span class="md-plain">計画から振り返りの期間を1週間に短縮したのにはいくつか理由があります。</span></p> <ul> <li><span style="letter-spacing: 0.0px;">2週間後どうなっているかわからない</span></li> <li><span style="letter-spacing: 0.0px;">2週間分の振り返りをリモートで行うと時間が掛かる</span></li> <li><span style="letter-spacing: 0.0px;">プロジェクトに関わりの無い人を長時間拘束してしまう</span></li> </ul> <p class="md-end-block md-p"> などです。</p> <p>私のチームでは同時に複数のプロジェクトを抱えているという特徴もありこのような理由で期間を短縮しました。</p> <p> </p> <p class="md-end-block md-p"><span class="md-plain">ちなみに朝会を含めた私達のチームで行うWeb会議ではカメラはOFFでやっています。</span></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200614/20200614231051.png" alt="f:id:sgtech:20200614231051p:plain" title="f:id:sgtech:20200614231051p:plain" class="hatena-fotolife" itemprop="image" /></p> <ul> <li>会議の度に部屋を片付けたくない</li> <li>服を着替えたくない</li> </ul> <p>など色々な理由があるのですが、<span class="md-plain">Web会議に対する心理的なハードルを少しでも下げたかったのでカメラはOFFで運用しています。</span></p> <p class="md-end-block md-p"><span class="md-plain">メンドクセと思われたらアウトです。</span></p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="私の作業環境"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200614/20200614231041.png" alt="f:id:sgtech:20200614231041p:plain" title="f:id:sgtech:20200614231041p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">私の作業環境</figcaption> </figure> <p class="md-end-block md-p"><span class="md-plain"><span class="inline-comment-marker" data-ref="1bdc7685-be44-4681-8c36-81737e51ec85">在宅勤務なんだからパジャマで仕事</span><span class="inline-comment-marker" data-ref="1f370569-d72d-498b-9834-7ed09ca69c57">したい</span><span class="inline-comment-marker" data-ref="1bdc7685-be44-4681-8c36-81737e51ec85">と思っている人もいるかもしれません。</span></span></p> <p class="md-end-block md-p"><span class="md-plain">ただカメラをONにしたほうが臨場感は出るので、オンライン発表などするときはカメラがあった方が良いですね。</span></p> <p class="md-end-block md-p"> </p> <p class="md-end-block md-p"><span class="md-plain">最初は時間が掛かって「もう昼じゃん」みたいなこともありましたが、進行の慣れやルールの見直しによって良い感じに進むようになってきました。</span></p> <p class="md-end-block md-p md-focus"><span class="md-plain">こりゃ駄目だなと思ったら柔軟にルールを変え改善していくことが大事です。</span></p> <h4 class="md-end-block md-p md-focus">ルールの見直しの一例</h4> <p>例えば当初は各プロジェクトに対して一人ひとり発言していたのですが、関わりの無い人には無駄な時間なのでプロジェクトごとの確認は行わないようになりました。<br /><span class="md-plain">その代わり各プロジェクトのリーダーが事前にプロジェクトの状況をチェックして問題がありそうであれば共有をするスタイルに変わりました。</span></p> <p class="md-end-block md-p md-focus"><span class="md-plain">発言に関しても、初めの頃は何か意見はありますかと呼びかけていましたが、これを司会が指名する方式に変更しました。<br />これは発言が被ることの防止や、会議の時間短縮に役立っています。</span></p> <h4 class="md-end-block md-heading"><span class="md-plain">気軽に相談や質問ができる環境を作る</span></h4> <p class="md-end-block md-p"><span class="md-plain">雑談や相談は非常に重要で、何か上手くいかない問題があった場合も誰かに相談した途端に解決することは良くあります。</span></p> <p class="md-end-block md-p"><span class="md-plain">雑談や相談がリモートではやりにくかったので、積極的に音声で質問や相談を行えるようにルールを作りました。</span></p> <p class="md-end-block md-p"><span class="md-plain">ルールと言っても話は単純で、事前にチャットで聞くだけです。</span></p> <p class="md-end-block md-p"><span class="md-plain">「今ちょっと良いですか?」</span></p> <p class="md-end-block md-p"><span class="md-plain">「5分待ってください」</span></p> <p class="md-end-block md-p"><span class="md-plain">「わかりました、待ちます」</span></p> <p class="md-end-block md-p"><span class="md-plain">みたいなやり取りをするだけです。</span></p> <p class="md-end-block md-p"><span class="md-plain"><span class="inline-comment-marker" data-ref="1e2fd1a1-4198-4ee1-83b4-eda934327525">数回チャットでやり取りをしても解決しなければ音声チャットに移るルールも作りました。</span></span></p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="時間が掛かりそうだと思ったらすぐに音声チャットへ"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200614/20200614231055.png" alt="f:id:sgtech:20200614231055p:plain" title="f:id:sgtech:20200614231055p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">時間が掛かりそうだと思ったらすぐに音声チャットへ</figcaption> </figure> <p><span class="md-plain">こんな簡単なやり取りですがチームで意識を合わせることでお互いに相談して良いんだ、質問して良いんだという雰囲気ができました。</span></p> <p class="md-end-block md-p md-focus"><span class="md-plain">チャットでのやり取りに関しては、以下のことに気を付けようとチームで共有しました。</span></p> <ul> <li class="md-end-block md-p md-focus"><span class="md-plain"><span style="color: #172b4d;">対面の会話より意図が伝わりにくいので、質問するときは前提条件などを丁寧に書こう</span></span></li> <li class="md-end-block md-p md-focus">対面の会話より感情が伝わり辛いので指摘等はきつくならないよう・誤解を招かないように表記に注意を払おう</li> <li>いいね 等のエモーションを多く使おう</li> </ul> <p>雑談に関しては、雑談専用のチャットルームを作ったり、お昼休みに行うフリーインフリーアウトのビデオチャットルームを作るなどして交流していました。</p> <h4 class="md-end-block md-heading md-focus"><span class="md-plain">結果どうだったか</span></h4> <p class="md-end-block md-p"><span class="md-plain md-expand">毎日朝会を音声チャットでやることで心理的な負担や孤独感を軽くすることができ、</span><span class="md-plain md-expand">音声チャットへの抵抗感も段々と軽減されていきました。</span></p> <p class="md-end-block md-p"><span class="md-plain md-expand">また各プロジェクトの状況もきちんと把握できるようになりました。</span></p> <p class="md-end-block md-p"><span class="md-plain md-expand">相談を積極的に行えるようなルール作り</span><span class="md-plain md-expand">雰囲気作りによって</span><span class="md-plain md-expand">相談や質問の頻度は格段に上がりました。</span></p> <p>相手を褒める姿勢は計画の振り返りの際に、メンバーのファインプレーを挙げたり、フォローされて助かったことなどを相手に伝える行動に繋がりました。</p> <p class="md-end-block md-p"><span class="md-plain">リモートワーク開始当初に比べてチームとして機能するようになったと実感しています。</span></p> <p class="md-end-block md-p"> </p> <p class="md-end-block md-p"><span class="md-plain">以下は週に一度行う振り返りの様子です。振り返りはKPT(Keep・Problem・Try)方式で行っています。</span>継続したい良かったこと、抱えている問題、トライする項目を書き出し共有する方式です。</p> <p class="md-end-block md-p"><span class="md-plain">コミュニケーションに関してはポジティブな意見が多く出ていることがわかります。</span></p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="カンバンを使ったKPT方式の振り返りの様子"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200614/20200614231024.png" alt="f:id:sgtech:20200614231024p:plain" title="f:id:sgtech:20200614231024p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption class="mceEditable">カンバンを使ったKPT方式の振り返りの様子</figcaption> </figure> <h4><span class="md-plain">まとめ</span></h4> <p class="md-end-block md-p"><span class="md-plain">チームで仕事をする上での強みは相互に補強できることにあると思っています。<br /></span><span class="md-plain">チームが上手く回っていないときにそれを妨げている要因は何なのかを見極めることが重要です。</span></p> <p class="md-end-block md-p"><span class="md-plain">それぞれチームによって事情は違うと思いますが、私達の問題はコミュニケーションにあったので、コミュニケーションを改善することに力を入れました。</span></p> <ul> <li class="md-end-block md-p">仕事のやり方、進め方を変える</li> <li class="md-end-block md-p"><span class="md-plain">Web会議への心理的なハードルを下げる</span></li> <li class="md-end-block md-p">機材を調達する(マイクが無いと音声チャットは厳しい)</li> <li class="md-end-block md-p">当たり前のことでもルールとして周知する</li> <li class="md-end-block md-p">チャットでのやり取りで気を付ける点を共有する</li> </ul> <p class="md-end-block md-p"><span class="md-plain">こうすることでリモートワークの良いところをそのままに、悪いところを解消できたのではないかと思います。</span></p> <p class="md-end-block md-p">今後も状況は変わっていくと思いますが、問題を見極めチームの力が発揮できるように頑張っていき<span class="inline-comment-marker" data-ref="7fea1a20-0462-4a9f-9ef0-4017c67ce558">ます。</span></p> <p> </p> <p>セガではより良いチームを目指し、一緒に働いてくれる方を募集しています。</p> <p>興味がある方は下記サイトにアクセスして下さい。</p> <p class="md-end-block md-p md-focus"> </p> <p> </p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="採用サイト|株式会社セガ -【SEGA Co., Ltd.】" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sega.co.jp%2Frecruit%2Findex.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html">www.sega.co.jp</a></cite></p> <p> </p> sgtech Pythonの勉強会(入門編)の事例紹介 ―― アプローチを変えてみる hatenablog://entry/26006613556676118 2020-04-27T10:00:00+09:00 2020-05-22T16:39:39+09:00 特にこういった方によんでいただけたら・・・ 今回のブログは主に次のような方に向けて、Python の社内勉強会を開催した事例を紹介します。 Python に興味があって学習したいと考えているが何から手をつけてよいかわからない Python などプログラミング言語の勉強会をこれから開こうと考えている TA(テクニカルアーティスト)やスクリプターなどに Python の使い手をもっと増やしたいと考えている プログラミング言語を学ぶ側と教える側、両方の方にとって何か少しでもヒントになれば幸いです。 今回のブログで伝えたいこと Pythonの勉強会(全4講演を予定)の入門編である第1回目の講演について… <h3>特にこういった方によんでいただけたら・・・</h3> <p>今回のブログは主に次のような方に向けて、Python の社内勉強会を開催した事例を紹介します。</p> <ul> <li>Python に興味があって学習したいと考えているが何から手をつけてよいかわからない</li> <li>Python などプログラミング言語の勉強会をこれから開こうと考えている</li> <li>TA(テクニカルアーティスト)やスクリプターなどに Python の使い手をもっと増やしたいと考えている</li> </ul> <p>プログラミング言語を学ぶ側と教える側、両方の方にとって何か少しでもヒントになれば幸いです。</p> <p> </p> <h3>今回のブログで伝えたいこと</h3> <p>Pythonの勉強会(全4講演を予定)の入門編である第1回目の講演について予想以上に盛況となった自身の成功体験から得た知見を最初に共有させていただきます。</p> <ul> <li>プログラミング(Python)を学びたいと思っているオトナでかつプログラミング経験ゼロないし初心者に対する入門としては<strong>ビジュアルプログラミング</strong>や<strong>作業分解</strong>が教材としては有効である</li> <li>いきなりPythonに手をつけることは一旦我慢して、まずは<span style="font-weight: bold;">プログラミング</span>の基本(<span style="font-weight: bold;">順次処理</span>、<span style="font-weight: bold;">条件分岐</span>、<span style="font-weight: bold;">繰り返し</span>)を学ぶことが近道である</li> <li>先にたっぷり<strong>自信</strong>をつけた上で少し困難なことにチャレンジして<strong>成功体験</strong>を得られるサイクルになるようになるべく交通整理することで挫折せず継続できる</li> </ul> <p> </p> <p>それではPythonを学びたい方、教えたい方への入門の参考教材として、<br />勉強会当日の内容についてご紹介しようと思います。</p> <h3>第1回目の勉強会の内容とは</h3> <p>当日はワークショップ形式にて開催しました。ワークショップ形式にすることで、</p> <ul> <li>グループ内での協力</li> <li>発想の違いの発見</li> <li>安心感の向上</li> <li>チームメンバを意識することで集中力の向上</li> </ul> <p>などの効果を期待して設定しました。</p> <p>またパソコンは使わずに、運営側で鉛筆とプログラムを書くための用紙を準備して、手ぶらでも参加できるようにしました。</p> <p> <strong>用紙イメージ</strong><br /><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200426/20200426204520.png" alt="f:id:sgtech:20200426204520p:plain" title="f:id:sgtech:20200426204520p:plain" class="hatena-fotolife" itemprop="image" width="159" /></p> <p>時間の使い方としては、</p> <ul> <li>事前説明に5分</li> <li>順次処理の学びに30分(ビジュアルプログラミング)</li> <li>順次処理+条件分岐+繰り返しの学びに25分(作業分解)</li> </ul> <p>で設定しました。</p> <h4>順次処理の学びについて</h4> <p>最初は<strong>ビジュアルプログラミング</strong>を通して、順次処理だけに集中して学んでいただきました。<br />ここでは、</p> <ul> <li>「自分はできるんだ」</li> <li>「プログラミングって想像してたより簡単かも」</li> </ul> <p>などといった、自分に自信をつけていただくことが最大の目的です。後半の<strong>作業分解</strong>の課題の難易度が1段上がることがわかっているため、ここでどの程度自信をつけていただくかによって、後半の課題に対する印象がガラッと変わります。</p> <p>あともう1つ大事な目的があります。それはプログラミングすることで課題を解決する力を高めることです。</p> <p> </p> <p>教材としては、コマンドをつかってキャラクタを操作して宝箱まで導くといったプログラミングのアナログ的なゲームを準備しました。</p> <p>それでは、コマンドから見ていきましょう。</p> <h5>コマンドの紹介</h5> <p>キャラクタは各コマンドの内容にしたがって動かすことができます。 </p> <table style="height: 305px;" border="1" width="407"> <tbody> <tr> <th>コマンド(記号)</th> <th>コマンドの内容</th> </tr> <tr> <td> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200426/20200426204457.png" alt="f:id:sgtech:20200426204457p:plain" title="f:id:sgtech:20200426204457p:plain" class="hatena-fotolife" itemprop="image" /></p> </td> <td><span style="font-size: 150%;">向いている方向に1マス進む</span></td> </tr> <tr> <td> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200426/20200426204501.png" alt="f:id:sgtech:20200426204501p:plain" title="f:id:sgtech:20200426204501p:plain" class="hatena-fotolife" itemprop="image" width="95" /></p> </td> <td><span style="font-size: 150%;">時計回りに90度回転</span></td> </tr> <tr> <td> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200426/20200426204505.png" alt="f:id:sgtech:20200426204505p:plain" title="f:id:sgtech:20200426204505p:plain" class="hatena-fotolife" itemprop="image" /></p> </td> <td> <p><span style="font-size: 150%;">反時計回りに90度回転</span></p> </td> </tr> </tbody> </table> <p>コマンド3つを理解したところで早速課題に移りたいと思います。</p> <h5> 課題その1</h5> <p>下図の青いキャラクタを先ほど学んだコマンドをつかって宝箱まで到着できれば、課題クリアです。参加者にはプログラムを書く用紙の縦1行を使って、コマンドを鉛筆で書き足してプログラムを完成させていただきます。</p> <p>正解はたくさんあります。正解の1例としては、下図右側の「プログラム例」をご覧ください。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200426/20200426204509.png" alt="f:id:sgtech:20200426204509p:plain" title="f:id:sgtech:20200426204509p:plain" class="hatena-fotolife" itemprop="image" /></p> <p><br /><br /></p> <p>またこの課題その1において難易度をあげたければ、以下のような条件を加えてあげましょう。</p> <ul> <li>課題その1-A:コマンド(どれでも構わない)を9つぴったり使って宝箱まで導いてください</li> <li>課題その2-B:3種類すべてのコマンドを使って宝箱まで導いてください</li> </ul> <h5> 課題その2</h5> <p>新しいルールとして「岩」を追加します。岩のあるマスはキャラクタは通ることができません。課題クリアの条件は課題その1と同じですが、参加者は岩をうまく避ける形でプログラムを作成する必要があります。ルールを追加することで課題の難易度をバランスよくあげていきます。</p> <p>こちらも正解はたくさんあります。正解の1例としては、下図右側の「プログラム例」をご覧ください。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200426/20200426204514.png" alt="f:id:sgtech:20200426204514p:plain" title="f:id:sgtech:20200426204514p:plain" class="hatena-fotolife" itemprop="image" /></p> <p>マスを増やしたり、岩の位置や数を変える(必ず宝箱には到達できる並びにしました。)ことで、難易度を調整することもできます。その場合はよりプログラムが複雑になり、コマンドを書き込む枠を増やす必要があるかもしれません。</p> <h5>ぷちエピソード</h5> <p>勉強会当日、道を岩で完全に塞ぐように配置して宝箱への道を絶ったあとに参加者の皆様に「この場合、どういうプログラムを書けば、宝箱まで到達できますか」と無茶ぶりな質問をしてみました。</p> <p>すると1人の優秀な方が、「<strong>マスの外は歩けないというルールは聞いてない</strong>ので、マスの外に出て迂回して移動するようにコマンドを書けば良いと思います」という異次元の回答を出してくれました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200426/20200426204524.png" alt="f:id:sgtech:20200426204524p:plain" title="f:id:sgtech:20200426204524p:plain" class="hatena-fotolife" itemprop="image" /></p> <p><br /><br /><span style="font-size: 13pt;">「とっても素晴らしい正解です!」と賞賛させていただきました。</span></p> <p>回答者の方が一枚上手でした。</p> <p>わたしはまだまだプログラマとして、ルールの詰めの部分で修行が足りていなかったというわけです。。。</p> <p>プログラミングの世界ではこういったルール抜け、欠陥のことをバグといいます。バグによってこちらが意図しないような想定外の問題を引き起こします。</p> <p>色々な状況や問題を事前にすべてもれなく想像できるようになれることが最高です。</p> <p> </p> <p>このブログを今よんでくださっているあなたも時間が許すようなら鉛筆と紙を準備して、今回の課題のプログラムをご自分の手で書いてみてください。</p> <p>プログラミングと聞くとパソコンで何か作業をするイメージがとても強いですが、実はそうではないことがわかっていただけたのではないでしょうか。</p> <p>順次処理がどういったものかイメージはつかめたでしょうか?</p> <p>プログラミングって意外とカンタンではありませんか?</p> <p>今回、記号(絵)を使ってプログラムを書きましたが、絵や図を用いるプログラミングを <strong>ビジュアルプログラミング </strong>といいます。ビジュアルプログラミングとして有名なものとして「ScratchJr(スクラッチジュニア)」、「Scratch(スクラッチ)」などがあります。無料のアプリケーションですので気になる方は調べて触ってみてください。</p> <p>ちなみにPythonはというと、文字や数字、また記号を用いるプログラミングで <span style="font-weight: bold;">テキストプログラミング </span>といいます。</p> <p><br />前半は以上となります。</p> <h4>順次処理に加えて、繰り返し、条件分岐の学び</h4> <p>後半では作業分解を行うことで、プログラミングの<strong>三種の神器</strong>である</p> <ul> <li>順次処理(シーケンスともいいます)</li> <li>繰り返し(ループともいいます)</li> <li>条件分岐</li> </ul> <p>について学んでいただきました。</p> <p><strong>どんな作業でもこの3つを駆使すれば再現できます。</strong></p> <p>では、当日準備した教材についてご紹介します。</p> <h4>カレー作りの工程を作業分解して学ぶ</h4> <p>まずはカレー作りの工程の例をあげて、「作業分解する」ということがどんな感じなのか学んでいただきました。</p> <p>わたしなりにカレー作りの工程を作業分解したものがこちらになります。</p> <ol> <li>野菜の皮をむいて野菜やお肉を一口大に切る</li> <li>野菜やお肉を油で炒めて鍋に入れて水を足す</li> <li>煮込む</li> <li><span style="color: #d32f2f;"><strong>野菜がやわらかくなったか?</strong></span><br /><span style="color: #d32f2f;"><strong>Yesなら5へ、Noなら3へ</strong></span></li> <li>ルゥを溶かして煮込む</li> <li>カレー完成(※作業ではないですがわかりやすくするために)</li> </ol> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200426/20200426204528.png" alt="f:id:sgtech:20200426204528p:plain" title="f:id:sgtech:20200426204528p:plain" class="hatena-fotolife" itemprop="image" /></p> <p>基本的には1から順に行う順次処理となりますが、ポイントは4の作業です。<br />野菜がやわらかいのかそうでないかで<strong>その後の進むべき道が枝分かれする</strong>ことが条件分岐の考えです。<br />そして「<strong>野菜がやわらかくなる」</strong>という条件が満たされるまでひたすら3→4→3→4→…を繰り返して野菜を煮込み続けることが繰り返しの考えです。</p> <p>几帳面な方だと、3と4の間にアクをとる作業を追加で入れたりするかもしれません。</p> <p>また人によっては2と3の間に隠し調味料を入れる作業を追加するかもしれませんし、野菜を水で洗ってないことには気づきましたか。あなたならどこに追加しますか?</p> <p>「作業分解する」ことについて、なんとなくイメージは掴んでいただけましたでしょうか。</p> <p> </p> <p>次は参加者に日頃よく行っているあることについて、実際に作業分解を行っていただきました。</p> <h4>お題は「洗濯」</h4> <p>当日はグループごとにメンバ全員で相談し合って「洗濯」の作業を分解していただきました。</p> <p>複数人で考えることで、他のメンバの考えを聞いて何か発見があったり、あと前半よりも難易度が上がっている点にみんなで考えれば怖くないといったことなどに期待しました。</p> <p>また自由に想像・発想してほしかったこともあって、あえてこちらからは条件はつけずに、どういう設定でどこまで細かく分解するかも含めて考えていただきました。</p> <h5><strong>当日の回答を少しだけ</strong></h5> <p>参考に勉強会当日に、あるグループが作成した洗濯の作業分解の回答を1つだけのせておきます。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200426/20200426204532.png" alt="f:id:sgtech:20200426204532p:plain" title="f:id:sgtech:20200426204532p:plain" class="hatena-fotolife" itemprop="image" width="253" /></p> <p><br /><br />条件分岐と繰り返しをちゃんと理解して使っていることがわかります。<br />今回紹介した回答はブログで掲載するためにぱっとみてわかりやすいものを選びましたが、他の回答ではもっと複雑に作業分解されているものも多くあったり、どのグループも理解力の高さに驚かされるものがたくさんありました。<br />たまたま賢い方ばかりが勉強会に参加されていた可能性も十分に考えられます。</p> <p>あなたが日頃無意識に行っている洗濯ではどういう手順で行ってますか?試しに書き出してみると、意外と色々なことを行っている自分(人)の優秀さに気づくかもしれません。</p> <p>もしロボット(コンピュータ)に洗濯させるとなると一から十まですべて手とり足とり教えてあげないといけません。</p> <p> </p> <p>以上が勉強会の内容となります。</p> <p>日頃の業務において何か改善したいと思ったときに、どういう手順でどの作業を行って解決するか、その一連の流れを考えることがとても大事です。作業分解を実際に行うことで、この課題を解決するための力、すなわちプログラミング能力を高めることが大いに期待できます。<br /><br /></p> <h3>講師としての成功体験とは</h3> <p>Pythonの勉強会の講師を行っての成功体験をいくつかご紹介しようと思います。</p> <ul> <li>参加人数110人は過去最高を記録</li> <li>アンケート結果がおおむね良好で、特に講演の理解についてはアンケート結果的に全員理解できた様子なのでわたし自身の目標としていた脱落者0についてはおそらく達成できた</li> <li>アンケートの所感欄でも非常にポジティブな所感を多くよせていただいた</li> </ul> <h5>実際のアンケート結果</h5> <p>設問:<strong>当セッションの内容は如何でしたか?<br /></strong><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200426/20200426204535.png" alt="f:id:sgtech:20200426204535p:plain" title="f:id:sgtech:20200426204535p:plain" class="hatena-fotolife" itemprop="image" width="359" /></p> <p>設問:<strong>講演の内容は理解できましたか?<br /></strong><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200426/20200426204542.png" alt="f:id:sgtech:20200426204542p:plain" title="f:id:sgtech:20200426204542p:plain" class="hatena-fotolife" itemprop="image" width="352" /></p> <p>設問:<strong>講演は今後の業務に役に立ちそうですか?<br /></strong><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200426/20200426204546.png" alt="f:id:sgtech:20200426204546p:plain" title="f:id:sgtech:20200426204546p:plain" class="hatena-fotolife" itemprop="image" width="347" /></p> <p><strong>印象に残る所感として</strong></p> <p>60個程度の勉強会に対する所感をいただきましたが、どの所感もわたしにとってはありがたい内容ばかりで、その中でも特に印象に残るものをピックアップしました。 </p> <ul> <li> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px '.Hiragino Kaku Gothic Interface';">グループの方と交流しながらできたのは楽しかったです。プログラミングへの難しそうという意識がなくなった気がします。</p> </li> <li> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px '.Hiragino Kaku Gothic Interface';">ムズカシいのを覚悟していたのですが、非常に楽しく参加できました!</p> </li> <li> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px '.Hiragino Kaku Gothic Interface';">分かりやすかった。プログラミングに対する恐怖感が減った気がした</p> </li> <li> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px '.Hiragino Kaku Gothic Interface';">プログラミングに苦手意識があったので、絵を使った導入で、これなら自分でも続けられるかも・・・?と思いました。<span style="font: 12.0px 'Helvetica Neue';">Pyson</span>使える様になればよいな・・・最後ちょっと慌ただしかったかも?</p> </li> <li> <p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px '.Hiragino Kaku Gothic Interface';">プログラミングをしたことがなかったので、理解できるのか不安でしたが、理解することができました。ありがとうございます。</p> </li> </ul> <p>以上の所感からは参加者の中にはやはり苦手意識や不安などをお持ちの方がそれなりにいらっしゃって、そういった方がプログラミングに対して自信を持ってくれたことが自分としては一番の成功体験でした。</p> <p>また「次回も楽しみ」といった次への前向きな所感も数多くよせていただいたことも講演者としては非常にありがたく、第2回目への準備にもさらに力が入るきっかけを与えてくれました。</p> <h4> 勉強会あとの反響として</h4> <p>今回はまだ第1回目ということもあって反響は少ないものの、資料に関するお問い合わせがあったり、別のグループ会社様からプログラミングの勉強会に関する相談の打ち合わせをさせていただいたりしました。とにかく評判がよかったことだけは確かなようです。 </p> <h3><strong>そういえば。 Python勉強会の開催のキッカケについて</strong></h3> <p>わたしがPythonの勉強会を企画するきっかけを与えてくださったのは何名かのTA(テクニカルアーティスト)の方の以下の声を拾ったからでした。<br />(声をあげていただいたTAの皆様にはこの場をお借りして心よりお礼申し上げます。)</p> <ul> <li>TAをもっと増やしたい</li> <li>Python使いを増やしたい</li> </ul> <p>Pythonの勉強会を開くにしても、ふたをあけてみて需要がなければ開催の意味がないので先に本当に需要があるのかどうか裏をとるために各部デザインセクションのマネージャの皆様のご協力の元で、グループ内のデザイナーの方へのアンケート調査を行いました。<br />するとアンケート結果から、</p> <ul> <li>Pythonの勉強会に参加したい割合は確かに多い(90%)</li> <li>Pythonを触ったことがないもしくは少ししか触ったことがない方の割合が多い(76%)</li> </ul> <p>という非常に興味深い傾向がわかりました。</p> <p>今回のPythonの勉強会はまさにこの約76%をターゲットにした内容になっています。</p> <p>またプログラミングの入門から行うのであれば、デザイナーだけに職種を絞る必要はないことなどから職種は問わないように最終的に変更しました。</p> <p>職種を絞らなかったことが、結果的に参加人数100人を超える勉強会につながりました。<br />(アンケート結果:デザイナー62%、それ以外の業種38%)</p> <h3>最後はこのブログの「<strong>オチ」をあてようのコーナー</strong></h3> <p>最後はこのブログの<strong>オチ</strong>をあてようのコーナーです。</p> <p>すでに過去のセガの技術ブログに足を運んでいただいた方や、他の企業様のエンジニアブログなどをよくご覧になっている方なら、すでにこのブログのオチがかんたんに予測できているのではないでしょうか?</p> <p>まだオチがわからない方は、いくつか過去のブログをチェックしてみてください。<a href="http://techblog.sega.jp/entry/2020/02/25/100000">この記事</a>や、<a href="http://techblog.sega.jp/entry/2018/01/25/100000">この記事</a>や、<a href="http://techblog.sega.jp/entry/2017/07/26/100000">この記事</a>などにヒントが隠されてます。</p> <p>そのまま行って帰ってこない可能性ももちろんありますが、そういったオチも正解の1つだと思います。</p> <p> <br />弊社ではPython勉強会以外にも、月例の勉強会としてグループ内の色々な立場の方が講師を行ってくださっています。社外からゲスト講師をお招きしてすることもあります。また月例の勉強会以外にも <a href="http://techblog.sega.jp/entry/2017/04/26/100000">SDC</a> や <a href="http://techblog.sega.jp/entry/2019/06/25/100000">各種イベント(GDCやCEDEC)の報告会</a>、プロジェクト内の勉強会などグループ内には多種多様な勉強会があります。</p> <p>弊社では、勉強会などを通じて自他共栄を行える人を求めています。</p> <p>みんなで共に成長して感動体験をたくさん創造しあえたら幸いです。(開発技術部 菊川) </p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="採用サイト|株式会社セガ -【SEGA Co., Ltd.】" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sega.co.jp%2Frecruit%2Findex.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html" onmousedown="ga('HatenaBlogUserTracker.send', 'event', 'recruit', 'games_banner_clicked','recruit_games_out', true);">www.sega.co.jp</a></cite></p> <p><strong style="font-style: normal; font-variant-caps: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; caret-color: #000000; color: #000000; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px;">©SEGA</strong></p> sgtech スケジュール作成をもっと簡単に。内製アプリケーション「ScheduleCanvas」 hatenablog://entry/26006613518242506 2020-02-25T10:00:00+09:00 2020-04-02T10:02:22+09:00 早速ですが皆さん。 プロジェクトの計画を立てるとき、スケジュールの作成が面倒だと感じたことはありませんか? 汎用的なExcel等のツールを使って作成すると、まずは管理するためにフォーマットを決めなければならず、途中でのタスクの入れ替えやパスの変更はなかなか容易ではありません。 市販のツールを使おうにもただ試すだけにはハードルが高すぎたり・・・。 そういった悩みを解消するために社内開発に踏み切ったのが、内製アプリケーション「ScheduleCanvas(スケジュールキャンバス)」です。 今回のBlogではこのツールの仕様と、スケジュール作成がどう変わったのかを紹介するとともに、ツール実装における… <p>早速ですが皆さん。</p> <p>プロジェクトの計画を立てるとき、スケジュールの作成が面倒だと感じたことはありませんか?</p> <p>汎用的なExcel等のツールを使って作成すると、まずは管理するためにフォーマットを決めなければならず、途中でのタスクの入れ替えやパスの変更はなかなか容易ではありません。</p> <p>市販のツールを使おうにもただ試すだけにはハードルが高すぎたり・・・。</p> <p>そういった悩みを解消するために社内開発に踏み切ったのが、内製アプリケーション「ScheduleCanvas(スケジュールキャンバス)」です。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200206/20200206212358.png" alt="f:id:sgtech:20200206212358p:plain" title="f:id:sgtech:20200206212358p:plain" class="hatena-fotolife" itemprop="image" /></p> <p>今回のBlogではこのツールの仕様と、スケジュール作成がどう変わったのかを紹介するとともに、ツール実装におけるノウハウの一部を少しだけ紹介します。</p> <p>今回このブログを担当するのは、セガゲームス 第3事業部 第3開発2部 テクニカルサポートセクションの麓です。</p> <p>まずは私からScheduleCanvasとはどんなアプリケーションなのかなど説明していきたいと思います。</p> <ul class="table-of-contents"> <li><a href="#ScheduleCanvasってどんなツールなの">ScheduleCanvasってどんなツールなの?</a><ul> <li><a href="#単体で使用できるアプリケーション">単体で使用できるアプリケーション</a></li> <li><a href="#ガントチャートと各リストで構成">ガントチャートと各リストで構成</a><ul> <li><a href="#タスクの作成">タスクの作成</a></li> <li><a href="#担当者変更">担当者変更</a></li> <li><a href="#休日の自動調整">休日の自動調整</a></li> <li><a href="#オート整列機能">オート整列機能</a></li> <li><a href="#リスト処理タスク一覧">リスト処理「タスク一覧」</a></li> <li><a href="#リストのフィルター機能">リストのフィルター機能</a></li> </ul> </li> <li><a href="#外部連携">外部連携</a></li> </ul> </li> <li><a href="#その効果は">その効果は?</a><ul> <li><a href="#質問ScheduleCanvasを利用するメリットを感じますか">質問:ScheduleCanvasを利用するメリットを感じますか?</a></li> <li><a href="#質問ScheduleCanvasを利用して効率化した部分はありましたか">質問:ScheduleCanvasを利用して、効率化した部分はありましたか?</a></li> <li><a href="#良い意見">良い意見</a></li> <li><a href="#改善が必要な意見">改善が必要な意見</a></li> </ul> </li> <li><a href="#今後も">今後も・・・</a></li> <li><a href="#実装ノウハウをちょっとだけ">実装ノウハウをちょっとだけ</a></li> </ul> <h3 id="ScheduleCanvasってどんなツールなの">ScheduleCanvasってどんなツールなの?</h3> <h4 id="単体で使用できるアプリケーション">単体で使用できるアプリケーション</h4> <p>このツール開発は、スケジュール表の作成、タスクの入れ替えをExcelから脱却し、煩雑なフォーマットを統一するためにスタートしました。</p> <p>また、WebサービスやDBを社内向けに作ってしまうと、外部協力会社との連携のときの障壁が多かったことと、とりあえずアプリケーションを作ってみることでどこまで効果があるのかを見てみるには大きなシステムは向かないということで、単体で動くexe、アプリケーションとして開発されました。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="アイコン"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200206/20200206212540.png" alt="f:id:sgtech:20200206212540p:plain" title="f:id:sgtech:20200206212540p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption>アイコン</figcaption> </figure> <h4 id="ガントチャートと各リストで構成">ガントチャートと各リストで構成</h4> <p>画面要素はガントチャートをベースにそこに表示されるデータがリスト形式になっています。</p> <p>ガントチャートによって、スケジュールの可視化ができ、マウス操作を充実させることで、簡単にタスクの入れ替えや調整ができるように作られています。</p> <p>主な動作をいくつか紹介します。</p> <h5 id="タスクの作成">タスクの作成</h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200206/20200206213605.gif" alt="f:id:sgtech:20200206213605g:plain" title="f:id:sgtech:20200206213605g:plain" class="hatena-fotolife" itemprop="image" /></p> <p><br /><br />タスクをガントチャート上で簡単に登録でき、タスク名も即座に変更することができます。</p> <h5 id="担当者変更">担当者変更</h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200206/20200206215139.gif" alt="f:id:sgtech:20200206215139g:plain" title="f:id:sgtech:20200206215139g:plain" class="hatena-fotolife" itemprop="image" /></p> <p>担当者の追加とタスクのアサイン変更もドラッグ&ドロップで手軽に行えます。</p> <h5 id="休日の自動調整">休日の自動調整</h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200207/20200207160420.gif" alt="f:id:sgtech:20200207160420g:plain" title="f:id:sgtech:20200207160420g:plain" class="hatena-fotolife" itemprop="image" /></p> <p>タスクの長さは工数(日数)ベースで設定されていますので、休日を跨ぐと自動で長さを調節します。</p> <h5 id="オート整列機能">オート整列機能</h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200207/20200207160951.gif" alt="f:id:sgtech:20200207160951g:plain" title="f:id:sgtech:20200207160951g:plain" class="hatena-fotolife" itemprop="image" /></p> <p>複数のタスクを並べ直して総工数を確認する機能も充実しています。</p> <p> </p> <p>また、ガントチャートに表示される情報は全てリスト形式で管理され、リストの編集性もできるだけExcelに近づくように(完全再現への道はまだ遠いですが)設計されています。</p> <p>例えば、リスト項目のコピペや追加、削除、順番の入れ替えは簡単にできるように作られています。</p> <h5 id="リスト処理タスク一覧">リスト処理「タスク一覧」</h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200207/20200207185005.gif" alt="f:id:sgtech:20200207185005g:plain" title="f:id:sgtech:20200207185005g:plain" class="hatena-fotolife" itemprop="image" /></p> <p>Excelのような外部アプリケーションのリストから、コピー&ペーストでタスク登録、一覧のセルの内容のコピーペースト、値も外部アプリケーションからコピーペーストで設定することもできます。</p> <h5 id="リストのフィルター機能">リストのフィルター機能</h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200207/20200207192447.gif" alt="f:id:sgtech:20200207192447g:plain" title="f:id:sgtech:20200207192447g:plain" class="hatena-fotolife" itemprop="image" /></p> <p>各要素のフォーカスを切り替えられるようなフィルター機能は大量のタスクを管理するのには重要な機能です。</p> <p> </p> <p>また、スケジュール作成の簡便化やフォーマットの統一等はScheduleCanvasを使ってもらうことで解決していますので、印刷や報告書などに活用できるようにExcel出力機能も用意しています。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200207/20200207193346.png" alt="f:id:sgtech:20200207193346p:plain" title="f:id:sgtech:20200207193346p:plain" class="hatena-fotolife" itemprop="image" /></p> <p>このように、主だった機能はゲーム開発者であるユーザーのニーズに常に答えるようにしてアプリケーションは開発されました。</p> <h4 id="外部連携">外部連携</h4> <p>Excelの他にも各種チケット管理やバグトラッキングシステムなどと連携させて、ガントチャート視覚化も実装済みですが、今回は記事のボリュームを考慮して割愛させていたできます。</p> <h3 id="その効果は">その効果は?</h3> <p>機能実装がある程度落ち着き、現在では多くのプロジェクトで試用してもらっています。</p> <p>そこで今後の開発継続に向けて参考にするために、ちょっとしたアンケートをとって見ました。</p> <p>集計結果は…。</p> <h5 id="質問ScheduleCanvasを利用するメリットを感じますか">質問:ScheduleCanvasを利用するメリットを感じますか?</h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200207/20200207194313.png" alt="f:id:sgtech:20200207194313p:plain" title="f:id:sgtech:20200207194313p:plain" class="hatena-fotolife" itemprop="image" /></p> <h5 id="質問ScheduleCanvasを利用して効率化した部分はありましたか">質問:ScheduleCanvasを利用して、効率化した部分はありましたか?</h5> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200207/20200207194316.png" alt="f:id:sgtech:20200207194316p:plain" title="f:id:sgtech:20200207194316p:plain" class="hatena-fotolife" itemprop="image" /></p> <p>ここでは概ねポジティブな印象です。</p> <p>また、意見として以下のようにもいただいていますので、ひとつひとつを参考にさらに使いやすいツールにするために開発を続行していきます。</p> <h5 id="良い意見">良い意見</h5> <ul> <li>スケジュールの入れ替え、パスの調整等にかかる時間が短縮した。</li> <li>ユーザーのタスク負担度が一目でわかる。</li> <li>今までバラバラだったスケジュールのフォーマットが統一され、見やすくなった。</li> </ul> <h5 id="改善が必要な意見">改善が必要な意見</h5> <ul> <li>タスクの検索がExcelの検索より一覧性がない。</li> <li>開発会社に委託する業務が多く、他社提出のスケジュール(Excel)との共存が難しい。</li> <li>動作をとにかく軽くしてほしい。</li> </ul> <p>他にもアンケートとは別にExcelで管理してたときよりも確実に30%は効率化できているという声もありました。</p> <p>社内ツールを開発する上で定期的なアンケートはとても有用で、現在主にどう使われていて、何が一番ボトルネックになっているのかのスコープを探るときに活用しています。</p> <h4 id="今後も">今後も・・・</h4> <p>内製アプリケーションということで、手軽なカスタマイズや要望に応じて機能実装を即時対応できるというのが大きなメリットとなります。</p> <p>単純なスケジューラーは数あれど、ゲーム開発の現場でゲーム開発の状況に応じて作られているアプリケーションは他の会社だったとしても同じような問題に行き当たることが多いと思います。</p> <p>こういったゲーム会社に特化した内製ツールだからこそ、会社の枠を超えていつか提供できるようにして、業界に貢献できたらという願いで製作しています。</p> <p>ご興味ある方は…と言いたいですが、現時点ではそういった準備が整っていないので今しばらくお待ち下さい。</p> <h3 id="実装ノウハウをちょっとだけ">実装ノウハウをちょっとだけ</h3> <p>ここからは実装担当の清水から、このアプリケーションの実装について軽く触れてもらおうと思います。</p> <p> </p> <p>というわけで本パートを担当させていただきます、セガゲームス 第3事業部 第3開発2部 テクニカルサポートセクションの清水です。</p> <p> </p> <p>今回は、いろいろと応用ができそうなExcel出力に関する実装について紹介しようと思います。</p> <p> ScheduleCanvasのExcelファイルの出力にはClosedXMLというオープンソースライブラリを使用しています。(<a href="https://github.com/ClosedXML/ClosedXML">https://github.com/ClosedXML/ClosedXML</a>)</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/n/nobutoshi_shimizu/20200213/20200213162255.png" alt="f:id:nobutoshi_shimizu:20200213162255p:plain" title="f:id:nobutoshi_shimizu:20200213162255p:plain" class="hatena-fotolife" itemprop="image" /></p> <p>簡単なコードでExcelワークシートを作成することができ、Excelファイル(.xlsx)で保存することができます。</p> <p>また、PCにExcelのソフトウェアがインストールされていなくてもExcelファイルを作成することができます。これは、スタンドアロンツールであるScheduleCanvasにとって、とてもありがたい特徴でした。</p> <p>NuGetからインストールできるのでVisual Studioを使用しているならば、インストールも簡単にできます。 </p> <p> </p> <p>ClosedXMLを用いてExcelファイルを作成するには以下のようなコードを書きます。</p> <blockquote> <p>//新規ワークブックを作成<br />var workbook = new XLWorkbook();</p> <p>//新規ワークシート「Sample Sheet」を作成し、先ほど作成したワークブックに追加<br />var worksheet = workbook.Worksheets.Add("Sample Sheet");</p> <p>//作成したワークブックを"HelloWorld.xlsx"として別名で保存<br />workbook.SaveAs("HelloWorld.xlsx");</p> </blockquote> <p>このコードでは、初めに新規ワークブックを作成し、そのワークブックに新たなワークシート「Sample Sheet」シートを作成、ワークブックを「HelloWorld.xlsx」として保存しています。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="作成されたHelloWorld.xlsx"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200223/20200223205604.png" alt="f:id:sgtech:20200223205604p:plain" title="f:id:sgtech:20200223205604p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption>作成されたHelloWorld.xlsx</figcaption> </figure> <p>では次に、ワークシートに何か値を入れてみましょう。</p> <blockquote> <p>//新規ワークブックを作成<br />var workbook = new XLWorkbook();</p> <p>//新規ワークシート「Sample Sheet」を作成し、先ほど作成したワークブックに追加<br />var worksheet = workbook.Worksheets.Add("Sample Sheet");</p> <p>//「Sample Sheet」シートのA1セルの内容に"Hello World!"を記入<br />worksheet.Cell("A1").Value = "Hello World!";</p> <p>//作成したワークブックを"HelloWorld.xlsx"として別名で保存<br />workbook.SaveAs("HelloWorld.xlsx");</p> </blockquote> <p>このコードでは、初めに新規ワークブックを作成し、そのワークブックに新たなワークシート「Sample Sheet」シートを作成、「Sample Sheet」シートのセルA1に「Hello World!」を記入して、ワークブックを「HelloWorld.xlsx」として保存しています。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="A1セルにHello World!を入力した出力結果"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200223/20200223205713.png" alt="f:id:sgtech:20200223205713p:plain" title="f:id:sgtech:20200223205713p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption>A1セルにHello World!を入力した出力結果</figcaption> </figure> <blockquote> <p>//「Sample Sheet」シートのA1セルの内容に"Hello World!"を記入<br />worksheet.Cell("A1").Value = "Hello World!";</p> </blockquote> <p>この部分がセルに値をセットする部分です。</p> <p>セルの指定方法は、複数あります。<br /> 以下のコードはいずれもA1セルを指定しています。</p> <blockquote> <p>//セルのアドレスの文字列で指定<br />worksheet.Cell("A1").Value = "Hello World!";</p> <p>//セルの行と列の数字で指定 ※最小は1、0だとエラーになる<br />worksheet.Cell(1, 1).Value = "Hello World!";</p> <p>//セルの行は数字、列は文字列で指定<br />worksheet.Cell(1, "A").Value = "Hello World!";</p> </blockquote> <p>実際にプログラムを組む際は一番よく使うのは、行と列ともに数字で指定する方法になるかと思います。</p> <p> </p> <p>セルには値だけでなく、背景色、フォント、文字列の配置位置、数値の書式、枠線のタイプ、枠線の色なども設定できます。</p> <blockquote> <p>//「Sample Sheet」シートのA1セルを変数に入れる<br />var cell = worksheet.Cell("A1");<br /> </p> <p>//セルの背景色(R=255,G=0,B=0)に設定<br />cell.Style.Fill.BackgroundColor = XLColor.FromArgb(255,0,0);</p> <p>//セルの文字のフォントをHGS創英角ポップ体に設定<br />cell.Style.Font.FontName = "HGS創英角ポップ体";</p> <p>//セルの文字の水平方向の配置位置を中央に設定<br />cell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;</p> <p>//セルの文字の垂直方向の配置位置を中央に設定<br />cell.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;</p> <p>//セルの数値の書式を"yyyy/mm"に設定 任意のフォーマットに指定可能<br />cell.Style.DateFormat.Format = "yyyy/mm";</p> <p>//セルの周りの枠線を点線に設定<br />cell.Style.Border.OutsideBorder = XLBorderStyleValues.MediumDashDotDot;</p> <p>//セルの周りの枠線の色を黒色に設定<br />cell.Style.Border.OutsideBorderColor = XLColor.Black;</p> <p> </p> <p>//文字の配置位置をわかりやすくするためにセルの大きさを変更<br />worksheet.Column(1).Width = 50;<br />worksheet.Row(1).Height = 50;</p> </blockquote> <figure class="figure-image figure-image-fotolife mceNonEditable" title="セルにいろいろ設定した出力結果"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200223/20200223205717.png" alt="f:id:sgtech:20200223205717p:plain" title="f:id:sgtech:20200223205717p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption>セルにいろいろ設定した出力結果</figcaption> </figure> <p>手作業でExcelを編集するときと同じように、セル単体ではなく範囲を対象に設定することもできます。</p> <blockquote> <p>//「Sample Sheet」シートのA1セルからC5セルの範囲を変数に入れる<br />//範囲の指定は左上のセルと右下のセルを指定する<br />var range = worksheet.Range(worksheet.Cell("A1"), worksheet.Cell("C5"));<br /> <br />//範囲内の全てのセルの背景色を青色に設定<br />range.Style.Fill.BackgroundColor = XLColor.Blue;</p> </blockquote> <figure class="figure-image figure-image-fotolife mceNonEditable" title="複数のセルを範囲指定して背景色を設定した出力結果"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200223/20200223205722.png" alt="f:id:sgtech:20200223205722p:plain" title="f:id:sgtech:20200223205722p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption>複数のセルを範囲指定して背景色を設定した出力結果</figcaption> </figure> <p>このほかにも、</p> <p>複数のセルを一つのセルにする「セルの結合」</p> <blockquote> <p>//結合したいセル範囲を指定して...<br />var mergerange = worksheet.Range(worksheet.Cell("B2"), worksheet.Cell("D4"));</p> <p>//Merge()で範囲のセルを結合する<br />mergerange.Merge();</p> <p> </p> <p>//値を設定してみる<br />mergerange.Value = "結合セル";<br />//文字の配置位置を中央に設定<br />mergerange.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;<br />mergerange.Style.Alignment.Vertical = XLAlignmentVerticalValues.Center;</p> </blockquote> <figure class="figure-image figure-image-fotolife mceNonEditable" title="セルの結合を設定した出力結果"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200223/20200223205727.png" alt="f:id:sgtech:20200223205727p:plain" title="f:id:sgtech:20200223205727p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption>セルの結合を設定した出力結果</figcaption> </figure> <p>ワークシート上のデータを抽出して表示できるようにする「オートフィルタの設定」</p> <blockquote> <p>//例示のために</p> <p><br />セルにデータを入力</p> <p>worksheet.Cell("B2").Value = "名前";<br />worksheet.Cell("C2").Value = "味";<br />worksheet.Cell("D2").Value = "知名度";<br />worksheet.Cell("E2").Value = "値段";<br /> <br />worksheet.Cell("B3").Value = "リンゴ";<br />worksheet.Cell("C3").Value = "甘い";<br />worksheet.Cell("D3").Value = "一般的";<br />worksheet.Cell("E3").Value = "500";<br /><br />worksheet.Cell("B4").Value = "みかん";<br />worksheet.Cell("C4").Value = "甘い";<br />worksheet.Cell("D4").Value = "一般的";<br />worksheet.Cell("E4").Value = "300";<br /> <br />worksheet.Cell("B5").Value = "チリドッグ";<br />worksheet.Cell("C5").Value = "辛い";<br />worksheet.Cell("D5").Value = "低い";<br />worksheet.Cell("E5").Value = "700";<br /><br /></p> <p>//オートフィルタを設定したいセル範囲を指定して...<br />var filterrange = worksheet.Range(worksheet.Cell("B2"), worksheet.Cell("E5"));</p> <p>//SetAutoFilter()でオートフィルタを設定する<br />filterrange.SetAutoFilter();</p> <p> </p> <p>//見やすいように範囲内のセルに枠線を設定<br />filterrange.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;<br />filterrange.Style.Border.InsideBorder = XLBorderStyleValues.Thin;<br />//見やすいようにセルの幅を設定<br />worksheet.ColumnWidth = 20;</p> </blockquote> <figure class="figure-image figure-image-fotolife mceNonEditable" title="オートフィルタを設定した出力結果"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200223/20200223205732.png" alt="f:id:sgtech:20200223205732p:plain" title="f:id:sgtech:20200223205732p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption>オートフィルタを設定した出力結果</figcaption> </figure> <p>特定の行や列を固定表示したままシートをスクロールできるようにする「ウィンドウ枠の固定」</p> <blockquote> <p>//固定するワークシートの1~2行目とA列B列をピンク色に設定<br />worksheet.Column(1).Style.Fill.BackgroundColor = XLColor.Pink;<br />worksheet.Column(2).Style.Fill.BackgroundColor = XLColor.Pink;<br />worksheet.Row(1).Style.Fill.BackgroundColor = XLColor.Pink;<br />worksheet.Row(2).Style.Fill.BackgroundColor = XLColor.Pink;</p> <p> </p> <p>//行と列の数字を指定して「ウィンドウ枠の固定」を行う<br />//Freeze(2, 2)だとC3セルを指定して「ウィンドウ枠の固定」したときと同じ状態になる<br />worksheet.SheetView.Freeze(2, 2);</p> <p> </p> <p>//セルの指定では0を指定するとエラーになったが、この処理は0が指定できる<br />//0を指定すると、行方向だけ、または、列方向だけにウィンドウ枠の固定ができる<br />worksheet.SheetView.Freeze(2, 0);</p> <p> </p> <p>//行方向だけ、または、列方向だけウィンドウ枠の固定をするための別メソッドもある<br />worksheet.SheetView.FreezeColumns(2);<br />worksheet.SheetView.FreezeRows(2);</p> </blockquote> <figure class="figure-image figure-image-fotolife mceNonEditable" title="ウィンドウ枠の固定を設定した出力結果"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200223/20200223205738.png" alt="f:id:sgtech:20200223205738p:plain" title="f:id:sgtech:20200223205738p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption>ウィンドウ枠の固定を設定した出力結果</figcaption> </figure> <p>上記のとおり、Excel上で設定できるものは基本的にコード上で設定することができます。</p> <p> </p> <p>ScheduleCanvasでは、これらを使ってツール上で表示している見た目と同じようなExcelファイルの出力を実現しています。</p> <p>以下の2つの図はScheduleCanvas上での見た目と出力したExcelの見た目をそれぞれキャプチャしたものです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="ScheduleCanvasの見た目"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200223/20200223205743.png" alt="f:id:sgtech:20200223205743p:plain" title="f:id:sgtech:20200223205743p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption>ScheduleCanvasの見た目</figcaption> </figure> <figure class="figure-image figure-image-fotolife mceNonEditable" title="ScheduleCanvasから出力したExcelファイルの見た目"> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200223/20200223205750.png" alt="f:id:sgtech:20200223205750p:plain" title="f:id:sgtech:20200223205750p:plain" class="hatena-fotolife" itemprop="image" /></p> <figcaption>ScheduleCanvasから出力したExcelファイルの見た目</figcaption> </figure> <p>なかなかの再現度ではないでしょうか。</p> <p>ここまで見た目にこだわるとコードも結構複雑になりますが、データを出力する際に見出しの行に色を付けたり、オートフィルタを設定するだけならば簡単に実装できます。</p> <p>皆さんも試してみてはいかがでしょうか。</p> <p> </p> <p>ひとまずはツールの実装の一例としてExcelファイルとの連携をご紹介しましたが、ユーザーの要件に応えるために一つのツールには他にも多くの技術が盛り込まれて実装されています。</p> <p>このようなゲームを作るための周辺ツールやワークフロー、ゲームエンジンのノウハウが豊富で、情報共有が盛んな職場で働いてみたいという方はぜひ、以下をチェックしてみてください。</p> <p> </p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="採用サイト|株式会社セガ -【SEGA Co., Ltd.】" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sega.co.jp%2Frecruit%2Findex.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html">www.sega.co.jp</a></cite><cite class="hatena-citation"></cite></p> <p>(C) SEGA</p> sgtech ゲームジャムでUnreal Engine 4を使ってみよう hatenablog://entry/26006613502966561 2020-01-27T10:00:00+09:00 2020-01-27T10:00:04+09:00 ごあいさつ 記事の対象 記事のモチベーション ジャム当日までの準備 開発PCや実行環境 ノートPCの例 スペックが低い環境の極端な例 マウスを使用する(重要) USBメモリ コントローラ XInput形式のものを持ち込む 年季の入ったコントローラや自作のアーケードコントローラ やってみたいことの妄想 ジャム当日:アイデア出し ワードマップから始める アイデアの大枠が決定した時、UE4のテンプレートが使えそうか考える ToDoリストを作成する ジャム当日:最初にやること バージョン管理システム(VCS)を決める? VCSを使用せずにUSBメモリを使用する VCSを使用する場合 Content直下… <ul class="table-of-contents"> <li><a href="#ごあいさつ">ごあいさつ</a><ul> <li><a href="#記事の対象">記事の対象</a></li> <li><a href="#記事のモチベーション">記事のモチベーション</a></li> </ul> </li> <li><a href="#ジャム当日までの準備">ジャム当日までの準備</a><ul> <li><a href="#開発PCや実行環境">開発PCや実行環境</a><ul> <li><a href="#ノートPCの例">ノートPCの例</a></li> <li><a href="#スペックが低い環境の極端な例">スペックが低い環境の極端な例</a></li> </ul> </li> <li><a href="#マウスを使用する重要">マウスを使用する(重要)</a></li> <li><a href="#USBメモリ">USBメモリ</a></li> <li><a href="#コントローラ">コントローラ</a><ul> <li><a href="#XInput形式のものを持ち込む">XInput形式のものを持ち込む</a></li> <li><a href="#年季の入ったコントローラや自作のアーケードコントローラ">年季の入ったコントローラや自作のアーケードコントローラ</a></li> </ul> </li> <li><a href="#やってみたいことの妄想">やってみたいことの妄想</a></li> </ul> </li> <li><a href="#ジャム当日アイデア出し">ジャム当日:アイデア出し</a><ul> <li><a href="#ワードマップから始める">ワードマップから始める</a><ul> <li><a href="#アイデアの大枠が決定した時UE4のテンプレートが使えそうか考える">アイデアの大枠が決定した時、UE4のテンプレートが使えそうか考える</a></li> </ul> </li> <li><a href="#ToDoリストを作成する">ToDoリストを作成する</a></li> </ul> </li> <li><a href="#ジャム当日最初にやること">ジャム当日:最初にやること</a><ul> <li><a href="#バージョン管理システムVCSを決める">バージョン管理システム(VCS)を決める?</a><ul> <li><a href="#VCSを使用せずにUSBメモリを使用する">VCSを使用せずにUSBメモリを使用する</a></li> <li><a href="#VCSを使用する場合">VCSを使用する場合</a></li> </ul> </li> <li><a href="#Content直下にゲームジャム用のフォルダを作成する">Content直下にゲームジャム用のフォルダを作成する</a><ul> <li><a href="#各々の名前のフォルダで作業する">各々の名前のフォルダで作業する</a></li> </ul> </li> <li><a href="#外部デバイスや使用したいコードのプラグインがある場合はCプロジェクトを作成する">外部デバイスや使用したいコードのプラグインがある場合は、C++プロジェクトを作成する</a><ul> <li><a href="#UE4DuinoArduinoとのシリアル通信">UE4Duino:Arduinoとのシリアル通信</a></li> <li><a href="#DirectInputJoystickの使用">DirectInput:Joystickの使用</a></li> <li><a href="#OceanProjectリアルな海と浮力のシミュレーション">OceanProject:リアルな海と浮力のシミュレーション</a></li> </ul> </li> <li><a href="#プロジェクト作成者が最初に配布する内容">プロジェクト作成者が最初に配布する内容</a></li> </ul> </li> <li><a href="#初めてUE4を触る方初めての方に教える方">初めてUE4を触る方・初めての方に教える方</a><ul> <li><a href="#書籍を見ながらコインを実装">書籍を見ながらコインを実装</a></li> <li><a href="#UIのチュートリアルを見ながらメニューゲーム中UI結果画面を作成">UIのチュートリアルを見ながらメニュー、ゲーム中UI、結果画面を作成</a></li> <li><a href="#レベルデザインやランドスケープツールの利用">レベルデザインやランドスケープツールの利用</a></li> <li><a href="#わからないところは質問しようわからなさそうなところに気づいたら教えよう">わからないところは質問しよう、わからなさそうなところに気づいたら教えよう</a></li> <li><a href="#よく聞かれたもの">よく聞かれたもの</a><ul> <li><a href="#ビューポートやアウトライナについて">ビューポートやアウトライナについて</a></li> <li><a href="#Blueprintの基本的な操作">Blueprintの基本的な操作</a></li> <li><a href="#Blueprintワイヤーの切断方法">Blueprintワイヤーの切断方法</a></li> </ul> </li> </ul> </li> <li><a href="#プランナーゲームデザイナー向けプログラマーも見てね">プランナー、ゲームデザイナー向け(プログラマーも見てね)</a><ul> <li><a href="#レベルデザイン">レベルデザイン</a></li> <li><a href="#待ち時間が発生したとき">待ち時間が発生したとき</a><ul> <li><a href="#仕様を簡略化できるかどこまで削ってよいか考える">仕様を簡略化できるか・どこまで削ってよいか考える</a></li> <li><a href="#チームにサウンドさんが居ない場合音素材を集めましょう">チームにサウンドさんが居ない場合、音素材を集めましょう。</a></li> </ul> </li> </ul> </li> <li><a href="#プログラマー向けTips">プログラマー向けTips</a><ul> <li><a href="#タイトルゲームリザルトタイトルのゲームシーケンスループを作成">タイトル→ゲーム→リザルト→タイトルのゲームシーケンスループを作成</a><ul> <li><a href="#マップを分割し遷移処理を作成">マップを分割し、遷移処理を作成</a></li> <li><a href="#得点などをリザルトで表示したい場合はGameInstanceクラスを作成して情報を持たせる">得点などをリザルトで表示したい場合はGameInstanceクラスを作成して情報を持たせる</a></li> <li><a href="#GameInstanceクラスの作成">GameInstanceクラスの作成</a></li> <li><a href="#UIのWidgetBlueprintをGameInstanceに持たせた例">UIのWidgetBlueprintをGameInstanceに持たせた例</a></li> </ul> </li> <li><a href="#パラメータを調節してもらうようにする">パラメータを調節してもらうようにする</a></li> <li><a href="#値を画面に表示し続ける">値を画面に表示し続ける</a></li> <li><a href="#デバッグキーを用意する">デバッグキーを用意する</a></li> <li><a href="#エディタで配置するか外部ファイルで配置するかランダムに任せるか">エディタで配置するか、外部ファイルで配置するか、ランダムに任せるか</a><ul> <li><a href="#エディタでの配置">エディタでの配置</a></li> <li><a href="#外部ファイルに記述">外部ファイルに記述</a></li> <li><a href="#ランダムに任せる">ランダムに任せる</a></li> </ul> </li> <li><a href="#とりあえず爆発させましょう">「とりあえず爆発させましょう」</a><ul> <li><a href="#爆発の起動">爆発の起動</a></li> </ul> </li> </ul> </li> <li><a href="#ジャム中の注意点など">ジャム中の注意点など</a><ul> <li><a href="#巨大なアセットが本当に必要か検討する">巨大なアセットが本当に必要か検討する</a></li> <li><a href="#ゲーム画面の発表時には電源を接続する">ゲーム画面の発表時には電源を接続する</a></li> </ul> </li> <li><a href="#ゲームジャムでUE4チームを作るには">ゲームジャムでUE4チームを作るには</a><ul> <li><a href="#ジャム運営の方へ">ジャム運営の方へ</a></li> <li><a href="#ジャム当日のチーム決めの後に選択肢として考えてみる">ジャム当日のチーム決めの後に、選択肢として考えてみる</a></li> </ul> </li> <li><a href="#おわりに">おわりに</a></li> <li><a href="#おまけこれまでの制作物">おまけ:これまでの制作物</a></li> </ul> <h3 id="ごあいさつ">ごあいさつ</h3> <p>はじめまして、セガ・インタラクティブ 第三研究開発部の若井です。アーケードゲームのプログラマーをしています。携わったタイトルは<a href="https://edel-sand.sega.jp/">え~でる すなば</a> や <a href="https://www.footista.jp/">WCCF FOOTISTA 2019</a> などです。Unreal Engine 4 (以下UE4)の活動としては昨年の「UNREAL FEST EAST 2019」にてWCCFシリーズのUE4移行について発表いたしました。<a href="https://www.slideshare.net/EpicGamesJapan/ue4-festeast2019-wccffootista2019">スライド</a>(リンク先の説明欄より、動画と台本付きの資料をダウンロードしてください。)</p> <h4 id="記事の対象">記事の対象</h4> <p>今回はゲームジャム(文章中は「ジャム」と略します)の定義を、<strong>会場へ集まって1、2日で制作するものから期間1ヶ月程度までのコンテスト</strong>とします。期間が長いものは当てはまりません。当てはまらない例:<a href="https://itch.io/jam/decadejam">期間が10年もあるジャム</a></p> <p>また、<span style="color: #ff0000;"><strong><span style="color: #000000;">記事内容は</span>ジャム特化の内容となっておりますので、製品開発に必ずしも役立つものではない(技術的負債になりえる)<span style="color: #000000;">ことをご了承ください。</span></strong></span></p> <h4 id="記事のモチベーション">記事のモチベーション</h4> <p><strong>今回は私がUE4を使用したジャムで実際に活用したノウハウの内、他のジャムにも転用できそうなものをご紹介します。</strong>全体の話もしますが、主にプログラマー向けの初歩的なものが多いです。</p> <p>ジャムでは結果よりもプロセスを楽しむことや経験することが重要であります。とはよく言われるものの、躓きが多いと楽しくない印象で終わることもあります。記事内のコンテンツで皆さんのジャムを快いものにすることができれば幸いです。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210259.gif" alt="f:id:sgtech:20200126210259g:plain" title="f:id:sgtech:20200126210259g:plain" class="hatena-fotolife" itemprop="image" width="351" /><span style="color: #666666;">思惑と違ってしまうジャムもしばしば</span></p> <p>おまけで記事の末尾にこれまでに制作したジャム作品を羅列しておきました。</p> <h3 id="ジャム当日までの準備">ジャム当日までの準備</h3> <p>前日の十分な睡眠の他に、開発環境など事前に用意できるものがあります。</p> <h4 id="開発PCや実行環境">開発PCや実行環境</h4> <p>UE4を用いた開発PCについて、<a href="https://docs.unrealengine.com/en-US/GettingStarted/RecommendedSpecifications/index.html">公式の推奨環境</a>があります。会場に集まるジャムの場合はノートPCを持ち込むことになります。ご自身のノートPCスペックを確認してみてください。ジャムの会場によってはPCの貸し出しを行っている場合があります。</p> <p>経験上UE4を使用する場合は3Dゲームを作ることが多いので、グラフィックカードの搭載された「ゲーミングノートPC」を持ち込むことをおすすめします(プログラマーの場合は特に必須)。</p> <h5 id="ノートPCの例">ノートPCの例</h5> <p>私はMSIのノートPCを愛用しています。冷却性能が優れておりジャム中に安定稼働しています。MSIさんのPRではございませんが製品名を挙げさせていただきます。各PCのスペックを参考にしてください。</p> <p>・PS63 Modern</p> <p>ジャムに持ち込んだときにゲーミングノートPCとしての役割を持てます。コンパクトでバッテリーも多いので、ジャム以外にも長めの勉強会などでメモ取り用として持っていける機種です。スペックとしては最低限で、2日程度の期間内でも処理負荷が大きいとゲーム開発中のカクつきが見受けられます。</p> <p>・GE75 Raider</p> <p>スリムでありながらVRゲームの開発にも対応できます。MSIのノートPCにはボタン1つでクーラー出力が最大(プロファイルの変更)となる機種があり、私はこのボタンをとても気に入っています。</p> <h5 id="スペックが低い環境の極端な例">スペックが低い環境の極端な例</h5> <p>おまけの④では、コンパクト性のためシングルボードコンピュータ (<a href="http://www.lattepanda.com/products/3.html">Latte Panda</a>)上でアプリケーションを動作させました。デフォルトの状態では処理速度が追いつかなかったため、ジャム中にゲームのプロファイリングをして重い処理を取り除いていく必要がありました。おすすめしません。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210128.png" alt="f:id:sgtech:20200126210128p:plain" title="f:id:sgtech:20200126210128p:plain" class="hatena-fotolife" itemprop="image" width="347" /><span style="color: #666666;">←FlyingTemplateで10FPS</span></p> <h4 id="マウスを使用する重要">マウスを使用する(重要)</h4> <p>テンプレートを使用したゲームではカメラ視点操作をマウスで行ったほうが楽な事が多々ありますので、用意しましょう。</p> <p>ビジュアルスクリプト「Blueprint」を使って開発することになります。慣れた操作でBlueprintノードを組み立てるためにノートPCと一緒にマウスを持ち込みましょう。</p> <p>特にプログラマーは短時間で大量のBlueprintノードを操作すると腕が痛くなります。湿布を用意するか軽いマウスを使用することをおすすめします。</p> <p>↓ ノードの総量はこのグラフ(おまけの⑩のBlueprint)くらいの量になるのではないでしょうか。ジャム中は試行錯誤でノードの作成と移動、ワイヤー接続と切断を繰り返しますので、グラフの見た目以上に手を動かすことになります。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210317.jpg" alt="f:id:sgtech:20200126210317j:plain" title="f:id:sgtech:20200126210317j:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p>おまけの⑩では、制作時のグラフ切り替えやクラス間の画面切り替え時間を減らすためにほぼ1つのグラフに処理が集約されています。</p> <p><span style="color: #cccccc;">仕事では書かないグラフなので見せるのはちょっと恥ずかしいです。</span></p> <h4 id="USBメモリ">USBメモリ</h4> <p>どのジャムでも、素材やプロジェクトを共有するための手段が必要になります。1人1つUSBメモリを持っておくのが吉です。</p> <p>共有ドライブが整備されたジャムもありますが、多くの会場では貧弱な無線環境ですのでUSBメモリのほうが共有しやすいです。</p> <p>チーム内の数が少ないとUSBメモリ使用のための待ち時間が発生することがあります。発生したことがあります。</p> <h4 id="コントローラ">コントローラ</h4> <h5 id="XInput形式のものを持ち込む">XInput形式のものを持ち込む</h5> <p>UE4は標準でXInputに対応しており、UE4のテンプレートは最初からキャラクターやカメラ操作のインプットアクションがアサインされています。</p> <p>ジャムで制作するゲームはXboxコントローラのようなインターフェースが適することが多く、キーボードが必須であるアイデアは稀です。</p> <p>持っている人は持ち込んでみましょう。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210552.jpg" alt="f:id:sgtech:20200126210552j:plain" title="f:id:sgtech:20200126210552j:plain" class="hatena-fotolife" itemprop="image" width="248" /></p> <h5 id="年季の入ったコントローラや自作のアーケードコントローラ">年季の入ったコントローラや自作のアーケードコントローラ</h5> <p>お気に入りのコントローラを持っていて、ジャムで使用したくなることがあります。しかしXInputに対応していないことがあります。</p> <p>UE4はDirectInput形式に対応しておらず、実際にUSBで繋げてみたがUE4のゲームで認識されない場合は概ねこちらが原因でしょう。</p> <p>DirectInput形式はXInputより古い形式であり、UE4で扱うにはコードを書く(OSSのPluginを導入するのが楽)必要があります。こちらの導入については後述します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210612.jpg" alt="f:id:sgtech:20200126210612j:plain" title="f:id:sgtech:20200126210612j:plain" class="hatena-fotolife" itemprop="image" width="299" /><span style="color: #cccccc;">自作コントローラそれはロマン</span></p> <h4 id="やってみたいことの妄想">やってみたいことの妄想</h4> <p>こんなゲームを作りたい、こんな技術を作りたいといった思いはジャムに反映されやすいです。アイデア出しの種にもなりますので、考えてみてください。末尾のおまけには私のジャム参加前のモチベーションを添えてみました。</p> <h3 id="ジャム当日アイデア出し">ジャム当日:アイデア出し</h3> <p>アイデア出しの裏で、UE4がインストールされていない人はこの間にインストールしましょう。</p> <h4 id="ワードマップから始める">ワードマップから始める</h4> <p>私がよく使う手法を紹介します。</p> <p>ゲームジャムはテーマとして単語や文章が与えられることが多いです。与えられたテーマより連想するワードを付箋などに書き出し、ワードマップにします。</p> <p>このとき、名詞・動詞・状態(ゴールや目的)などを意識します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126225159.jpg" alt="f:id:sgtech:20200126225159j:plain" title="f:id:sgtech:20200126225159j:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p>出てきたマップについてみんなで議論することになります。ここでの強力な手法の1つに「<span style="color: #333333; font-family: Helvetica, Arial, 'BIZ UDGothic', 'Hiragino Kaku Gothic ProN', 'Hiragino Sans', メイリオ, Meiryo, sans-serif; font-size: 15.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">EMS Framework Method</span>」というものがあります。</p> <p><a href="https://www.inside-games.jp/article/2014/09/11/80444.html">EMS Framework Methodについて紹介されている記事</a></p> <p>こちらを少し簡略化して、「プレイヤー(名詞)が〇〇<span style="color: #333333; font-family: Helvetica, Arial, 'BIZ UDGothic', 'Hiragino Kaku Gothic ProN', 'Hiragino Sans', メイリオ, Meiryo, sans-serif; font-size: 15.4px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">して(動詞)、□□という結果になる(状態)</span>」という枠にワードを当てはめます。名詞、動詞、状態のうち2つ当てはめれば、ワードマップに無い言葉も生まれてくることでしょう。 </p> <p>例えばおまけ⑫では、「☆」というテーマが与えられて「ヒトデ」「流れ星」といったワードが出てきました。枠内の名詞・結果に当てはめてみると、「ヒトデが〇〇して(流れ)星になる」となるので、残りの〇〇を皆で考えた結果、ビッグなスターになるということで「巨大化」という動詞が生まれてきました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210936.png" alt="f:id:sgtech:20200126210936p:plain" title="f:id:sgtech:20200126210936p:plain" class="hatena-fotolife" itemprop="image" width="399" /></p> <h5 id="アイデアの大枠が決定した時UE4のテンプレートが使えそうか考える">アイデアの大枠が決定した時、UE4のテンプレートが使えそうか考える</h5> <p>UE4の使用経験のあるプログラマーは、決定されたアイデアにUE4のテンプレートを流用できるか考えてみましょう。流用できる場合は制作が楽になります。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210623.png" alt="f:id:sgtech:20200126210623p:plain" title="f:id:sgtech:20200126210623p:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p>流用しない場合は考える楽しみがあります。おまけ⑨ではテンプレートを使用しませんでしたが、未知のものを作れそうなワクワク感がありました。</p> <p>末尾のおまけでは、各ゲームが使用したテンプレートを記載しました。</p> <h4 id="ToDoリストを作成する">ToDoリストを作成する</h4> <p>ゲームに必要な機能、要素を分割して、やるべきこと・やっていることを可視化します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210428.png" alt="f:id:sgtech:20200126210428p:plain" title="f:id:sgtech:20200126210428p:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p>運用につきましては過去の記事に詳しく書かれておりますので、こちらをご覧ください。</p> <p><iframe class="embed-card embed-blogcard" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" title="GameJamで覚えるタスクボード(カンバン) - SEGA TECH Blog" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftechblog.sega.jp%2Fentry%2F2017%2F05%2F26%2F100000" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://techblog.sega.jp/entry/2017/05/26/100000">techblog.sega.jp</a></cite></p> <p> </p> <h3 id="ジャム当日最初にやること">ジャム当日:最初にやること</h3> <p>テーマ決めより使用するテンプレート(または空のプロジェクト)はプログラマーが判断すると思うので、その方がプロジェクトを作成して配布するといいでしょう。</p> <h4 id="バージョン管理システムVCSを決める">バージョン管理システム(VCS)を決める?</h4> <p><span style="color: #ff0000;">今現在Blueprintは更新が衝突したときのマージをマージツールで実現することが難しいです。よって衝突を防ぐためにファイル単位で担当を決めて作業することになります。</span></p> <p>もし衝突した場合はUE4プロジェクトを両方開いて、Blueprintグラフ上で作業することになります。幸いBlueprintグラフはコピペが効きます。</p> <p>おまけの⑪では、画像↓のようにPlayerやEnemy、大砲(Cannon)から放たれるMEGA DRIVEなどに分けました。Playerと大砲を担当する人とEnemyを担当する人に分かれ、各々でクラスファイルを実装しつつ相手のクラスに処理を追加したい場合は相手に仕込んでもらうようにしました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210419.png" alt="f:id:sgtech:20200126210419p:plain" title="f:id:sgtech:20200126210419p:plain" class="hatena-fotolife" itemprop="image" width="348" /></p> <p>では、どのVCSを選びましょうか。</p> <h5 id="VCSを使用せずにUSBメモリを使用する">VCSを使用せずにUSBメモリを使用する</h5> <p><span style="color: #ff0000;">私のオススメUSBメモリを使用することです。</span>経験上これがベストでした。</p> <p>最初にプロジェクトを共有した後は図のような手順でローカルからUSBメモリへの更新と、USBメモリからの更新をローカルに適用します。</p> <p> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210424.png" alt="f:id:sgtech:20200126210424p:plain" title="f:id:sgtech:20200126210424p:plain" class="hatena-fotolife" itemprop="image" width="350" /></p> <p>②のUSBメモリにコピーする際、周りのメンバーに何を更新したのか共有することを忘れないようにしてください。</p> <p>私のオススメは定期的に全員で進捗確認の時間を設け、確認後にUSBにコピーすることです。確認をしたので、どんな更新がマスタープロジェクトに入っているか把握することができます。もちろん、プランナーやレベルデザイナーが最新の状態を触るために細かくやり取りすることも大事です。</p> <p>USBメモリ側でもバックアップをしてもいいですが、<strong>ジャムの後半になるとそんなことは忘れます。</strong>①の部分も忘れられ②と③になることでしょう。しかし、このファイル共有作業において自分の更新分がどこかで消滅するとモチベーションが結構下がってしまうものです。面倒でも自分のローカルでバックアップを取るようにしましょう。そうすれば手違いが起きてしまったときに担当者がバックアップから取り出して確認し復旧しやすいです。</p> <p>私の主観ですがUSBメモリの受け渡し形式はコミュニケーションの機会が増えるので、実装内容や予定の相談を行いやすいと感じます。</p> <h5 id="VCSを使用する場合">VCSを使用する場合</h5> <ul> <li>安定したネットワーク環境であること</li> <li>VCSを全員が操作できて問題解決もできる</li> </ul> <p>といったチームであれば問題ないと思います。また、チームのプログラマーが3人以上であれば検討してよいと思います。</p> <p>私は無線環境での更新の遅さやSVNのCleanupに悩まされた経験があります。ジャムの後半に問題が起こるととても焦ります。</p> <h4 id="Content直下にゲームジャム用のフォルダを作成する">Content直下にゲームジャム用のフォルダを作成する</h4> <p>このとき、名前を「数字_ゲームジャム(プロジェクト)名」にします。記号や数字を頭に持ってくることで並びが一番上に来ます。フォルダ名をチームで共有して、作業フォルダを明らかにしましょう。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210121.png" alt="f:id:sgtech:20200126210121p:plain" title="f:id:sgtech:20200126210121p:plain" class="hatena-fotolife" itemprop="image" /></p> <p>ゲームジャム後半などで、作業フォルダを見失うことを避けることができます。</p> <p>例えばテンプレートやスターターコンテンツまたはMarket Placeのアセットなどを導入すると、Content「コンテンツ」フォルダ以下が肥大化することが多々あります。</p> <p>下図は過去のゲームジャム(おまけの③)フォルダ構成なのですが、主な作業フォルダである「SGJ201707」を見つけることに苦労します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210125.png" alt="f:id:sgtech:20200126210125p:plain" title="f:id:sgtech:20200126210125p:plain" class="hatena-fotolife" itemprop="image" /></p> <p>ゲームジャム2日目などはフォルダ名がとっさに思い出せないことやアルファベット順に並んでいることも頭から抜けていることがあります。ぜひ一番上に表示されるような名前を付けてみてください。</p> <p>「Debug」フォルダを作成するときも「00_Debug」などにすると探しやすくなります。</p> <h5 id="各々の名前のフォルダで作業する">各々の名前のフォルダで作業する</h5> <p>個人名のフォルダを作成し、自分の名前のフォルダ以下で開発を行うで複数人が同じアセットに対して作業することを防ぐことができます。</p> <p>デバッグフォルダと同様、先頭に数字を入れると探しやすくなります。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210940.png" alt="f:id:sgtech:20200126210940p:plain" title="f:id:sgtech:20200126210940p:plain" class="hatena-fotolife" itemprop="image" /></p> <h4 id="外部デバイスや使用したいコードのプラグインがある場合はCプロジェクトを作成する">外部デバイスや使用したいコードのプラグインがある場合は、C++プロジェクトを作成する</h4> <p>UE4の標準機能では実現できないために外部のOSSを使用するときは、プロジェクト作成時にブループリントベースではなくC++ベースのプロジェクトを作成する必要があります。</p> <p>これまでジャムで使用したことがあるサードパーティのプラグインを紹介します。</p> <h5 id="UE4DuinoArduinoとのシリアル通信">UE4Duino:Arduinoとのシリアル通信</h5> <p>傾きや照度などセンサー情報の受け取りや、回路へシグナルを出力してLEDを点灯させる等の場合に使います。(おまけの④で使用)</p> <p><a href="https://github.com/RVillani/UE4Duino">GitHub - RVillani/UE4Duino: Unreal Engine 4 plugin for COM communication on Windows</a></p> <p>使用方法はGitHubのREADMEに載っている画像がわかりやすいです。</p> <p>OpenSerialPort関数で得たSerialObjectの参照を使用してメッセージ送受信の関数を呼びます。Arduinoからメッセージを受け取る場合はRead〇〇関数、メッセージを送る場合はPrint関数です。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210730.png" alt="f:id:sgtech:20200126210730p:plain" title="f:id:sgtech:20200126210730p:plain" class="hatena-fotolife" itemprop="image" width="298" /></p> <p> </p> <p>おまけ④では複数発のLEDを制御するため、やりとりするメッセージの形式を「LED_(インデックス)_(点灯か消灯か)」に決ました。</p> <p>Arduino側では受け取ったメッセージを解釈してLEDを点灯(消灯)させる処理を書き、UE4アプリ側では形式に合ったメッセージの文字列を合成して送信する処理を書きました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210734.png" alt="f:id:sgtech:20200126210734p:plain" title="f:id:sgtech:20200126210734p:plain" class="hatena-fotolife" itemprop="image" width="397" /></p> <p> </p> <p>おまけ④以外のジャムでもUE4Duinoを使用する機会があり、傾きセンサの情報の取得を試みましたが、期間中にうまくいかず挫折したことがあります。</p> <p>2日間のジャムで1日目にUE4で挫折して2日目でUnityを使って1から作り直したという苦い思い出です。悔しくて家でUE4バージョンも作り直しました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210133.gif" alt="f:id:sgtech:20200126210133g:plain" title="f:id:sgtech:20200126210133g:plain" class="hatena-fotolife" itemprop="image" width="351" /></p> <h5 id="DirectInputJoystickの使用">DirectInput:Joystickの使用</h5> <p>XInput非対応のコントローラを接続したいときにOSSのPluginを導入します。</p> <p>・<a href="https://github.com/Ikarus76/UEJoystickPlugin">GitHub - Ikarus76/UEJoystickPlugin: Unofficial Joystick Plugin for the Unreal Engine</a></p> <p> フォーラム:<a href="https://forums.unrealengine.com/development-discussion/engine-source-github/21886-joystick-plugin?51237-Joystick-Plugin=">Joystick Plugin - Unreal Engine Forums</a></p> <p> </p> <p>UEJoystickプラグインではスティックの軸値関数とボタンのインプットイベントより、望みの値を簡単に取得できます。PluginのReadmeにもあるように、Input用のActorまたはComponentを配置することを忘れないようにしてください。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210619.png" alt="f:id:sgtech:20200126210619p:plain" title="f:id:sgtech:20200126210619p:plain" class="hatena-fotolife" itemprop="image" width="179" /></p> <p> </p> <p>おまけの④ではAmazonでアーケードコントローラのDIYセットを購入し、専用のコントローラを作成しました。よく売っているタイプのエンコーダ接続は下図のようになります(4ボタン)。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210615.png" alt="f:id:sgtech:20200126210615p:plain" title="f:id:sgtech:20200126210615p:plain" class="hatena-fotolife" itemprop="image" width="348" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210946.jpg" alt="f:id:sgtech:20200126210946j:plain" title="f:id:sgtech:20200126210946j:plain" class="hatena-fotolife" itemprop="image" /></p> <p>スティックはAxis値が中途半端(1.0ではなく、0.999などの値)になっていることがありますので、0.0や1.0を計算のしきい値にするような場合は注意してください。</p> <h5 id="OceanProjectリアルな海と浮力のシミュレーション">OceanProject:リアルな海と浮力のシミュレーション</h5> <p>おまけの⑪では、海と船を使用するためOSSのOceanProjectを使用しました。</p> <p><a href="https://github.com/UE4-OceanProject/OceanProject">GitHub - UE4-OceanProject/OceanProject: An Ocean Simulation project for Unreal Engine 4</a></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210556.gif" alt="f:id:sgtech:20200126210556g:plain" title="f:id:sgtech:20200126210556g:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p>とてもリアルな海、浮力のシミュレーションなどが含まれています。</p> <p>素早く自分の好きな物体へ浮力を適用するためのヒントとしては、OceanProject内で既に浮力が与えられているBlueprintのメッシュを差し替えて流用することです。</p> <p>↑の動画で見えるように、オブジェクトへ◇型をした浮力シミュレーション用のテストポイントがアタッチされています。テストポイントの位置や、細かい浮力パラメータを調整することができます。</p> <p>OceanProjectを初めて触る場合、導入して使い方を覚える時間を考慮すると2日のジャムでは時間が足りないかもしれません。三角関数の単純な浮き沈み処理を書いた方が早くて楽だと思います。</p> <h4 id="プロジェクト作成者が最初に配布する内容">プロジェクト作成者が最初に配布する内容</h4> <p>以下のフォルダを共有します。</p> <ul> <li>Configフォルダ</li> <li>Contentフォルダ</li> <li>DerivedDataCacheフォルダ</li> <li>〇〇.uproject ファイル</li> <li>Pluginsフォルダ(追加した場合。中のIntermediateは除外)</li> <li>Binariesフォルダ(C++プロジェクトの場合)</li> <li>Sourceフォルダ (C++プロジェクトの場合)</li> </ul> <p>また、大きなテンプレートやアセットを最初から導入していた場合、共有DDCを設定してあげると初回のシェーダコンパイルが走らず、親切です。こちらの記事を参考に、</p> <p><a href="http://historia.co.jp/archives/9294/">[UE4] DDCを共有してストレスフリーな開発を!|株式会社ヒストリア</a></p> <p>「Path=%GAMEDIR%/DDC」を記述、.uprojectと同じフォルダに「DDC」という名前のフォルダを作成してプロジェクトのエディタを起動しましょう。</p> <p>エディタを起動し、シェーダのコンパイルが終了したらDDCファイルごと共有します。</p> <p>おまけの⑪では、サイズの大きいOceanProjectというOSSを最初に導入しました。導入時の共有DDC設定をすることで、渡してすぐに実行を試してもらうことができました。</p> <h3 id="初めてUE4を触る方初めての方に教える方">初めてUE4を触る方・初めての方に教える方</h3> <p>おまけ⑫のジャムではメンバー5人のうちUE4の経験者は私だけでした。教えながら・調べながらのスタイルもゲームジャムですので、やってみたいという気持ちだけで当日を迎えても大丈夫です。</p> <p>操作方法を教わりながら、初めての方が間近で挑戦されているところを見てきたので、事例を紹介します。</p> <h4 id="書籍を見ながらコインを実装">書籍を見ながらコインを実装</h4> <p>おまけ⑥のジャムでは、学生のプログラマー(UE4やUnityの経験無し)が書籍を見ながら、プレイヤーが触れると消滅するコインを作成しました。</p> <p><a href="https://www.borndigital.co.jp/book/6359.html" style="outline: 0px;">Unreal Engine 4 で極めるゲーム開発 | ボーンデジタル</a></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210326.png" alt="f:id:sgtech:20200126210326p:plain" title="f:id:sgtech:20200126210326p:plain" class="hatena-fotolife" itemprop="image" width="301" /><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210330.png" alt="f:id:sgtech:20200126210330p:plain" title="f:id:sgtech:20200126210330p:plain" class="hatena-fotolife" itemprop="image" width="300" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210349.png" alt="f:id:sgtech:20200126210349p:plain" title="f:id:sgtech:20200126210349p:plain" class="hatena-fotolife" itemprop="image" width="401" /></p> <p>具体的には15章3節の「ピックアップアイテムを作る」の部分です。</p> <h4 id="UIのチュートリアルを見ながらメニューゲーム中UI結果画面を作成">UIのチュートリアルを見ながらメニュー、ゲーム中UI、結果画面を作成</h4> <p>おまけ⑫のジャムでは、内定者学生のプログラマー(Unityの経験者)が公式webのチュートリアルドキュメントを見ながらUIを実装しました。</p> <p><a href="https://docs.unrealengine.com/en-US/Engine/UMG/QuickStart/index.html">UMG UI Designer Quick Start Guide | Unreal Engine Documentation</a> </p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210334.png" alt="f:id:sgtech:20200126210334p:plain" title="f:id:sgtech:20200126210334p:plain" class="hatena-fotolife" itemprop="image" width="303" /><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210338.png" alt="f:id:sgtech:20200126210338p:plain" title="f:id:sgtech:20200126210338p:plain" class="hatena-fotolife" itemprop="image" width="302" /></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210341.png" alt="f:id:sgtech:20200126210341p:plain" title="f:id:sgtech:20200126210341p:plain" class="hatena-fotolife" itemprop="image" width="299" /></p> <p>制限時間を表現する処理にも挑戦していました。</p> <h4 id="レベルデザインやランドスケープツールの利用">レベルデザインやランドスケープツールの利用</h4> <p>おまけ⑫のジャムでは、Unity経験者のプランナー2人がプレイヤーのパラメータ調整とステージ作成を分担や協力をしてレベルデザインや見た目の調整をしていました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210949.png" alt="f:id:sgtech:20200126210949p:plain" title="f:id:sgtech:20200126210949p:plain" class="hatena-fotolife" itemprop="image" width="300" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210954.png" alt="f:id:sgtech:20200126210954p:plain" title="f:id:sgtech:20200126210954p:plain" class="hatena-fotolife" itemprop="image" width="301" /></p> <p><br /><br />Unity経験者は慣れるスピードが早いのだとは思いますが、右の画像の海感は素晴らしいです。パラメータ調整も小数点第二位の値までこだわっており、完成度の高いゲームができあがっていました。</p> <h4 id="わからないところは質問しようわからなさそうなところに気づいたら教えよう">わからないところは質問しよう、わからなさそうなところに気づいたら教えよう</h4> <p>エディタ操作方法やBlueprintの実装方法など、初めての方にはわからないことが沢山あります。UE4の経験者は都度補足してあげることが重要ですし、初心者の方はわからないことを都度経験者に伝えることが重要になります。</p> <p>初心者の方はUE4エディタに慣れてきたら、次はwebで検索して試すことにチャレンジしてみましょう。</p> <p>こちらの写真は前回記事の写真でして、↑のUIチュートリアルを進めている方に対してドキュメントの内容と自分たちのゲームを照らし合わせて補足しているときのものです。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210345.png" alt="f:id:sgtech:20200126210345p:plain" title="f:id:sgtech:20200126210345p:plain" class="hatena-fotolife" itemprop="image" width="348" /></p> <h4 id="よく聞かれたもの">よく聞かれたもの</h4> <p>UE4初めての方よりどういった質問や回答が多かったかを挙げてみます。</p> <h5 id="ビューポートやアウトライナについて">ビューポートやアウトライナについて</h5> <p>レベルデザインにおいて物体の配置(移動や回転)や見たい位置へのカメラ移動のとき、操作に対して思ったより動きが小さい場合や大きすぎる場合があります。</p> <p>ビューポートの上部にある設定項目をいじりましょう。特にカメラ速度とフィールドの大きさが噛み合っていないと移動に時間をとられます。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210756.png" alt="f:id:sgtech:20200126210756p:plain" title="f:id:sgtech:20200126210756p:plain" class="hatena-fotolife" itemprop="image" width="502" /></p> <p> </p> <p>アウトライナの中でフォルダ分けしたいときは、フォルダのアイコンを押します。</p> <p>おまけの⑫では捕食対象の種類によってフォルダ分けし、パラメータ変更時に選択しやすくなっていました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210759.png" alt="f:id:sgtech:20200126210759p:plain" title="f:id:sgtech:20200126210759p:plain" class="hatena-fotolife" itemprop="image" width="275" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210825.png" alt="f:id:sgtech:20200126210825p:plain" title="f:id:sgtech:20200126210825p:plain" class="hatena-fotolife" itemprop="image" width="302" /></p> <p> </p> <p>フィールドが広大な場合は、オブジェクトをアウトライナで選択した状態で「F」キーを押すとカメラがオブジェクトの近くに移動してフォーカスされます。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210830.gif" alt="f:id:sgtech:20200126210830g:plain" title="f:id:sgtech:20200126210830g:plain" class="hatena-fotolife" itemprop="image" width="348" /> 約1.5kmの距離を一瞬で移動</p> <h5 id="Blueprintの基本的な操作">Blueprintの基本的な操作</h5> <p>隣に座って画面を操作してもらいながら口頭で説明することが多いです。ドキュメントを見て貰う場合はマウス操作の説明や、画像に赤い枠などの印をつけて説明されているものを紹介しましょう。 </p> <p> </p> <p>さわりとして、マウスの操作方法や画面の説明をすることが多いです。</p> <p>↓こちらのドキュメントと同様な話をします。</p> <p><a href="https://tech.pjin.jp/blog/2019/10/23/ue4_blueprint_01/">【UE4】ブループリント入門【第1回】 | TECH Projin</a></p> <p> </p> <p>算術演算子や、変数の定義方法もよく聞かれます。</p> <p>↓こちらのドキュメントと同様な話をします。</p> <p><a href="https://thinkit.co.jp/article/12031">ブループリントの基本を覚えよう | Think IT(シンクイット)</a></p> <p> </p> <h5 id="Blueprintワイヤーの切断方法">Blueprintワイヤーの切断方法</h5> <p><strong>Blueprintワイヤーの切断方法</strong>は質問率ナンバーワンです。しかし多くの入門ドキュメントでは接続方法の近くに切断方法が書かれておらず、「Blueprint 切断」といったキーワードで検索しなおすケースが多いです。</p> <p>切断と、ついでに付替のショートカットを覚えましょう。</p> <ul> <li><strong>切断:ワイヤー上でAlt+Click</strong></li> <li><strong>付替:ワイヤー(切断側)上でCtrl+Click</strong></li> </ul> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210803.gif" alt="f:id:sgtech:20200126210803g:plain" title="f:id:sgtech:20200126210803g:plain" class="hatena-fotolife" itemprop="image" width="450" /></p> <p>ノードのピンから右クリックでも切断できますが、ショートカットの方が早く便利です。</p> <h3 id="プランナーゲームデザイナー向けプログラマーも見てね">プランナー、ゲームデザイナー向け(プログラマーも見てね)</h3> <p>アイデア出しが終わったあとには、プレゼン資料の作成や詳細仕様を考えることに頭を悩ませると思います。今まで一緒にジャムをした方の立ち回りについてプログラマーの目線からご紹介します。</p> <h4 id="レベルデザイン">レベルデザイン</h4> <p>動くものを触ってみることが重要です。触ってみた結果、当初考えていたイメージと異なっていることに気づき、改修や調整の判断ができます。レベルデザイン担当者の試行回数が多かったときほど、手触りのよいゲームになっていると感じます。</p> <p>なので、プログラマーにお願いしてパラメータを調節できるようにしてもらいましょう。プログラマー向けTipsにヒントを書いておきました。</p> <p>例えばおまけの⑫では、プログラマーがプレイヤーの成長率(ジャンプの高さや身体の大きさ、乗り越えられる段差の高さなど)を調節できるようにして、プランナーの2人が地形とパラメータの調整を進めました。↓の画像は地形の調整用マップと、見た目の最終マップです。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210404.png" alt="f:id:sgtech:20200126210404p:plain" title="f:id:sgtech:20200126210404p:plain" class="hatena-fotolife" itemprop="image" width="300" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210408.png" alt="f:id:sgtech:20200126210408p:plain" title="f:id:sgtech:20200126210408p:plain" class="hatena-fotolife" itemprop="image" width="300" /></p> <p> </p> <h4 id="待ち時間が発生したとき">待ち時間が発生したとき</h4> <p>まだ基本的な動きが完成しておらず、ゲームを実行しての確認ができず手が空いてしまうケースはよくあります。むしろ、動きを早期に確認できるジャムは稀だと思います。</p> <h5 id="仕様を簡略化できるかどこまで削ってよいか考える">仕様を簡略化できるか・どこまで削ってよいか考える</h5> <p>アイデア出しのとき、ゲームが単調にならない要素を考えると思います。ゲーム中のキャラクターや制限の種類を増やすと面白そうなものになるでしょう。しかし期間の短いジャム中にアイデアの全てを入れ込むことは至難です。</p> <p>アイデア出しの部分で言及したToDoリストなど要素分けしてリスト化したものに優先度をつけて、最低限必要なものが何であるか考えましょう。</p> <p> </p> <p>おまけの⑫において削った仕様の例を紹介します。</p> <p>・ゲームの終了条件</p> <p>アイデア段階では「ゴール地点にたどり着く」「制限時間に達する」「自分より大きい捕食対象より一定のダメージを受ける」でした。開発を進める中で、ダメージを受ける要素が無くてもゲームになることに加え、捕食対象の動作(ダメージを与えようとしてくる)実装と調整の時間が足りないと判断してダメージの仕様は無くなりました。</p> <p>・キャラクターの種類</p> <p>アイデア段階での捕食対象は大きく4種類、さらにカラー変更で見た目のバリエーションも増やす考えがありましたが、最終的には3種類(最低限、水中・陸上・空中に存在するもの)となりました。プログラマー側から提案して種類を減らさせていただきました。</p> <h5 id="チームにサウンドさんが居ない場合音素材を集めましょう">チームにサウンドさんが居ない場合、音素材を集めましょう。</h5> <p>UE4で使用できるオーディオファイルの形式はWAV形式です。UE4.22以降ならAIFF、FLAC、Ogg Vorbis形式を使用できます。</p> <p>フリーの音源など外部より取得したものは音量にばらつきがある可能性がありますので、確認して波形の正規化をしてあげると扱いやすくなります。</p> <p>フリーソフトのAudacityを使用した正規化とWAV形式への変換を紹介します。</p> <p>Audacityはこちらより入手します。<a href="https://www.audacityteam.org/about/credits/">https://www.audacityteam.org/</a></p> <p>Audacityへ音源をインポートしたときに、波形の枠上下いっぱいになっていなければ音量が小さいです。右の画像は-1.0dbで正規化されたものです。右の画像のようになっていれば扱いやすいです。<br /><br /><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210531.png" alt="f:id:sgtech:20200126210531p:plain" title="f:id:sgtech:20200126210531p:plain" class="hatena-fotolife" itemprop="image" width="300" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210548.png" alt="f:id:sgtech:20200126210548p:plain" title="f:id:sgtech:20200126210548p:plain" class="hatena-fotolife" itemprop="image" width="301" /></p> <p> </p> <p>正規化をします。Ctrl+Aで波形を全選択したあと、「エフェクト」&gt;「ノーマライズ」を実行します。出てくるウィンドウはそのままでOKです。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210535.png" alt="f:id:sgtech:20200126210535p:plain" title="f:id:sgtech:20200126210535p:plain" class="hatena-fotolife" itemprop="image" width="300" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210540.png" alt="f:id:sgtech:20200126210540p:plain" title="f:id:sgtech:20200126210540p:plain" class="hatena-fotolife" itemprop="image" width="300" /></p> <p> </p> <p>WAVファイルのエクスポートは、「ファイル」&gt;「書き出し」&gt;「WAVとして書き出し」を実行します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210544.png" alt="f:id:sgtech:20200126210544p:plain" title="f:id:sgtech:20200126210544p:plain" class="hatena-fotolife" itemprop="image" width="301" /></p> <p>UE4へのインポートは、フォルダを選択してインポートボタンです。右クリックからもできます。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210706.png" alt="f:id:sgtech:20200126210706p:plain" title="f:id:sgtech:20200126210706p:plain" class="hatena-fotolife" itemprop="image" width="281" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210710.png" alt="f:id:sgtech:20200126210710p:plain" title="f:id:sgtech:20200126210710p:plain" class="hatena-fotolife" itemprop="image" width="281" /></p> <p> </p> <p>インポートされたアセットを右クリックし、キューを作成します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210714.png" alt="f:id:sgtech:20200126210714p:plain" title="f:id:sgtech:20200126210714p:plain" class="hatena-fotolife" itemprop="image" width="280" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210718.png" alt="f:id:sgtech:20200126210718p:plain" title="f:id:sgtech:20200126210718p:plain" class="hatena-fotolife" itemprop="image" width="279" /></p> <p> </p> <p>例えばBGMの場合はループさせたいので、キューアセットを開いてWave Playerノードを選択し、詳細パネルのLoopingにチェックを入れます。</p> <p>また風の音や爆発音といったSEについて、アウトプットノードを選択したときの詳細パネルでピッチ項目を弄ってゲームの雰囲気と合わせます。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210726.png" alt="f:id:sgtech:20200126210726p:plain" title="f:id:sgtech:20200126210726p:plain" class="hatena-fotolife" itemprop="image" width="279" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210721.png" alt="f:id:sgtech:20200126210721p:plain" title="f:id:sgtech:20200126210721p:plain" class="hatena-fotolife" itemprop="image" width="278" /></p> <h3 id="プログラマー向けTips">プログラマー向けTips</h3> <h4 id="タイトルゲームリザルトタイトルのゲームシーケンスループを作成">タイトル→ゲーム→リザルト→タイトルのゲームシーケンスループを作成</h4> <p>ゲームに備わっているべきシーケンスだと思います。もちろん、ゲームの部分を作ることに熱中して作成できなかったとしてもOK。それもゲームジャムです。</p> <p>このシーケンスがスムーズに作られていると、プレイする人の頭が準備されるだけでなく、試遊する方がプレイするときに制作者がいちいちスタートボタンや停止ボタンを押さなくても良くなります。</p> <p>ゲームジャムでは試遊の時間が設けられていることが多いです。自分のゲーム近くで案内操作している時間が多いと、他のジャム作品を遊ぶ時間が少なくなります。それはもったいないので、ぜひ自立したゲームシーケンスを目指してください。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210252.gif" alt="f:id:sgtech:20200126210252g:plain" title="f:id:sgtech:20200126210252g:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p>↑おまけ⑥を制作したジャムで配布されたテンプレートにおける遷移動作です。</p> <h5 id="マップを分割し遷移処理を作成">マップを分割し、遷移処理を作成</h5> <p>ゲームジャム中はメインとなるゲームのマップを繰り返し実行して開発するので、タイトルを切り離しておくべきです。</p> <p>ゲーム中にリザルトを表示させようとなると、表示の裏で動く様々な処理を止める必要があるかもしれません。意外と手間である場合もありますので、リザルトも分かれていると悩まなくて良いです。タイトルやリザルトの表示は一瞬でも、それを遷移する時間がちりつもで嵩んでいきます。</p> <p>分割することで、UI作成+表示+マップ遷移の役割としてゲーム部分の役割と切り離すことができます。これは重要なことで、プログラマーが2人以上の場合はプレイヤー+ゲーム部分担当と、UI+シーケンス(+他のキャラクター)担当に分かれることがとても多いです。同じマップファイルを触らなくなるので、更新が衝突することも無くなります。</p> <p> </p> <p>レベルの遷移はOpenLevelノードで行います。正しく該当のマップに遷移するか、必ず確認するようにしましょう。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210437.png" alt="f:id:sgtech:20200126210437p:plain" title="f:id:sgtech:20200126210437p:plain" class="hatena-fotolife" itemprop="image" width="248" /></p> <p>実行時にLevel Nameの名前を持ったマップアセットの探索が走ります。ジャム規模のプロジェクトで探索時間が問題になることは無いと思いますが、Gameからのフルパスを指定しておけば転ばぬ先の杖です。指定方法は、マップアセットを右クリックして「リファレンスをコピー」を実行してペーストした結果より、「World'」から「.マップ名'」までの文字を抜き出します。例えば</p> <p>「World'/Game/00_GameJam2020/Map/Result.Result'」がコピーされるので、「/Game/00_GameJam2020/Map/Result」を使用します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210440.png" alt="f:id:sgtech:20200126210440p:plain" title="f:id:sgtech:20200126210440p:plain" class="hatena-fotolife" itemprop="image" width="299" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210445.png" alt="f:id:sgtech:20200126210445p:plain" title="f:id:sgtech:20200126210445p:plain" class="hatena-fotolife" itemprop="image" width="298" /></p> <p>繰り返しになりますが、正しく該当のマップに遷移するか必ず確認するようにしましょう。</p> <h5 id="得点などをリザルトで表示したい場合はGameInstanceクラスを作成して情報を持たせる">得点などをリザルトで表示したい場合はGameInstanceクラスを作成して情報を持たせる</h5> <p>Mapを遷移するとActorがベースクラスのBlueprintは破棄されます。プレイヤーのキャラクタークラス等に得点情報を持たせてしまうと、マップ遷移時に情報が失われてしまいます。</p> <p>GameInstanceクラスはプロジェクトに1つだけ設定され、アプリケーション起動時より常駐となります。このクラスにリザルトの情報を持たせる実装が楽です。</p> <h5 id="GameInstanceクラスの作成">GameInstanceクラスの作成</h5> <p>コンテンツブラウザ上の右クリックメニューよりブループリントクラスを選択し、親クラスの選択ウィンドウにて「すべてのクラス」を展開した中よりGameInstanceクラスを選択します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210456.png" alt="f:id:sgtech:20200126210456p:plain" title="f:id:sgtech:20200126210456p:plain" class="hatena-fotolife" itemprop="image" width="299" /><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210502.png" alt="f:id:sgtech:20200126210502p:plain" title="f:id:sgtech:20200126210502p:plain" class="hatena-fotolife" itemprop="image" width="298" /></p> <p> </p> <p>今回はBP_Jam_GameInstanceという名前にしました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210506.png" alt="f:id:sgtech:20200126210506p:plain" title="f:id:sgtech:20200126210506p:plain" class="hatena-fotolife" itemprop="image" /></p> <p> </p> <p>「編集」 &gt; 「プロジェクト設定」で開いたウィンドウより、左側の「マップ&amp;モード」を選択、中の「ゲームインスタンス」に先程作成したクラスを設定します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210512.png" alt="f:id:sgtech:20200126210512p:plain" title="f:id:sgtech:20200126210512p:plain" class="hatena-fotolife" itemprop="image" width="299" /><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210509.png" alt="f:id:sgtech:20200126210509p:plain" title="f:id:sgtech:20200126210509p:plain" class="hatena-fotolife" itemprop="image" width="298" /></p> <p> </p> <p>作成したゲームインスタンスの参照を取得するには、GetGameInstanceノードのアウトプットをキャストします。関数ライブラリなどに取得関数を作成すると便利です。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210518.png" alt="f:id:sgtech:20200126210518p:plain" title="f:id:sgtech:20200126210518p:plain" class="hatena-fotolife" itemprop="image" width="350" /></p> <p><span style="color: #ff0000;"><strong>※技術的負債ポイントです。</strong><span style="color: #000000;">GameInstance参照が各所に飛び散ると、起動と同時に芋づる式に参照アセットがロードされるので、規模が大きくなるうちに気づけば初回起動にとても時間がかかる問題にぶち当たります。</span></span></p> <p><span style="color: #ff0000;"><span style="color: #000000;">回避策の1つに、</span></span><span style="color: #ff0000;"><span style="color: #000000;">BlueprintInterfaceを使用する方法があります。ジャムではおすすめしませんので、もしあなたがジャム中であれば読み飛ばしてください。</span></span></p> <p><span style="color: #ff0000;"><span style="color: #000000;">他のBlueprintクラスと同様に右クリックからクラスを選択します。</span></span></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210849.png" alt="f:id:sgtech:20200126210849p:plain" title="f:id:sgtech:20200126210849p:plain" class="hatena-fotolife" itemprop="image" width="372" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210852.png" alt="f:id:sgtech:20200126210852p:plain" title="f:id:sgtech:20200126210852p:plain" class="hatena-fotolife" itemprop="image" width="198" /></p> <p> </p> <p><span style="color: #ff0000;"><span style="color: #000000;">ダブルクリックでクラスの編集画面に入り、「+」ボタンでインターフェース関数を追加します。続いて引数や返り値を定義します。</span></span></p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210855.png" alt="f:id:sgtech:20200126210855p:plain" title="f:id:sgtech:20200126210855p:plain" class="hatena-fotolife" itemprop="image" width="350" /></p> <p> </p> <p>次に今回プロジェクトのGameInstanceクラスを開き、「クラス設定」よりBlueprintInterfaceクラスを指定し、インターフェース項目に追加された関数の中身を実装します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210900.png" alt="f:id:sgtech:20200126210900p:plain" title="f:id:sgtech:20200126210900p:plain" class="hatena-fotolife" itemprop="image" width="300" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210905.png" alt="f:id:sgtech:20200126210905p:plain" title="f:id:sgtech:20200126210905p:plain" class="hatena-fotolife" itemprop="image" width="297" /></p> <p> </p> <p>使用するときは、GetGameInstance関数のアウトプットから呼び出すことができます。右上にメールが開封されたようなアイコンが付いているものがインターフェース関数です。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210910.png" alt="f:id:sgtech:20200126210910p:plain" title="f:id:sgtech:20200126210910p:plain" class="hatena-fotolife" itemprop="image" /></p> <p>ジャム中にこの方式を使用するデメリットとしては、ノードをダブルクリックしても実装した部分が開きません。BlueprintInterfaceクラスが開きます。実装内容を調整したいときは自分でBlueprintInterfaceクラスを実装したクラスを開いて該当の関数を見つけるい必要があります。ちょっとした手間が貴重な時間や精神を削ります。</p> <p>もしジャムのGameInstanceに適用する場合、何度も調整する必要がないように変数のSet, Get程度にとどめましょう。</p> <p>もう少しこの辺りの問題について知りたい場合、こちらの記事の「プログラム編」を読んでみてください。</p> <p><a href="https://jp.gamesindustry.biz/article/1810/18101801/">特徴的なアートスタイルはこうして作られた。「OCTOPATH TRAVELER」開発秘話 - GamesIndustry.biz Japan Edition</a></p> <p> </p> <h5 id="UIのWidgetBlueprintをGameInstanceに持たせた例">UIのWidgetBlueprintをGameInstanceに持たせた例</h5> <p>おまけの⑫では、この図のような構成で作りました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210433.png" alt="f:id:sgtech:20200126210433p:plain" title="f:id:sgtech:20200126210433p:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p>WidgetBlueprintクラスをGameInstanceに持たせておくと、ゲーム中のUI情報をリザルト画面で流用することができて楽になります。リザルトのマップにおいて、ゲーム中に更新されたWidgetBlueprintを表示(AddToViewport)してUI上部のゲージを非表示にするだけで、スコアのリザルトを反映することができました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210448.png" alt="f:id:sgtech:20200126210448p:plain" title="f:id:sgtech:20200126210448p:plain" class="hatena-fotolife" itemprop="image" width="300" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210453.png" alt="f:id:sgtech:20200126210453p:plain" title="f:id:sgtech:20200126210453p:plain" class="hatena-fotolife" itemprop="image" width="300" /></p> <h4 id="パラメータを調節してもらうようにする"> <br />パラメータを調節してもらうようにする</h4> <p>例えば、Blueprint関数ライブラリにパラメータを取得する関数を作成して、ゲームデザイナーの役割の人にアウトプットの数値を弄ってもらうようにします。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210354.png" alt="f:id:sgtech:20200126210354p:plain" title="f:id:sgtech:20200126210354p:plain" class="hatena-fotolife" itemprop="image" width="299" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210357.png" alt="f:id:sgtech:20200126210357p:plain" title="f:id:sgtech:20200126210357p:plain" class="hatena-fotolife" itemprop="image" width="299" /></p> <p> </p> <p>関数ライブラリではなくマクロライブラリにする場合は、FormatText(テキストをフォーマット)ノードなどに気をつけましょう。この場合、関数ライブラリの出力は正しく値が渡りますが、マクロライブラリの出力値はnullとなります。<br /><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210401.png" alt="f:id:sgtech:20200126210401p:plain" title="f:id:sgtech:20200126210401p:plain" class="hatena-fotolife" itemprop="image" width="444" /></p> <h4 id="値を画面に表示し続ける">値を画面に表示し続ける</h4> <p>PrintTextやPrintStringノードにおけるDuration(表示時間)を0にすると1フレームだけ描画されるので、Tickで毎フレーム呼び出すことで常に1つ表示されているように見えます。</p> <p>例えば以下のように残り時間、体力、得点といったパラメータを表示しておくことをおすすめします。FormatText(テキストをフォーマット)ノード内に{hoge}を記述することでInputピンを増やすことができます。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210608.png" alt="f:id:sgtech:20200126210608p:plain" title="f:id:sgtech:20200126210608p:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p><br />ずっと左上に出続けます。<br /><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210116.gif" alt="f:id:sgtech:20200126210116g:plain" title="f:id:sgtech:20200126210116g:plain" class="hatena-fotolife" itemprop="image" /></p> <p>見ながら動作確認やレベルデザインに活用できます。短い期間でも数値の扱いでバグが生まれやすいので、おかしいなと思ったときにすぐ気づくこともできるでしょう。</p> <p> </p> <h4 id="デバッグキーを用意する">デバッグキーを用意する</h4> <p>「ゲームをクリアしたことにする」「アイテムを取得したことにする」「次のレベルへ飛ばす」といったショートカットはレベルデザインやデバッグ作業を高速化します。キーボードを押した時に呼ばれるイベントを作成しましょう。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210914.png" alt="f:id:sgtech:20200126210914p:plain" title="f:id:sgtech:20200126210914p:plain" class="hatena-fotolife" itemprop="image" /></p> <p>グラフ上で右クリックして任意のキーボードイベントを検索するときに、なかなか見つからず苦労している方をジャム中によく見かけます。</p> <p>たとえば「a」キーの場合、日本語環境では「a キー」、英語環境では「a keyb」まで入力することでサジェストを絞り込むことができます。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210918.png" alt="f:id:sgtech:20200126210918p:plain" title="f:id:sgtech:20200126210918p:plain" class="hatena-fotolife" itemprop="image" width="248" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210922.png" alt="f:id:sgtech:20200126210922p:plain" title="f:id:sgtech:20200126210922p:plain" class="hatena-fotolife" itemprop="image" width="249" /></p> <p> </p> <p>または検索窓に「@」を入力(サジェストにキーボードイベントしか出てこない!)してインプットイベントをとりあえず作成し、イベントノードを選択した状態の詳細パネルから、Input Key部分から対応するキーやボタンを変更します。グラフ上で右クリックするよりも探しやすいと思います。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210927.png" alt="f:id:sgtech:20200126210927p:plain" title="f:id:sgtech:20200126210927p:plain" class="hatena-fotolife" itemprop="image" width="277" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210932.png" alt="f:id:sgtech:20200126210932p:plain" title="f:id:sgtech:20200126210932p:plain" class="hatena-fotolife" itemprop="image" width="326" /></p> <h4 id="エディタで配置するか外部ファイルで配置するかランダムに任せるか"> <br />エディタで配置するか、外部ファイルで配置するか、ランダムに任せるか</h4> <h5 id="エディタでの配置">エディタでの配置</h5> <p>ゲームプレイのイメージをしやすく、プレイの実行自体もすぐに行えるので思ったことをすぐ試せる強みがあります。</p> <p>熱中しだすと時間を消費するので、レベルデザインの担当者が時間を区切って取り組む必要があります。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210653.png" alt="f:id:sgtech:20200126210653p:plain" title="f:id:sgtech:20200126210653p:plain" class="hatena-fotolife" itemprop="image" width="350" /></p> <p>プログラマー側では、調整してほしいパラメータを公開するようにしましょう。</p> <p><a href="https://docs.unrealengine.com/ja/Engine/Blueprints/UserGuide/Variables/index.html">ブループリント変数 | Unreal Engine ドキュメント</a></p> <p> </p> <p>おまけの⑥ではコインのBlueprintに「BigCoin」フラグを設けて、レベルデザイナーがフラグをオンオフすることでサイズとスコアの異なるコインの使い分けができるようにしました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210703.png" alt="f:id:sgtech:20200126210703p:plain" title="f:id:sgtech:20200126210703p:plain" class="hatena-fotolife" itemprop="image" width="299" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210656.png" alt="f:id:sgtech:20200126210656p:plain" title="f:id:sgtech:20200126210656p:plain" class="hatena-fotolife" itemprop="image" width="297" /></p> <h5 id="外部ファイルに記述">外部ファイルに記述</h5> <p>設定箇所が多くエディタ内の操作では時間がかかる場合には、外部ファイルでまとめて設定できるような方法を検討するといいでしょう。</p> <p>おまけの⑩では、ステージの起伏設定箇所が100個以上有ったため、Excelに入力してcsvよりUE4のDataTableへインポートするようにしました。Excelを使用する場合は、「条件付き書式」&gt; 「セルの強調表示ルール」を設定することをおすすめします。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210626.png" alt="f:id:sgtech:20200126210626p:plain" title="f:id:sgtech:20200126210626p:plain" class="hatena-fotolife" itemprop="image" width="350" /></p> <p> </p> <p>例えばゲーム中の見た目と同様な色の使用や、設定の種類によって色をアサインすることで入力の段階から動作イメージをしやすくなります。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210630.png" alt="f:id:sgtech:20200126210630p:plain" title="f:id:sgtech:20200126210630p:plain" class="hatena-fotolife" itemprop="image" width="292" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210642.png" alt="f:id:sgtech:20200126210642p:plain" title="f:id:sgtech:20200126210642p:plain" class="hatena-fotolife" itemprop="image" width="290" /></p> <p>CSVのインポートや、どのようにCSVを記述したらよいかは、こちらの記事がわかりやすいです。</p> <ul> <li><a href="http://historia.co.jp/archives/779/">[UE4] CSVデータを扱う方法 DataTable編|株式会社ヒストリア</a></li> <li><a href="http://historia.co.jp/archives/13885/">[UE4]様々な型のデータテーブルをCSVからインポートする|株式会社ヒストリア</a></li> </ul> <h5 id="ランダムに任せる">ランダムに任せる</h5> <p>限られた時間の中で、手が回らない場合はランダムな配置に任せるのも手です。</p> <p>プレイごとに内容が変わるので、いままで判明していなかった面白い部分や面白くない部分が見つかります。またジャムの終了後、試遊のために並んでいる人や気になって近くで見ている人達が自分でプレイするまでに飽きないです。</p> <p>ただし同じゲーム内容を再現できないので、バランスを担保することが難しいです。</p> <p>おまけの⑨のゲーム設計は、プレイヤー進行方向より流れてくるアイテムを取り続けるというものでした。しかし、アイテムをステージ上に手動配置する時間が足りず、ランダムを使用することにしました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210634.png" alt="f:id:sgtech:20200126210634p:plain" title="f:id:sgtech:20200126210634p:plain" class="hatena-fotolife" itemprop="image" width="241" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210647.png" alt="f:id:sgtech:20200126210647p:plain" title="f:id:sgtech:20200126210647p:plain" class="hatena-fotolife" itemprop="image" width="296" /></p> <p> </p> <p>0.35秒ごとに前方の4箇所からランダムで出現させる処理(右の関数)を書きました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210638.png" alt="f:id:sgtech:20200126210638p:plain" title="f:id:sgtech:20200126210638p:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p>40秒程度のゲームで100個以上のアイテムを出現させています。プログラムは1時間以内で書けましたが、同じ量を手動で配置して調整するとなると2, 3時間必要でしょう。</p> <h4 id="とりあえず爆発させましょう">「とりあえず爆発させましょう」</h4> <p>ジャムの終盤でよく聞く言葉です。</p> <p>理由はどうあれ、もう爆発させるしかない。爆発は全てを解決します。</p> <p>Content Examples(機能別サンプル)より爆発を持ってきてみましょう。</p> <p> </p> <p>Epic Games LauncherのUnrealEngine(左側)より、ラーニング(上側)より「機能別サンプル」を探してプロジェクトを作成します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210138.png" alt="f:id:sgtech:20200126210138p:plain" title="f:id:sgtech:20200126210138p:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p> </p> <p>作成してプロジェクトを開いたら(シェーダコンパイルを待つ必要はありません)、コンテンツブラウザの検索窓に「explosion」と入力します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210156.png" alt="f:id:sgtech:20200126210156p:plain" title="f:id:sgtech:20200126210156p:plain" class="hatena-fotolife" itemprop="image" width="347" /></p> <p> </p> <p>爆発アセット「P_Explosion_Bomb」を右クリック、「アセットアクション」→「移行」を選択します。(英語環境では「Asset Actions」→「Migrate」)</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210144.png" alt="f:id:sgtech:20200126210144p:plain" title="f:id:sgtech:20200126210144p:plain" class="hatena-fotolife" itemprop="image" width="350" /></p> <p> </p> <p>下図のように爆発アセットに参照されているテクスチャやマテリアルが階層表示されます。OKを選択し、移行先プロジェクトのContentフォルダを選択してOKします。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210147.png" alt="f:id:sgtech:20200126210147p:plain" title="f:id:sgtech:20200126210147p:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p> </p> <p>画面右下に移行完了のメッセージが出ます。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210152.png" alt="f:id:sgtech:20200126210152p:plain" title="f:id:sgtech:20200126210152p:plain" class="hatena-fotolife" itemprop="image" width="351" /></p> <p> </p> <p>移行先のプロジェクトを開き、アクターを作成します。コンテンツブラウザで右クリック→ブループリント→ブループリントクラスを選択。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210202.png" alt="f:id:sgtech:20200126210202p:plain" title="f:id:sgtech:20200126210202p:plain" class="hatena-fotolife" itemprop="image" width="348" /></p> <p>ウィンドウからActorを選択します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210246.png" alt="f:id:sgtech:20200126210246p:plain" title="f:id:sgtech:20200126210246p:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p> </p> <p>作成したActorは「BP_Explosion」としました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210206.png" alt="f:id:sgtech:20200126210206p:plain" title="f:id:sgtech:20200126210206p:plain" class="hatena-fotolife" itemprop="image" /></p> <p> </p> <p>ダブルクリックで開き、コンポーネントタブの「コンポーネントを追加」をクリック、検索窓に入力して「ParticleSystem」を絞り込んで選択します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210210.png" alt="f:id:sgtech:20200126210210p:plain" title="f:id:sgtech:20200126210210p:plain" class="hatena-fotolife" itemprop="image" /></p> <p> </p> <p>コンポーネントタブはこのようになります。このParticleSystemを選択した状態(色が黄色になっている状態)にします。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210214.png" alt="f:id:sgtech:20200126210214p:plain" title="f:id:sgtech:20200126210214p:plain" class="hatena-fotolife" itemprop="image" /></p> <p> </p> <p>同じ画面の詳細タブから、「Particles」の項目を探し、中の「Template」行にあるプルダウンエリアをクリック、出てきたサジェストより移行してきた「P_Explosion_Bomb」を選択してください。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210219.png" alt="f:id:sgtech:20200126210219p:plain" title="f:id:sgtech:20200126210219p:plain" class="hatena-fotolife" itemprop="image" width="346" /></p> <p> </p> <p>Templateに適応された状態です。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210224.png" alt="f:id:sgtech:20200126210224p:plain" title="f:id:sgtech:20200126210224p:plain" class="hatena-fotolife" itemprop="image" width="348" /></p> <p> </p> <p>ちょっとだけ余裕がある人は、イベントグラフタブに移動してください。ない人はこれで「BP_Explosion」での作業は終わりです。画像を2個飛ばして「爆発の起動」から読んでください。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210229.png" alt="f:id:sgtech:20200126210229p:plain" title="f:id:sgtech:20200126210229p:plain" class="hatena-fotolife" itemprop="image" width="350" /></p> <p> </p> <p>BeginPlayノードより、Delay(2秒を設定)、DestroyActor(self:自分自身)とノードを作成して接続します。これで2秒後に自分自身を破棄します。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210232.png" alt="f:id:sgtech:20200126210232p:plain" title="f:id:sgtech:20200126210232p:plain" class="hatena-fotolife" itemprop="image" width="354" /></p> <h5 id="爆発の起動">爆発の起動</h5> <p>「BP_Explosion」をSpawnActorするだけで起動します。例えばレベルブループリントのBeginPlayでSpawnしてみます。爆発させたい位置(Transform内のPosition)をステージ真ん中辺りに指定しました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210236.png" alt="f:id:sgtech:20200126210236p:plain" title="f:id:sgtech:20200126210236p:plain" class="hatena-fotolife" itemprop="image" width="351" /></p> <p> </p> <p>実行するとすぐ爆発します。終わり。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210241.gif" alt="f:id:sgtech:20200126210241g:plain" title="f:id:sgtech:20200126210241g:plain" class="hatena-fotolife" itemprop="image" width="351" /></p> <p><br /><br /><br /></p> <h3 id="ジャム中の注意点など">ジャム中の注意点など</h3> <h4 id="巨大なアセットが本当に必要か検討する">巨大なアセットが本当に必要か検討する</h4> <p>UE4のMarketPlaceやラーニングコンテンツでは高品質なアセットが並び、中には無料で手に入るものがあります。</p> <p>これらは使いやすいと思いきや、大きいリソースはジャム中のイテレーションを鈍化させる原因になります。</p> <p>おまけの⑧では広大な3つのステージを同時に使用しました。</p> <ol> <li> <p><a href="https://docs.unrealengine.com/ja/Resources/SampleGames/ShooterGame/index.html">シューティング ゲーム | Unreal Engine ドキュメント</a></p> </li> <li> <p><a href="https://unrealengine.com/marketplace/ja/product/infinity-blade-fire-lands">Infinity Blade: Fire Lands:Epic Games:Epic Content - UE4 マーケットプレイス</a></p> </li> <li><a href="https://unrealengine.com/marketplace/ja/product/infinity-blade-ice-lands">Infinity Blade: Ice Lands:Epic Games:Epic Content - UE4 マーケットプレイス</a></li> </ol> <p>ShooterGameのビル内に、Fire LandsとIceLandsを入れこむ贅沢な使い方をしました。入れこむための配置調整に時間がかかった上に、結果としてマップを開く時間がとてつもなく長くなり、アプリのパッケージング時間も膨大となりました。</p> <p>結果として提出するための動画撮影時間が足らずに中途半端なコンテストのエントリーになってしまいました。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210412.gif" alt="f:id:sgtech:20200126210412g:plain" title="f:id:sgtech:20200126210412g:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p>ゲームの本質的に不要であれば、無理に入れない方が良いかもしれません。</p> <h4 id="ゲーム画面の発表時には電源を接続する">ゲーム画面の発表時には電源を接続する</h4> <p>ノートPCがバッテリー動作の場合、充分な電力がグラフィックカードへ送られず3Dゲームの実行が不安定になることがあります。</p> <p>発表場所近くで電源を使用できるよう運営に手配していただくようにしましょう。</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210523.jpg" alt="f:id:sgtech:20200126210523j:plain" title="f:id:sgtech:20200126210523j:plain" class="hatena-fotolife" itemprop="image" /></p> <h3 id="ゲームジャムでUE4チームを作るには">ゲームジャムでUE4チームを作るには</h3> <p>テンプレートの活用やBlueprint開発、エディタでの高速なイテレーションによって、UE4はジャムの強力な味方になります。</p> <p>しかしUE4だけの制限をしていないジャムにおいて、UE4チームが生まれる機会は少ないです。Global Game Jam (毎年世界同時に開催される最も大規模なジャム)では、Unityに比べてUE4で制作されるゲームの数は10分の1程度です。世界中の比率と日本国内の比率は同じくらいです。</p> <p>UE4を使いたいなと思っていても、チームではUnityを使用する場合が多いと思います。</p> <h5 id="ジャム運営の方へ">ジャム運営の方へ</h5> <p>UE4チームが組まれるためには、ジャム運営側の協力が必要だと思っています。あらかじめ参加者に希望(リーダーや使用ツール)を募るケースが多いと思いますので、参加時にエンジンの希望を出してもらうようにしてみましょう。</p> <p>次に参加者の希望を公開 (公開する旨は伝わるようにする)して、ジャムのwebページで見えるように並べます。UE4の希望者は他にUE4の希望者が居ると集まりやすいです。</p> <p>または、ジャムの参加枠にUE4枠を作成してみてください。どこからともなく集まります。connpassなどのサービスで枠を作成できます。</p> <h5 id="ジャム当日のチーム決めの後に選択肢として考えてみる">ジャム当日のチーム決めの後に、選択肢として考えてみる</h5> <p>チーム内にUE4経験者が居る場合は、UE4チームになってみることを検討してみてください。UE4未経験者が経験者に教わりながら触り始めて、機能実装やレベルデザインを主体的に行っている様子を何度も見てきました。ここでの経験者は私以外であるパターンもいくつか知っています。</p> <h3 id="おわりに">おわりに</h3> <p>今回は個人的な活動を書き起こしてみました。私が活用したことのないものは書いておりませんので、良さげなノウハウや苦労した話を持っているよ!という方は、ぜひブログやスライドにして公開していただけたらと思います。</p> <p>セガではグループ内で定期的にゲームジャムを開催しており、私のように毎回UE4を使う人や、その時によってアナログゲーム制作や電子工作を絡める方など、やりたいことを試す機会に恵まれています。ご興味がありましたら、ぜひ採用情報をチェックしてみてください。</p> <p><a href="http://sega-interactive.co.jp/recruit/" onmousedown="ga('HatenaBlogUserTracker.send', 'event', 'recruit', 'sic_banner_clicked','recruit_sic_out', true);">採用情報| 株式会社セガ・インタラクティブ</a></p> <p>そして私とUE4のチームを組んでください。</p> <p> </p> <h3 id="おまけこれまでの制作物">おまけ:これまでの制作物</h3> <p>簡単な説明・期間・画像を載せてみました。</p> <p>Sega Game Jamで制作したものは[SGJ]とつけました。</p> <p>画像の下にジャム前のモチベーションを書きました。</p> <p><br />①: [SGJ]超電磁的なコインを飛ばすVRゲーム:1日</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210958.gif" alt="f:id:sgtech:20200126210958g:plain" title="f:id:sgtech:20200126210958g:plain" class="hatena-fotolife" itemprop="image" width="350" /></p> <p>ジャム前は、VR元年ということもありVRゲームを作りたいモチベーションでした。</p> <p>バーチャルリアリティのテンプレートを使用しています。</p> <p><br />②: クレー射撃のようなVRゲーム:2日</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126205831.gif" alt="f:id:sgtech:20200126205831g:plain" title="f:id:sgtech:20200126205831g:plain" class="hatena-fotolife" itemprop="image" width="250" /></p> <p>ジャム前はとにかくVRゲームを作りたいモチベーションと、オリンピック競技的なものを作りたいと思っていました。</p> <p>バーチャルリアリティのテンプレートを使用しています。</p> <p> </p> <p>③: [SGJ]巨大化して求婚するゲーム:2日</p> <p> ※Sega Game Jam内に限り、セハガールモデルの使用が認められていました</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210107.gif" alt="f:id:sgtech:20200126210107g:plain" title="f:id:sgtech:20200126210107g:plain" class="hatena-fotolife" itemprop="image" width="350" /></p> <p>ジャム前は特に何も考えずに挑みました。</p> <p>サードパーソンのテンプレートを使用しています。</p> <p> </p> <p>④:[SGJ]コントローラやLED連動システムごと作った宇宙探査ゲーム:2日</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126225439.gif" alt="f:id:sgtech:20200126225439g:plain" title="f:id:sgtech:20200126225439g:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p>ジャム前はアーケードゲーム筐体を作りたいと思っていました。</p> <p>フライングのテンプレートを使用しています。</p> <p><br />⑤: 爆弾の設置側と解除側のゲーム:1ヶ月程度</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126205856.gif" alt="f:id:sgtech:20200126205856g:plain" title="f:id:sgtech:20200126205856g:plain" class="hatena-fotolife" itemprop="image" width="350" /></p> <p>ジャム前はUE4のリプレイ機能(DemoRec)を使いたいなと思っていました。</p> <p>サードパーソンのテンプレートを使用しています。</p> <p> </p> <p>⑥: 昼と夜を切り替え対応する足場を乗り継ぐゲーム:2日</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126205842.gif" alt="f:id:sgtech:20200126205842g:plain" title="f:id:sgtech:20200126205842g:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p>ジャム前はUE4のライトシナリオ機能を使いたいと思っていました。</p> <p>ジャム専用のサイドスクロールテンプレートを使用しています。</p> <p> </p> <p>⑦: [SGJ]おじさんが失った青春を取り戻すゲーム:2日</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210112.gif" alt="f:id:sgtech:20200126210112g:plain" title="f:id:sgtech:20200126210112g:plain" class="hatena-fotolife" itemprop="image" width="348" /></p> <p>ジャム前は特に何も考えずに挑みました。</p> <p>サードパーソンのテンプレートを使用しています。</p> <p> </p> <p>⑧: プリンがぷるぷるするゲーム:1ヶ月程度</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126205917.gif" alt="f:id:sgtech:20200126205917g:plain" title="f:id:sgtech:20200126205917g:plain" class="hatena-fotolife" itemprop="image" width="299" /> <img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210741.gif" alt="f:id:sgtech:20200126210741g:plain" title="f:id:sgtech:20200126210741g:plain" class="hatena-fotolife" itemprop="image" width="298" /></p> <p>ジャム前は、ゲームにならなさそうなものを無理やりゲームにしたいと思っていました。</p> <p>サードパーソンのテンプレートを使用しました。プリンの軟体シミュレーションにはNVIDIA FleXを使用しています。</p> <p> </p> <p>⑨: つばめが綺麗な円を描くゲーム:2日</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126205932.gif" alt="f:id:sgtech:20200126205932g:plain" title="f:id:sgtech:20200126205932g:plain" class="hatena-fotolife" itemprop="image" width="353" /></p> <p>ジャム前は特に何も考えずに挑みました。</p> <p>テンプレートは使用していません。</p> <p> </p> <p>⑩: 地形をリバースさせ、せり上がる衝撃でジャンプし続けるゲーム:5日</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210004.gif" alt="f:id:sgtech:20200126210004g:plain" title="f:id:sgtech:20200126210004g:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p>ジャム前は、アプリケーション容量を小さく収めるチャレンジ枠に挑戦したいと思っていました。地形をランタイムで生成しています。(ProceduralMeshComponent)</p> <p>テンプレートは使用していません。</p> <p> </p> <p>⑪: [SGJ]大崎オフィスにグループ会社が集結するということで、各事業所を回ってグループシナジーを集めていくタイムリーネタだったゲーム:2日</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210045.gif" alt="f:id:sgtech:20200126210045g:plain" title="f:id:sgtech:20200126210045g:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p>ジャム前は、メガドライブミニ要素をどこかしらに入れたいと思っていました。実際にプレイヤーの前方より発射されます。</p> <p>テンプレートは使用せず、OSSのOceanProjectを使用しています。</p> <p> </p> <p>⑫: [SGJ]ヒトデが魚や人を食べて大きくなって星になるゲーム:2日</p> <p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20200126/20200126210021.gif" alt="f:id:sgtech:20200126210021g:plain" title="f:id:sgtech:20200126210021g:plain" class="hatena-fotolife" itemprop="image" width="349" /></p> <p>ジャム前は、チーム分けでUnityチームのプログラムリーダーになっていたのでUnityの復習をしていました。当日の話し合いでUE4を使うことになりました。</p> <p>サードパーソンのテンプレートを使用しています。</p> <p> </p> <p>以上です。ここまで見ていただき、ありがとうございました。</p> sgtech SEGA GAME JAM 再始動!テーマは☆!! hatenablog://entry/26006613488201883 2019-12-25T10:00:00+09:00 2020-05-29T18:43:43+09:00 セガゲームス、セガ・インタラクティブ含め、セガサミーグループが大崎に集約され、いよいよシナジー効果が期待される中、先月11月2日にSEGA GAME JAMが再始動しました。 皆さんこんにちは。SEGA GAME JAM運営の麓です。 SEGA GAME JAMの運営としてはデザイナー向けの対応や、ポスターデザイン、ロゴデザイン、Tシャツデザインの調整などを担当しつつ、当日は主にデザイナーとして参加しています。 普段私はテクニカルアーティストとしてツール環境整備周りを担当していて、アセットを作らなくなって久しいのですが(元々はデザイナーでした)、GAME JAM中はただひたすらデザインアセット… <p><img class="hatena-fotolife" title="f:id:sgtech:20191207144708j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207144708.jpg" alt="f:id:sgtech:20191207144708j:plain" /></p> <p>セガゲームス、セガ・インタラクティブ含め、セガサミーグループが大崎に集約され、いよいよシナジー効果が期待される中、先月11月2日にSEGA GAME JAMが再始動しました。</p> <p>皆さんこんにちは。SEGA GAME JAM運営の麓です。</p> <p>SEGA GAME JAMの運営としてはデザイナー向けの対応や、ポスターデザイン、ロゴデザイン、Tシャツデザインの調整などを担当しつつ、当日は主にデザイナーとして参加しています。</p> <p>普段私はテクニカルアーティストとしてツール環境整備周りを担当していて、アセットを作らなくなって久しいのですが(元々はデザイナーでした)、GAME JAM中はただひたすらデザインアセットを作り続けることになる刺激的な時間をいつも過ごしています。</p> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191207145048j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207145048.jpg" alt="f:id:sgtech:20191207145048j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191207145029j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207145029.jpg" alt="f:id:sgtech:20191207145029j:plain" /></div> </div> <h3>SEGA GAME JAMって?</h3> <p>今さらですが、今回初めてこのブログから読み始める方のために簡単にSEGA GAME JAMについて説明します。</p> <p>SEGA GAME JAMは2日間の限られた時間で、小規模グループに分かれて、それぞれのグループで一からゲームを作ってしまおう!というイベントで、2012年7月の初回から年2回程のペースで開催されているイベントです。</p> <p>参加するのはセガサミーグループ全体を対象とし、ゲーム制作部門ではない人も過去には参加しています。</p> <p>CEDEC2013で効果や詳細は公表していますので、ご興味をお持ちの方は以下にアクセスしていただけるとより詳しく知ることができます。(要ログイン)</p> <p><a href="https://cedil.cesa.or.jp/cedil_sessions/view/1027">SEGA Game Jamがもたらした組織活性化の効果</a></p> <h3>SEGA GAME JAMの変化について</h3> <p>さて、今まで十数回にわたって、羽田は大鳥居で開催されていましたが、グループ各社が大崎に集約されて取り巻く環境や事情が変化してきました。</p> <p>あえて挙げるとすると3点。</p> <ol> <li>参加者の裾野が広がった</li> <li>会場がすごくイベントっぽくなった</li> <li>ゲーム制作の作業時間が短くなった</li> </ol> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191207145439j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207145439.jpg" alt="f:id:sgtech:20191207145439j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191207145705j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207145705.jpg" alt="f:id:sgtech:20191207145705j:plain" /></div> </div> <h4>参加者の裾野が広がった</h4> <p>昨年まではセガゲームス、セガ・インタラクティブは羽田の大鳥居に社屋を構えていて、SEGA GANE JAMの会場も大鳥居でした。</p> <p>そのためか、基本的に参加者は自然と大鳥居に近い場所に住んでいるセガゲームス、セガ・インタラクティブのメンバーに偏っていました。 </p> <p>大崎に集約された後、その新社屋が会場となることで距離的な制約などは緩和され、セガサミーグループ内の様々な人が気軽に参加できるようになりました。</p> <p>内定者の皆さんもより参加しやすくなったのではないでしょうか。</p> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191207151552j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207151552.jpg" alt="f:id:sgtech:20191207151552j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191207151529j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207151529.jpg" alt="f:id:sgtech:20191207151529j:plain" /></div> </div> <p>※写真左は会場の隣でやっていた『ぷよぷよ!!クエスト』のイベントから差し入れのカレーです。</p> <h4>会場がすごくイベントっぽくなった</h4> <p>新社屋内の多目的スペース「TUNNEL TOKYO」を活用できるようになり、イベント感が増しました。</p> <p>※「TUNNEL TOKYO」についての詳細は以下を参照してください。</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="TUNNEL TOKYO|トンネルトウキョウ|セガサミーとPegasus Tech Ventures共同運営の大崎コワーキングスペース" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Ftunnel-tokyo.jp%2F" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://tunnel-tokyo.jp/">tunnel-tokyo.jp</a></cite></p> <p>会場がイベントらしくなることで、テンションも上がりますし、より楽しい雰囲気の中で時間が過ごせるようになります。</p> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191207151139j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207151139.jpg" alt="f:id:sgtech:20191207151139j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191207151237j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207151237.jpg" alt="f:id:sgtech:20191207151237j:plain" /></div> </div> <h4>ゲーム制作作業時間が短くなった</h4> <p>一見ネガティブな印象を持たれがちですが、会場の事情や昨今の働き方改革に合わせる形でイベント自体も時間の効果的な使い方へのチャレンジが必要になりました。</p> <p>改めて、当日のタイムスケジュールを振り返ってみましょう。</p> <p> </p> <p>一日目 (11/2)</p> <ul> <li>8:30  受付開始</li> <li>9:00  開始</li> <li>9:05  テーマ決め</li> <li>9:20  チーム分け</li> <li>15:00 企画発表</li> <li>20:00 α 版発表</li> <li>20:30 写真撮影</li> <li>21:30 会場 Close</li> </ul> <p>二日目 (11/3)</p> <ul> <li>07:30 会場 Open ~ 随時制作再開</li> <li>12:00 β 版発表</li> <li>18:00 制作終了</li> <li>18:15 発表会</li> <li>19:00 試遊会&順次撤収開始</li> <li>20:00 完全撤収</li> <li>20:30 打ち上げ 参加は任意</li> </ul> <p> </p> <p>以上から、ゲーム制作に使える時間は<strong>22時間</strong>程度というのがわかるかと思います。</p> <p>そんな中でもちゃんと一つのゲームを作り上げることができたのは、参加した皆さんの実力の高さを実感しました。</p> <h3>SEGA GAME JAMの効果について</h3> <p>効果の程は?というと、SEGA GAME JAMの根本の趣旨は変わらないのでそこは今までと変わりません。例えば、</p> <ul> <li>グループ会社、事業部、世代を超えた絆が生まれる!</li> <li>失敗を恐れずチャレンジできる!</li> <li>変わるきっかけが生まれる!</li> </ul> <h4>グループ会社、事業部、世代を超えた絆が生まれる!</h4> <p>このイベントが終わるとまた日常の自分たちの仕事へと戻っていきます。</p> <p>しかし、ここで一緒にゲーム制作できた経験と記憶は消えることがありません。</p> <p>仕事の中での再会もありますし、連絡を取り合って新しいアイデアを元に何かが生まれたりすることもあります。</p> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191207145830j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207145830.jpg" alt="f:id:sgtech:20191207145830j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191207145859j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207145859.jpg" alt="f:id:sgtech:20191207145859j:plain" /></div> </div> <h4>失敗を恐れずチャレンジできる!</h4> <p>普段ふと思いついたことも、やりたいなーって思っていることも何かきっかけと時間がないとなかなか手をつけられなくて悩むことも多いと思います。</p> <p>せっかく2日間という時間と協力してくれるメンバーを得る機会なので、いろんなチャレンジができます。</p> <p>例えば普段プログラマーの仕事をしている一参加者もこの二日間は延々写真とビデオを撮り続けて、最後にはSEGA GAME JAMのプロモーションビデオを完成させました。また、私も普段使うことのないデザインアセット作成用のツールをいくつも試してきました。</p> <p>そして過去には、モバイル開発にいた人もボルダリングを体験できるVRゲームをチームの力で作り上げることができました。</p> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191207152537j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207152537.jpg" alt="f:id:sgtech:20191207152537j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191207145452j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207145452.jpg" alt="f:id:sgtech:20191207145452j:plain" /></div> </div> <h4>変わるきっかけが生まれる!</h4> <p>実は過去に、総務などゲーム開発をしない部門にいた人もこのイベントをきっかけに開発へと転身したということもありました。</p> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191207152338j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207152338.jpg" alt="f:id:sgtech:20191207152338j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191207152308j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191207/20191207152308.jpg" alt="f:id:sgtech:20191207152308j:plain" /></div> </div> <h3>これからも・・・</h3> <p>手短ですが、今回のBlog記事ではSEGA GAME JAMの再始動を改めて宣言し、ここ大崎で起きた変化を少しでも紹介したかったので筆をとってみました。</p> <p><br />ゲーム作りの本質は変わりません。遊んでくれる方が笑顔で感動体験をしてくれる事が何よりの喜びです。</p> <p> </p> <p>そのための、チャレンジの場、交流の場として、そしてゲーム作りを楽しむためにも SEGA GAME JAM は引き続き開催していきたいと思っています。</p> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191208195859j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191208/20191208195859.jpg" alt="f:id:sgtech:20191208195859j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191208195841j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191208/20191208195841.jpg" alt="f:id:sgtech:20191208195841j:plain" /></div> </div> <p>※最後のプレイ会の一場面</p> <p>最後に、そんなGAME JAMが開催できるような社内交流が盛んで、開かれた職場環境で働いてみたいという方は以下をチェックしてみてください。</p> <p> </p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="採用サイト|株式会社セガ -【SEGA Co., Ltd.】" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sega.co.jp%2Frecruit%2Findex.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html">www.sega.co.jp</a></cite></p> <p><br /><cite class="hatena-citation"></cite></p> <h3>おまけ </h3> <p>ここまでTech blogなのに何のノウハウも公開していないことに気づきました。</p> <p>イベント開催レポなのでそんなにお話しできることもないのですが、一つだけ、社内GAME JAMを開催していたり、これから開催しようと思っているゲーム業界の皆さんへ・・・。</p> <p>参加者のモチベーションが上がる要素の一つとして「<strong>いろいろな業界関係者が見学してくれるとモチベーションが上がる</strong>」という意見が過去の開催アンケートにいくつか見られました。</p> <p>「社内」ということで多少難しい面もあるかと思いますが、少し調整を頑張ってゲーム業界周辺の関係者を見学に誘ってみてはいかがでしょうか?</p> <p> </p> <p>それでは、ここまで読んでいただきありがとうございました。</p> <p>良いJAM生活を。</p> <p> </p> <p>そして良いお年をお迎えください。</p> sgtech セガのモーションキャプチャースタジオ紹介 hatenablog://entry/26006613472327828 2019-11-28T10:00:00+09:00 2020-05-29T18:44:29+09:00 はじめに はじめまして。セガゲームスのモーションキャプチャーチームに所属している北川と申します。 業務内容としてはモーションキャプチャーエンジニアとしてワークフローの構築や収録オペレーターといったことをしています。(簡単にいうとモーションキャプチャーの撮影周り全般です) モーションキャプチャーチーム内では、以下の三つの班に分かれて業務を行っています。 ・撮影班:撮影~収録したマーカーデータの処理や小道具作成など ・エディット班:収録データのキャラクターへの流し込みと修正作業 ・サポート班:上記の班をサポート 私はその中でも撮影班として収録業務を行っているので、今回はなかなか話をする機会のないセ… <h4><strong>はじめに</strong></h4> <p>はじめまして。セガゲームスのモーションキャプチャーチームに所属している北川と申します。</p> <p>業務内容としてはモーションキャプチャーエンジニアとしてワークフローの構築や収録オペレーターといったことをしています。(簡単にいうとモーションキャプチャーの撮影周り全般です)</p> <p>モーションキャプチャーチーム内では、以下の三つの班に分かれて業務を行っています。</p> <p>・撮影班:撮影~収録したマーカーデータの処理や小道具作成など</p> <p>・エディット班:収録データのキャラクターへの流し込みと修正作業</p> <p>・サポート班:上記の班をサポート</p> <p>私はその中でも撮影班として収録業務を行っているので、今回はなかなか話をする機会のないセガのモーションキャプチャースタジオについてお話をさせていただきます。</p> <p> </p> <p> </p> <h3><strong>セガモーションキャプチャースタジオとは</strong></h3> <h5>セガモーションキャプチャースタジオの歴史</h5> <p>セガは『バーチャファイター』(1993年発売)の開発時からと業界でもかなり早くモーションキャプチャーをゲーム開発に導入しました。</p> <p>導入当初はモーションキャプチャーの専門チームとしては存在せず、2000年頃よりモーションキャプチャーチームとして部をまたがってプロジェクトをサポートするようになりました。</p> <p>写真は過去のスタジオ写真の一部になります。スタジオも数回引っ越しをしていますし、使用しているシステムも様々な変化があります。</p> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214712j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214712.jpg" alt="f:id:sgtech:20191127214712j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214716j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214716.jpg" alt="f:id:sgtech:20191127214716j:plain" /></div> </div> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214705j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214705.jpg" alt="f:id:sgtech:20191127214705j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214708j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214708.jpg" alt="f:id:sgtech:20191127214708j:plain" /></div> </div> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214722j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214722.jpg" alt="f:id:sgtech:20191127214722j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214728j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214728.jpg" alt="f:id:sgtech:20191127214728j:plain" /></div> </div> <p>現在の所属はセガゲームスになりますが、セガ・インタラクティブ、アトラス、サミー、マーザ・アニメーションプラネットなどセガサミーグループの様々なプロジェクトに関わっています。</p> <p>直近のタイトルでは以下のモーション収録に携わりました。</p> <p>『龍が如く7 光と闇の行方』『東京2020オリンピック The Official Video Game』『新サクラ大戦』<br />『ファンタシースターオンライン2』『WCCF FOOTISTA』『Wonderland Wars』『けものフレンズ3』<br />『Fate/Grand Order Arcade』『艦これアーケード』『ペルソナ5 ザ・ロイヤル』『キャサリン・フルボディ』</p> <p>  </p> <h5>スタジオスペック</h5> <ul> <li>カメラ:Vicon社 反射光学式カメラ 約100台           <p><img class="hatena-fotolife" title="f:id:sgtech:20191127214815j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214815.jpg" alt="f:id:sgtech:20191127214815j:plain" width="124" /></p> </li> <li>収録エリア:18m x 10m x 4m(横幅 x 奥行き x 高さ)</li> <li>常設設備:壁面鏡・ワイヤーアクション用設備・チェック用大型モニター</li> </ul> <p>過去のモーションキャプチャーを利用するタイトルがバーチャファイターシリーズをはじめとした格闘アクションだった事もあり、『シェンムー』(1999年発売)制作の頃から立体的なアクションの要求に応えるためワイヤーアクション用の設備を設置しました。<br />現在のスタジオではワイヤーアクションの為に天井からのH鋼を二本に増やすだけでなく、床内にワイヤー用の専用フックも設置してより複雑なアクションがとれるようになっています。 </p> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214737j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214737.jpg" alt="f:id:sgtech:20191127214737j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214741j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214741.jpg" alt="f:id:sgtech:20191127214741j:plain" /></div> </div> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214638j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214638.jpg" alt="f:id:sgtech:20191127214638j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214732j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214732.jpg" alt="f:id:sgtech:20191127214732j:plain" /></div> </div> <p> </p> <h3><strong>収録環境の工夫</strong></h3> <h5>リファレンス用のビデオ収録</h5> <p>反射光学式のモーションキャプチャーは収録しただけだとただの点データ(座標データ)になってしまいます。そうするとマーカーを付けていない部分の動きや表情などは収録することができません。</p> <p>そのため、後作業で参考にするためにキャプチャー収録と同期をしてビデオを録画することが非常に有用になってきます。</p> <p>昔はSD画質でも問題なかったのですが、指の表現や表情も撮影時のものを参考にすることが増えてきたことによってHD画質での録画の要望が高まってきました。しかし、要望の増え始めた頃はVicon社のキャプチャーシステムと同期してHDで録画するシステムは存在していない状況でした。</p> <p>その話をモーションキャプチャーチームをサポートしてくれているプログラマーに話したところ、プログラマー同士の雑談から動画の処理に詳しい者がシステム作成に手を挙げてくれました。</p> <p>そこからモーションキャプチャーチームの要望をヒアリングしたうえで、ハードの選定や録画・エンコードソフト、キャプチャーシステムとのリンク部分などを作成してくれました。</p> <p>これによって国内でも非常に早い段階でHD画質でのリファレンス映像の収録環境を構築することができました。このシステムは今でも欠かすことのできないものとして運用されています。</p> <p>社内のふとした繋がりによって当初想定していたより素早く期待以上の環境構築をすることができたと同時に、セガ社内の人材の厚さを実感しました。</p> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214651j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214651.jpg" alt="f:id:sgtech:20191127214651j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214655j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214655.jpg" alt="f:id:sgtech:20191127214655j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214701j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214701.jpg" alt="f:id:sgtech:20191127214701j:plain" /></div> </div> <h5> リアルタイムプレビューのクオリティアップ</h5> <p>ビデオ収録でも触れましたが、収録したデータは座標情報のみとなり点と線の表示となってしまいます。そのため、MotionBuilderというソフトを同時に使用して確認用にキャラクターを動かす事が一般的です。<br />ただ<span style="color: #000000;">アクター(演者)さんとキャラクターとの体型の差などから不自然に動いてしまう場合も多々あり、エディット班では後処理を行う際にセガ独自のリターゲット方法を利用しており、アクターさんとキャラクターの動きの誤差を少なくすることで作業の軽減を図っています。</span></p> <p><span style="color: #000000;">そこで</span><span style="color: #000000;">エディット班とサポート班に協力をしてもらい、リアルタイムプレビューにも同様のリターゲットが行えるように改良を行っていきました。</span>これによって収録をしている段階で動きの誤差が少なくなり、アクターさん・プロジェクトスタッフ双方のイメージの共有の齟齬が少なくなり再収録などのリスクも非常に低くなりました。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20191127214646j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214646.jpg" alt="f:id:sgtech:20191127214646j:plain" /></p> <p><br /><br /></p> <h5>指の収録</h5> <p>最近では指の動きを収録する事例なども多く見かけるようになりましたが、セガでは2010年頃からボディと一緒に簡易的な指のモーションの収録も行うようになりました。</p> <p>それ以前は必要に応じてグローブデバイスを使うなどしたこともありますが課題も多く、指は収録後にビデオやイメージを基にプロジェクトのモーションデザイナーが手作業で動かすことがほとんどでした。その手法だと数をこなしたり、自然な動きを再現するのに非常に時間がかかってします。そこで収録時のアクターさんの動きを体と一緒に収録できれば指の自然な表現ができるのではと実装に向けて検証を始めました。</p> <p>検証当初は5本の指全てにマーカーを付けての収録など様々なテストをしました。しかし出来上がるクオリティとデータクリーンアップ作業の工数を鑑みて、親指・人差し指・小指の3か所のみにマーカーを付け、その動きを基に5本の指を動かすようにしました。これによって手の開閉タイミングや細かい動きのニュアンスも収録できるようになり、プロジェクトからも好評で今ではすべての撮影で欠かせないものとなっています。</p> <p>導入当初はリアルタイムプレビューでは満足に動かすことができず、撮影後のデータ処理の段階で初めて動く状況でしたが、改良を重ね現在ではリアルタイムプレビュー上でも動かせるようになっています。</p> <p>末端の動きではありますが開閉や指差しなどだけでも表情のように印象が大きく変わるので、特にダンスやイベントシーンの収録時にイメージ共有がしやすくなりました。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20191127214750j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214750.jpg" alt="f:id:sgtech:20191127214750j:plain" /></p> <p><br /><br /></p> <p> </p> <p> </p> <h4><strong>その他</strong></h4> <h5>小道具やセット</h5> <p>モーションキャプチャーの収録はカメラやソフトなどを見るととても複雑なシステムを使用しているように見えますが、実際の収録現場はアナログな作業が非常に多く存在しています。</p> <p>生の動きであるアクターさんの動きをデジタルデータに変換するのがモーションキャプチャーです。なので、可能な限り演じやすく・ロスなくデータ化することが非常に重要になってきます。もちろんそのまま使用することはほとんどありませんが、だからこそその素材になる収録データはできる限りアクターさんの動きをしっかりと撮ることが最終的なクオリティにも貢献できると思っています。</p> <p>収録しやすくなるように小道具やセットも可能な限りリクエストに応えられるように様々な準備を行います。演技しやすいように発泡スチロールや塩ビパイプなどを組み合わせて大きくても軽い小道具を作成したり、イメージに近くデータ収録に問題がないセットにするなど様々な工夫をして収録をしています。この部分は実際に現場で動きながら作業をするので、テクニカルなだけでなくADや大道具的な作業も行っています。</p> <p>以下の画像はごく一部ですが、すべてチーム内のスタッフが作成したものです。よく見るとわかりますが、マーカーがついており小道具の動きも収録を行っています。収録したオブジェクトの動きもリアルタイムプレビュー上でしっかりと反映し武器などを構えた状態も確認できるようにしています。</p> <p> </p> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214755j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214755.jpg" alt="f:id:sgtech:20191127214755j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214800j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214800.jpg" alt="f:id:sgtech:20191127214800j:plain" /></div> </div> <h5>様々な収録システム</h5> <p>モーションキャプチャーといっても様々なメーカーのいろいろな収録システムが存在します。セガのモーションキャプチャースタジオも当初から現在のViconのシステムではありませんでした。古くは磁気式といわれるものやVicon社以外のシステムを運用していました。</p> <p>それらの経験は現在の収録にも活かされており、メインで使用しているシステムだけでなく他のシステムに関しても情報を収集したり撮影によっては他のシステムを運用したりしています。</p> <p>例えばスタジオの広さが室内ではとても足りない場合や、収録をしたい環境(セットなど)を再現するのが困難な場合は持ち出して収録をすることができる慣性センサー式のシステム(Xsens MVN)を使用して収録を行ったりもしています。</p> <p>また、映画製作で行われているパフォーマンスキャプチャーについても要望が高まっていることからフェイシャルキャプチャーやバーチャルカメラも同時に撮れる環境づくりを順次進めています。市販のものを購入するだけでなく、使い勝手を考え顔の動き・表情を収録するためのHMC(ヘッドマウントカメラ)や3DCG上のカメラを操作することができるバーチャルカメラを独自に作成もしています。</p> <p>社内のスタジオとしてできるだけ多くの要望に応え、より良いものをプロジェクトに届けるべく様々な検証やサービスの展開を行っています。</p> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214810j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214810.jpg" alt="f:id:sgtech:20191127214810j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20191127214805j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214805.jpg" alt="f:id:sgtech:20191127214805j:plain" /></div> </div> <p> </p> <p> </p> <h3><strong>最後に</strong></h3> <p>今回はモーションキャプチャースタジオでの収録に関連した部分にスポットを当てて書いてきました。収録現場はPCでの作業もありますが、実際に自分が動いて対応をすることが多くあります。ビデオの収録やキャラを見ながらの確認などをしっかりと整備したことによって、イメージを共有しやすくしたり現場での撮影補助に集中することができるようになりました。動き回ることの多い現場だからこそ周辺のツールなどのありがたみを感じます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20191127214746j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191127/20191127214746.jpg" alt="f:id:sgtech:20191127214746j:plain" /></p> <p><br /><br /></p> <p>写真:撮影班一同</p> <p> </p> <p>モーションキャプチャーチームでは一緒にプロジェクトを支えるメンバーを募集しています。</p> <p>興味のある方はぜひサイトにアクセスしてみてください。</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="採用サイト|株式会社セガ -【SEGA Co., Ltd.】" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sega.co.jp%2Frecruit%2Findex.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html">www.sega.co.jp</a></cite></p> <p><br /><cite class="hatena-citation"></cite></p> <p>©SEGA</p> <p> </p> sgtech 【Unity】Unite Tokyo 2019 「大量のアセットも怖くない!~HTTP/2による高速な通信の実装例~」講演と壇上では語られなかった6つのこと。 hatenablog://entry/26006613457579997 2019-10-30T10:00:00+09:00 2020-05-29T18:44:56+09:00 皆さんこんにちは。セガゲームス、開発技術部の山田です。 以前は OpenGL の話を本ブログで紹介したのですが、今回は Unite Tokyo で講演してきたお話です。 本記事は講演の時と同じく、前半は山田、後半は竹原でお送りします。 目次 Unite Tokyo 2019 資料など 質疑中の様子 講演中に語られなかったこと Keep Alive の話 同時ファイルオープン数について 講演で語られなかったこと (竹原より) HPACK の圧縮率を確認する [HPACK]HTTP/2 のヘッダ管理 [HPACK]Huffman Coding での圧縮 [HPACK]インデックス値を用いた圧縮 :… <p>皆さんこんにちは。セガゲームス、開発技術部の山田です。 <a href="http://techblog.sega.jp/entry/2016/10/27/140454">以前は OpenGL の話を本ブログで紹介</a>したのですが、今回は Unite Tokyo で講演してきたお話です。 本記事は講演の時と同じく、前半は山田、後半は竹原でお送りします。</p> <p><b>目次</b></p> <ul class="table-of-contents"> <li><a href="#Unite-Tokyo-2019">Unite Tokyo 2019</a><ul> <li><a href="#資料など">資料など</a></li> <li><a href="#質疑中の様子">質疑中の様子</a></li> </ul> </li> <li><a href="#講演中に語られなかったこと">講演中に語られなかったこと</a><ul> <li><a href="#Keep-Alive-の話">Keep Alive の話</a></li> <li><a href="#同時ファイルオープン数について">同時ファイルオープン数について</a></li> </ul> </li> <li><a href="#講演で語られなかったこと-竹原より">講演で語られなかったこと (竹原より)</a><ul> <li><a href="#HPACK-の圧縮率を確認する">HPACK の圧縮率を確認する</a><ul> <li><a href="#HPACKHTTP2-のヘッダ管理">[HPACK]HTTP/2 のヘッダ管理</a></li> <li><a href="#HPACKHuffman-Coding-での圧縮">[HPACK]Huffman Coding での圧縮</a></li> <li><a href="#HPACKインデックス値を用いた圧縮--Static-Table">[HPACK]インデックス値を用いた圧縮 : Static Table</a></li> <li><a href="#HPACKインデックス値を用いた圧縮--Dynamic-Table">[HPACK]インデックス値を用いた圧縮 : Dynamic Table</a></li> <li><a href="#HPACKまとめ">[HPACK]まとめ</a></li> </ul> </li> <li><a href="#HTTP2-特有の設定を-libcurl-から行うには">HTTP/2 特有の設定を libcurl から行うには?</a></li> <li><a href="#優先度制御の現在とこれから">優先度制御の現在とこれから</a></li> <li><a href="#PKP-と-Expect-CT">PKP と Expect-CT</a><ul> <li><a href="#Certificate-Transparency-とはざっくり説明">Certificate Transparency とは(ざっくり説明)</a></li> <li><a href="#Expect-CT-ヘッダの現状">Expect-CT ヘッダの現状</a></li> </ul> </li> <li><a href="#最後に">最後に</a></li> </ul> </li> </ul> <h1 id="Unite-Tokyo-2019">Unite Tokyo 2019</h1> <p>Unityユーザーのためのテクニカルな講演やブース出展が数多く行われる、国内最大のUnityカンファレンスイベント「Unite Tokyo 2019」が 2019年9月25日、26日に開催されました。そこで、私と竹原より、「大量のアセットも怖くない~HTTP/2による高速な通信の実装例」という講演を行いました。 お越しいただいた方々ありがとうございました。</p> <p>講演の結論は<b>「Unityで標準的な作り方をした場合において、 HTTP/2を使ってアセットバンドルをダウンロードすることは相性がよいです」</b> と話しました。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191028/20191028000857.jpg" alt="f:id:sgtech:20191028000857j:plain" title="f:id:sgtech:20191028000857j:plain" class="hatena-fotolife" itemprop="image"></span></p> <h2 id="資料など">資料など</h2> <p>資料や講演ムービーは既に公開されており、次のページでアクセスできます。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flearning.unity3d.jp%2F3330%2F" title="大量のアセットも怖くない!~HTTP/2による高速な通信の実装例~ | Unity Learning Materials" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://learning.unity3d.jp/3330/">learning.unity3d.jp</a></cite></p> <h2 id="質疑中の様子">質疑中の様子</h2> <p>予想していたよりも多くの方に質疑コーナーに来て頂けまして、色々と質問や情報交換ができました。 とても有意義な時間でした。ありがとうございました。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191028/20191028000853.jpg" alt="f:id:sgtech:20191028000853j:plain" title="f:id:sgtech:20191028000853j:plain" class="hatena-fotolife" itemprop="image"></span></p> <h1 id="講演中に語られなかったこと">講演中に語られなかったこと</h1> <p>講演では説明できなかった色々なことを本ブログで補足したいと思います。</p> <h2 id="Keep-Alive-の話">Keep Alive の話</h2> <p>Keep Alive を使った HTTP/1.1 なら HTTP/2 との速度差はそれほどつかないのでは?と思う方もいるでしょう。自分もそう考えていた時期があったので、この点に悩む方は多いのではないかと考えています。</p> <p>前提として、https での通信を考えます。 Keep Alive で削減できるのは TCP の再接続のコストです。実際にデータを送受信するまでの前準備の部分です。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191028/20191028000903.png" alt="f:id:sgtech:20191028000903p:plain" title="f:id:sgtech:20191028000903p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>HTTP/1.1 では、複数のコネクションを張って並列にデータのダウンロードを行う実装とします。 このとき多くの場合で3~6が使われることと思います。しかし、それぞれのコネクションで輻輳制御が行われるために、帯域を有効活用することができません。 これを分かりやすく説明してくれているのが 「IIJ Technical WEEK 2015」においての「HTTP/2からQUICへ続く Webプロトコルの進化」という講演内容です。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.iij.ad.jp%2Fdev%2Ftech%2Ftechweek%2F2015%2F" title="2015 | IIJの技術 | インターネットイニシアティブ(IIJ)" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://www.iij.ad.jp/dev/tech/techweek/2015/">www.iij.ad.jp</a></cite></p> <p>「HTTP/2からQUICへ続く Webプロトコルの進化」という講演資料の19ページから21ページにて解説をされています。 次の図は、この資料より引用させていただきました。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191028/20191028000900.png" alt="f:id:sgtech:20191028000900p:plain" title="f:id:sgtech:20191028000900p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>HTTP/1.1 ではファイルごとに1つのコネクションを使います。Unity での標準的な作りをする場合においてファイルサイズは小さめであり、1コネクションにおいて輻輳ウィンドウサイズが十分に大きい状態で通信を行い続けることができません。 HTTP/2 ではストリームの機能を用いて複数ファイルのダウンロードを1つのコネクションに多重化するため、使用できる帯域を最大限使うことができます。</p> <p>RTTの観点からも HTTP/2 ほうが有利です。 HTTP/1.1 の場合、Keep-Alive で再接続のコストを抑えていても、ファイルを取得するときに出すリクエストで RTT 分の時間が掛かります。 この間は、そのコネクションにおいてファイルのダウンロードは進行していません。仮に 100 ファイルあったとすると 100 *0.5RTT の時間分はファイルのデータダウンロードに使えていないことになります。HTTP/2 では多重化により他のデータやりとりの1部としてファイルのリクエストも紛れ込んでいるので、通信路としての無駄が少なくなっています。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191028/20191028000906.png" alt="f:id:sgtech:20191028000906p:plain" title="f:id:sgtech:20191028000906p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>ただし、どのような条件下でも HTTP/2 のほうが速いかというとそうでもないので状況に応じて考える必要があります。</p> <p>必要なファイルを結合してアーカイブファイルを作成し、それをダウンロードするというフローであれば HTTP/1.1 でも効率の良い通信が実現できます。 Unite Tokyo 2019 の KLab さんの講演「「禍つヴァールハイト」最大100人同時プレイ!モバイルオンラインゲームの実装テクニック」の中でも語られておりました。 tar 形式と Range パラメータを使ってというアイデアはとても面白いと思います。 KLab さんの方式は事前に必要なデータをガッツリダウンロードするような MO/MMO のようなものに向いているのではないかと考えております。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Flearning.unity3d.jp%2F3345%2F" title="「禍つヴァールハイト」最大100人同時プレイ!モバイルオンラインゲームの実装テクニック | Unity Learning Materials" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://learning.unity3d.jp/3345/">learning.unity3d.jp</a></cite></p> <h2 id="同時ファイルオープン数について">同時ファイルオープン数について</h2> <p>講演中では印象優先で Windows ではファイル数 512 という表現をさせてもらいました。 しかし、その制限は実は Windows そのものによる制限ではなく、 Visual C++ が提供している C Runtime (CRT) による制限となっています。 Windows 自体はもっと多くのハンドルを同時に扱うことができます。</p> <p>fopen/fclose といった C言語の世界の関数が CRT に属します。 Windows で生のファイルを操作する場合は Win32API に属する CreateFile 関数を使用します。 Windows 専用ということもあって、ファイルの共有Read/Write, 256文字を超えるファイルパスによるアクセスなど色々とできることが多いです。</p> <p>(Windows API (Win32API) や、Windows カーネルの話も機会があったら本ブログで書けたらと思います。)</p> <p><br></p> <h1 id="講演で語られなかったこと-竹原より">講演で語られなかったこと (竹原より)</h1> <p>それではここからは竹原が担当させて頂きます。</p> <p>私のパートでは HTTP/2 に関する仕様や libcurl の実装面でのもう少しディープな解説をさせて頂こうと思います。</p> <h2 id="HPACK-の圧縮率を確認する">HPACK の圧縮率を確認する</h2> <p>HTTP/1.1 までの通信では、HTTP ヘッダはプレーンテキスト形式で記述され、クッキー等により時にはその合計サイズは 1 キロバイトを超えることもありました。 HTTP/2 ではこうしたヘッダのサイズ問題を解消するべく <B>HPACK</B> という専用の圧縮機構が採用されています。</p> <p>講演を聞いてこの HPACK で実際どれくらいヘッダが圧縮されるのか、気になった方もいると思います。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191024/20191024153931.png" alt="f:id:sgtech:20191024153931p:plain" title="f:id:sgtech:20191024153931p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>そこで、この項では HPACK の仕組みを、「どれくらいヘッダサイズが削減されるか」についても触れながら簡単に解説してみます。 かなり効果があるので、独自拡張等ヘッダに色々仕込んでいる場合は導入を検討してみても面白いと思います。</p> <h3 id="HPACKHTTP2-のヘッダ管理">[HPACK]HTTP/2 のヘッダ管理</h3> <p>講演でも触れたように、 HTTP/2 のヘッダはバイナリとして扱われるようになりました。 更にパラメータは <B>全て小文字で表現されるようになった</B> のに加え、従来のリクエストラインやヘッダの表現形式も若干変更されています。</p> <p>例えば、 HTTP/1.1 の典型的なリクエストラインとヘッダの組み合わせである以下は</p> <pre class="code" data-lang="" data-unlink>GET /resource HTTP/1.1 Host: sega.com Accept: text/html</pre> <p>HTTP/2 では次のような集合として表現されます。</p> <pre class="code" data-lang="" data-unlink>:method = GET :scheme = https :path = /resource host = sega.com accept = text/html</pre> <p>HPACK ではこれらの Header Name/Value の組み合わせをヘッダフィールドと呼び、文字列で表すか、独自のインデックス値でエンコードして表すか選択することが可能です。 更に、文字列で表す場合は Huffman Coding(ハフマン符号) で圧縮するかどうかも選択することができます。</p> <h3 id="HPACKHuffman-Coding-での圧縮">[HPACK]Huffman Coding での圧縮</h3> <p>Huffman Coding は、出現頻度の高い文字には短いビット列を割り当て、低い文字には長いビット列を割り当てることにより圧縮を図る方式です。</p> <p>例えば、文字 A が 1 回、B が 3 回、C が 5 回、D が 2 回、E が 1 回出現するような文字列「ABBBCCCCCDDE」に対して以下のように符号を割り当てます。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191024/20191024154846.png" alt="f:id:sgtech:20191024154846p:plain" title="f:id:sgtech:20191024154846p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>この割り当てられた符号を使って前述の文字列「ABBBCCCCCDDE」を表現すると、</p> <p><code>1110 10 10 10 0 0 0 0 0 110 110 1111</code></p> <p>となり、全体を 25bit で表現することができるようになりました。</p> <p>実際の符号の割り当てには、圧縮したいデータ内の文字の出現頻度をベースにして構築した Huffman Tree という二分木を利用します。 Huffman Tree の構造はベースにしたデータ内の文字の出現頻度により変化するので、適用したいデータのパターン毎に用意する必要があります。 そこで、 HPACK では過去に利用された HTTP のリクエスト・レスポンスのヘッダを解析した結果を基にして構築した専用の Huffman Tree が採用されています。</p> <p><a href="https://tools.ietf.org/html/rfc7541#appendix-B">RFC 7541 - HPACK: Header Compression for HTTP/2</a></p> <p>それでは、Huffman Coding でどの程度のデータの圧縮が可能なのか、先ほどのヘッダフィールドの内容を例に確認してみましょう。</p> <p>まずは :method を Huffman Coding してみると</p> <pre class="code" data-lang="" data-unlink>&#34;:method&#34; 1011100 101001 00101 01001 100111 00111 100100 &#34;GET&#34; 1100010 1100000 1101111</pre> <p>となるので、これを合算して 61bit に圧縮できることがわかります。<br> ※ヘッダフィールドは Name/Value でそれぞれ管理されるので "=" は不要となります</p> <p>HPACK では Huffman Coding されたデータがオクテット単位に揃わない場合、余ったデータ部は 1 でパディングされるというルールがあるので実際には</p> <pre class="code" data-lang="" data-unlink>&#34;:method&#34; 1011100 101001 00101 01001 100111 00111 100100 &#34;GET&#34; 1100010 1100000 1101111 {111}</pre> <p>となり、 64bit(8byte) のデータ長となります。</p> <p>元々の文字列は ":method" → 7byte, "GET" → 3byte で 10byte ですので、 <B>20% 圧縮された</B>ことが分かります。<br> ※ HTTP/3 に使われている QPACK では、このパディングが不要となり、さらに圧縮率が上がっています!</p> <p>このように、 Huffman Coding を用いると、頻出文字で構成されるデータであれば大幅にデータを圧縮可能です。 上記よりもう少し頻出文字が多い文字列だと 30% を超える圧縮率になることもあります。 反面、バックスラッシュ(19bit)やアンダースコア(15bit)といった出現頻度の低い文字については、元の8bitより遙かに大きくなってしまうので注意が必要です。 実装によっては、 Huffman Coding を掛けた前後のサイズを比較し小さい方を採用する、というような工夫もしているものもあるようです。</p> <h3 id="HPACKインデックス値を用いた圧縮--Static-Table">[HPACK]インデックス値を用いた圧縮 : Static Table</h3> <p>HPACK には Huffman Coding の他にも、Header Name と Header Value を対応させた辞書である Indexing Table という独自の圧縮機構が用意されています。 Indexing Table には Static Table と Dynamic Table の二種類が存在しています。</p> <p>Static Table は Huffman Tree のように過去の利用頻度の高いヘッダが予め登録されているテーブルで、HTTP/2 の RFC に全 61 種類が定義されています。</p> <p><a href="https://tools.ietf.org/html/rfc7541#appendix-A">RFC 7541 - HPACK: Header Compression for HTTP/2</a></p> <p>先ほど例に挙げたヘッダを上記の RFC の Static Table で表現しようとすると</p> <pre class="code" data-lang="" data-unlink>:method → 2 :scheme → 7 :path → 4 host → 38 accept → 19</pre> <p>と対応していますので、以下のように表現できるようになります。</p> <pre class="code" data-lang="" data-unlink> 2 7 4 /resource 38 sega.com 19 text/html</pre> <p>※インデックスは 1byte で扱われます</p> <p>結果、 63byte → 31byte となり、<B>約 51% 削減という Huffman Coding を大幅に超えた</B>値で圧縮することができました。</p> <p>※実際には Literal Header Field という独自の形式でヘッダフィールドを表現する為に、圧縮率はこの値より少し小さくなります。詳細は <a href="https://tools.ietf.org/html/rfc7541#section-6">RFC 7541 - HPACK: Header Compression for HTTP/2</a> を参照ください</p> <p>更にテーブルを適用できなかった文字列部には Huffman Coding を掛けてさらにデータを圧縮することも可能です。</p> <h3 id="HPACKインデックス値を用いた圧縮--Dynamic-Table">[HPACK]インデックス値を用いた圧縮 : Dynamic Table</h3> <p>Dynamic Table は、通信に使用したヘッダフィールドを動的にテーブルに登録していき、 Static Table のようにインデックス値で指定できるようにする圧縮機構です。 テーブルへの登録可能な上限サイズの初期値は 4096 オクテットで、上限を超えた場合はファー ストインファーストアウトのルールで登録が抹消されていきます。 Dynamic Table のインデックスは Static Table のインデックスの続きの 62 から始まり、追加する毎にインクリメントされていきます。</p> <p>先ほどの Static Table で表現したヘッダフィールドをさらに Dynamic Table に登録してみましょう。</p> <pre class="code" data-lang="" data-unlink> 2 → 2 のまま 7 → 7 のまま 4 /resource → 新規に 63 に登録 38 sega.com → 新規に 64 に登録 19 text/html → 新規に 65 に登録</pre> <p>すると、以下のようにかなりすっきりとした形で表現できるようになります。</p> <pre class="code" data-lang="" data-unlink> 2 7 62 63 64</pre> <p>結果、 63byte → 5byte となり、圧縮率は<B>驚異の約 92%</B> まで上がりました。</p> <p>Dynamic Table のサイズは前述した通り 4096 オクテット(変更は可能です)なので、なんでもかんでも登録するわけにはいきません。 しかし、同じヘッダのリクエストを何度も送信する場合にはかなりの効果をあげますので、こうした事例では Dynamic Table を積極的に利用するのをお勧めします。</p> <h3 id="HPACKまとめ">[HPACK]まとめ</h3> <p>若干長くなってしまいましたが、 HPACK を利用すると大幅にヘッダを圧縮することができることを理解して頂けたと思います。</p> <p>最近のゲームは API リクエストをかなり頻繁に送信するものや独自にヘッダを拡張しているケースも多く、これらの積み重ねによって結構なデータ送信量になってしまうこともあります。 こうしたデータを削減するにも HTTP/2 はかなり効果的です。</p> <p><B>アセットのダウンロードだけでなく API 通信にも HTTP/2 をお勧めします</B>。</p> <p><br></p> <h2 id="HTTP2-特有の設定を-libcurl-から行うには">HTTP/2 特有の設定を libcurl から行うには?</h2> <p>HPACK の高い圧縮率を見ると使ってみたくなるのはプログラマの性ですよね。</p> <p>それでは libcurl から HPACK はどのように操作できるのでしょうか。……と期待を煽っておいて申し訳ありませんが、実は libcurl を用いた場合は HPACK についてのパラメータを<B>変更することはできません</B>。</p> <p>libcurl が依存している nghttp2 という OSS のレイヤーで「Huffman Coding」及び「Static/Dynamic Table」の利用については以下のようにそれぞれよろしくやってくれます。</p> <ul> <li>Huffman Coding エンコード実施後、元の値より小さい場合のみ適用されます。</li> <li>Static Table 自動的に適用されます。</li> <li>Dynamic Table 特定の条件を満たすもののみ登録されます。</li> </ul> <p>Dynamic Table への登録条件は以下の通りです。</p> <pre class="code" data-lang="" data-unlink>/* Don&#39;t index authorization header field since it may contain low entropy secret data (e.g., id/password). Also cookie header field with less than 20 bytes value is also never indexed. This is the same criteria used in Firefox codebase. */</pre> <p>※ nghttp2 のソースコードコメントより</p> <p>要約すると、</p> <ul> <li>id や password, authorization 等のセキュリティ上問題になるようなヘッダーフィールドはインデックス化しない</li> <li>20 byte 未満の Cookie ヘッダーフィールドはインデックス化しない</li> <li>これらは Firefox で使用されている基準と同じである</li> </ul> <p>という内容です。</p> <p>この基準以外で Dynamic Table を利用したい場合は、 nghttp2 に用意されている HPACK API を利用すると良いでしょう。</p> <p><a href="https://nghttp2.org/documentation/tutorial-hpack.html">Tutorial: HPACK API &mdash; nghttp2 1.41.0-DEV documentation</a></p> <p>※筆者も libcurl との併用が可能かどうか等については未検証です</p> <p>また、 libcurl から制御できない HTTP/2 のパラメータは、実は HPACK だけではなく他にもいくつかあります。</p> <p>例えば、</p> <ul> <li>クライアントが指定する「最大ストリーム数の設定」 : SETTINGS_MAX_CONCURRENT_STREAMS</li> <li>Dynamic Table の最大サイズ : SETTINGS_HEADER_TABLE_SIZE</li> <li>ストリームの初期ウィンドウサイズ : SETTINGS_INITIAL_WINDOW_SIZE</li> </ul> <p>等はすべて libcurl 内で隠蔽されています。</p> <p>この辺りの HTTP/2 独自のパラメータを細かく制御したい人は nghttp2 をそのまま使うのをお勧めします。 ただし、 libcurl はクッキーの制御や HTTP/1 系への対応等、実装に手間のかかる所をケアしてくれています。 HTTP/2 のパラメータをどこまで制御したいか、プロジェクトの都合に合わせてどちらを使うか決めるのが良いと思います。</p> <p><br></p> <h2 id="優先度制御の現在とこれから">優先度制御の現在とこれから</h2> <p>講演中で HTTP/2 の優先度については仕様が見直し中、という話をさせて頂きました。</p> <p>それでは、具体的にどのような仕様に見直し中なのか、少し補足しようと思います。</p> <p>まず、三行でまとめると以下の通りです。</p> <ul> <li>優先度は現在 <B>HTTP バージョンに紐づかない</B> 仕様として現在審議中です</li> <li>従来の HTTP/2 の優先度に関しては <B>優先度制御しない</B> 機能が追加予定です</li> <li>現在策定中の <B>HTTP/3 では、優先度の機能を持たない</B>ことに決まりました</li> </ul> <p>これだけではつまらないので、新しく提案されている優先度がどのようなものなのかについても軽く説明しようと思います。</p> <p>※あくまで議論中の仕様なので今後変更される可能性があります</p> <p>新しく提案された優先度はとてもシンプルです。</p> <p>まず、Stream Weight は <B>urgency level (緊急度)</B> に置き換わり、全 8 段階へと縮小されました。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191024/20191024155737.png" alt="f:id:sgtech:20191024155737p:plain" title="f:id:sgtech:20191024155737p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>※ここで言う「ファイルダウンロード」とはブラウザ経由での大きなサイズのファイルのダウンロードなどを指します</p> <p>その他の変更点や特徴は以下の通りです。</p> <ul> <li>制御は HTTP ヘッダで行います</li> <li>ヘッダで設定した値をさらに変更したい場合は HTTP/2,3 共に Priority フレームを利用する方向で話が進んでいるようです</li> <li>クライアントからの urgency はあくまで hint であり、サーバ側の都合で urgency の値を上書き可能なようです</li> <li>progressive jpeg 等のリソースの識別用のフラグも用意されます</li> <li>HTTP/2 との優先度の互換性についてはこれから検討するようです</li> </ul> <p>新しい優先度は基本的には web ページを基準に議論が進んでいる仕様のようですが、ゲームでも似たような区分でデータ分けは可能なので、割と使い易いのではないかと思います。 優先度についてより詳細が気になる方は、以下のページも参照してみてください</p> <ul> <li>最近実施された QUIC Working Group Interim Meeting - October 2019 で使用された優先度の資料 <ul> <li><a href="https://github.com/quicwg/wg-materials/blob/master/interim-19-10/HTTP%20Priorities%20Update.pdf">wg-materials/HTTP Priorities Update.pdf at master &middot; quicwg/wg-materials &middot; GitHub</a></li> </ul> </li> <li>現在議論が進められているリポジトリ <ul> <li><a href="https://github.com/kazuho/draft-kazuho-httpbis-priority">GitHub - kazuho/draft-kazuho-httpbis-priority</a></li> </ul> </li> </ul> <p><br></p> <h2 id="PKP-と-Expect-CT">PKP と Expect-CT</h2> <p>講演の中で Public Key Pinning (PKP) について触れました。</p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20191024/20191024160646.png" alt="f:id:sgtech:20191024160646p:plain" title="f:id:sgtech:20191024160646p:plain" class="hatena-fotolife" itemprop="image"></span></p> <p>しかしこの PKP は、実は世の中的には古い仕様として<B>非推奨</B>となりつつあります。 理由は、講演でも触れたように、証明書の更新タイミングに運用側に負荷が掛かるからです。 例えば、 2019/1/29 にリリースされた Chrome 72 では PKP は既に廃止となっています。</p> <p>それでは、中間者攻撃への対策はどうすれば良いのでしょうか?</p> <p>そこで出番となるのが <B>Expect-CT ヘッダ</B>です。</p> <p>Expect-CT ヘッダーは、サーバが Certificate Transparency (CT) に対応していることをクライアントに伝える為に使用されます。</p> <h3 id="Certificate-Transparency-とはざっくり説明">Certificate Transparency とは(ざっくり説明)</h3> <p>CT は証明書の発行のログと突き合わせることで、対象の証明書が不正なものであるかどうかを検知する機構です。 CT には Signed Certificate Timestamp (SCT) という、上記のログを管理するサーバに対象の証明書が登録された時刻を保証するタイムスタンプを利用します。 (利用の仕方は証明書に埋め込んだり、TLS Extension として送信したり、色々あります) この値からログ管理サーバに問い合わせを行うことで、自分たちの知らない所で証明書が発行されていないか(偽装されていないか)を確認します。</p> <p>これ以上深堀りするととても長くなりますので、詳細が気になる方は <a href="https://tools.ietf.org/html/rfc6962">RFC 6962 - Certificate Transparency</a> を参照してください。</p> <h3 id="Expect-CT-ヘッダの現状">Expect-CT ヘッダの現状</h3> <p>リーグ・オブ・ワンダーランド導入時にもこの Expect-CT の検討は行ったのですが、まだ draft であった為に導入には早いとして最終的に PKP を選択しました。</p> <p>それでは現在はどうなのか……というと現状 draft で止まっている状態なようです。</p> <p><a href="https://github.com/httpwg/http-extensions#expect-ct">GitHub - httpwg/http-extensions: HTTP Extensions in progress</a></p> <p>しかし、 Nginx や Apache では対応されているようですので、将来を見据えて PKP ではなく Expect-CT を採用してみるのも面白いかと思います。</p> <h2 id="最後に">最後に</h2> <p>私たちは、新しい技術でユーザの体験を変えていける、チャレンジ精神のある方を求めています。</p> <p>当記事で弊社に興味を持った方は是非下のリンクをクリックしてください。</p> <p><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sega.co.jp%2Frecruit%2Findex.html" title="採用サイト|株式会社セガ -【SEGA Co., Ltd.】" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html">www.sega.co.jp</a></cite></p> sgtech ゲーム開発に使われるプログラミング言語 hatenablog://entry/26006613439577476 2019-09-25T10:00:00+09:00 2020-05-29T18:45:44+09:00 ゲーム=プログラム? みなさんこんばんは。セガゲームス開発技術部の林です。 長年、技術と名のつく部門で技術者をやっています。このブログも TECH とついているためぜひ何か情報を発信してみたいと考えていましたが、やっと順番が回ってきました。 これまでやってきたことを控えめに表現するとゲームタイトルを開発しているチームのお手伝いです。遠慮せずに表現すると、技術的に難易度の高い部分を引き受けて成功に導くのが役割です。 そのため、家庭用ゲーム・アーケードゲーム・スマートフォンアプリなどいろいろなタイプや規模のゲーム開発に触れる機会が数多くありました。そこで、今回ブログのテーマとしてはその全てに関わる… <h3> ゲーム=プログラム?</h3> <p>みなさんこんばんは。セガゲームス開発技術部の林です。</p> <p>長年、技術と名のつく部門で技術者をやっています。このブログも TECH とついているためぜひ何か情報を発信してみたいと考えていましたが、やっと順番が回ってきました。</p> <p>これまでやってきたことを控えめに表現するとゲームタイトルを開発しているチームのお手伝いです。遠慮せずに表現すると、技術的に難易度の高い部分を引き受けて成功に導くのが役割です。</p> <p>そのため、家庭用ゲーム・アーケードゲーム・スマートフォンアプリなどいろいろなタイプや規模のゲーム開発に触れる機会が数多くありました。そこで、今回ブログのテーマとしてはその全てに関わる内容をご紹介したいと思います。</p> <p> </p> <p>ゲーム開発に使用するプログラミング言語について取り上げます。</p> <p> </p> <p>プログラム上のテクニックや技術の詳細ではなく、実際の開発現場でどのプログラミング言語が何に使われているのかをご紹介します。また、単に列挙するだけでなく、そのプログラミング言語の使われ方を通じて、ゲーム開発中にプログラミングが必要な場面としてどのようなことが行われているかの雰囲気もお伝えできればと思います。</p> <h3><br />プログラミング言語</h3> <p>ゲームはプログラムとデータでできています。最近プログラミングは特殊な技術者だけに必要なものではなく、その論理的な考え方は現代に生きる上で必要だとしてプログラミング教育が行われるようになりました。2020年からは小学校でのプログラミング教育が必修化されます。そういった流れから、ゲームはプログラムで動いており、プログラミングすることでゲームを動作させられるということを知っている人も多くなっているはずです。</p> <p>そのプログラムを記述してゲーム機を含むコンピューターに命令するために使用するのがプログラミング言語です。プログラミング言語には非常に多くの種類が存在しており、ゲーム開発現場でもその中から選択された数多くのプログラミング言語が使用されています。</p> <p>ゲーム業界と一般的なIT産業で全く違うプログラミング言語を使うということはなく、基本的には同じものを使いますが、全体に対する割合や重要度は業界によって異なる特徴が出ます。</p> <p>この記事は、ゲーム業界を目指す方にとって、どのプログラミング言語を学習すればよいかの参考になるかもしれません。</p> <h3><br />よく使われるプログラミング言語</h3> <h4><img class="hatena-fotolife" title="f:id:sgtech:20190916160513p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190916/20190916160513.png" alt="f:id:sgtech:20190916160513p:plain" /><br />C++</h4> <p>家庭用ゲームとアーケードゲームの多くは <strong>C++</strong>言語 で書かれています。ゲームは特に高速な動作が要求されるプログラムであり、高速な動作が期待できる <strong>C++</strong> で実行速度を意識して書くことが重要です。</p> <p><strong>C++</strong> やその元になった <strong>C</strong>言語 はハードウェア(コンピューター)に近い層の「原始的」な言語であり、ハードウェアの性能を100パーセント引き出すことに適しています。</p> <p><strong>C++</strong> は十分に使いこなすには難易度が高めの言語ですが、その分機能が非常に多く、様々な目的に対して様々なやり方でプログラムを記述できる大きな自由度があります。そのため大規模なものを含む様々なプロジェクトで使用することができます。</p> <p> </p> <p>また、ゲームそのもののプログラムだけでなく、特に速度の要求されるサーバープログラムやゲーム開発に必要なツール類の開発にも使用されます。</p> <p>ゲーム開発において、ゲームプログラマーはゲーム本体のプログラムだけでなく、ゲームを作るのに必要なツールを作るためにもプログラミングします。一つのゲームを完成させるためには数多くのツールを作り、そのツールでゲームを組み立てていく作業が多くあります。</p> <p> </p> <p><strong>C++</strong> の元になった <strong>C</strong>言語 は過去に広く使われていたため今でも一部に残っています。シンプルなため他言語との橋渡し部分に使われることもあります。<strong>C++</strong> を学習する場合は必然的に <strong>C</strong>言語 も学ぶことになります。</p> <p> </p> <h4><img class="hatena-fotolife" title="f:id:sgtech:20190916155107p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190916/20190916155107.png" alt="f:id:sgtech:20190916155107p:plain" /><br />C#</h4> <p>スマートフォン向けゲームの多くは Unity というゲームエンジンを使って開発されています。この Unity では主に <strong>C#</strong>言語 を使ってプログラミングを行います。</p> <p> </p> <p>また、<strong>C#</strong> は Windows PC 上で動くツールを作成するのにも向いており、ゲーム開発に使う社内ツールの多くは <strong>C#</strong> でプログラミングされています。 得意な処理を分担して、 <strong>C#</strong> と <strong>C++</strong> を併用しているツールもたくさんあります。</p> <p> </p> <h4><img class="hatena-fotolife" title="f:id:sgtech:20190916162024p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190916/20190916162024.png" alt="f:id:sgtech:20190916162024p:plain" /><br />Java</h4> <p>現代はすべてのゲーム機やスマートフォンがネットワークに接続しています。インターネットを経由した接続先にはサーバーが用意され、サーバーと通信することでネットワークゲームを実現しています。そういったネットワークゲームのサーバーや、ゲームと連動しているWEBサイトのサーバーなどゲーム会社は様々なサーバーを提供しており、それらのサーバー上でプログラムが動いています。サーバー上で動いているプログラムには様々な言語が使われていますが、 <strong>Java</strong>言語 が使われているケースが比較的多いです。</p> <p> </p> <p>また、サーバーの場合は <strong>Java</strong> やその他の言語で直接プログラムを書くだけでなく、既存のソフトウェアをインストールして動かして使うことも多くあります。間接的にそれらのソフトウェアを作成するのに使われたプログラミング言語を使っているということができます。一部をカスタマイズして使うこともあります。</p> <p> </p> <p>Java は他にも Android アプリ開発に使用することができ、一部のアプリで使用されています。</p> <p> </p> <h4><img class="hatena-fotolife" title="f:id:sgtech:20190916163211p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190916/20190916163211.png" alt="f:id:sgtech:20190916163211p:plain" /><br />Python</h4> <p><strong>Python</strong> は様々な用途に使える人気の言語です。ゲーム業界や映像業界で広く使われているCGツールである Autodesk Maya の中でも実行できるため、面倒な繰り返し作業を自動処理させるなど、ツールを使いやすくするためにもよく使われています。</p> <p> </p> <p>また、 <strong>Python</strong> は最近技術の進歩が目覚ましい人工知能(AI)の処理を記述するのに向いています。ゲーム開発現場においても人工知能を活用したツールを作るために使われる機会が増えてきました。</p> <p> </p> <h4><img class="hatena-fotolife" title="f:id:sgtech:20190916164031p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190916/20190916164031.png" alt="f:id:sgtech:20190916164031p:plain" /><br />JavaScript</h4> <p><strong>JavaScript</strong> は、主にWEBページを作るために使われます。<strong>JavaScript</strong> を使うとWEBサイトで様々な機能や演出が実現できるようになります。このページにも使われていますね。</p> <p>ゲームプレイヤー向けのWEBサイトだけでなく、ゲーム開発中に必要な情報を蓄積する社内向けWEBサイトも作成されます。チームではそれを参照しながら仕事を進めます。</p> <p> </p> <p>また、<strong>JavaScript</strong> は Adobe Photoshop などのツールを自動化したり便利にするスクリプト処理にも使うことができます。</p> <p> </p> <p><strong>JavaScript</strong> のプログラムを直接書かず、<strong>TypeScript</strong> という <strong>JavaScript</strong> を強化した言語で記述し、それを <strong>JavaScript</strong> に変換してから使うこともあります。</p> <h3><br />その他の言語</h3> <p>その他にもシーンに応じて多くのプログラミング言語が業務に使われています。ここからはそれぞれ簡単に紹介していきます。</p> <h4>シェーダー言語</h4> <p>現代のゲーム機で画面表示を行うためには、専用のプログラミング言語を使って表示方法を細かく記述する必要があります。これをシェーダー言語といいます。キャラクターやメニューなどあらゆる画面表示はシェーダー言語の指示によって行われています。ゲームにとって表示の美しさや個性はとても大事なため、シェーダー言語によるプログラミングも重要です。</p> <p>シェーダー言語としては、 <strong>HLSL</strong> や <strong>GLSL</strong> などが使用されます。</p> <h4>アセンブリ言語</h4> <p>最も原始的でハードウェアに近い言語である <strong>アセンブリ</strong>言語 は、大きなプログラムを書くことには向いていませんが、特に高速に処理を行いたい部分にピンポイントに利用されています。</p> <p>なお、最近メガドライブミニの登場で話題のメガドライブなど過去の16bitゲーム機時代のころまでは、ゲームプログラム全てが <strong>アセンブリ</strong>言語 で書かれていました。</p> <h4>スクリプト系言語</h4> <p>ゲームプログラム本体でもツールそのものでもなく、開発時に必要な様々な処理を行うためにも多くのプログラムが書かれます。 <strong>Ruby</strong> 、 <strong>Perl</strong> 、そしてすでに出てきた <strong>Python</strong> や <strong>JavaScript</strong> は作業を補助するためのスクリプト言語として使われます</p> <p><strong>Visual Basic</strong> もそういった処理の他、ゲーム開発でデータの管理によく使われる Microsoft Excel の制御にも使われます。</p> <p>開発時ではなく、ゲーム実行時にゲームの動作を補助するスクリプト言語として、 <strong>Lua</strong> や <strong>Squirrel</strong> が使われることもあります。</p> <h4>その他の言語</h4> <p>iOSアプリの開発には <strong>Objective-C</strong> や <strong>Swift</strong> 、Androidアプリの開発には <strong>Kotlin</strong> といった目的に特に合ったプログラミング言語を使用することがあります。ゲームエンジン Unreal Engine 4 では専用ビジュアル言語である <strong>Blueprints</strong> が使われます。</p> <p>bash 、 cmd.exe(コマンドプロンプト)、 PowerShell といった作業環境で使用する言語もプログラミング言語だと言えそうです。</p> <p>既存のプログラミング言語ではできないことを実現するために、独自のプログラミング言語を新たに開発してそれを使うこともあります。</p> <h3><br />多様なプログラミング言語との付き合い方</h3> <p>ここまで多くのプログラミング言語を紹介してきましたが、ゲーム開発はチーム作業ですので、これら全てを一人で使いこなせるようになっている必要はありません。ここまで紹介してきたものの中で私が実際に業務で使ったことがある言語は半分ほどです。</p> <p>使ったことがある言語でも、ほとんどが入社後に初めて触れています。セガに入社した時点では全く存在していなかった言語もあります。今後もゲーム機や開発に使う技術、プログラミング言語の進化に合わせて様々な局面に適した新しい言語がどんどん登場してくるでしょう。</p> <p> </p> <p>プログラマーとして特に得意な言語はもちろんあったほうがよいですが、仕事で必要になった時に新しい言語をすぐに使いこなせるようになっておくと仕事の幅が広がります。まずは書きたい処理をすぐにスラスラと書ける得意な言語を軸として一つ二つ準備しつつ、それ以外の言語は新たに使いながら学んでいくことができれば問題ありません。</p> <p> </p> <p>どのプログラミング言語を習得しておけばよいかという問いに対しては、どんなプログラミング言語でもすぐに習得できるようになっておけばよいというのが答えになります。</p> <p> </p> <p>私たちは、常に新しい分野に好奇心を持ち、多くのプログラミング言語を使いこなしてゲーム開発に取り組める方を求めています。興味のある方は次にもアクセスしてみてください。<br /><cite class="hatena-citation"></cite></p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="採用サイト|株式会社セガ -【SEGA Co., Ltd.】" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sega.co.jp%2Frecruit%2Findex.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html">www.sega.co.jp</a></cite></p> <p>記載されている会社名、製品名は、各社の登録商標または商標です。</p> <p>セガ・セガロゴとメガドライブは株式会社セガホールディングスまたはその関連会社の登録商標または商標です。</p> <p style="box-sizing: border-box; font-family: 'Segoe UI', 'Helvetica Neue', 'Apple Color Emoji', 'Segoe UI Emoji', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">©SEGA</p> sgtech CEDEC 2019 セガグループによるセッション紹介! hatenablog://entry/26006613405185235 2019-08-27T10:00:00+09:00 2020-05-29T18:46:16+09:00 皆さんこんにちは!セガゲームス、第3事業部の麓です。 今年でSEGA TECHBogもこの8月に4年目を迎え、とても多くの方々がこのブログを知り、読んでくださるようになってきまして、続けることの大切さを噛み締めているところです。 来月にパシフィコ横浜で開催されるゲーム業界最大のカンファレンス CEDEC2019 会期:2019年9月4日(水)~9月6日(金)にセガグループ(および関連会社)からも何名か今年も登壇します!それでは今回で4回目となる、セガグループ関係者によるセッションと登壇者紹介に加え、ここでしか見れない講演者からのメッセージや、当日の資料からの抜粋等、紹介します。 セッション ス… <p>皆さんこんにちは!<br />セガゲームス、第3事業部の麓です。</p> <p>今年でSEGA TECHBogもこの8月に4年目を迎え、とても多くの方々がこのブログを知り、読んでくださるようになってきまして、続けることの大切さを噛み締めているところです。</p> <p>来月にパシフィコ横浜で開催されるゲーム業界最大のカンファレンス</p> <p><a href="http://cedec.cesa.or.jp/2019">CEDEC2019</a></p> <p>会期:2019年9月4日(水)~9月6日(金)<br />にセガグループ(および関連会社)からも何名か今年も登壇します!<br />それでは今回で4回目となる、セガグループ関係者によるセッションと登壇者紹介に加え、ここでしか見れない講演者からのメッセージや、当日の資料からの抜粋等、紹介します。</p> <p> </p> <ul class="table-of-contents"> <li><a href="#セッション">セッション</a><ul> <li><a href="#スクラムチームでモブプロ-立ちはだかる導入運用の壁とその成果-">スクラムチームでモブプロ!-立ちはだかる導入・運用の壁とその成果-</a><ul> <li><a href="#セッション内容と講演者より">セッション内容と講演者より</a></li> <li><a href="#講演者">講演者</a></li> <li><a href="#スナップショット">スナップショット</a></li> <li><a href="#セッションについて">セッションについて</a></li> </ul> </li> <li><a href="#Mesh-Effect-Shape2Dカートゥーン調デザインからその魅力のままにアニメーションする3Dエフェクトメッシュを軽量かつ効率良く作る">Mesh Effect Shape:2Dカートゥーン調デザインから、その魅力のままにアニメーションする3Dエフェクトメッシュを軽量かつ効率良く作る!</a><ul> <li><a href="#セッション内容と講演者より-1">セッション内容と講演者より</a></li> <li><a href="#講演者-1">講演者</a></li> <li><a href="#スナップショット-1">スナップショット </a></li> <li><a href="#セッションについて-1">セッションについて</a></li> </ul> </li> </ul> </li> <li><a href="#ラウンドテーブル">ラウンドテーブル</a><ul> <li><a href="#ワーママワーパパたちの働き方と悩み御社の悩みは何ですか他社はどう解決しているの">ワーママ・ワーパパたちの働き方と悩み/御社の悩みは何ですか?他社はどう解決しているの?</a><ul> <li><a href="#セッション内容">セッション内容</a></li> <li><a href="#講演者-2">講演者</a></li> <li><a href="#スナップショット-2">スナップショット</a></li> <li><a href="#講演者からのコメント">講演者からのコメント</a></li> <li><a href="#セッションについて-2">セッションについて</a></li> </ul> </li> <li><a href="#日々の業務から少しずつ始めるTA育成について話すラウンドテーブル">日々の業務から少しずつ始める!TA育成について話すラウンドテーブル</a><ul> <li><a href="#セッション内容-1">セッション内容</a></li> <li><a href="#講演者-3">講演者</a></li> <li><a href="#講演者からのコメント-1">講演者からのコメント</a></li> </ul> </li> </ul> </li> <li><a href="#パネルディスカッション">パネルディスカッション</a><ul> <li><a href="#ゲーム開発におけるOSSライセンス管理の実際-パネルディスカッション">ゲーム開発におけるOSSライセンス管理の実際 (パネルディスカッション)</a><ul> <li><a href="#セッション内容-2">セッション内容</a></li> <li><a href="#講演者-4">講演者</a></li> </ul> </li> </ul> </li> </ul> <h3 id="セッション"><span style="font-size: 150%;">セッション</span></h3> <h4 id="スクラムチームでモブプロ-立ちはだかる導入運用の壁とその成果-"><span style="font-size: 150%;">スクラムチームでモブプロ!-立ちはだかる導入・運用の壁とその成果-</span></h4> <h5 id="セッション内容と講演者より"><strong>セッション内容と講演者より</strong></h5> <p><span style="color: #201f1e; font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, system-ui, Roboto, 'Helvetica Neue', sans-serif; font-size: 14.6667px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; float: none; display: inline !important;">私たちは約3年、スクラムチームとして開発業務に携わっています。</span><br style="color: #201f1e; font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, system-ui, Roboto, 'Helvetica Neue', sans-serif; font-size: 14.6667px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff;" /><span style="color: #201f1e; font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, system-ui, Roboto, 'Helvetica Neue', sans-serif; font-size: 14.6667px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; float: none; display: inline !important;">事業に貢献したい、属人化を解消したい、新しい事にチャレンジしたいという課題を解決する手段を探してる中で、モブプロの導入を決めました。</span><br style="color: #201f1e; font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, system-ui, Roboto, 'Helvetica Neue', sans-serif; font-size: 14.6667px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff;" /><span style="color: #201f1e; font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, system-ui, Roboto, 'Helvetica Neue', sans-serif; font-size: 14.6667px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; float: none; display: inline !important;">導入を決めたものの、モブプロの導入を思い描いた方ならすぐに直面する壁からエンジニアならではの壁など、いくつかの壁に直面しました。</span><br style="color: #201f1e; font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, system-ui, Roboto, 'Helvetica Neue', sans-serif; font-size: 14.6667px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff;" /><span style="color: #201f1e; font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, system-ui, Roboto, 'Helvetica Neue', sans-serif; font-size: 14.6667px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; float: none; display: inline !important;">その壁をチームがどう乗り越え、どう成長し、どのような成果が生まれたのか、実践から感じたメリットやデメリットを含め、お話させていただきます。</span><br style="color: #201f1e; font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, system-ui, Roboto, 'Helvetica Neue', sans-serif; font-size: 14.6667px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff;" /><span style="color: #201f1e; font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, system-ui, Roboto, 'Helvetica Neue', sans-serif; font-size: 14.6667px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; float: none; display: inline !important;">チームが抱える課題を分析しその解決手段を模索している方へ、参考にしていただければ幸いです。</span></p> <h5 id="講演者">講演者</h5> <p><strong>株式会社セガゲームス DMS事業部 システム開発部 研究開発2課 課長</strong></p> <p><strong>横島 太志</strong></p> <p>09月04日(水) 15:20 〜 15:45(ショートセッション)</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="スクラムチームでモブプロ!-立ちはだかる導入・運用の壁とその成果- " src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2019%2Fsession%2Fdetail%2Fs5c8f2a3ba68a6" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2019/session/detail/s5c8f2a3ba68a6">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット"><strong>スナップショット</strong></h5> <p> </p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190816164322j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190816/20190816164322.jpg" alt="f:id:sgtech:20190816164322j:plain" /></p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190816164332j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190816/20190816164332.jpg" alt="f:id:sgtech:20190816164332j:plain" /></p> <p> </p> <h5 id="セッションについて"><strong>セッションについて</strong></h5> <p><span style="color: #201f1e; font-family: 'Segoe UI', 'Segoe UI Web (West European)', 'Segoe UI', -apple-system, system-ui, Roboto, 'Helvetica Neue', sans-serif; font-size: 14.6667px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; float: none; display: inline !important;">役割を分担開発を行うスピード感とは違った側面にあるモブプロにおけるスピード感の実感など、予想外の効果についても触れさせていただきます。</span></p> <p> </p> <h4 id="Mesh-Effect-Shape2Dカートゥーン調デザインからその魅力のままにアニメーションする3Dエフェクトメッシュを軽量かつ効率良く作る"><span style="color: #000000; font-family: 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 150%; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: bold; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; float: none; display: inline !important;">Mesh Effect Shape:2Dカートゥーン調デザインから、その魅力のままにアニメーションする3Dエフェクトメッシュを軽量かつ効率良く作る!</span></h4> <h5 id="セッション内容と講演者より-1">セッション内容と講演者より</h5> <p>Marzaが久しぶりにCEDECへ戻ってきました。<br />水、火、煙などのエフェクトを2Dカートゥーン調デザインの魅力そのままの形で3Dオブジェクトとして制作できる手法をご紹介します。<br />デザインを重視したアプローチに始まり、カスタマイズされたスカルプトツールを使い工程によってはツールで自動化し、メッシュのレゾリューションも自由にコントロールできるなど、バリエーションに富んだ機能を用意し、直感的にボリュームを持ったシェープを作ることが可能です。<br />本セッションのエフェクトはUnityを使用した弊社の新作ショートフィルムで使われていますので、その実例と共にご紹介します。</p> <p>使用ツール:Python、2Dペイント、 Maya、Unity</p> <h5 id="講演者-1">講演者</h5> <p><strong>マーザ・アニメーションプラネット株式会社</strong></p> <p> </p> <p><strong>映像事業1部 リアルタイムチーム チームマネージャー 高橋 聡</strong></p> <p><strong>技術課 Assistant Technical Director Brent Forrest</strong></p> <p><strong>技術課 Technical Director 松成 隆正</strong></p> <p>09月05日(木) 11:20 〜 12:20</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="Mesh Effect Shape:2Dカートゥーン調デザインから、その魅力のままにアニメーションする3Dエフェクトメッシュを軽量かつ効率良く作る! " src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2019%2Fsession%2Fdetail%2Fs5c9d9674182f0" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2019/session/detail/s5c9d9674182f0">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット-1">スナップショット </h5> <p><img class="hatena-fotolife" title="f:id:sgtech:20190816170139j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190816/20190816170139.jpg" alt="f:id:sgtech:20190816170139j:plain" /></p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190816170202j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190816/20190816170202.jpg" alt="f:id:sgtech:20190816170202j:plain" /></p> <h5 id="セッションについて-1">セッションについて</h5> <p>ゲームエンジンを利用した新たな進化を遂げたMarzaの新作と共に、手描きの魅力を真にCGの世界に落とし込んだ、ユニークなエフェクトをお届けします。<br />また、表現の進化だけではなくパイプライン面での進化もお話しします。</p> <p> </p> <h3 id="ラウンドテーブル"><span style="font-size: 150%;">ラウンドテーブル</span></h3> <h4 id="ワーママワーパパたちの働き方と悩み御社の悩みは何ですか他社はどう解決しているの"><span style="color: #000000; font-family: 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 150%; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: bold; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; float: none; display: inline !important;">ワーママ・ワーパパたちの働き方と悩み/御社の悩みは何ですか?他社はどう解決しているの?</span></h4> <h5 id="セッション内容">セッション内容</h5> <p><<2017年から始まったラウンドテーブルです/CEDECでの恒例化を目指しています>></p> <p>2018ラウンドテーブルでは、</p> <p>受講者の皆さんに、</p> <p>「私たち1人1人の動きで、働きやすいゲーム会社環境を作っていきましょう」</p> <p>「来年のCEDECまでに、何か1つ新しいアクションを起こしましょう」</p> <p>「きっと、何かが変わっていきます」</p> <p>と呼び掛け、終了しました。</p> <p>この1年、皆さんの周りで、何が変わったでしょうか?</p> <p>引き続き、抱えている問題点は何でしょうか?</p> <p>自社だけでは解決できない問題があれば、皆に相談しましょう。話し合いましょう。</p> <p>皆さんが抱えている問題の、糸口が見つかる場にしたいです。解決が難しい問題でも、相談できる相手がいるだけで、勇気づけられるものです。</p> <p>冒頭で、セガでのその後1年の動きを簡単に説明します。</p> <p>5グループ程度に分かれて、皆さんの会社では、この1年でどのような動きがあったか、働きかけを行ったか、等、情報の共有をしていただきます。</p> <p>現在抱えている悩みに関しても、共有して下さい。</p> <p>その後、グループごとに発表。</p> <p>発表された各社の内容に、意見や、質問がある場合は、質疑応答を行います。</p> <p>他社事例の情報は、自社へ持ち帰り、社内で情報の共有を行っていただきたいです。それぞれの会社で、さらなる1アクションを興こすキッカケにしたいと願っています。業界の、働き方改革に繋げていきましょう。</p> <h5 id="講演者-2">講演者</h5> <p><strong>株式会社セガゲームス エンタテインメント事業本部 第4事業部</strong></p> <p><strong>茂呂 真由美</strong></p> <p><strong>株式会社セガインタラクティブ コンテンツ研究開発本部 デザイナー</strong></p> <p><strong>鈴木 こずえ</strong></p> <p>09月04日(水) 11:20 〜 12:20</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="ワーママ・ワーパパたちの働き方と悩み/御社の悩みは何ですか?他社はどう解決しているの? " src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2019%2Fsession%2Fdetail%2Fs5c865fd25a6fb" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2019/session/detail/s5c865fd25a6fb">cedec.cesa.or.jp</a></cite></p> <h5 id="スナップショット-2">スナップショット</h5> <p><img class="hatena-fotolife" title="f:id:sgtech:20190816172117p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190816/20190816172117.png" alt="f:id:sgtech:20190816172117p:plain" /></p> <p> </p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190816172440j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190816/20190816172440.jpg" alt="f:id:sgtech:20190816172440j:plain" width="238" /> <img class="hatena-fotolife" title="f:id:sgtech:20190816172412j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190816/20190816172412.jpg" alt="f:id:sgtech:20190816172412j:plain" width="134" /></p> <h5 id="講演者からのコメント">講演者からのコメント</h5> <p>他社様と情報共有することにより、直面しうる問題と、具体的な対応例を知ることができます。<br />ここで刺激を受け、自社に持ち帰った後、自ら、何か行動を興していただきたいのです。<br />業界全体のワークライフバランス、意識改革に繋げていきたい、という目的で主催しました。<br /><br />私たち1人1人の動きで、働きやすいゲーム会社環境を作っていきましょう。変えていきましょう。<br />Keep on Moving!</p> <p> </p> <p>「ラウンドテーブル」ですので、悩みを抱えている方、共有したい自社事例のある方は、積極的にテーブル席についていただければと思います。<br />見学希望の方は、ラウンドテーブルが始まったら、各テーブルの話しが聞こえる場所に移動して、是非、現場の生の声を聞いて下さいね。<br />(立ちたくない!という方は、椅子ごと移動していただければ!)</p> <h5 id="セッションについて-2">セッションについて</h5> <p>ラウンドテーブル開催前、セガでのその後1年の動きを5分程度で説明、共有します。<br />社内共通コミュニケーションツール「Office365 Teams」を利用して、グループ会社間でのシナジーをどう高めていったか、活用法もご紹介します。</p> <p> </p> <h4 id="日々の業務から少しずつ始めるTA育成について話すラウンドテーブル"><span style="color: #000000; font-size: 150%;"><a aria-controls="collapse-183" aria-expanded="true" class="text-dark" data-toggle="collapse" href="https://cedec.cesa.or.jp/2019/session#collapse-183" style="box-sizing: border-box; color: #000000; text-decoration: none; background-color: #ffffff; font-family: 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: bold; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">日々の業務から少しずつ始める!TA育成について話すラウンドテーブル</a></span></h4> <h5 id="セッション内容-1">セッション内容</h5> <p>本ラウンドテーブルは、昨年度の「若手テクニカルアーティスト(以下、TA)の育成とその役割について話すラウンドテーブル」、および、一昨年度の「若手TAの業務効率改善への貢献、育成について話すラウンドテーブル」の議論に続くものです。</p> <p>近年、その需要から各社でTA業務を専門で行う若手を育成しようという動きが広がっています。昨年、一昨年のラウンドテーブルを通じて、TA育成について若手にTA業務をやらせてみること、その機会を与えることが大事ではないかと議論が交わされました。しかし、そのようなTAの育成を行うためには育成する側の環境や人材にある程度の余裕が必要になり、現実的には余裕がないためTA育成に向けた活動を行うことは困難の場合が多いという課題も判明しました。 </p> <p>そこで今年は、実業務へのアサインを通じたTA育成に焦点を当て、日々の業務へのアサインから少しずつTAを育成していくことはできないか、どのような業務へアサインすることがTAとしての知見を得ることにつながるのかをラウンドテーブルという形で突き詰め共有し、業界への貢献へとつなげていきたいと考えています。</p> <h5 id="講演者-3">講演者</h5> <p><strong>株式会社セガゲームス 第3事業部 第3開発2部 テクニカルサポートセクション プログラマー</strong></p> <p><strong>清水 宣寿 他</strong></p> <p>09月04日(水) 14:50 〜 15:50</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="日々の業務から少しずつ始める!TA育成について話すラウンドテーブル " src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2019%2Fsession%2Fdetail%2Fs5c9e6b8752bba" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2019/session/detail/s5c9e6b8752bba">cedec.cesa.or.jp</a></cite></p> <h5 id="講演者からのコメント-1">講演者からのコメント</h5> <div> <div> <div data-tid="messageBodyContainer"> <div data-tid="messageBodyContent"> <div> <div> <div> <div>CEDEC2018で「若手テクニカルアーティストの育成とその役割について話すラウンドテーブル」で登壇した清水です。 昨年に引き続き、テクニカルアーティスト(以下、TA)の育成についてのラウンドテーブルを開催いたします。</div> <div> <div> <div>今年は、「日々の業務から少しずつ始める!TA育成について話すラウンドテーブル」です。 昨年のラウンドテーブルではTAの育成について、機会と環境を与えることができれば十分に育てることができる。というまとめになりました。 今回はその機会を増やすために、実業務を通じて少しづつTAを育成していくことはできないか?という考えのもと、TAスキルを伸ばせる実業務について議論します。 当日は話のタネになるように、登壇者7名がTAスキルを伸ばせた実業務をまとめた表を持っていきます。</div> <div> <div> <div>一緒にTA育成について議論を交わし合いませんか? ご参加、お待ちしています。</div> </div> </div> </div> </div> </div> </div> </div> </div> </div> </div> </div> <h3 id="パネルディスカッション"><span style="font-size: 150%;">パネルディスカッション</span></h3> <h4 id="ゲーム開発におけるOSSライセンス管理の実際-パネルディスカッション"><span style="color: #000000; font-family: 'ヒラギノ角ゴ ProN W3', メイリオ, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 150%; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: bold; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; float: none; display: inline !important;">ゲーム開発におけるOSSライセンス管理の実際 (パネルディスカッション)</span></h4> <h5 id="セッション内容-2">セッション内容</h5> <p>本セッションでは、複数の企業のOSS管理の責任者にお集まり頂き、各社での取り組みをシェアいただきます。</p> <p>具体的な管理法、注意すべきOSS、困ったライセンスなどをご紹介頂きます。</p> <p>参加者のOSS管理への啓蒙、実際の問題の解決に役立つ情報をご提供します。</p> <h5 id="講演者-4">講演者</h5> <p><strong>株式会社セガゲームス 開発技術部 課長</strong></p> <p><strong>山中 勇毅 他</strong></p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="ゲーム開発におけるOSSライセンス管理の実際 (パネルディスカッション) " src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedec.cesa.or.jp%2F2019%2Fsession%2Fdetail%2Fs5c9ae4b13c986" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedec.cesa.or.jp/2019/session/detail/s5c9ae4b13c986">cedec.cesa.or.jp</a></cite></p> <p> </p> <p>今回紹介したセッションで聴講したい!と思ったセッションはありましたか?<br />多くの開発者の集まるCEDECは、パシフィコ横浜 会議センター(神奈川県横浜市西区みなとみらい)で9月4日(水)~9月6日(金)の間、開催されます。</p> <p>CEDECに参加して情報収集や交流をし、ゲーム業界の今を知り、業界の未来について語り合いませんか?<br />それでは皆さんCEDECでお会いましょう!</p> <p> </p> <p>私達は将来CEDECに登壇してみたいと思っている、技術に興味のある方を求めています。<br />そんな貴方、以下にアクセスしてみませんか?</p> <p> </p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="採用サイト|株式会社セガ -【SEGA Co., Ltd.】" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sega.co.jp%2Frecruit%2Findex.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html">www.sega.co.jp</a></cite></p> <p><br /><cite class="hatena-citation"></cite></p> <p> </p> <p>最後に、今月はこのSEGA TECHBlogの運営について<strong>CGWORLD.jp</strong>に取材いただきまして、記事として公開もされました。</p> <p>これまでの3年間、このブログを通じで何が起きて、生まれてきたか、これからのアイデアなどお話しさせていただいています。</p> <p>よかったらこちらも合わせて読んで頂ければ幸いです!!</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="自社技術の継続発信でプレゼンスを上げる! SEGA TECH Blog担当者に聞く企業ブログを長く続けるコツ | インタビュー | CGWORLD.jp" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcgworld.jp%2Finterview%2F1908-segablog.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cgworld.jp/interview/1908-segablog.html">cgworld.jp</a></cite></p> <p> </p> <p><span style="color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">※複数社登壇の場合でもセガの社員のみ表記しています </span><br style="color: #000000; font-family: Helvetica, Arial, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', sans-serif; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;" /><br /></p> sgtech 『Readyyy!』でのLive2D活用事例 hatenablog://entry/26006613377159448 2019-08-05T10:00:00+09:00 2019-08-05T18:46:30+09:00 2019年6月末でサービスを終了した『Readyyy!』。その『Readyyy!』にテクニカルアーティストとして参加していましたセガゲームスの宮下です。『Readyyy!』をプレイしてくださった皆様、本当にありがとうございました。 また、社内はもちろん、大勢の社外の方々のお力添えでリリースした『Readyyy!』でしたが、アプリのサービスを早々に終了させる結果になってしまったこと、誠に申し訳ありませんでした。スタッフ一同一丸となって取り組みましたが、力及びませんでした。そんな中『Readyyy!』をプレイしていただき、サービス終了を惜しんでくださる皆様からは、厳しいご意見をはじめ、心温まるお手… <p>2019年6月末でサービスを終了した『Readyyy!』。その『Readyyy!』にテクニカルアーティストとして参加していましたセガゲームスの宮下です。『Readyyy!』をプレイしてくださった皆様、本当にありがとうございました。</p><br /> <p>また、社内はもちろん、大勢の社外の方々のお力添えでリリースした『Readyyy!』でしたが、アプリのサービスを早々に終了させる結果になってしまったこと、誠に申し訳ありませんでした。スタッフ一同一丸となって取り組みましたが、力及びませんでした。</p><p>そんな中『Readyyy!』をプレイしていただき、サービス終了を惜しんでくださる皆様からは、厳しいご意見をはじめ、心温まるお手紙、想いの詰まった色紙などをいただきました。皆様のお声は開発チームまでちゃんと届いており、スタッフ一同ありがたく読ませていただいております。そして、そのような𠮟咤激励のお声にどう応えていくのか、日々考えながら業務に励んでおります。</p><br /> <p>テクニカルアーティストの自分と致しましては、『Readyyy!』の開発を通じて得た知見や技術を、この「セガテックブログ」の場で伝え、そして楽しんでいただくことで、皆様からのお声に少しでも応えられたらと思い、このブログを書かせていただきました。</p><br /> <p>今回『Readyyy!』でのLive2D活用事例として2つご紹介します。</p><p>1つは<b>ライティング表現</b>で、主にその仕組みやテクスチャの使い方に関する内容です。すでにプレイできなくなっているアプリの画面などを用いての説明となってしまい、重ね重ね申し訳ありません。</p><p>もう1つは、今後も『Readyyy!』のアイドルたちの姿を届けられることになったコンテンツ、<b>多人数の同時生配信</b>についてです。こちらは、多人数同時生配信の仕組みと、それを作り上げていくスタッフとのやりとりの様子をお伝えします。もしかするとその当時のやりとりで気になるところもあるかもしれませんが、お付き合いいただけますと幸いです。</p><br /> <p>それでは、始めさせていただきます。<br /> <br /> <br /> </p> <ul class="table-of-contents"> <li><a href="#Live2Dとは">Live2D®とは?</a></li> <li><a href="#Live2Dライティング表現のあれこれ">Live2Dライティング表現のあれこれ</a><ul> <li><a href="#使っているテクスチャについて">使っているテクスチャについて</a><ul> <li><a href="#アルベドマップ">アルベドマップ</a></li> <li><a href="#シャドウマップとスペキュラマップ">シャドウマップとスペキュラマップ</a></li> </ul> </li> <li><a href="#陰影のバリエーションについて">陰影のバリエーションについて</a></li> <li><a href="#テクスチャの種類のまとめ">テクスチャの種類のまとめ</a></li> <li><a href="#シャドウマップとスペキュラマップの縮小">シャドウマップとスペキュラマップの縮小</a></li> <li><a href="#シェーダーでレイヤー合成">シェーダーでレイヤー合成</a></li> <li><a href="#桜や建物などの落ち影">桜や建物などの落ち影</a></li> <li><a href="#逆光陰影のクオリティアップ">逆光陰影のクオリティアップ</a></li> <li><a href="#RGBA-Crunched-ETC2のノイズ軽減について">RGBA Crunched ETC2のノイズ軽減について</a></li> </ul> </li> <li><a href="#多人数による同時生配信">多人数による同時生配信</a><ul> <li><a href="#2人同時生配信の誕生">2人同時生配信の誕生</a></li> <li><a href="#5人同時生配信への道">5人同時生配信への道</a></li> <li><a href="#マイクデバイスを選択できない問題">マイクデバイスを選択できない問題</a></li> <li><a href="#バックグラウンドのUnityアプリではコントローラーが反応しない">バックグラウンドのUnityアプリでは、コントローラーが反応しない</a></li> <li><a href="#しゃべっていないアイドルが口パクをしてしまう">しゃべっていないアイドルが口パクをしてしまう</a></li> <li><a href="#多人数生配信のまとめ">多人数生配信のまとめ</a></li> </ul> </li> <li><a href="#最後に">最後に…</a></li> </ul> <div class="section"> <h3 id="Live2Dとは">Live2D®とは?</h3> <p>Live2Dとは、元のイメージを保ったままイラストを動かしたり、疑似的に3Dのように見せられる特徴を持つ、株式会社Live2D<a href="#f-75e06e90" name="fn-75e06e90" title="[https://www.live2d.com/ja/]">*1</a>が開発した技術やソフト、データのことです。ソフトの正式名称は「Live2D Cubism」と言います。「Cubism SDK 3.0<a href="#f-122739e9" name="fn-122739e9" title="UnityでLive2Dを扱うためのプログラム [https://live2d.github.io/#unity]">*2</a>」でUnity<a href="#f-f58bd1b3" name="fn-f58bd1b3" title="ゲームを作るための統合開発環境 [https://unity.com/ja] ">*3</a>からLive2Dへのアクセス方法が一新されたのですが、柔軟性が高くとても良い出来だったので『Readyyy!』で採用することに決めました。ただし「Live2D Cubisim」と「Cubism SDK 3.0」だけではライティングの実現には足りていません。新たなシェーダーとコンポーネント<a href="#f-3f1b3aa7" name="fn-3f1b3aa7" title="特定の機能を持たせたプログラムのかたまり">*4</a>の開発、それを活用するための特別なデータが必要でした。</p> </div> <div class="section"> <h3 id="Live2Dライティング表現のあれこれ">Live2Dライティング表現のあれこれ</h3> <p><center><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190726/20190726221016.gif" alt="f:id:sgtech:20190726221016g:plain:w500" title="f:id:sgtech:20190726221016g:plain:w500" class="hatena-fotolife" style="width:500px" itemprop="image"></span></center></p><p>『Readyyy!』のLive2Dでのライティング表現が一部で話題<a href="#f-867a5eb5" name="fn-867a5eb5" title="https://togetter.com/li/1316881">*5</a>になっていましたが、開発初期にプロトタイプを部内で紹介したときも、驚きの声とともに「力技?!」という声があがりました。そのときは「力技とは心外だな」と内心ふくれていたのですが、いまにして思えば…まあ力技ですね。やっていることは単純なんです。</p><p>それでは、『Readyyy!』のアイドルの1人、上條雅楽(かみじょううた)君に手伝ってもらって、ライティングの仕組みを説明していきます。</p><p><figure class="figure-image figure-image-fotolife" title="『Readyyy!』の上條雅楽君"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002118.png" alt="f:id:sgtech:20190725002118p:plain" title="f:id:sgtech:20190725002118p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>『Readyyy!』の上條雅楽君</figcaption></figure></p> <div class="section"> <h4 id="使っているテクスチャについて">使っているテクスチャについて</h4> <p>ライティングを実現するために、1ポリゴンにつき3つのテクスチャを使ってます。具体的には、アルベドマップ(色)、シャドウマップ(影)、スペキュラマップ(光沢)です。<br /> 「Live2D Cubism」はマルチテクスチャに対応していないので、この3つのテクスチャを生成するために、3回の出力作業が必要ですが、この面倒な作業はSikuliX<a href="#f-2b30751b" name="fn-2b30751b" title="http://sikulix.com/ GUI上での操作をRubyやPythonで自動化するツール。">*6</a>を使ってほぼ自動化しています。UV座標はLive2Dのものをそのまま利用して、ライティングの主な処理はUnity上のシェーダーで行っています。</p> <div class="section"> <h5 id="アルベドマップ">アルベドマップ</h5> <p>まず、体と顔のアルベドマップが1枚ずつ、計2枚あります。画像サイズは1024x1024ピクセルと600x600ピクセル<a href="#f-2bf93202" name="fn-2bf93202" title="ETC2は2のべき乗ではなく4の倍数でOK">*7</a>で、フォーマットはRGBA Crunched ETC2を使っています。これはUnity2017.3から導入されたフォーマットで、ストレージの消費量削減に抜群の効果があります。それまでは、JPEGファイルをダイレクトに使う計画で、その場合だと、RAMへの展開後にTrueColorになってしまい、メモリ消費量も膨大だったので、このフォーマットには助けられました。</p><p>なおRGBA Crunched ETC2はノイズが目立つので、軽減するようにアルベドマップのサイズは比較的大きめにしてあります。ノイズの軽減については、またあとで説明しますね。</p><p><figure class="figure-image figure-image-fotolife" title="アルベドマップ"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002113.jpg" alt="f:id:sgtech:20190725002113j:plain" title="f:id:sgtech:20190725002113j:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>アルベドマップ</figcaption></figure></p> </div> <div class="section"> <h5 id="シャドウマップとスペキュラマップ">シャドウマップとスペキュラマップ</h5> <p>続いて、シャドウマップとスペキュラマップです。<br /> <center><figure class="figure-image figure-image-fotolife" title="シャドウマップとスペキュラマップ"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002216.jpg" alt="f:id:sgtech:20190725002216j:plain" title="f:id:sgtech:20190725002216j:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>シャドウマップ(上)とスペキュラマップ(下)</figcaption></figure></center></p><p>シャドウマップとスペキュラマップに関しては、グレースケールで、かつ、ちょうど合計4枚なので、劣化しないTrueColorフォーマットを使ってRGBAチャンネルにパッキングしています。先ほども言いましたが、TrueColorだとメモリ消費が大きいので、画像サイズをぎりぎりの380x380ピクセルまで下げています。ETC2フォーマットで圧縮したケースも試してみましたが、見栄えが悪かったので不採用にしました。</p><p><figure class="figure-image figure-image-fotolife" title="パッキングされたシャドウマップとスペキュラマップ"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002108.png" alt="f:id:sgtech:20190725002108p:plain" title="f:id:sgtech:20190725002108p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>パッキングされたシャドウマップとスペキュラマップ</figcaption></figure></p> </div> </div> <div class="section"> <h4 id="陰影のバリエーションについて">陰影のバリエーションについて</h4> <p>ちょっとややこしいのですが、アイドル1ポーズにつき、シャドウマップとスペキュラマップをそれぞれ3種類用意しています(下の画像の左から、<b>逆光</b>、<b>左順光</b>、<b>右順光</b>)。これは太陽や照明の位置の違いを表現するためで、このバリエーションはライティングの効果を発揮するための大切な部分です。なぜなら、これが1種類しかないと、この一連の仕組みはあまり意味がなくなってしまうからです。</p><p><figure class="figure-image figure-image-fotolife" title="シャドウマップのバリエーション例"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002155.jpg" alt="f:id:sgtech:20190725002155j:plain" title="f:id:sgtech:20190725002155j:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>シャドウマップのバリエーション例</figcaption></figure></p> </div> <div class="section"> <h4 id="テクスチャの種類のまとめ">テクスチャの種類のまとめ</h4> <table> <tr> <th>マップの種類</th> <th>画像サイズ</th> <th>作業上の枚数</th> <th>実際の枚数</th> <th>画像 </th> </tr> <tr> <td>アルベド</td> <td>1024x1024</td> <td>2</td> <td>2</td> <td><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002113.jpg" alt="f:id:sgtech:20190725002113j:plain:w300" title="f:id:sgtech:20190725002113j:plain:w300" class="hatena-fotolife" style="width:300px" itemprop="image"></span></td> </tr> <tr> <td>シャドウ、スペキュラ</td> <td>380x380</td> <td>2x3、2x3</td> <td>3</td> <td><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002213.jpg" alt="f:id:sgtech:20190725002213j:plain:w300" title="f:id:sgtech:20190725002213j:plain:w300" class="hatena-fotolife" style="width:300px" itemprop="image"></span></td> </tr> </table><p>ここまでの説明を表にまとめてみました。つまり1ポーズあたり5枚のテクスチャが必要ということです。なお『Readyyy!』では、アイドル1人に対してポーズを7種類用意する予定でした。また衣装差分は5種類あるため、5x7x5で合計175枚のテクスチャが1人あたりに必要となります。なかなかのボリュームですね。</p> </div> <div class="section"> <h4 id="シャドウマップとスペキュラマップの縮小">シャドウマップとスペキュラマップの縮小</h4> <p>少し話を戻します。シャドウマップとスペキュラマップの画像サイズを下げた(380x380ピクセル、下の画像の左)ということは、アルベドマップ(1024x1024ピクセル)と比較して、相当ぼけているということなんですが、思いの外うまくなじんでいます。それどころか、64x64ピクセルまで縮小しても破綻しないんですね。</p><p>解像度を下げても破綻しないというのは、いわゆる3Dのシャドウマップと似ていますね。</p><p>ノイズ軽減のためアルベドが大きめという理由もあるのですが、シャドウマップとスペキュラマップはアルベドマップと同じサイズであるべきという固定観念にとらわれていたので、個人的にこの発見は大きいものでした。</p><p><center><figure class="figure-image figure-image-fotolife" title="シャドウマップのサイズによる見た目の変化"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002204.jpg" alt="f:id:sgtech:20190725002204j:plain:w1000" title="f:id:sgtech:20190725002204j:plain:w1000" class="hatena-fotolife" style="width:1000px" itemprop="image"></span><figcaption>シャドウマップのサイズによる見た目の変化</figcaption></figure></center></p><p>アートディレクターからのチェックで、縮小は380x380ピクセルで止めたのですが、曇り空のときは、右の64x64ピクセルバージョンを使うように提案してみてもおもしろかったですね。<br /> <br /> </p> </div> <div class="section"> <h4 id="シェーダーでレイヤー合成">シェーダーでレイヤー合成</h4> <p>シェーダー上で、先ほどのアルベドマップとシャドウマップを乗算し、スペキュラマップを加算してライティングを実現しています。</p> <pre class="code" data-lang="" data-unlink>fixed4 main_tex = tex2D(_MainTex, IN.texcoord); fixed4 packed_tex = tex2D(_PackedTex, IN.texcoord); fixed3 albedo = main_tex.rgb; fixed3 shadow = packed_tex.rrr; fixed3 specular = packed_tex.ggg; // 計算を省略しています! fixed3 clr = albedo * lerp( IN.ambient, fixed3(1,1,1), shadow ) + specular; return fixed4( clr.rgb, main_tex.a );</pre><p>Photoshopのレイヤー合成みたいなことをシェーダーでやっているわけですね。</p><p><figure class="figure-image figure-image-fotolife" title="アルベドのみ"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002125.png" alt="f:id:sgtech:20190725002125p:plain" title="f:id:sgtech:20190725002125p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>アルベドのみ</figcaption></figure><figure class="figure-image figure-image-fotolife" title="シャドウのみ"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002130.png" alt="f:id:sgtech:20190725002130p:plain" title="f:id:sgtech:20190725002130p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>シャドウのみ</figcaption></figure></p><p>また、 影の色味の違いを表現するために、頂点カラーを利用しています。頂点カラーは「Live2D Cubisim」上で直接設定可能なのですが、ヒューマンエラーが発生しそうなので、ノード名に特定のキーワードを入れてもらって、Unityでのインポート時に、自動的にキーワードから頂点カラーを設定するようにしました。ただし、間接的な方法を採用したことで「Live2D Cubism」上で色を視認できないという弊害が発生してしまい、肌なのに服のキーワードになっているなどの設定ミスが多発することになりました。チェックにも修正にも結構時間がかかってしまったので、この方法は、もっと検討改良すべきでした。</p><p>髪の毛(赤色)、肌(緑色)、服とヘッドセット(青色)として設定していますが、この色をダイレクトに乗算しているわけではありません。</p><p><figure class="figure-image figure-image-fotolife" title="頂点カラーのみ"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002136.png" alt="f:id:sgtech:20190725002136p:plain" title="f:id:sgtech:20190725002136p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>頂点カラーのみ</figcaption></figure></p><p>あくまで質感の種類を識別するために使っていて、このようなシェーダーコードにしています。</p> <pre class="code" data-lang="" data-unlink>ambient = _HairAmbient*v.color.r + _SkinAmbient*v.color.g + _ClothAmbient*v.color.b;</pre><p>本来質感が異なる場合は、マテリアルを分けて表現しますが、今回はドローコール数を増やしたくないため、このような仕組みにしています。</p><p><figure class="figure-image figure-image-fotolife" title="合成結果"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002118.png" alt="f:id:sgtech:20190725002118p:plain" title="f:id:sgtech:20190725002118p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>合成結果</figcaption></figure></p> </div> <div class="section"> <h4 id="桜や建物などの落ち影">桜や建物などの落ち影</h4> <p>Live2Dへの落ち影は、かなり反響があったので、うれしかったですね。桜や建物の落ち影用のテクスチャは、必要な背景にだけ用意しており、スクリーン座標系を使ってシェーダーで計算しています。</p><p><figure class="figure-image figure-image-fotolife" title="桜の落ち影"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002142.png" alt="f:id:sgtech:20190725002142p:plain" title="f:id:sgtech:20190725002142p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>桜の落ち影</figcaption></figure></p><br /> <p><figure class="figure-image figure-image-fotolife" title="落ち影テクスチャ"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002148.png" alt="f:id:sgtech:20190725002148p:plain" title="f:id:sgtech:20190725002148p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>落ち影テクスチャ</figcaption></figure></p> <p>スクリーン座標系はUV座標系よりも単純で、シェーダーでよく使うテクニックです。Live2Dに対して、落ち影テクスチャをプロジェクションマッピングしているといったほうがわかりやすいかもしれません。</p><p>『Readyyy!』では、Live2Dを半透明化させて消すときに、一時的にレンダーテクスチャを使っています。そのときにスクリーン座標系が画面全体ではなくレンダーテクスチャの大きさのものに変化にしてしまうため、同じ計算方法のままだと、落ち影がずれてしまうのです。その問題に対応するために、少し面倒な計算になっています。</p> <pre class="code" data-lang="" data-unlink>half4 screenPos = ComputeScreenPos(OUT.position); half2 uv2 = screenPos.xy / screenPos.w; // _ViewportScaleX等は、CPU側で計算している uv2.x = uv2.x * _ViewportScaleX + _ViewportOffsetX; uv2.y = uv2.y * _ViewportScaleY + _ViewportOffsetY;</pre><p>言い忘れていましたが、背景ごとのライティング用パラメーターの設定は、手動で行っています。</p><p><center><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002249.gif" alt="f:id:sgtech:20190725002249g:plain" title="f:id:sgtech:20190725002249g:plain" class="hatena-fotolife" itemprop="image"></span></center><br /> </p> </div> <div class="section"> <h4 id="逆光陰影のクオリティアップ">逆光陰影のクオリティアップ</h4> <p>もともと逆光陰影は1段階でした。下は2段階と1段階の比較画像です。<br /> <center><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002231.jpg" alt="f:id:sgtech:20190725002231j:plain" title="f:id:sgtech:20190725002231j:plain" class="hatena-fotolife" itemprop="image"></span></center><br /> 1段階のものでは物足りなさを感じていたので、順光時の陰影とブレンドして陰影を2段階とする手法を提案し承認されました。手作業でテクスチャをブレンドするのは面倒なので、スクリプト言語のRuby<a href="#f-05cdf2ea" name="fn-05cdf2ea" title="まつもとゆきひろ氏が開発した、個人的に大好きなスクリプト言語。テクニカルアーティストにはどちらかというと人気はない。">*8</a>とRMagick<a href="#f-4c44743e" name="fn-4c44743e" title="画像処理ライブラリImageMagickのRubyインターフェス。Rubyで簡単に画像を処理できるようになる。">*9</a>という画像処理ライブラリで自動化しました。</p><p>そういえば、最近、RMagickのメモリ使用量を減らしたという素晴らしい記事を見つけまして、一人で大興奮していました。RMagickのメモリリークには、苦労させられていたので!ありがとうございます!うれしさのあまり、テクニカルアーティストの同僚たちにもチャットで共有したのですが、特に反応はありませんでした。テクニカルアーティストの使うスクリプト言語は主にPython<a href="#f-e5856b8d" name="fn-e5856b8d" title="Mayaをはじめ多くのツールに組み込まれているスクリプト言語。DeepLearningでも良く使われている。テクニカルアーティストに大人気。">*10</a>ですから、まあそりゃそうですよね。<br /> <center><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwatson.hatenablog.com%2Fentry%2F2019%2F06%2F15%2F174638" title="RMagick のメモリ使用量を改善した - @watson1978 の日記" class="embed-card embed-blogcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://watson.hatenablog.com/entry/2019/06/15/174638">watson.hatenablog.com</a></cite></center><br /> </p> </div> <div class="section"> <h4 id="RGBA-Crunched-ETC2のノイズ軽減について">RGBA Crunched ETC2のノイズ軽減について</h4> <p>RGBA Crunched ETC2のストレージ上での圧縮性能はとても高いのですが、そのかわりノイズが発生します。このノイズに対抗するには、テクスチャを大きくすればいいのですが、比例してRAMとストレージの消費量も増えるので、それとクオリティとを天秤にかけることになります。『Readyyy!』ではLive2Dのテクスチャの他に、フォトにもこのテクニック(大きくするだけなんですが!)を使っています。</p><p>フォトとはガチャで引くことのできる、アイドルの写真のことです。</p><p><figure class="figure-image figure-image-fotolife" title="『Readyyy!』のフォト"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002059.jpg" alt="f:id:sgtech:20190725002059j:plain" title="f:id:sgtech:20190725002059j:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>『Readyyy!』のフォト</figcaption></figure></p><p>『Readyyy!』は画面サイズ1334x750ピクセルの想定で作っているので、画面サイズに近い1336(4の倍数)、画面サイズを大きく超えた2048、4096ピクセルの3種類のフォト用の画像で、ノイズがどのように変化するか比較してみました。</p><p><center></p> <table> <tr> <td>横幅(ピクセル)</td> <td>RAM(MB)</td> <td>ストレージ(MB)</td> <td>フィット後に切り抜いた一部画像</td> </tr> <tr> <td>1336</td> <td>4</td> <td>4</td> <td>(参考データ)TrueColorだった場合</td> </tr> <tr> <td>1336</td> <td>1.2</td> <td>0.2</td> <td><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002220.png" alt="f:id:sgtech:20190725002220p:plain:w300" title="f:id:sgtech:20190725002220p:plain:w300" class="hatena-fotolife" style="width:300px" itemprop="image"></span></td> </tr> <tr> <td>2048</td> <td>2.8</td> <td>0.45</td> <td><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002224.png" alt="f:id:sgtech:20190725002224p:plain:w300" title="f:id:sgtech:20190725002224p:plain:w300" class="hatena-fotolife" style="width:300px" itemprop="image"></span></td> </tr> <tr> <td>4096</td> <td>12</td> <td>1.3</td> <td><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002228.png" alt="f:id:sgtech:20190725002228p:plain:w300" title="f:id:sgtech:20190725002228p:plain:w300" class="hatena-fotolife" style="width:300px" itemprop="image"></span></td> </tr> </table><p></center><br /> </p> <p>上は、1334x750ピクセルの画面サイズにフィットさせて、一部分を切り抜いた画像と容量の表です。4096ピクセルのものが一番きれいですが『Readyyy!』ではバランスを取って2048ピクセルのものを採用しました。</p><p>ここで「フォトにはアルファチャンネルがなさそうなのに、なぜRGBA Crunched ETC2フォーマットを使うのか?」という疑問をもつ方がいるでしょう。その理由はiOSとAndroid両方で有効なCrunchedなフォーマットがRGBA Crunched ETC2しかないからです。ですから実はアルファチャンネル分、無駄にRAMを使っているのですが、それを踏まえてもストレージ上での圧縮性能が魅力的ということなのです。</p><p>最後のは少し余談でしたが、Live2Dのライティング表現については、以上です!</p><p>つづいて「多人数による同時生配信」に話を移しましょう。</p> </div> </div> <div class="section"> <h3 id="多人数による同時生配信">多人数による同時生配信</h3> <p><figure class="figure-image figure-image-fotolife" title="SHOWROOMさんでの生配信の様子"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002236.jpg" alt="f:id:sgtech:20190725002236j:plain" title="f:id:sgtech:20190725002236j:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>SHOWROOMさんでの生配信の様子</figcaption></figure></p><p>IPプロデューサーのOさんから、生配信の相談は突然やってきました。</p><p>「2月14日のバレンタインデーに、アイドル2人で生配信をやりたい!」</p><p>2人同時に生配信するには、リアルタイムでアイドル2人の映像を生成して、配信サービスを提供しているSHOWROOMさんのサーバーに転送する必要があります。私がLive2Dのデータ組み込みやライティングを含めた実装まわりを担当していたので、引き受けることになりました。</p><p>ところで、この生配信の見た目って何かに似ています。そう『Readyyy!』のアドベンチャーパートです。</p><p><center><figure class="figure-image figure-image-fotolife" title="『Readyyy!』のアドベンチャーパート画面"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002200.jpg" alt="f:id:sgtech:20190725002200j:plain" title="f:id:sgtech:20190725002200j:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>『Readyyy!』のアドベンチャーパート画面</figcaption></figure></center></p><p>事前に収録した音声を使っているのと、スクリプターさんが、あらかじめ設定したポーズを表示している点が異なりますが、要するに、この生配信というのは『Readyyy!』のアドベンチャーパートのようなものをリアルタイムで生成しようという試みなんです。</p><p>アイドル1人での生配信は、SHOWROOMさんのスマホアプリ「SHOWROOM V」で確立されていましたが、2人の仕組みは備わっていなかったので、セガ側で用意する必要がありました。</p><p>そのときは配信日までの時間と生配信に関する知識が不足していて、とても間に合わせる自信がなかったので、Oさんとの相談の結果、1か月後の「3月14日のホワイトデー」までに2人同時生配信の仕組みを用意する、ということになりました。リハーサルのことを考慮するとその1週間ぐらい前が締め切りですね。</p><p>ところで、Live2Dをバーチャルキャラクターとして操作するツールというと、「FaceRig」が有名ですね。<br /> <center><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fstore.steampowered.com%2Fapp%2F274920%2FFaceRig%2F%3Fl%3Djapanese" title="Steam:FaceRig" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://store.steampowered.com/app/274920/FaceRig/?l=japanese">store.steampowered.com</a></cite></center></p> <p>『Readyyy!』のLive2Dは、アイドル1人に対して7種類のポーズがあるのですが、これは「FaceRig」でいうところのアバターが7種類あるという意味になります。ネットの情報を調べた限りでは「FaceRig」は多機能なんですが、生配信中に7つのアバターを切り替えていくやり方には向いていないと判断し(もし問題なくできるとしたらごめんなさい!)、Unityで簡易的なアプリを作ることにしました。</p> <div class="section"> <h4 id="2人同時生配信の誕生">2人同時生配信の誕生</h4> <p>こうして会社のヘッドセットを借りての検証と開発の日々が始まりました。自席でマイクに向かって声を出す恥ずかしさと言ったら…。なので人が少なくなった夜中に声を出したり、会議室を取ってそこで検証したり、いろんな人に「これって、もはやテクニカルアーティストの仕事じゃないよね…。」とも言われたり。褒め言葉と解釈しましたが。</p><p>通常バーチャルキャラクターといえば、カメラによる顔認識などで実際の動きをトレースして、キャラに反映するものですが、今回は割り切ってウェブカメラは使わずに、インタラクティブなものはマイクから入力された声の音量による口パクの動きのみ。体の動きはキーボードの操作でポーズやアニメーションを切り替えるだけ、例えば「1」を押すと喜んでいるポーズ、「2」を押すと悲しんでいるポーズになる、というような何ともレトロな仕組みにしました。</p><p>FaceRigの代わりになるUniyアプリはできたので、次は2人同時の部分をどう実現するかです。</p><p>参考にしたのがこのサイトです。<br /> <center><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.cg-method.com%2Fentry%2Fobs-multiple-avatar-simultaneous-video-distribution%2F" title="【FaceRig】モデルを複数人同時で配信する方法" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://www.cg-method.com/entry/obs-multiple-avatar-simultaneous-video-distribution/">www.cg-method.com</a></cite></center><br /> なるほど。2人目は「Skype」や「Discard」でビデオ通話して、そこからキャプチャしているんですね。しかし今回の場合、すぐそばに2台のノートPCがあるのに、わざわざネットワークを介してビデオ通話というのは、ちょっと大げさすぎますし、無意味に遅延が発生してしまいますよね。</p><p>数日、他の仕事しながらぼんやり考えた結果「ネットワークの代わりにHDMIを使うアイデア」にたどり着きました。</p> <ol> <li>市販のキャプチャボックスを使って2台のノートPCを、HDMIとUSBでつなぐ。</li> <li>ヘッドセットをノートPCにつなぐ。普通のマイクでも可。</li> <li>それぞれでUnityアプリを立ち上げて、アイドルが映った状態にする。</li> <li>下記図の左側のノートPCから、右側のノートPCに画面を転送する。右側のノートPCにはUnityアプリの画面が2つ映った状態になる。</li> <li>右側のノートPCのOBS<a href="#f-a603ae16" name="fn-a603ae16" title="正式には「OBS Studio」という。生配信で使われるオープンフリーなソフトウェアのこと。">*11</a>上で、2人のアイドルをクロマキー合成する。</li> <li>OBSからSHOWROOMさんのサーバーに転送する。</li> </ol><p><center><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002244.jpg" alt="f:id:sgtech:20190725002244j:plain" title="f:id:sgtech:20190725002244j:plain" class="hatena-fotolife" itemprop="image"></span></center></p><p>この方法で、2人同時生配信を実現できました!<br /> ただし、HDMIを使う方法には2つ問題がありました。</p><p>問題の1つは、HDMIでの動画と音声の転送の遅延です。これにより相互のマイクで音声を拾った場合に、遅延した音声も合わせて配信されてエコーがかかったような現象が発生しました。</p><p>もう1つは、HDMIでPC同士を接続することの不安定さです。なかなか認識しなくて、何度もHDMIを抜き差しして、やっと成功する…といった具合で、本番の配信中に接続が切れないかと心配でした。</p><p>結局未解決のまま生配信したのですが、そのときダイジェストがこちらです。</p><p><center><iframe width="480" height="270" src="https://www.youtube.com/embed/l6w1hAccri4?feature=oembed" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><cite class="hatena-citation"><a href="https://www.youtube.com/watch?v=l6w1hAccri4">www.youtube.com</a></cite></center></p><p>なんとかそれっぽくなりましたね。</p><p>なお、機材のセットアップや生配信中のOBSの操作、トラブル対応のため本番は毎回立ち会っています。</p> </div> <div class="section"> <h4 id="5人同時生配信への道">5人同時生配信への道</h4> <p>この段階では、Oさんには「同時に生配信できる人数は2人までですからっ」とクギを刺していました。</p><p>ところが、その後この仕組みを使ってユニットごとに「新曲発表」の生配信をするという企画が立ち上がりました。それも、そのユニットのメンバー全員(2人〜5人)で、です。</p><p>新曲発表1組目は「La-Veritta(ラヴェリッタ)」という2人組のユニットだったので、トラブル<a href="#f-46e3acf2" name="fn-46e3acf2" title="1人の声が突然ロボットみたいな声になるというトラブルが発生し、めちゃくちゃ焦りましたが、Unityアプリを再起動したら直った。">*12</a>もありましたが、そのままの仕組みで乗り切れました。</p><p>2組目の「Just 4U(ジャストフォーユー)」という4人組ユニットのときは、Oさんの提案で、2人ずつ入れ替わりで生配信しました。結果、トラブルもなく大成功でしたが、でも私は負けた気がしたのです。そのときの視聴者の書き込みからもメンバー4人全員がそろっている姿を見たいという気持ちを感じましたし、なにより、できない理由が<b>技術的な事情</b>というところに、敗北感を覚えました。</p><p>このままではつまらない。『Readyyy!』で一番人数の多いユニット「SP!CA(スピカ)」は5人組なので、5人同時生配信の仕組みを作ってやる、と心に決めました。</p><p><center><figure class="figure-image figure-image-fotolife" title="「SP!CA」のメンバー"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002104.jpg" alt="f:id:sgtech:20190725002104j:plain" title="f:id:sgtech:20190725002104j:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>「SP!CA」のメンバー</figcaption></figure></center></p><p>単純に5台のPCをHDMIでつなげば、今の仕組みのまま対応できるかもしれません。ただPCが2台のときでさえ多少不安定なのに、5台だなんてとんでもない…。トラブルが発生することは容易に想像できます。</p><p>そんなことをぼやいていたら、いつもお世話になっているインフラ屋のAさんの助言がヒントになりました。</p><p>Aさん「1台で完結させればいいんじゃない?」</p><p>Aさんも深い意味で言ったわけではなかったと思うのですが、理にかなっています。1台…そうか…できるかも…。</p><p>PC1台で5人同時生配信を行う仕組みはこうなりました。まず以下の機材を用意します。</p> <ul> <li>デスクトップPC1台</li> <li>USB接続のマイク5本</li> <li>USB接続のコントローラー5台(実は4台でよかった)</li> <li>液晶モニター2台</li> <li>USBハブ2個</li> <li>Live2Dのアイドルを表示する自作Unityアプリ <ul> <li>使用するマイクやコントローラーを切り替える機能</li> <li>マイクからの音量に合わせてアイドルが口パクする機能</li> <li>アイドルを切り替える機能</li> <li>コントローラーでアイドルのポーズを切り替える機能</li> </ul></li> <li>OBS</li> </ul><p>セットアップの手順はこうです。</p> <ol> <li>PCにマイクとコントローラーを5台ずつ、つなぎます。</li> <li>そのPCで自作Unityアプリを5つ<a href="#f-a078421a" name="fn-a078421a" title="1アプリで5人表示させる方法もアリかもしれませんが、生配信中にアイドルの数を増減させる演出をすることがあり、別々のアプリにしておいてOBSで人数を管理する方法がやりやすかった。">*13</a>立ち上げます。</li> <li>Unityアプリ上で、それぞれ、アイドル、マイク、コントローラーの設定をします。</li> <li>OBSでUnityアプリの画面をすべて取り込んで、クロマキー合成します。</li> <li>OBSからSHOWROOMさんのサーバーへ転送。</li> </ol><p><center><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002240.jpg" alt="f:id:sgtech:20190725002240j:plain" title="f:id:sgtech:20190725002240j:plain" class="hatena-fotolife" itemprop="image"></span></center></p><p>これだけの機材の数になると、セットアップの手間もかなりのものになったのですが、その苦労の甲斐あってか、5人同時生配信の野望を達成できました!また、PCが1台になったことで遅延の問題も解決して一石二鳥です。</p><p>『Readyyy!』のアプリでは、パフォーマンスの都合上、アイドルの同時表示数を3人に制限していたので、ある意味で「生配信はアプリを超えた!」とも言えます。</p><p><center><figure class="figure-image figure-image-fotolife" title="生配信中の「SP!CA」のメンバー"><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190725/20190725002209.png" alt="f:id:sgtech:20190725002209p:plain" title="f:id:sgtech:20190725002209p:plain" class="hatena-fotolife" itemprop="image"></span><figcaption>生配信中の「SP!CA」のメンバー</figcaption></figure></center></p><p>ツイッター上でも5人全員そろっていることへの驚きの反応があったので、うれしかったですね。ちなみに明るさが人によって異なっているのは、話している人が誰かをわかりやすくするためです。</p><p>では次に、5人同時生配信をする上で遭遇したトラブルを3つ紹介します。</p> </div> <div class="section"> <h4 id="マイクデバイスを選択できない問題">マイクデバイスを選択できない問題</h4> <p>Unity2017.4では、複数マイクデバイスから任意の1つを選択できないバグがあり、どう解決するか悩まされましたが、そのバグが修正されたUnity2018.2を使うことで、あっさり解決しました。直っててよかったです…。</p><p><center><a href="https://issuetracker.unity3d.com/issues/microphone-dot-start-is-not-recording-the-audio-from-selected-recording-device">Unity Issue Tracker - Microphone.start is not recording the audio from selected recording device</a></center><br /> </p> </div> <div class="section"> <h4 id="バックグラウンドのUnityアプリではコントローラーが反応しない">バックグラウンドのUnityアプリでは、コントローラーが反応しない</h4> <p>Unityアプリを5つ立ち上げるので、すべてのアプリをアクティブにしておくことはできません。そのためUnityアプリがバックグラウンドの状態でも、操作できるようにしておく必要があります。</p><p><center><iframe src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fqiita.com%2Fkaikiofkaiki%2Fitems%2Ff705716f9e45c11b5288" title="Unityが非フォーカス/バックグラウンドでも入力を受け取るテクニック集 - Qiita" class="embed-card embed-webcard" scrolling="no" frameborder="0" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;"></iframe><cite class="hatena-citation"><a href="https://qiita.com/kaikiofkaiki/items/f705716f9e45c11b5288">qiita.com</a></cite></center></p><p>このサイトを参考にXInputを使って解決したまではよかったのですが、リハーサルで、5台目のコンローラーがまったく反応しないトラブルに遭遇しました。ネットで調べてみると、XInputはコントローラーを4台までしかサポートしていないそうで。そのためUnityアプリを修正して、5人目はキーボードでポーズを切り替えるようにしました。キーボードでの操作は2人同時生配信のときに実装していたので、対応自体はスムーズでしたが、まさかそんな落とし穴があるとは…。でも、プログラマのK君に聞いたら常識のようでした。</p> </div> <div class="section"> <h4 id="しゃべっていないアイドルが口パクをしてしまう">しゃべっていないアイドルが口パクをしてしまう</h4> <p>指向性のマイクを用意したのですが、それでもマイク同士が近いため、他のメンバーの声を拾ってしまい、しゃべってないアイドルが口パクをしてしまう問題が発生しました。超指向性のマイクを導入する方法もありましたが、今回はコントローラーの右トリガーを引いたときにのみ口パクをするようにプログラムを修正しました。ちょっとかっこ悪い解決方法ですね。</p><p>先ほど紹介した2人同時配信のダイジェスト動画もよく見ると、右側のアイドル(全)の口が時々、左側のアイドル(淳之介)につられて動いているのが分かります。</p> </div> <div class="section"> <h4 id="多人数生配信のまとめ">多人数生配信のまとめ</h4> <p>生配信の仕組み作りについては、世間のVTuberさんにとっては目新しいことはなかったと思いますが(結果的に)遅延のない5人同時生配信の試みはちょっとおもしろかったんじゃないでしょうか?条件は異なりますが「FaceRig」のマルチアバター機能も4人までみたいですし。<br /> 生配信自体、まったく新しいチャレンジだったので、プレッシャーがありながらも「SP!CA」5人全員を登場させることができたときは、達成感ありました(疲労感も…)。また、生配信中にトラブルがよく発生するので、臨機応変で、かつ、一か八かの対応も、普段のゲーム開発では味わえないスリリングさがありました。あと、OBSというツールがほんとよく出来ています。</p> </div> </div> <div class="section"> <h3 id="最後に">最後に…</h3> <p>『Readyyy!』でのLive2D活用事例、いかがだったでしょうか?今後も「応援し続けてよかった」と思えるくらい楽しんでいただけるよう、アイドルの生配信をはじめとするさまざまな可能性に、『Readyyy!』に関係するスタッフ一丸となって取り組んでいきます。</p><p>この記事が、皆様のモチベーションに少しでもプラスの影響を与えることができたのなら、幸いです。</p><br /> <br /> <p>©SEGA</p> </div><div class="footnote"> <p class="footnote"><a href="#fn-75e06e90" name="f-75e06e90" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://www.live2d.com/ja/">https://www.live2d.com/ja/</a></span></p> <p class="footnote"><a href="#fn-122739e9" name="f-122739e9" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text">UnityでLive2Dを扱うためのプログラム <a href="https://live2d.github.io/#unity">https://live2d.github.io/#unity</a></span></p> <p class="footnote"><a href="#fn-f58bd1b3" name="f-f58bd1b3" class="footnote-number">*3</a><span class="footnote-delimiter">:</span><span class="footnote-text">ゲームを作るための統合開発環境 <a href="https://unity.com/ja">https://unity.com/ja</a> </span></p> <p class="footnote"><a href="#fn-3f1b3aa7" name="f-3f1b3aa7" class="footnote-number">*4</a><span class="footnote-delimiter">:</span><span class="footnote-text">特定の機能を持たせたプログラムのかたまり</span></p> <p class="footnote"><a href="#fn-867a5eb5" name="f-867a5eb5" class="footnote-number">*5</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://togetter.com/li/1316881">https://togetter.com/li/1316881</a></span></p> <p class="footnote"><a href="#fn-2b30751b" name="f-2b30751b" class="footnote-number">*6</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="http://sikulix.com/">http://sikulix.com/</a> GUI上での操作をRubyやPythonで自動化するツール。</span></p> <p class="footnote"><a href="#fn-2bf93202" name="f-2bf93202" class="footnote-number">*7</a><span class="footnote-delimiter">:</span><span class="footnote-text">ETC2は2のべき乗ではなく4の倍数でOK</span></p> <p class="footnote"><a href="#fn-05cdf2ea" name="f-05cdf2ea" class="footnote-number">*8</a><span class="footnote-delimiter">:</span><span class="footnote-text">まつもとゆきひろ氏が開発した、個人的に大好きなスクリプト言語。テクニカルアーティストにはどちらかというと人気はない。</span></p> <p class="footnote"><a href="#fn-4c44743e" name="f-4c44743e" class="footnote-number">*9</a><span class="footnote-delimiter">:</span><span class="footnote-text">画像処理ライブラリImageMagickのRubyインターフェス。Rubyで簡単に画像を処理できるようになる。</span></p> <p class="footnote"><a href="#fn-e5856b8d" name="f-e5856b8d" class="footnote-number">*10</a><span class="footnote-delimiter">:</span><span class="footnote-text">Mayaをはじめ多くのツールに組み込まれているスクリプト言語。DeepLearningでも良く使われている。テクニカルアーティストに大人気。</span></p> <p class="footnote"><a href="#fn-a603ae16" name="f-a603ae16" class="footnote-number">*11</a><span class="footnote-delimiter">:</span><span class="footnote-text">正式には「OBS Studio」という。生配信で使われるオープンフリーなソフトウェアのこと。</span></p> <p class="footnote"><a href="#fn-46e3acf2" name="f-46e3acf2" class="footnote-number">*12</a><span class="footnote-delimiter">:</span><span class="footnote-text">1人の声が突然ロボットみたいな声になるというトラブルが発生し、めちゃくちゃ焦りましたが、Unityアプリを再起動したら直った。</span></p> <p class="footnote"><a href="#fn-a078421a" name="f-a078421a" class="footnote-number">*13</a><span class="footnote-delimiter">:</span><span class="footnote-text">1アプリで5人表示させる方法もアリかもしれませんが、生配信中にアイドルの数を増減させる演出をすることがあり、別々のアプリにしておいてOBSで人数を管理する方法がやりやすかった。</span></p> </div> sgtech GDC報告会に見るセガの学習機会と共有の取り組み hatenablog://entry/17680117127205491470 2019-06-25T10:00:00+09:00 2020-05-29T18:48:50+09:00 はじめまして SEGA Tech Blogをご覧のみなさまこんにちは。セガゲームス開発技術部の小林です。開発技術部ではスタジオサポート以外にも勉強会の開催やグループ内の情報共有のお手伝いを行っています。もちろんこのBlogのお手伝いもしています。 SEGA Tech Blogでは毎回スタジオの開発者が素晴らしい技術ネタを書いていますが、今回は5月15日に開催したGDC2019*1社内報告会の事例を踏まえまして、弊社における学習機会の外郭のお話をしたいと思います。 GDCとは GDC(Game Developers Conference)とは毎年2月下旬から3月上旬に行われる世界各国のゲーム開発… <p> </p> <h3>はじめまして</h3> <p>SEGA Tech Blogをご覧のみなさまこんにちは。セガゲームス開発技術部の小林です。<br />開発技術部ではスタジオサポート以外にも勉強会の開催やグループ内の情報共有のお手伝いを行っています。<br />もちろんこのBlogのお手伝いもしています。</p> <p>SEGA Tech Blogでは毎回スタジオの開発者が素晴らしい技術ネタを書いていますが、今回は5月15日に開催したGDC2019<a href="#f-628a09d1" name="fn-628a09d1" title="先月の記事のGCC2019と似てますね">*1</a>社内報告会の事例を踏まえまして、弊社における学習機会の外郭のお話をしたいと思います。</p> <p> </p> <h3>GDCとは</h3> <p>GDC(Game Developers Conference)とは毎年2月下旬から3月上旬に行われる世界各国のゲーム開発者を中心としたカンファレンスです。2015年まではGDC China、2016年まではGDC Europeなども別の日程でありましたが、2017年からはこの時期に行われるGDCのみとなっています。</p> <p>2019年は3月18日から22日にかけてサンフランシスコのモスコーニセンターにおいて20のTopics、約800近いセッションが行われました<a href="#f-9ebaa1b3" name="fn-9ebaa1b3" title="オフィシャルページに記載されているTopicsは以下。Advocacy、Audio、Business &amp;amp; Marketing、Career Development、Design、Game Career Seminar、Production &amp;amp; Team Management、Programming、Special Event、Vision、Visual Arts、AI Summit、Community Management Summit、Educators Summit、Entertainment VR/AR、Mobile Summit、Game Narrative Summit、Game VR/AR、Independent Games Summit、UX Summit">*2</a>。セッション数上位のTopicsはProgramming、Design、Business &amp; Marketing、Visual Artsあたりとなります。Topicsの種類は業界のトレンドによって追加されます<a href="#f-86a726c3" name="fn-86a726c3" title="数年前はVRのセッションが爆発的に増加し、VRDCという単独のイベントも行われました">*3</a>。この時期なると日本の業界関係者のSNSにおいて、渡航組と残留組の食べ物写真の応酬が行われるのも風物詩となっています。</p> <p>また、GDC2019では"Game Developers Choice Awards"において弊社小玉理恵子さんが業界の発展に貢献したゲーム開発者に贈られる“PIONEER AWARD”を受賞しました。</p> <p> </p> <h3>毎年派遣しています</h3> <p>弊社では毎年GDCに社員を派遣しています。ここ数年の実績ではセガゲームス、セガ・インタラクティブあわせて約20人ほどの社員が参加しています。セッション数上位にあるようにプログラマー、デザイナーの参加者が多い傾向にありますが、プランナーやサウンドの参加者が皆無な訳ではありません。</p> <p> </p> <table><caption>GDC参加実績</caption> <tbody> <tr> <th>年次</th> <th>総数</th> <th>管理職</th> <th>プログラマー</th> <th>デザイナー</th> <th>プランナー</th> <th>サウンド</th> <th>その他</th> </tr> <tr> <td>GDC2016</td> <td>18</td> <td>0</td> <td>10</td> <td>5</td> <td>0</td> <td>1</td> <td>2</td> </tr> <tr> <td>GDC2017</td> <td>14</td> <td>0</td> <td>6</td> <td>4</td> <td>2</td> <td>1</td> <td>1</td> </tr> <tr> <td>GDC2018</td> <td>20</td> <td>1</td> <td>9</td> <td>8</td> <td>2</td> <td>0</td> <td>0</td> </tr> <tr> <td>GDC2019</td> <td>23</td> <td>1</td> <td>12</td> <td>9</td> <td>1</td> <td>0</td> <td>0</td> </tr> </tbody> </table> <p> </p> <p>人選は各部門に委ねられています。なるべく多くの情報を持ち帰り展開してくれる人を選ぶ部署もありますし、トレンド技術を消化してもらう為に、専門的な知識を持った人を選ぶ部署もあります。また、刺激を受けてきてもらう為に若手を選ぶ部署もあるようです。参加経験の浅い人が不安を解消してモチベーションが高い状態で参加できるように、<span style="color: #111111; font-family: 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', メイリオ, Meiryo, 'MS Pゴシック', 'MS PGothic', 'MS UI Gothic', Helvetica, Arial, sans-serif;">当部の</span><a href="http://techblog.sega.jp/entry/2016/09/26/173024">粉川</a>が相談用チャットや勉強会を開催して、事前準備するべきことや、心構え、開催されるセミナー情報などのフォローもしています。</p> <p> </p> <h3> GDC社内報告会</h3> <p>GDC参加者から有志によりレポートとは別に報告会を開催して情報を共有をしています。それが今回開催したGDC2019社内報告会です。普段の勉強会は社内事例を取り扱う事が多いので11階にあるLIGTH HOUSEというセミナールームを利用する事が多いのですが、今回は外部のセミナー報告会ということで9階のTunnel Tokyoのオープンラウンジで開催しました。9階には総合受付や多くの会議室があり、大型LEDサイネージにプレゼン資料を表示するのでミーティングで近くを通る方や来訪者の方もこちらを興味深くみていました。 </p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="Tunnel Tokyoのオープンラウンジ"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190623220920j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190623/20190623220920.jpg" alt="f:id:sgtech:20190623220920j:plain" /></p> <figcaption>Tunnel Tokyoのオープンラウンジ</figcaption> </figure> <p>報告会は以下の内容で行われました。</p> <p>・せっかく海外行けるのに英語?新人?そんなの気にしない!!<br />・AAAタイトルのデータとツール(主にスパイダーマン事例紹介<br />・自動テスト関連<br />・サウンドの実装事例とミドルウェアの紹介<br />・Deep Learning 活用事例にみるゲーム開発・運用への活用のありかた<br />・ツール関連、テクニカルアーティスト関連、プロシージャル関連<br />・God Of Warとスパイダーマンのアニメーションセッション話題。 </p> <p> </p> <p>今回の報告会では新人から、参加16回目の常連まで幅位広いキャリアの人が登壇しました。異なるキャリア、異なる職種の人が、会社の実情を踏まえた上で情報共有してくれる会は、社外で行われている報告会とはまた別の意義があると感じています。</p> <p> </p> <h3>ある若手に着目して</h3> <p><img class="hatena-fotolife" title="f:id:sgtech:20190623220925p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190623/20190623220925.png" alt="f:id:sgtech:20190623220925p:plain" /></p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="リハーサルと本番の様子"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190623220911p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190623/20190623220911.png" alt="f:id:sgtech:20190623220911p:plain" /></p> <figcaption>リハーサルと本番の様子</figcaption> </figure> <p>写真は「ツール関連、テクニカルアーティスト関連、プロシージャル関連」で登壇した4年目のTA・<a href="http://techblog.sega.jp/entry/2018/10/25/100000">清水</a>です。GDCへの参加は今回初めてだったそうです。彼は若手ですが、社内の勉強会や<a href="https://2018.cedec.cesa.or.jp/session/detail/s5aafcb42e41b7">CEDEC</a>などで積極的に発表活動を行なっていて、その成果が認められてGDCへ参加する機会を得ました。清水曰く、GDCでは、発表の内容はもちろんのこと、発表の仕方にも感銘を受けたそうです。聴いて欲しい内容を浸透させるために如何に聴衆の心を掴むかという方法を生で体感できたのは、GDCに行って最も価値がある体験の一つだったと語ってくれました。また、上司がセミナー受講や登壇することに対する理解があることも自分が積極的に活動できる理由であるとも語ってくれました。</p> <p> </p> <h3>良いゲームをつくるために</h3> <p>ゲーム開発を行っている以上、最も重要なアウトプットはゲームそのものです。より良いゲームを作るためには思考を繰り返す必要があり、その思考を回す為には情報のインプットが必要です。一度自分がゲームというアウトプットを行なった後は更なる情報のインプットはもちろんの事、自分が行った事をまとめてアウトプットする事も重要だと考えています。それは周りに情報をインプットする機会を与えているだけにとどまらず、伝えた人々からフィードバックを受けることが、自身の新たなインプットにつながるからです。グループ全体を見回すと面白い知見を持っている者がたくさんおります。こうした情報を知る機会、また、広める機会をこれからもお手伝いできればと思っています。</p> <p> </p> <h3>最後に</h3> <p>弊社では多くのインプット、アウトプットの機会と設備を備えています。また、海外カンファレンスに参加するチャンスもある弊社に興味を持った方は是非下のリンクをクリックしてください。ゲームを世に出す事はもちろん、自分の学んだ事をみんなに伝えて自他共栄を行える人を求めています。</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="採用サイト|株式会社セガ -【SEGA Co., Ltd.】" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sega.co.jp%2Frecruit%2Findex.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html">www.sega.co.jp</a></cite></p> <p><br /><cite class="hatena-citation"></cite></p> <p> </p> <p>弊社の開発関連人員の知見を広げる勉強会を開催してくださる方や講師を引き受けてくださる方もあわせて募集しています。</p> <p> </p> <p><span style="color: #000000; font-family: 'Segoe UI', 'Helvetica Neue', 'Apple Color Emoji', 'Segoe UI Emoji', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">©SEGA</span></p> <p> </p><div class="footnote"> <p class="footnote"><a href="#fn-628a09d1" name="f-628a09d1" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">先月の記事のGCC2019と似てますね</span></p> <p class="footnote"><a href="#fn-9ebaa1b3" name="f-9ebaa1b3" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text">オフィシャルページに記載されているTopicsは以下。Advocacy、Audio、Business &amp; Marketing、Career Development、Design、Game Career Seminar、Production &amp; Team Management、Programming、Special Event、Vision、Visual Arts、AI Summit、Community Management Summit、Educators Summit、Entertainment VR/AR、Mobile Summit、Game Narrative Summit、Game VR/AR、Independent Games Summit、UX Summit</span></p> <p class="footnote"><a href="#fn-86a726c3" name="f-86a726c3" class="footnote-number">*3</a><span class="footnote-delimiter">:</span><span class="footnote-text">数年前はVRのセッションが爆発的に増加し、VRDCという単独のイベントも行われました</span></p> </div> sgtech 徹底解説!セガゲームスのテクニカルアーティスト hatenablog://entry/17680117127169776286 2019-05-27T10:00:00+09:00 2020-05-29T18:49:34+09:00 こんにちは。 皆様いかがお過ごしでしょうか? セガゲームス 第3事業部のテクニカルアーティスト。麓です。 普段はこのブログの裏方をしているのですが、今回は今年の3/30に大阪で開催された、ゲームクリエイターズカンファレンス2019(以後GCC2019)*1にて、株式会社カプコンの塩尻様とパネルディスカッション形式で講演致しまして、時間内で全て語りきれなかったということもあり、セッションのフォロー記事という形で筆を取らせていただきました。 セッションのおさらいも兼ねていますので参加できなかった方にもお伝えできるように、講演時に話した内容からも引用しつつまとめていきます。 尚、このブログではセガゲ… <p>こんにちは。</p> <p>皆様いかがお過ごしでしょうか?</p> <p>セガゲームス 第3事業部のテクニカルアーティスト。麓です。</p> <p> </p> <p>普段はこのブログの裏方をしているのですが、今回は今年の3/30に大阪で開催された、ゲームクリエイターズカンファレンス2019(以後GCC2019)<a href="#f-ed3259ad" name="fn-ed3259ad" title="ゲームクリエイターズカンファレンスhttp://www.gc-conf.com/">*1</a>にて、株式会社カプコンの塩尻様とパネルディスカッション形式で講演致しまして、時間内で全て語りきれなかったということもあり、セッションのフォロー記事という形で筆を取らせていただきました。</p> <p>セッションのおさらいも兼ねていますので参加できなかった方にもお伝えできるように、講演時に話した内容からも引用しつつまとめていきます。</p> <p>尚、このブログではセガゲームスの事例のみを解説させていただきますので、ご了承ください。</p> <ul class="table-of-contents"> <li><a href="#タイトル怖く無いテクニカルアーティストという仕事">タイトル「怖く無い、テクニカルアーティストという仕事」</a></li> <li><a href="#TAについて簡単に">TAについて簡単に・・・</a></li> <li><a href="#1日にどんな仕事をしているの">1日にどんな仕事をしているの?</a></li> <li><a href="#具体的にどんな効率化が出来たの">具体的にどんな効率化が出来たの?</a><ul> <li><a href="#Photoshop効率化">Photoshop効率化</a></li> <li><a href="#座標系を超えろ3Dツール間コンバート">座標系を超えろ!?3Dツール間コンバート</a></li> <li><a href="#横断サポートの強み">横断サポートの強み</a></li> </ul> </li> <li><a href="#どんなツールを作成しているの">どんなツールを作成しているの?</a><ul> <li><a href="#ワークフロー構築ツール">ワークフロー構築ツール</a></li> <li><a href="#データデバッグビューア">データデバッグビューア</a></li> </ul> </li> <li><a href="#TAのプロジェクトへの関わり方は">TAのプロジェクトへの関わり方は?</a></li> <li><a href="#若手新人TAについて">若手、新人TAについて</a></li> <li><a href="#まとめ">まとめ</a></li> </ul> <h3 id="タイトル怖く無いテクニカルアーティストという仕事">タイトル「怖く無い、テクニカルアーティストという仕事」</h3> <p><img class="hatena-fotolife" title="f:id:sgtech:20190421145618p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190421/20190421145618.png" alt="f:id:sgtech:20190421145618p:plain" /></p> <p>「テクニカルアーティスト(以下TAと略します)って大手企業のみしか関係の無い職種だろうから、ウチはあんまり関係ないなあ。その様な人材は、技術力が高くてデキる人なんだから、ウチにはいないなあ。中途で採用や教育もしたいけど、そんなヒマも余裕もウチにはないなあ。」<br />関西圏<a href="#f-c575b5e8" name="fn-c575b5e8" title="GCC2019は関西で開催したカンファレンスということで関西圏向けということになっています。">*2</a>でCGやゲームを生業としている企業は、データの状態や仕様がはっきりとしない状態で制作に入らなければいけない事が多く、各アーティストは効率が悪くとも、<strong>“</strong><strong>根性</strong><strong>”</strong>で頑張って納期に間に合わせているといった実情をよく耳にします。<br />根性が必要になるときは必ずありますが、<strong>出来るだけラクできる所はラクした方が、</strong><strong>空いた時間を</strong><strong>工数削減</strong><strong>やクオリティ</strong><strong>UP</strong><strong>に</strong><strong>あてられるので、その方がいいですよね?</strong></p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190421145615p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190421/20190421145615.png" alt="f:id:sgtech:20190421145615p:plain" /><br />今回の講演は、上のような状況に悩まされるゲーム会社の方へ向けて構成しました。</p> <h3 id="TAについて簡単に">TAについて簡単に・・・</h3> <p>CG World Entryの記事から引用すると、</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190421151853p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190421/20190421151853.png" alt="f:id:sgtech:20190421151853p:plain" /></p> <p>という事で一般的な認識としては上記元記事「<a href="https://entry.cgworld.jp/terms/%E3%83%86%E3%82%AF%E3%83%8B%E3%82%AB%E3%83%AB%E3%82%A2%E3%83%BC%E3%83%86%E3%82%A3%E3%82%B9%E3%83%88.html">CGWorld Entry.jp</a>」を参照していただくとして、様々な会社の事情を元にTAに必要な知識をリストアップすると・・・</p> <ul> <li>C#やPythonなど業務に必要な各言語でのプログラム技術、及びShader関連知識</li> <li>絵が描ける、パースが取れる、色彩の説明が出来るなどアートスキル </li> <li>ゲームエンジンのフロー知識と、DCCからの出力フロー知識(描画フロー把握、用語知識など)</li> <li>ゲームハードに関しての基本知識(ハードスペック、描画性能など)</li> <li>VMやNASなどのストレージやライセンスサーバ関連、SubversionやPerforceなどサーバ知識技能。</li> <li>Windows、MacOS、Linux、iOS、Androidなど色々なOSへの造詣</li> <li>Mayaや3DS MAX、Houdiniと言ったメジャーな3DDCCツールの知識</li> <li>PhotoShopやSubstance、ZBrushや3D-coatといった様々なツール知識</li> <li>過去のツールやゲームハードに関しての様々な知識</li> <li>Havok,Simplygon,SpeedTreeやumbraなど様々なミドルウェア製品知識</li> <li>MotionCapture関連での作業フローの理解と、VICONや各社ツールの知識</li> <li>画角やEV値やルーメン、カンデラといった単語が理解出来るくらいの照明技術やカメラ映像知識</li> <li>SiggraphやGDC、CEDECなどでの様々な新規技能を能動的に取得できる知識欲</li> <li>交渉力、説得力、判断力などのコミュニケーションスキル</li> <li>技術的な仕組みを判りやすくまとめ、説明できるプレゼン力</li> </ul> <p>等々・・・</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190421145613p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190421/20190421145613.png" alt="f:id:sgtech:20190421145613p:plain" /></p> <p>だと思います!<br />なのでどれか1つのスキルを持っているだけでもいいんです。<br />極論これから始めてもいいんです。効率化を考える事からぜひ始めましょう!<br />現状の作業の中で、“これ面倒だな”とか“単調な作業をなんとかしたいな”と思える人は向いていますので、そこからDCCツールを深いところまで覚えてみたり、Scriptを覚えたり、Shaderを書いてみたりして、第1歩を踏み出しましょう!</p> <h3 id="1日にどんな仕事をしているの">1日にどんな仕事をしているの?</h3> <p>普段何をやっているのか、どんな風にタスクをこなしているのか見えずらいとよく言われるTAですが一つ、とある1日を抜き出して見ました。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190421152743p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190421/20190421152743.png" alt="f:id:sgtech:20190421152743p:plain" /></p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190421152759p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190421/20190421152759.png" alt="f:id:sgtech:20190421152759p:plain" /></p> <p>この部分に関しては以前各ゲーム会社のTAで対談させていただいた以下の記事内でも深く触れています。</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="カプコン・セガゲームス・バンダイナムコスタジオ 3社TA座談会(前編)>>TAの仕事の「今」と「これから」 | 特集 | CGWORLD.jp" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcgworld.jp%2Ffeature%2F201811-ta1.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cgworld.jp/feature/201811-ta1.html">cgworld.jp</a></cite></p> <p>ざっと斜め読みしただけでも1日にいろんな事が起き、いろんなタスクをこなしています。<br />専門知識を持って各所のミーティングに参加し、情報共有ができる身軽さ。これが無いとTAは回っていかないという事がなんとなく読み取れますでしょうか?</p> <p>また、本当に細かいことでも1時間単位でもどんな問い合わせ、作業があり、どういう事を行ったかというログを記録しておくことはとても重要です。多くのタスクを同時にこなしていると、普段何をやっているか分からないと言われることがありますし、自分自身もよく分からなくなることも多々あります。</p> <h3 id="具体的にどんな効率化が出来たの">具体的にどんな効率化が出来たの?</h3> <p>普段の仕事は個人単位、チーム単位様々ですが、ここでは個人単位の割と簡単で良くある実例をあげて解説します。<br />対応時期が古いものもあるので現在ではまた違った手法もあるかもしれませんが・・・。</p> <h4 id="Photoshop効率化">Photoshop効率化</h4> <p><相談内容>Photoshopで多くのアイコンなどのパターン画像を作成して、一つ一つのアイコンをレイヤーセットで管理しています。そのデザイナーはレイヤーセットを必要なものだけ表示させ、別名でPNGに保存を手作業でレイヤーセット分だけやろうとしていました。その数60枚ほど。修正の度に毎回その作業をするのは地獄です。</p> <p><対応>メニューから選ぶだけで所定のフォルダにレイヤーセット毎の画像を保存する、スクリプトを作成して提供しました。<strong>30分〜1時間を予定していた作業が1分弱</strong>で終わるようになりました。</p> <p>Photoshopだけに関わらず、3D用のツール以外の効率化作業は細かい単位で割とよく発生します。こういう処理をその場その場でサクッと作ってしまうといったような対応をTAには求められます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190429160108p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190429/20190429160108.png" alt="f:id:sgtech:20190429160108p:plain" /></p> <h4 id="座標系を超えろ3Dツール間コンバート">座標系を超えろ!?3Dツール間コンバート</h4> <p><相談内容>過去に3dsMaxでキャラクターデータ、XSIでモーションデータを作っていてその二つのデータをMayaで融合させ、ゲームエンジンへ持って行きたいが、アニメーションが合わない。</p> <p><対応>キャラとアニメーションが合わない原因は3dsMaxとXSIの座標系と大きさの単位の違いの問題が絡み合っていました。キャラのコンバートは3体のみだったので一つ一つ対応。アニメーション数がそれなりにあるということで、"SEGA BatchFramework"<a href="#f-b863c307" name="fn-b863c307" title="Maya,SoftimaeXSI,3dsMax用に作られた自動化フロー作成ツール※詳細は次を参照 cedil.cesa.or.jp ">*3</a>の仕組みでワークフローを自動化。手作業でコンバートするつもりだったアニメーションデータをボタン一つで対応可能に。<strong>1体1分程度の手作業を10秒位に短縮。また、検証作業自体もある程度短縮。</strong></p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="上記事例の座標の違い"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190429162908p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190429/20190429162908.png" alt="f:id:sgtech:20190429162908p:plain" /></p> <figcaption>上記事例の座標の違い</figcaption> </figure> <h4 id="横断サポートの強み">横断サポートの強み</h4> <p><相談内容>プロジェクトAからもらったデータを流用しようとしているプロジェクトB、この2プロジェクト間では使っているゲームエンジンが違いデータの整合性が取れずお互いがお互いのエンジンの事情も知らない。</p> <p><対応>プロジェクトAのサポートをしたことがあるTAがどうやってデータを変換すれば欲しいフォーマットになるのかを検証し、自動化フローまで製作。<strong>検証時間の削減と変換時間の短縮。そもそも変換が出来なかったら</strong><strong>目コピで一から作っていたかもしれない・・・。</strong></p> <p>TAはセガゲームスの場合複数のプロジェクトやパートに対してワークフロー、パイプラインの構築を手伝ったりします。<br />その性質上、各プロジェクトやパートのデータ事情に詳しくなり、自然にプロジェクト間の架け橋を担うようになります。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190502204737p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190502/20190502204737.png" alt="f:id:sgtech:20190502204737p:plain" /></p> <h3 id="どんなツールを作成しているの">どんなツールを作成しているの?</h3> <h4 id="ワークフロー構築ツール">ワークフロー構築ツール</h4> <p>効率化をするための個々のツールはたくさん作成していますが、処理内容を詳細に分析していくと、複数のプロジェクトでも共通のオペレーションが存在しています。</p> <p>例えば命名規則だったり、何かをエクスポートする処理だったりといった、フローのプリセット化、オペレーションの共有化を目指して用意しているものの一つが上記に出てきた「SEGA BatchFramework」です。</p> <p>●講演資料からスナップショット</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190505172145p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190505/20190505172145.png" alt="f:id:sgtech:20190505172145p:plain" /></p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190505172248p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190505/20190505172248.png" alt="f:id:sgtech:20190505172248p:plain" /></p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190505172312p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190505/20190505172312.png" alt="f:id:sgtech:20190505172312p:plain" /></p> <p><a href="https://cedil.cesa.or.jp/cedil_sessions/view/1319">CEDEC2015当時の講演資料</a>を見ていただけますとさらに詳しく知ることができると思いますが、このツールの大きな効果は以下の2点です。</p> <ul> <li> <p>処理内容を再利用することにより、ワークフローの自動化を構成する時間を短縮できた。</p> </li> <li> <p>自動化を自分で考えられるようになり、さらに素養がある人の場合は自分でアクションの一つを作るように登録用のスクリプトをVBSやpython、mel、maxScriptなどで作成できるようになった。</p> </li> </ul> <h4 id="データデバッグビューア">データデバッグビューア</h4> <p>過去のBlog記事からの引用となりますが、パイプラインを走っているデータがどういう状態になっているのかを視覚化するためのツールは必要不可欠です。</p> <p>ここまでにいくつか出てきた要件の「データの検証作業」に大きく貢献しています。</p> <p>こういったツールがないと、実際にゲームエンジンで描画されたデータを見て、「もしかしたらこれが間違っているのかもしれない・・・」と推測だけでデータのデバッグをする羽目になります。</p> <p><iframe class="embed-card embed-blogcard" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" title="新卒からのTAが内製ツールに動画撮影機能をつけてみた話 - SEGA TECH Blog" src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Ftechblog.sega.jp%2Fentry%2F2018%2F10%2F25%2F100000" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="http://techblog.sega.jp/entry/2018/10/25/100000">techblog.sega.jp</a></cite></p> <p> </p> <p>これ以外にもこのSEGA Techblogの過去の記事では、セガグループのTAがそれぞれ記事を書いていて、そのツールも紹介しています。</p> <p>是非、過去記事も参考にしてみてください。</p> <p><a href="http://techblog.sega.jp/archive">記事一覧 - SEGA TECH Blog</a></p> <h3 id="TAのプロジェクトへの関わり方は">TAのプロジェクトへの関わり方は?</h3> <p>この図に関しては時代や会社事情により様々ですが、セガゲームスの場合はまず各プロジェクトにTAがそれなりにアサインされていて、その人とのコミュニケーションを密にとる横断型TAチームがあります。</p> <p>基本的にTAはノウハウの共有も担うものですので、プロジェクト担当のTAはプロジェクト内のセクション間に、そして全体横断型のTAチームはプロジェクト間のノウハウの共有に一役買っています。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190421171115p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190421/20190421171115.png" alt="f:id:sgtech:20190421171115p:plain" /></p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190421171133p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190421/20190421171133.png" alt="f:id:sgtech:20190421171133p:plain" /></p> <p>また、TA同士の密な情報共有により、問題解決への対応速度はどんどん上がっていきます。</p> <p>たとえ相談された人が知らなくても、知っていそうなTAに聞けばいいのですから。</p> <h3 id="若手新人TAについて">若手、新人TAについて</h3> <p>採用は右のバナーのリクルートページを参照いただければお分かりだと思いますが、(新卒採用情報→職種紹介)数年前から1年目からTA職を担える人を採用しています。</p> <p>過去にCEDEC等ではTAは<strong>ある程度現場の経験を積まないとなれない</strong>とされてきました。以前はTAの数は少なく、一人で多くの問題に手早く対応しなければいけませんでした。また、迅速な対応を求められるため、ある程度データ制作をしたことがないと本当に困っていることや、もっと全体を見通しての効率化にたどり着くことができなかったのです。</p> <p>ですが今では会社全体を見てもTAは足りないと言われつつもそれなりに増え、役割分担も明確になりつつあります。</p> <p>そういった状況ですので、先人のTAから多くのことを学ぶことができますので、経験不足の壁を埋める速度は懸念事項からは除外されてきつつあります。</p> <p>ゲーム制作未経験なTAはまず、出来るだけデザインワークフローに関わる仕事をすることが多いです。</p> <p>例えば上記データデバッグビューアの項のように、中間ファイルフォーマットのビューアを担当することで、デザイナーはどういうデータを出力しているのかを知ることができます。</p> <p>そして実際にデータを作成しているデザイナーとも出来るだけ接点を作り、要件定義→仕様検討→実装までを一人で対応する機会を設けます。</p> <p>もちろん周囲は全力でこれを助けます。</p> <p>こうして現在も暗中模索の中、TAを育てる取り組みを繰り返しています。</p> <p>この過程ではシニアTAの存在も大きく影響します。もし新人からTAをやらせてみたい場合は、まずはシニアTAの地位確立、立ち回り確保も重要になります。 </p> <p>そうしてTAはアートアセットのパスを主軸にしながらも、必要に応じて各所のパイプをつなぐ役割を担うものです。</p> <p>ゲーム全体や開発全体のパイプ役として日々活躍しています。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190505175520p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190505/20190505175520.png" alt="f:id:sgtech:20190505175520p:plain" /></p> <h3 id="まとめ">まとめ</h3> <p>TAがいる現場といない現場ではデザインワークフローはかなりの差が出ます。</p> <p>アーティストの作業面の<strong>フラストレーションの改善、工数の削減、クリエイティブな作業への注力、そしてノウハウの共有。</strong></p> <p>セクションを超えた円滑なパイプライン構築など。</p> <p>最初の文章では(GCC2019ということもあり)関西圏へ向けてのメッセージとして発信していますが、これは日本のゲーム業界全てに当てはまることだと思います。</p> <p>是非とも"御社"でもTAの採用、育成を推進してみませんか?</p> <p>また、セガゲームスにはこのようにTAが活躍しやすい土壌があります。</p> <p>ゲームを作ることも好きだけど、より作るための効率改善に興味があり、自分の強みを活かせると感じているみなさん。</p> <p>セガゲームスで一緒に働きませんか?</p> <p> </p> <p><a href="http://sega-games.co.jp/recruit/index.html" onmousedown="ga('gtm4.send', 'event', 'recruit', 'games_banner_clicked','recruit_games_out', true);">採用情報 | セガ企業情報サイト</a></p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="採用サイト|株式会社セガ -【SEGA Co., Ltd.】" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fwww.sega.co.jp%2Frecruit%2Findex.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html">www.sega.co.jp</a></cite></p> <p> </p> <p>©️SEGA</p><div class="footnote"> <p class="footnote"><a href="#fn-ed3259ad" name="f-ed3259ad" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">ゲームクリエイターズカンファレンス<a href="http://www.gc-conf.com/">http://www.gc-conf.com/</a></span></p> <p class="footnote"><a href="#fn-c575b5e8" name="f-c575b5e8" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text">GCC2019は関西で開催したカンファレンスということで関西圏向けということになっています。</span></p> <p class="footnote"><a href="#fn-b863c307" name="f-b863c307" class="footnote-number">*3</a><span class="footnote-delimiter">:</span><span class="footnote-text">Maya,SoftimaeXSI,3dsMax用に作られた自動化フロー作成ツール※詳細は次を参照</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="ルーティンワークとさようなら!! 簡単なシステムでデザインデータを改変する方法。" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fcedil.cesa.or.jp%2Fcedil_sessions%2Fview%2F1319" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://cedil.cesa.or.jp/cedil_sessions/view/1319">cedil.cesa.or.jp</a></cite></p> <p></span></p> </div> sgtech Unityで、PBRなライティング環境をセットアップしてみよう hatenablog://entry/17680117127070445339 2019-04-25T10:00:00+09:00 2020-05-29T18:50:14+09:00 window.addEventListener("load", function onLoad() { window.removeEventListener("load", onLoad); var codes = document.querySelectorAll("pre.code"); var len = codes.length; for (var i = 0; i こんにちは。セガ・インタラクティブ技術統括室の大森です。 TAとして、アーケードタイトルにUnityを採用する際の描画設計を お手伝いしています。 Unity5以降、Unityの標準シェーダーにはPBRワークフローが採用さ… <p><script type="text/javascript"> window.addEventListener("load", function onLoad() { window.removeEventListener("load", onLoad); var codes = document.querySelectorAll("pre.code"); var len = codes.length; for (var i = 0; i < len; i++) { (function () { var code = codes[i]; // select all on double click code.addEventListener("dblclick", function () { var range = document.createRange(); range.selectNodeContents(code); var selection = document.getSelection(); selection.removeAllRanges(); selection.addRange(range); }); })(); } }); </script><br /> こんにちは。セガ・インタラクティブ技術統括室の大森です。<br /> TAとして、アーケードタイトルにUnityを採用する際の描画設計を お手伝いしています。</p><br /> <p>Unity5以降、Unityの標準シェーダーにはPBRワークフローが採用されています。アート素材の量産性が高いことから すっかり普及したPBRワークフローですが、その恩恵を受ける為にはフォトリアル系の知識が欠かせません。</p><p>ところで、Unityプロジェクトの初期設定は、旧来シェーダーでの絵作りとも互換性を保つように設定されていて、そのままPBRワークフローを始めると混乱を招く部分があります。社内では この混乱を避ける為、プロジェクト立ち上げ時に、カラースペースやライティング単位を設定しておく事を勧めています。</p><br /> <p>この記事では、ライティング環境のセットアップに使えるシェーダーやスクリプトを共有しつつ、具体的なライティング設定の一例を紹介します。ぜひハンズオンで、自作のモデルやステージデータを使って、試しながら読んで頂けたらと思います。</p><br /> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/k/katsuhiko_omori/20190402/20190402225501.jpg" alt="f:id:katsuhiko_omori:20190402225501j:plain" title="f:id:katsuhiko_omori:20190402225501j:plain" class="hatena-fotolife" itemprop="image"></span><br /> <span style="font-size: 104%;color: #304252">このスクリーンショットで、ターゲットとした屋外ライティング環境は以下のようになります。</span></p> <table> <tr> <th>太陽に直交した面に 入ってくる光の量(照度)</th> <td>太陽から <b>85,000</b></td> <td>青空(半球)から <b>20,000</b></td> <td>合計    <b>105,000</b></td> <td>[lux]</td> </tr> <tr> <th>太陽の傾斜角が66.6度。水平地面に 入ってくる光の量(照度)</th> <td>太陽から <b>78,000</b></td> <td>青空(半球)から <b>20,000</b></td> <td>合計    <b>98,000</b></td> <td>[lux]</td> </tr> <tr> <th>この環境に照らされたグレー18.42%地面の明るさ(輝度)</th> <td> </td> <td>青空から=日陰   <b>1,173</b></td> <td>合計=日向    <b>5,747</b></td> <td>[nt]</td> </tr> <tr> <th>青空の明るさ(輝度)</th> <td> </td> <td> </td> <td>平均     <b>6,366</b></td> <td>[nt]</td> </tr> <tr> <th></th> <td> </td> <td> </td> <td>白い雲    <b>10,000</b></td> <td>[nt]</td> </tr> <tr> <th></th> <td> </td> <td> </td> <td>水平線    <b>8,000</b></td> <td>[nt]</td> </tr> <tr> <th></th> <td> </td> <td> </td> <td>青い空    <b>4,000</b></td> <td>[nt]</td> </tr> <tr> <th></th> <td> </td> <td> </td> <td>天頂部    <b>1,500</b></td> <td>[nt]</td> </tr> <tr> <th>カメラの露出補正(EV100準拠の絶対補正値)</th> <td> </td> <td> </td> <td><b>15</b></td> <td>[EV]</td> </tr> </table><p><span style="font-size: 104%;color: #304252">…これが常に正しい値!という訳ではなく、現実にありうる値の一例として。</BR>この環境をセットアップしていきます。</span></p><br /> <p></p> <ul class="table-of-contents"> <li><a href="#Unityプロジェクトを作成する">Unityプロジェクトを作成する</a><ul> <li><a href="#必要なパッケージをインストールする">必要なパッケージをインストールする</a></li> <li><a href="#SEGA-TECH-Blogからスクリプトをインポートする">SEGA TECH Blogからスクリプトをインポートする</a></li> </ul> </li> <li><a href="#マテリアルカラーの測定">マテリアルカラーの測定</a><ul> <li><a href="#マテリアルを作る">マテリアルを作る</a></li> <li><a href="#マテリアルカラーを測定する">マテリアルカラーを測定する</a></li> <li><a href="#カラースペースを変更する">カラースペースを変更する</a></li> </ul> </li> <li><a href="#ライトカラーの測定">ライトカラーの測定</a><ul> <li><a href="#ライトカラーを計測する">ライトカラーを計測する</a></li> <li><a href="#ライト強度のカラースペースを変更する">ライト強度のカラースペースを変更する</a></li> <li><a href="#ライトの照度と表面の輝度を比較する">ライトの照度と表面の輝度を比較する</a></li> </ul> </li> <li><a href="#太陽の明るさを設定する">太陽の明るさを設定する</a><ul> <li><a href="#屋外環境のシーンデータを用意する">屋外環境のシーンデータを用意する</a></li> <li><a href="#太陽のライトカラーを設定する">太陽のライトカラーを設定する</a></li> <li><a href="#太陽の向きを設定する">太陽の向きを設定する</a></li> </ul> </li> <li><a href="#空の明るさを設定する">空の明るさを設定する</a><ul> <li><a href="#空の輝度を設定する">空の輝度を設定する</a></li> <li><a href="#空の照度を設定する">空の照度を設定する</a></li> </ul> </li> <li><a href="#地面照り返しの明るさを設定する">地面照り返しの明るさを設定する</a><ul> <li><a href="#地面照り返しの照度を設定する">地面照り返しの照度を設定する</a></li> </ul> </li> <li><a href="#カメラの露出を設定する">カメラの露出を設定する</a><ul> <li><a href="#Post-Processingのセットアップ">Post-Processingのセットアップ</a></li> <li><a href="#手動で露出補正する">手動で露出補正する</a></li> <li><a href="#マテリアルにバリエーションを出してみる">マテリアルにバリエーションを出してみる</a></li> <li><a href="#カラーグレーディングにACESを利用する">カラーグレーディングにACESを利用する</a></li> <li><a href="#オートで露出補正する">オートで露出補正する</a></li> </ul> </li> <li><a href="#まとめ">まとめ</a><ul> <li><a href="#つくったライティング環境の活用">つくったライティング環境の活用</a></li> <li><a href="#Standard">Standard</a></li> <li><a href="#LWRP">LWRP</a></li> <li><a href="#HDRP">HDRP</a></li> <li><a href="#Gammaワークフロー全般">Gammaワークフロー全般</a></li> <li><a href="#ライティング環境の求め方">ライティング環境の求め方</a><ul> <li><a href="#屋外の場合">屋外の場合</a></li> <li><a href="#屋内の場合">屋内の場合</a></li> <li><a href="#露出補正値">露出補正値</a></li> <li><a href="#自前のシェーダーに測定機能を付けたい">自前のシェーダーに測定機能を付けたい</a></li> </ul> </li> <li><a href="#みなさんも一緒に働きませんか">みなさんも一緒に働きませんか?</a></li> </ul> </li> </ul><p></br></p> <div class="section"> <h3 id="Unityプロジェクトを作成する"><span style="color: #607075">Unityプロジェクトを作成する</span></h3> <p><span style="font-size: 104%;color: #304252">今回のハンズオンは、Unity2018.3以降に対応しています。<a href="#f-262ea02b" name="fn-262ea02b" title="Unity2019.1では Global Illminationの初期設定が変更された為、環境ライティング系の調整結果が Blogと異なる値に落ち着く。また、Unity2018.2以前のバージョンでは、シェーダー内の Core RP Libraryへのパスを書き換える必要がある。">*1</a><br /> 標準の フォワードレンダリング+HDRカメラ設定を、そのまま使用して進めます。<br /> ポスプロにはPost Processing V2を、シェーダー内部のライブラリとしてCore RP Libraryも利用します。</span></p><p><span style="font-size: 104%;color: #304252">まずは、新しいプロジェクトを作り、必要なパッケージとスクリプトをインストールしましょう。</span></p> <div class="section"> <h4 id="必要なパッケージをインストールする">必要なパッケージをインストールする</h4> <ol> <li>Unityを起動し、プロジェクトを新規作成。Templateは3Dにする</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122620.gif" alt="f:id:sgtech:20190422122620g:plain" title="f:id:sgtech:20190422122620g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>PostProcessingとRender-Pipelines.Coreのパッケージをインストールする <ul> <li>パッケージマネージャ ウィンドウを開く<span style="color: #ff7200"> Window > Package Manager</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122817.gif" alt="f:id:sgtech:20190422122817g:plain" title="f:id:sgtech:20190422122817g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Advanced > Show Preview Packages をオンにして プレビューパッケージを表示する</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122815.gif" alt="f:id:sgtech:20190422122815g:plain" title="f:id:sgtech:20190422122815g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>PostProcessingをインストールする</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122813.gif" alt="f:id:sgtech:20190422122813g:plain" title="f:id:sgtech:20190422122813g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Render-Pipelines.Coreをインストールする</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122811.gif" alt="f:id:sgtech:20190422122811g:plain" title="f:id:sgtech:20190422122811g:plain" class="hatena-fotolife" itemprop="image"></span></li> </ul></li> </ol><p></BR></p> </div> <div class="section"> <h4 id="SEGA-TECH-Blogからスクリプトをインポートする">SEGA TECH Blogからスクリプトをインポートする</h4> <p><div style="border:1px solid #F06040;padding:6px;border-radius:10px;width : 80%;"><span style="font-size: 85%;color: #F06040">…すみません、このBlog、スクリプトファイルを直接添付することが 出来ません。</BR>お手数おかけしますが、以下3つのスクリプトを テキストファイルに コピペ, 保存し、</BR>Unityプロジェクトにインポートしてご利用ください。</span></div></p> <ol> <li>それぞれの、▼<span style="color: #1d4c86"><b>ファイル名</b></span> をクリックして、コード内容を表示</li> <li>表示された<b>コードをダブルクリックすると全文選択</b>されるので、右クリック>コピーする</li> <li>メモ帳に コードをペーストし、それぞれ指定のファイル名で、Unityプロジェクトの Assetsフォルダ内へ保存する</li> </ol><p><details><summary><span style="color: #1d4c86"><b>litColorSpace.cs</b></span></summary></p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synStatement">using</span> UnityEditor; <span class="synStatement">using</span> UnityEditor.SceneManagement; <span class="synStatement">using</span> UnityEngine; <span class="synStatement">using</span> UnityEngine.Rendering; <span class="synType">namespace</span> SegaTechBlog { <span class="synType">public</span> <span class="synType">class</span> litColorSpace : MonoBehaviour { <span class="synPreProc">#if UNITY_EDITOR</span> [MenuItem(<span class="synConstant">&quot;SegaTechBlog/LightsIntensity/Linear&quot;</span>)] <span class="synType">private</span> <span class="synType">static</span> <span class="synType">void</span> luliTrue() { GraphicsSettings.lightsUseLinearIntensity = <span class="synConstant">true</span>; EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo(); var scn = EditorSceneManager.GetSceneManagerSetup(); EditorSceneManager.OpenScene(scn[<span class="synConstant">0</span>].path); } [MenuItem(<span class="synConstant">&quot;SegaTechBlog/LightsIntensity/Gamma&quot;</span>)] <span class="synType">private</span> <span class="synType">static</span> <span class="synType">void</span> luliFalse() { GraphicsSettings.lightsUseLinearIntensity = <span class="synConstant">false</span>; EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo(); var scn = EditorSceneManager.GetSceneManagerSetup(); EditorSceneManager.OpenScene(scn[<span class="synConstant">0</span>].path); } <span class="synPreProc">#endif</span> } } </pre><p></details></p><p><details><summary><span style="color: #1d4c86"><b>litChkLib.hlsl</b></span></summary></p> <pre class="code lang-cs" data-lang="cs" data-unlink><span class="synPreProc">#ifndef SEGATB_CHS_INCLUDED</span> <span class="synPreProc">#define SEGATB_CHS_INCLUDED</span> <span class="synComment">// ------------------------------------------------------------------------------------</span> <span class="synComment">// SEGATB _ COMMON FOR ALL PASS</span> #include <span class="synConstant">&quot;Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl&quot;</span> CBUFFER_START(UnityPerCamera) float4 _Time; float3 _WorldSpaceCameraPos; float4 _ProjectionParams; float4 _ScreenParams; float4 _ZBufferParams; float4 unity_OrthoParams; CBUFFER_END CBUFFER_START(UnityPerCameraRare) float4x4 unity_CameraToWorld; CBUFFER_END CBUFFER_START(UnityLighting) float4 _WorldSpaceLightPos0; float4 unity_4LightPosX0; float4 unity_4LightPosY0; float4 unity_4LightPosZ0; half4 unity_4LightAtten0; half4 unity_LightColor[<span class="synConstant">8</span>]; half4 unity_DynamicLightmap_HDR; CBUFFER_END CBUFFER_START(UnityShadows) float4 unity_LightShadowBias; CBUFFER_END CBUFFER_START(UnityPerDraw) float4x4 unity_ObjectToWorld; float4x4 unity_WorldToObject; float4 unity_LODFade; float4 unity_WorldTransformParams; real4 unity_SpecCube0_HDR; float4 unity_LightmapST; float4 unity_DynamicLightmapST; real4 unity_SHAr; real4 unity_SHAg; real4 unity_SHAb; real4 unity_SHBr; real4 unity_SHBg; real4 unity_SHBb; real4 unity_SHC; CBUFFER_END CBUFFER_START(UnityPerFrame) float4x4 glstate_matrix_projection; float4x4 unity_MatrixV; float4x4 unity_MatrixInvV; float4x4 unity_MatrixVP; CBUFFER_END CBUFFER_START(UnityReflectionProbes) float4 unity_SpecCube0_BoxMax; float4 unity_SpecCube0_BoxMin; float4 unity_SpecCube0_ProbePosition; CBUFFER_END <span class="synPreProc">#define UNITY_MATRIX_M unity_ObjectToWorld</span> <span class="synPreProc">#define UNITY_MATRIX_I_M unity_WorldToObject</span> <span class="synPreProc">#define UNITY_MATRIX_V unity_MatrixV</span> <span class="synPreProc">#define UNITY_MATRIX_I_V unity_MatrixInvV</span> <span class="synPreProc">#define UNITY_MATRIX_P OptimizeProjectionMatrix(glstate_matrix_projection)</span> <span class="synPreProc">#define UNITY_MATRIX_VP unity_MatrixVP</span> #include <span class="synConstant">&quot;Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl&quot;</span> float4x4 OptimizeProjectionMatrix(float4x4 M) { M._21_41 = <span class="synConstant">0</span>; M._12_42 = <span class="synConstant">0</span>; <span class="synStatement">return</span> M; } float3 CheckColorValue(float3 color, <span class="synType">float</span> targetValue, <span class="synType">float</span> targetScale, <span class="synType">float</span> range) { targetValue *= targetScale; <span class="synType">float</span> lum = dot(color, float3(<span class="synConstant">0.2126729</span>, <span class="synConstant">0.7151522</span>, <span class="synConstant">0.072175</span>)); float3 outColor; outColor.g = saturate(max(range - abs(lum - targetValue), <span class="synConstant">0.0</span>) * <span class="synConstant">10000</span>) * <span class="synConstant">1.2</span>; <span class="synComment">// just in range</span> outColor.r = saturate(max(lum - targetValue + range, <span class="synConstant">0.0</span>) * <span class="synConstant">10000</span>) - outColor.g * <span class="synConstant">0.5</span>; <span class="synComment">// over range</span> outColor.b = saturate(max(targetValue - lum + range, <span class="synConstant">0.0</span>) * <span class="synConstant">10000</span>) - outColor.g * <span class="synConstant">0.5</span>; <span class="synComment">// under range</span> <span class="synType">float</span> rhythm = sin(lum / targetScale * <span class="synConstant">10.0</span> + _Time.w) * <span class="synConstant">0.35</span>; outColor.g += <span class="synConstant">0.123</span>; <span class="synStatement">return</span> outColor * (<span class="synConstant">0.65</span> + rhythm); } <span class="synComment">// ------------------------------------------------------------------------------------</span> <span class="synComment">//</span> <span class="synPreProc">#ifdef SEGATB_FORWARD</span> #include <span class="synConstant">&quot;Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl&quot;</span> #include <span class="synConstant">&quot;Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonLighting.hlsl&quot;</span> #include <span class="synConstant">&quot;Packages/com.unity.render-pipelines.core/ShaderLibrary/BSDF.hlsl&quot;</span> #include <span class="synConstant">&quot;Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl&quot;</span> #include <span class="synConstant">&quot;Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl&quot;</span> <span class="synType">float</span> _ChkTargetValue, _ChkTargetScale, _ChkRange; half4 _LightColor0; UNITY_INSTANCING_BUFFER_START(PerInstance) UNITY_DEFINE_INSTANCED_PROP(float4, _AlbedoColor) UNITY_DEFINE_INSTANCED_PROP(<span class="synType">float</span>, _Metallic) UNITY_DEFINE_INSTANCED_PROP(<span class="synType">float</span>, _Anisotropy) UNITY_DEFINE_INSTANCED_PROP(<span class="synType">float</span>, _Smoothness) UNITY_DEFINE_INSTANCED_PROP(<span class="synType">float</span>, _EmitIntensity) UNITY_INSTANCING_BUFFER_END(PerInstance) TEXTURE2D_SHADOW(_ShadowMapTexture); SAMPLER(sampler_ShadowMapTexture); TEXTURECUBE(unity_SpecCube0); SAMPLER(samplerunity_SpecCube0); TEXTURE2D(unity_Lightmap); SAMPLER(samplerunity_Lightmap); TEXTURE2D(unity_LightmapInd); TEXTURE2D(unity_DynamicLightmap); SAMPLER(samplerunity_DynamicLightmap); TEXTURE2D(unity_DynamicDirectionality); TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); TEXTURE2D(_MetallicGlossMap); SAMPLER(sampler_MetallicGlossMap); TEXTURE2D(_NormalMap); SAMPLER(sampler_NormalMap); <span class="synComment">// ------------------------------------------------------------------</span> <span class="synType">struct</span> VertexInput { float4 posOS : POSITION; float3 normalOS : NORMAL; float4 tangentOS : TANGENT; float4 uv0 : TEXCOORD0; float2 uvLM : TEXCOORD1; float2 uvDLM : TEXCOORD2; float4 vColor : COLOR; UNITY_VERTEX_INPUT_INSTANCE_ID }; <span class="synType">struct</span> VertexOutput { float4 posCS : SV_POSITION; float4 uv : TEXCOORD0; float4 tangentToWorldAndPosWS[<span class="synConstant">3</span>] : TEXCOORD1; float3 viewDirWS : TEXCOORD4; float4 posNDC : TEXCOORD5; float4 ambientOrLightmapUV : TEXCOORD6; UNITY_VERTEX_INPUT_INSTANCE_ID }; <span class="synType">struct</span> GeometrySTB { float3 posWS; float3 verNormalWS; float3 normalWS; float3 tangentWS; float3 binormalWS; }; <span class="synType">struct</span> CameraSTB { float3 posWS; float3 dirWS; <span class="synType">float</span> distanceWS; float2 pixelPosSCS; }; <span class="synType">struct</span> LightSTB { float3 dirWS; float3 color; <span class="synType">float</span> atten; }; <span class="synType">struct</span> SubLightsGeometrySTB { float3 lightVectorWS[<span class="synConstant">4</span>]; <span class="synType">float</span> distanceSqr[<span class="synConstant">4</span>]; <span class="synType">float</span> lightAtten[<span class="synConstant">4</span>]; }; <span class="synType">struct</span> MaterialSTB { float3 albedoColor; float3 reflectColor; <span class="synType">float</span> grazingTerm; <span class="synType">float</span> alpha; <span class="synType">float</span> perceptualRoughness; float2 anisoRoughness; <span class="synType">float</span> surfaceReduction; <span class="synType">float</span> microOcclusion; float3 emitColor; float3 testValue; <span class="synType">float</span> reflectOneForTest; }; <span class="synType">struct</span> LitParamPerViewSTB { <span class="synType">float</span> specOcclusion; <span class="synType">float</span> NdotV; <span class="synType">float</span> envRefl_fv; float3 reflViewWS; <span class="synType">float</span> partLambdaV; }; <span class="synType">struct</span> LitParamPerLightSTB { float3 specularColor; float3 diffuseColor; float3 testValue; }; <span class="synType">struct</span> LitParamPerEnvironmentSTB { float3 reflectColor; float3 diffuseColor; float3 testValue; }; float4 GetPosNDC(float4 posCS) { float4 posNDC; float4 ndc = posCS * <span class="synConstant">0.5f</span>; posNDC.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w; posNDC.zw = posCS.zw; <span class="synStatement">return</span> posNDC; } <span class="synType">float</span> F_Pow5(<span class="synType">float</span> u) { <span class="synType">float</span> x = <span class="synConstant">1.0</span> - u; <span class="synType">float</span> x2 = x * x; <span class="synType">float</span> x5 = x * x2 * x2; <span class="synStatement">return</span> x5; } float3 BoxProjectedCubemapDirection(float3 reflViewWS, float3 posWS, float4 cubemapCenter, float4 boxMin, float4 boxMax) { UNITY_BRANCH <span class="synStatement">if</span> (cubemapCenter.w &gt; <span class="synConstant">0.0</span>) { float3 nrdir = normalize(reflViewWS); float3 rbmax = (boxMax.xyz - posWS) / nrdir; float3 rbmin = (boxMin.xyz - posWS) / nrdir; float3 rbminmax = (nrdir &gt; <span class="synConstant">0.0f</span>) ? rbmax : rbmin; <span class="synType">float</span> fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z); posWS -= cubemapCenter.xyz; reflViewWS = posWS + nrdir * fa; } <span class="synStatement">return</span> reflViewWS; } <span class="synComment">// ------------------------------------------------------------------</span> GeometrySTB GetGeometry(VertexOutput input, float2 uv) { GeometrySTB output; output.posWS = float3(input.tangentToWorldAndPosWS[<span class="synConstant">0</span>].w, input.tangentToWorldAndPosWS[<span class="synConstant">1</span>].w, input.tangentToWorldAndPosWS[<span class="synConstant">2</span>].w); float3 verTangentWS = input.tangentToWorldAndPosWS[<span class="synConstant">0</span>].xyz; float3 verBinormalWS = input.tangentToWorldAndPosWS[<span class="synConstant">1</span>].xyz; output.verNormalWS = normalize(input.tangentToWorldAndPosWS[<span class="synConstant">2</span>].xyz); <span class="synPreProc">#ifdef _NORMALMAP</span> half4 normalMap = SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, uv); float3 normalMapTS; normalMapTS.xy = normalMap.wy *<span class="synConstant">2.0</span> - <span class="synConstant">1.0</span>; normalMapTS.z = sqrt(<span class="synConstant">1.0</span> - saturate(dot(normalMapTS.xy, normalMapTS.xy))); output.normalWS = normalize(verTangentWS * normalMapTS.x + verBinormalWS * normalMapTS.y + output.verNormalWS * normalMapTS.z); output.tangentWS = normalize(verTangentWS - dot(verTangentWS, output.normalWS) * output.normalWS); float3 newBB = cross(output.normalWS, output.tangentWS); output.binormalWS = newBB * FastSign(dot(newBB, verBinormalWS)); <span class="synPreProc">#else</span> output.normalWS = output.verNormalWS; output.tangentWS = normalize(verTangentWS); output.binormalWS = normalize(verBinormalWS); <span class="synPreProc">#endif</span> <span class="synStatement">return</span> output; } CameraSTB GetCamera(VertexOutput input, GeometrySTB geo) { CameraSTB output; output.posWS = _WorldSpaceCameraPos; output.dirWS = normalize(input.viewDirWS); output.distanceWS = LinearEyeDepth(geo.posWS, UNITY_MATRIX_V); output.pixelPosSCS = input.posNDC.xy / input.posNDC.w; <span class="synStatement">return</span> output; } LightSTB GetMainLight(CameraSTB cam) { LightSTB output; <span class="synPreProc">#if defined (DIRECTIONAL) || defined (DIRECTIONAL_COOKIE)</span> <span class="synPreProc"> #if defined(_NOPIDIV) &amp;&amp; !defined(_VSUN_LIGHT_COLOR) &amp;&amp; !defined(_VPOINT_LIGHT_COLOR)</span> output.color = _LightColor0.rgb *PI; <span class="synPreProc"> #else</span> output.color = _LightColor0.rgb; <span class="synPreProc"> #endif</span> half atten = <span class="synConstant">1.0</span>; <span class="synPreProc"> #if defined(SHADOWS_SCREEN)</span> atten = SAMPLE_TEXTURE2D(_ShadowMapTexture, sampler_ShadowMapTexture, cam.pixelPosSCS).x; <span class="synPreProc"> #endif</span> output.atten = atten; output.dirWS = _WorldSpaceLightPos0.xyz; <span class="synPreProc">#else</span> output.color = <span class="synConstant">0</span>; output.atten = <span class="synConstant">0</span>; output.dirWS = float3(<span class="synConstant">0</span>,<span class="synConstant">0</span>,<span class="synConstant">1</span>); <span class="synPreProc">#endif</span> <span class="synStatement">return</span> output; } SubLightsGeometrySTB GetSubLightsGeometry(GeometrySTB geo) { SubLightsGeometrySTB output; float4 toLightX = unity_4LightPosX0 - geo.posWS.x; float4 toLightY = unity_4LightPosY0 - geo.posWS.y; float4 toLightZ = unity_4LightPosZ0 - geo.posWS.z; float4 distanceSqr = <span class="synConstant">0.0</span>; distanceSqr += toLightX * toLightX; distanceSqr += toLightY * toLightY; distanceSqr += toLightZ * toLightZ; output.lightVectorWS[<span class="synConstant">0</span>] = float3(toLightX.x, toLightY.x, toLightZ.x); output.lightVectorWS[<span class="synConstant">1</span>] = float3(toLightX.y, toLightY.y, toLightZ.y); output.lightVectorWS[<span class="synConstant">2</span>] = float3(toLightX.z, toLightY.z, toLightZ.z); output.lightVectorWS[<span class="synConstant">3</span>] = float3(toLightX.w, toLightY.w, toLightZ.w); output.distanceSqr[<span class="synConstant">0</span>] = distanceSqr.x; output.distanceSqr[<span class="synConstant">1</span>] = distanceSqr.y; output.distanceSqr[<span class="synConstant">2</span>] = distanceSqr.z; output.distanceSqr[<span class="synConstant">3</span>] = distanceSqr.w; output.lightAtten[<span class="synConstant">0</span>] = unity_4LightAtten0.x; output.lightAtten[<span class="synConstant">1</span>] = unity_4LightAtten0.y; output.lightAtten[<span class="synConstant">2</span>] = unity_4LightAtten0.z; output.lightAtten[<span class="synConstant">3</span>] = unity_4LightAtten0.w; <span class="synStatement">return</span> output; } LightSTB GetSubLight(<span class="synType">uint</span> index, SubLightsGeometrySTB subLightsGeo) { LightSTB output; <span class="synPreProc">#if defined(_NOPIDIV) &amp;&amp; !defined(_VSUN_LIGHT_COLOR) &amp;&amp; !defined(_VPOINT_LIGHT_COLOR)</span> output.color = unity_LightColor[index].xyz * PI; <span class="synPreProc">#else</span> output.color = unity_LightColor[index].xyz; <span class="synPreProc">#endif</span> UNITY_BRANCH <span class="synStatement">if</span> ((output.color.r + output.color.g + output.color.b) != <span class="synConstant">0.0</span>) { <span class="synType">float</span> distanceSqr = max(subLightsGeo.distanceSqr[index], (PUNCTUAL_LIGHT_THRESHOLD * PUNCTUAL_LIGHT_THRESHOLD)); <span class="synPreProc">#if defined(_NOPIDIV)</span> output.atten = <span class="synConstant">1.0</span> / (<span class="synConstant">1.0</span> + distanceSqr * subLightsGeo.lightAtten[index]); <span class="synPreProc">#else</span> <span class="synType">float</span> invDistanceSqr = <span class="synConstant">1.0</span> / distanceSqr; <span class="synType">float</span> lightAttenFactor = distanceSqr * subLightsGeo.lightAtten[index] * <span class="synConstant">0.04</span>; lightAttenFactor *= lightAttenFactor; lightAttenFactor = saturate(<span class="synConstant">1.0</span> - lightAttenFactor); lightAttenFactor *= lightAttenFactor; output.atten = max(invDistanceSqr * lightAttenFactor, <span class="synConstant">0.0</span>); <span class="synPreProc">#endif</span> output.dirWS = SafeNormalize(subLightsGeo.lightVectorWS[index]); } <span class="synStatement">else</span> { output.atten = <span class="synConstant">0.0</span>; output.dirWS = float3(<span class="synConstant">0</span>,<span class="synConstant">0</span>,<span class="synConstant">1</span>); } <span class="synStatement">return</span> output; } MaterialSTB GetMaterial(float2 uv) { MaterialSTB output; half4 colParams = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv); half4 matParams = SAMPLE_TEXTURE2D(_MetallicGlossMap, sampler_MetallicGlossMap, uv); float4 matColor = UNITY_ACCESS_INSTANCED_PROP(PerInstance, _AlbedoColor); <span class="synType">float</span> metallic = UNITY_ACCESS_INSTANCED_PROP(PerInstance, _Metallic); <span class="synType">float</span> anisotropy = UNITY_ACCESS_INSTANCED_PROP(PerInstance, _Anisotropy); <span class="synType">float</span> smoothness = UNITY_ACCESS_INSTANCED_PROP(PerInstance, _Smoothness); <span class="synType">float</span> emmision = UNITY_ACCESS_INSTANCED_PROP(PerInstance, _EmitIntensity); <span class="synType">float</span> occlusion = <span class="synConstant">1.0</span>; <span class="synPreProc">#ifdef _COLMAP</span> matColor *= colParams; <span class="synPreProc">#endif</span> <span class="synPreProc">#ifdef _METMAP</span> metallic *= matParams.x; <span class="synPreProc">#endif</span> <span class="synPreProc">#ifdef _OCCMAP</span> occlusion *= matParams.y; <span class="synPreProc">#endif</span> <span class="synPreProc">#ifdef _SMTMAP</span> smoothness *= matParams.w; <span class="synPreProc">#endif</span> <span class="synType">float</span> oneMinusReflectivity = (<span class="synConstant">1.0</span> - metallic) * <span class="synConstant">0.96</span>; output.albedoColor = matColor.rgb * oneMinusReflectivity; output.reflectColor = lerp(half3(<span class="synConstant">0.04</span>, <span class="synConstant">0.04</span>, <span class="synConstant">0.04</span>), matColor.rgb, metallic); output.grazingTerm = saturate(smoothness + (<span class="synConstant">1.0</span> - oneMinusReflectivity)); output.alpha = matColor.a; output.perceptualRoughness = PerceptualSmoothnessToPerceptualRoughness(smoothness); ConvertAnisotropyToRoughness(output.perceptualRoughness, anisotropy, output.anisoRoughness.x, output.anisoRoughness.y); output.anisoRoughness.x = max(output.anisoRoughness.x, <span class="synConstant">0.0005</span>); output.anisoRoughness.y = max(output.anisoRoughness.y, <span class="synConstant">0.0005</span>); output.surfaceReduction = <span class="synConstant">1.0</span> / (output.perceptualRoughness * output.perceptualRoughness + <span class="synConstant">1.0</span>); output.microOcclusion = occlusion; output.emitColor = matColor.rgb * emmision; <span class="synPreProc">#if defined(_VMAT_COLOR)</span> output.testValue = matColor.rgb; <span class="synPreProc">#elif defined(_VMAT_DIFFUSE_COLOR)</span> output.testValue = output.albedoColor; <span class="synPreProc">#elif defined(_VMAT_METALLIC)</span> output.testValue = metallic; <span class="synPreProc">#elif defined(_VMAT_SMOOTHNESS)</span> output.testValue = smoothness; <span class="synPreProc">#elif defined(_VMAT_OCCLUSION)</span> output.testValue = occlusion; <span class="synPreProc">#else</span> output.testValue = <span class="synConstant">0</span>; <span class="synPreProc">#endif</span> output.reflectOneForTest = lerp(<span class="synConstant">0.04</span>, <span class="synConstant">1.0</span>, metallic); <span class="synStatement">return</span> output; } LitParamPerViewSTB GetLitParamPerView(GeometrySTB geo, CameraSTB cam, MaterialSTB mat) { LitParamPerViewSTB output; output.specOcclusion = GetHorizonOcclusion(cam.dirWS, geo.normalWS, geo.verNormalWS, <span class="synConstant">0.8</span>); output.NdotV = ClampNdotV(dot(geo.normalWS, cam.dirWS)); output.envRefl_fv = F_Pow5(saturate(output.NdotV)); output.reflViewWS = reflect(-cam.dirWS, geo.normalWS); <span class="synType">float</span> TdotV = dot(geo.tangentWS, cam.dirWS); <span class="synType">float</span> BdotV = dot(geo.binormalWS, cam.dirWS); output.partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, output.NdotV, mat.anisoRoughness.x, mat.anisoRoughness.y); <span class="synStatement">return</span> output; } LitParamPerLightSTB GetLitByTheLight(GeometrySTB geo, CameraSTB cam, MaterialSTB mat, LitParamPerViewSTB lip, LightSTB theLight) { LitParamPerLightSTB output; <span class="synType">float</span> NdotL = dot(geo.normalWS, theLight.dirWS); <span class="synPreProc">#if defined(_VSUN__) &amp;&amp; defined(_VPOINT__)</span> UNITY_BRANCH <span class="synStatement">if</span> (NdotL &gt; <span class="synConstant">0.0</span>) { <span class="synPreProc">#endif</span> float3 halfDir = SafeNormalize(theLight.dirWS + cam.dirWS); <span class="synType">float</span> LdotV = dot(theLight.dirWS, cam.dirWS); <span class="synType">float</span> NdotH = dot(geo.normalWS, halfDir); <span class="synType">float</span> LdotH = dot(theLight.dirWS, halfDir); <span class="synType">float</span> TdotL = dot(geo.tangentWS, theLight.dirWS); <span class="synType">float</span> BdotL = dot(geo.binormalWS, theLight.dirWS); <span class="synType">float</span> TdotH = dot(geo.tangentWS, halfDir); <span class="synType">float</span> BdotH = dot(geo.binormalWS, halfDir); <span class="synType">float</span> spec_fv = F_Pow5(saturate(LdotH)); <span class="synType">float</span> occlusion = ComputeMicroShadowing(mat.microOcclusion * <span class="synConstant">1.6</span> +<span class="synConstant">0.2</span>, NdotL, <span class="synConstant">1.0</span>); float3 occlusionCol = GTAOMultiBounce(occlusion, mat.albedoColor); <span class="synType">float</span> specTermD = D_GGXAniso(TdotH, BdotH, NdotH, mat.anisoRoughness.x, mat.anisoRoughness.y); <span class="synType">float</span> specTermG = V_SmithJointGGXAniso(<span class="synConstant">0</span>, <span class="synConstant">0</span>, lip.NdotV, TdotL, BdotL, NdotL, mat.anisoRoughness.x, mat.anisoRoughness.y, lip.partLambdaV); float3 specTermF = mat.reflectColor + (<span class="synConstant">1</span> - mat.reflectColor) * spec_fv; output.specularColor = (specTermD * specTermG * saturate(NdotL) * theLight.atten * occlusion * lip.specOcclusion) * specTermF * theLight.color; <span class="synType">float</span> diffuseTerm = DisneyDiffuse(lip.NdotV, NdotL, LdotV, mat.perceptualRoughness); output.diffuseColor = (diffuseTerm * saturate(NdotL) * theLight.atten * occlusionCol) * theLight.color; <span class="synPreProc">#if defined(_VSUN_LIGHT_COLOR) || defined(_VPOINT_LIGHT_COLOR)</span> output.testValue = theLight.color; <span class="synPreProc">#elif defined(_VSUN_LIGHT_ILLUMINANCE) || defined(_VPOINT_LIGHT_ILLUMINANCE) || defined(_VGET_TOTAL_ILLUMINANCE)</span> output.testValue = theLight.color *saturate(NdotL) * theLight.atten * occlusion; <span class="synPreProc">#elif defined(_VSUN_SHADE_LAMBERT) || defined(_VPOINT_SHADE_LAMBERT)</span> output.testValue = theLight.color *saturate(NdotL) * theLight.atten * occlusion *INV_PI; <span class="synPreProc">#elif defined(_VSUN_SHADE_SPECULAR) || defined(_VPOINT_SHADE_SPECULAR) || defined(_VGET_TOTAL_REFLECTION)</span> output.testValue = (specTermD * specTermG * saturate(NdotL) * theLight.atten * occlusion * lip.specOcclusion) * (mat.reflectOneForTest + (<span class="synConstant">1</span> - mat.reflectOneForTest) * spec_fv) * theLight.color; <span class="synPreProc">#elif defined(_VSUN_SHADE_SPEC_DGF) || defined(_VPOINT_SHADE_SPEC_DGF)</span> output.testValue.r = specTermD; output.testValue.g = specTermG; output.testValue.b = specTermF; <span class="synPreProc">#elif defined(_VSUN_SHADE_SPEC_D) || defined(_VPOINT_SHADE_SPEC_D)</span> output.testValue = specTermD; <span class="synPreProc">#elif defined(_VSUN_SHADE_SPEC_G) || defined(_VPOINT_SHADE_SPEC_G)</span> output.testValue = specTermG; <span class="synPreProc">#elif defined(_VSUN_SHADE_SPEC_F) || defined(_VPOINT_SHADE_SPEC_F)</span> output.testValue = mat.reflectOneForTest + (<span class="synConstant">1</span> - mat.reflectOneForTest) * spec_fv; <span class="synPreProc">#else</span> output.testValue = <span class="synConstant">0</span>; <span class="synPreProc">#endif</span> <span class="synPreProc">#if defined(_VSUN__) &amp;&amp; defined(_VPOINT__)</span> } <span class="synStatement">else</span> { output.specularColor = <span class="synConstant">0.0</span>; output.diffuseColor = <span class="synConstant">0.0</span>; output.testValue = <span class="synConstant">0</span>; } <span class="synPreProc">#endif</span> <span class="synStatement">return</span> output; } LitParamPerEnvironmentSTB GetLitByEnvironment(VertexOutput input, GeometrySTB geo, MaterialSTB mat, LitParamPerViewSTB lip) { LitParamPerEnvironmentSTB output; <span class="synType">float</span> occlusion = ComputeMicroShadowing(mat.microOcclusion * <span class="synConstant">0.8</span> +<span class="synConstant">0.3</span>, lip.NdotV, <span class="synConstant">1.0</span>); float3 occlusionCol = GTAOMultiBounce( saturate(mat.microOcclusion *<span class="synConstant">1.2</span>), mat.albedoColor); <span class="synPreProc">#if defined(LIGHTPROBE_SH)</span> output.diffuseColor = max( SHEvalLinearL0L1(geo.normalWS, unity_SHAr, unity_SHAg, unity_SHAb)+ input.ambientOrLightmapUV.rgb, <span class="synConstant">0.0</span>); <span class="synPreProc">#elif defined(DIRLIGHTMAP_COMBINED)</span> half4 decodeInstructions = half4(LIGHTMAP_HDR_MULTIPLIER, LIGHTMAP_HDR_EXPONENT, <span class="synConstant">0.0</span>h, <span class="synConstant">0.0</span>h); { float4 direction = SAMPLE_TEXTURE2D(unity_LightmapInd, samplerunity_Lightmap, input.ambientOrLightmapUV.xy); float4 encodedIlluminance = SAMPLE_TEXTURE2D(unity_Lightmap, samplerunity_Lightmap, input.ambientOrLightmapUV.xy); float3 illuminance = DecodeLightmap(encodedIlluminance, decodeInstructions); <span class="synType">float</span> halfLambert = dot(geo.normalWS, direction.xyz - <span class="synConstant">0.5</span>) + <span class="synConstant">0.5</span>; output.diffuseColor = illuminance * halfLambert / max(<span class="synConstant">1e-4</span>, direction.w); } <span class="synPreProc"> #if defined(DYNAMICLIGHTMAP_ON)</span> { float4 direction = SAMPLE_TEXTURE2D(unity_DynamicDirectionality, samplerunity_DynamicLightmap, input.ambientOrLightmapUV.zw); float4 encodedIlluminance = SAMPLE_TEXTURE2D(unity_DynamicLightmap, samplerunity_DynamicLightmap, input.ambientOrLightmapUV.zw); float3 illuminance = DecodeLightmap(encodedIlluminance, decodeInstructions); <span class="synType">float</span> halfLambert = dot(geo.normalWS, direction.xyz - <span class="synConstant">0.5</span>) + <span class="synConstant">0.5</span>; output.diffuseColor += illuminance * halfLambert / max(<span class="synConstant">1e-4</span>, direction.w); } <span class="synPreProc"> #endif</span> <span class="synPreProc">#else</span> output.diffuseColor = <span class="synConstant">0.0</span>; <span class="synPreProc">#endif</span> output.diffuseColor *= occlusionCol; <span class="synPreProc">#if defined(UNITY_SPECCUBE_BOX_PROJECTION)</span> float3 reflViewWS = BoxProjectedCubemapDirection(lip.reflViewWS, geo.posWS, unity_SpecCube0_ProbePosition, unity_SpecCube0_BoxMin, unity_SpecCube0_BoxMax); <span class="synPreProc">#else</span> float3 reflViewWS = lip.reflViewWS; <span class="synPreProc">#endif</span> half reflMipLevel = PerceptualRoughnessToMipmapLevel(mat.perceptualRoughness); half4 encodedIrradiance = SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflViewWS, reflMipLevel); <span class="synPreProc">#if !defined(UNITY_USE_NATIVE_HDR)</span> half3 irradiance = DecodeHDREnvironment(encodedIrradiance, unity_SpecCube0_HDR); <span class="synPreProc">#else</span> half3 irradiance = encodedIrradiance.rbg; <span class="synPreProc">#endif</span> output.reflectColor = mat.microOcclusion * mat.surfaceReduction * irradiance * lerp(mat.reflectColor, mat.grazingTerm, lip.envRefl_fv); <span class="synPreProc">#if defined(_VENV_LIGHT_ILLUMINANCE)</span> output.testValue = output.diffuseColor *PI; <span class="synPreProc">#elif defined(_VENV_SHADE_LAMBERT)</span> output.testValue = output.diffuseColor; <span class="synPreProc">#elif defined(_VENV_SHADE_REFLECTION)</span> output.testValue = mat.microOcclusion * mat.surfaceReduction * irradiance * lerp(<span class="synConstant">1.0</span>, mat.grazingTerm, lip.envRefl_fv); <span class="synPreProc">#elif defined(_VMAT_SPECULAR_COLOR)</span> output.testValue = lerp(mat.reflectColor, mat.grazingTerm, lip.envRefl_fv); <span class="synPreProc">#elif defined(_VGET_TOTAL_ILLUMINANCE)</span> output.testValue = output.diffuseColor *PI; <span class="synPreProc">#elif defined(_VGET_TOTAL_REFLECTION)</span> output.testValue = occlusion * mat.surfaceReduction * irradiance; <span class="synPreProc">#else</span> output.testValue = <span class="synConstant">0</span>; <span class="synPreProc">#endif</span> <span class="synStatement">return</span> output; } <span class="synComment">// ------------------------------------------------------------------</span> VertexOutput ChsForwardVertex( VertexInput input) { VertexOutput output; UNITY_SETUP_INSTANCE_ID(input); UNITY_TRANSFER_INSTANCE_ID(input, output); float4 posWS = mul(UNITY_MATRIX_M, float4(input.posOS.xyz, <span class="synConstant">1.0</span>)); output.posCS = mul(UNITY_MATRIX_VP, posWS); float3 camPosWS = _WorldSpaceCameraPos; output.viewDirWS = camPosWS - posWS.xyz; float3 normalWS = normalize( mul( (float3x3) UNITY_MATRIX_M, input.normalOS)); float4 tangentWS = float4( normalize( mul( (float3x3) UNITY_MATRIX_M, input.tangentOS.xyz)), input.tangentOS.w); <span class="synType">float</span> sign = tangentWS.w * unity_WorldTransformParams.w; float3 binormalWS = cross( normalWS, tangentWS.xyz) * sign; float4 ndc = output.posCS * <span class="synConstant">0.5f</span>; output.posNDC.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w; output.posNDC.zw = output.posCS.zw; <span class="synPreProc">#ifdef DIRLIGHTMAP_COMBINED</span> output.ambientOrLightmapUV.xy = input.uvLM.xy * unity_LightmapST.xy + unity_LightmapST.zw; <span class="synPreProc"> #ifdef DYNAMICLIGHTMAP_ON</span> output.ambientOrLightmapUV.zw = input.uvDLM.xy * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; <span class="synPreProc"> #else</span> output.ambientOrLightmapUV.zw = <span class="synConstant">0</span>; <span class="synPreProc"> #endif</span> <span class="synPreProc">#elif LIGHTPROBE_SH</span> output.ambientOrLightmapUV.rgb = SHEvalLinearL2(normalWS, unity_SHBr, unity_SHBg, unity_SHBb, unity_SHC); output.ambientOrLightmapUV.w = <span class="synConstant">0</span>; <span class="synPreProc">#else</span> output.ambientOrLightmapUV = <span class="synConstant">0</span>; <span class="synPreProc">#endif</span> output.uv.xy = input.uv0.xy; output.uv.zw = <span class="synConstant">0</span>; output.tangentToWorldAndPosWS[<span class="synConstant">0</span>].xyz = tangentWS.xyz; output.tangentToWorldAndPosWS[<span class="synConstant">1</span>].xyz = binormalWS; output.tangentToWorldAndPosWS[<span class="synConstant">2</span>].xyz = normalWS; output.tangentToWorldAndPosWS[<span class="synConstant">0</span>].w = posWS.x; output.tangentToWorldAndPosWS[<span class="synConstant">1</span>].w = posWS.y; output.tangentToWorldAndPosWS[<span class="synConstant">2</span>].w = posWS.z; <span class="synStatement">return</span> output; } float4 ChsForwardFragment( VertexOutput input ) : SV_Target { UNITY_SETUP_INSTANCE_ID(input); float2 uv = input.uv.xy; GeometrySTB geo = GetGeometry(input, uv); CameraSTB cam = GetCamera(input, geo); MaterialSTB mat = GetMaterial(uv); LitParamPerViewSTB lip = GetLitParamPerView(geo, cam, mat); LightSTB sun = GetMainLight(cam); LitParamPerLightSTB litSun = GetLitByTheLight(geo, cam, mat, lip, sun); LitParamPerEnvironmentSTB litEnv = GetLitByEnvironment(input, geo, mat, lip); LitParamPerLightSTB litSubLights; litSubLights.diffuseColor = <span class="synConstant">0.0</span>; litSubLights.specularColor = <span class="synConstant">0.0</span>; litSubLights.testValue = <span class="synConstant">0.0</span>; <span class="synPreProc">#ifdef LIGHTPROBE_SH</span> <span class="synPreProc"> #ifdef VERTEXLIGHT_ON</span> SubLightsGeometrySTB subLightsGeo = GetSubLightsGeometry(geo); <span class="synStatement">for</span> (<span class="synType">int</span> i = <span class="synConstant">0</span>; i &lt; <span class="synConstant">3</span>; i++) { LightSTB subLight = GetSubLight(i, subLightsGeo); UNITY_BRANCH <span class="synStatement">if</span> (subLight.atten != <span class="synConstant">0.0</span>) { LitParamPerLightSTB litSubLight = GetLitByTheLight(geo, cam, mat, lip, subLight); litSubLights.diffuseColor += litSubLight.diffuseColor; litSubLights.specularColor += litSubLight.specularColor; litSubLights.testValue += litSubLight.testValue; } } <span class="synPreProc"> #endif</span> <span class="synPreProc">#endif</span> float3 color = ( litSun.diffuseColor + litEnv.diffuseColor + litSubLights.diffuseColor ) * mat.albedoColor + litSun.specularColor + litEnv.reflectColor + litSubLights.specularColor + mat.emitColor; <span class="synType">float</span> alpha = mat.alpha; <span class="synPreProc">#if defined(_VMAT_COLOR) || defined(_VMAT_DIFFUSE_COLOR) || defined(_VMAT_METALLIC) || defined(_VMAT_SMOOTHNESS) || defined(_VMAT_OCCLUSION)</span> color = mat.testValue; <span class="synPreProc">#elif defined(_VGET_TOTAL_ILLUMINANCE) || defined(_VGET_TOTAL_REFLECTION)</span> color = litSun.testValue + litEnv.testValue + litSubLights.testValue; <span class="synPreProc">#elif defined(_VGET_SUN_ONLY)</span> color = litSun.diffuseColor * mat.albedoColor + litSun.specularColor; <span class="synPreProc">#elif defined(_VGET_ENV_ONLY)</span> color = litEnv.diffuseColor * mat.albedoColor + litEnv.reflectColor; <span class="synPreProc">#elif defined(_VGET_POINTLIGHT_ONLY)</span> color = litSubLights.diffuseColor * mat.albedoColor + litSubLights.specularColor; <span class="synPreProc">#elif defined(_VSUN_LIGHT_COLOR) || defined(_VSUN_LIGHT_ILLUMINANCE) || defined(_VSUN_SHADE_LAMBERT) || defined(_VSUN_SHADE_SPECULAR) || defined(_VSUN_SHADE_SPEC_DGF) || defined(_VSUN_SHADE_SPEC_D) || defined(_VSUN_SHADE_SPEC_G) || defined(_VSUN_SHADE_SPEC_F)</span> color = litSun.testValue; <span class="synPreProc">#elif defined(_VENV_LIGHT_ILLUMINANCE) || defined(_VENV_SHADE_LAMBERT) || defined(_VENV_SHADE_REFLECTION) || defined(_VMAT_SPECULAR_COLOR)</span> color = litEnv.testValue; <span class="synPreProc">#elif defined(_VPOINT_LIGHT_COLOR) || defined(_VPOINT_LIGHT_ILLUMINANCE) || defined(_VPOINT_SHADE_LAMBERT) || defined(_VPOINT_SHADE_SPECULAR) || defined(_VPOINT_SHADE_SPEC_DGF) || defined(_VPOINT_SHADE_SPEC_D) || defined(_VPOINT_SHADE_SPEC_G) || defined(_VPOINT_SHADE_SPEC_F)</span> color = litSubLights.testValue; <span class="synPreProc">#endif</span> <span class="synPreProc">#ifdef _CHECKVALUE</span> color = CheckColorValue(color, _ChkTargetValue, _ChkTargetScale, _ChkRange); <span class="synPreProc">#endif</span> <span class="synStatement">return</span> float4(color, alpha); } <span class="synPreProc">#endif </span><span class="synComment">//SEGATB_FORWARD</span> <span class="synComment">// ---------------------------------------------------------------------------</span> <span class="synComment">//</span> <span class="synPreProc">#ifdef SEGATB_SHADOWCASTER</span> <span class="synType">struct</span> VertexInput { float4 posOS : POSITION; float3 normalOS : NORMAL; UNITY_VERTEX_INPUT_INSTANCE_ID }; <span class="synType">struct</span> VertexOutput { float4 posCS : SV_POSITION; }; <span class="synComment">// ------------------------------------------------------------------</span> VertexOutput DepthOnlyVertex(VertexInput input) { VertexOutput output; UNITY_SETUP_INSTANCE_ID(input); float4 posWS = mul(UNITY_MATRIX_M, float4(input.posOS.xyz, <span class="synConstant">1.0</span>)); <span class="synStatement">if</span> (unity_LightShadowBias.z != <span class="synConstant">0.0</span>) { float3 normalWS = normalize(mul((float3x3) UNITY_MATRIX_M, input.normalOS)); float3 lightDirWS = normalize(_WorldSpaceLightPos0.xyz - posWS.xyz * _WorldSpaceLightPos0.w); <span class="synType">float</span> shadowCos = dot(normalWS, lightDirWS); <span class="synType">float</span> shadowSine = sqrt(<span class="synConstant">1</span> - shadowCos * shadowCos); <span class="synType">float</span> normalBias = unity_LightShadowBias.z * shadowSine; posWS.xyz -= normalWS * normalBias; } output.posCS = mul(UNITY_MATRIX_VP, posWS); <span class="synStatement">if</span> (unity_LightShadowBias.y != <span class="synConstant">0.0</span>) { <span class="synPreProc">#ifdef UNITY_REVERSED_Z</span> output.posCS.z += max(-<span class="synConstant">1</span>, min(unity_LightShadowBias.x / output.posCS.w, <span class="synConstant">0</span>)); output.posCS.z = min(output.posCS.z, output.posCS.w * UNITY_NEAR_CLIP_VALUE); <span class="synPreProc">#else</span> output.posCS.z += saturate(unity_LightShadowBias.x / output.posCS.w); output.posCS.z = max(output.posCS.z, output.posCS.w * UNITY_NEAR_CLIP_VALUE); <span class="synPreProc">#endif</span> } <span class="synStatement">return</span> output; } half4 DepthOnlyFragment(VertexOutput input) : SV_TARGET { <span class="synStatement">return</span> <span class="synConstant">0</span>; } <span class="synPreProc">#endif </span><span class="synComment">//SEGATB_SHADOWCASTER</span> <span class="synComment">// ---------------------------------------------------------------------------</span> <span class="synComment">//</span> <span class="synPreProc">#ifdef SEGATB_META</span> float4 _AlbedoColor; <span class="synType">float</span> _Metallic, _EmitIntensity; <span class="synType">float</span> unity_OneOverOutputBoost; <span class="synType">float</span> unity_MaxOutputValue; <span class="synType">float</span> unity_UseLinearSpace; CBUFFER_START(UnityMetaPass) bool4 unity_MetaVertexControl; <span class="synComment">// x = use uv1 as raster position // y = use uv2 as raster position</span> bool4 unity_MetaFragmentControl; <span class="synComment">// x = return albedo // y = return normal</span> CBUFFER_END TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); TEXTURE2D(_MetallicGlossMap); SAMPLER(sampler_MetallicGlossMap); <span class="synComment">// ------------------------------------------------------------------</span> <span class="synType">struct</span> VertexInput { float4 posOS : POSITION; float2 uv0 : TEXCOORD0; float2 uvLM : TEXCOORD1; float2 uvDLM : TEXCOORD2; }; <span class="synType">struct</span> VertexOutput { float4 posCS : SV_POSITION; float4 uv : TEXCOORD0; }; <span class="synType">struct</span> MaterialSTB { float3 albedoColor; float3 emitColor; }; <span class="synComment">// ------------------------------------------------------------------</span> MaterialSTB GetMaterial(float2 uv) { MaterialSTB output; half4 colParams = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, uv); half4 matParams = SAMPLE_TEXTURE2D(_MetallicGlossMap, sampler_MetallicGlossMap, uv); float4 matColor = _AlbedoColor; <span class="synType">float</span> metallic = _Metallic; <span class="synType">float</span> emmision = _EmitIntensity; <span class="synPreProc">#ifdef _COLMAP</span> matColor *= colParams; <span class="synPreProc">#endif</span> <span class="synPreProc">#ifdef _METMAP</span> metallic *= matParams.x; <span class="synPreProc">#endif</span> <span class="synPreProc">#if !defined(EDITOR_VISUALIZATION)</span> output.albedoColor = matColor.rgb *( <span class="synConstant">1.0</span> - metallic *<span class="synConstant">0.5</span>) *( <span class="synConstant">0.5</span> + matColor.a *<span class="synConstant">0.5</span>) ; <span class="synPreProc">#else</span> output.albedoColor = matColor; <span class="synPreProc">#endif</span> output.emitColor = matColor.rgb * emmision; <span class="synStatement">return</span> output; } <span class="synComment">// ------------------------------------------------------------------</span> VertexOutput MetaVertex(VertexInput input) { VertexOutput output; float3 posTXS = input.posOS.xyz; <span class="synStatement">if</span> (unity_MetaVertexControl.x) { posTXS.xy = input.uvLM * unity_LightmapST.xy + unity_LightmapST.zw; posTXS.z = posTXS.z &gt; <span class="synConstant">0</span> ? REAL_MIN : <span class="synConstant">0.0f</span>; } <span class="synStatement">if</span> (unity_MetaVertexControl.y) { posTXS.xy = input.uvDLM * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw; posTXS.z = posTXS.z &gt; <span class="synConstant">0</span> ? REAL_MIN : <span class="synConstant">0.0f</span>; } output.posCS = mul(UNITY_MATRIX_VP, float4(posTXS, <span class="synConstant">1.0</span>)); output.uv.xy = input.uv0.xy; output.uv.zw = <span class="synConstant">0</span>; <span class="synStatement">return</span> output; } half4 MetaFragment(VertexOutput input) : SV_TARGET { half4 color = <span class="synConstant">0</span>; float2 uv = input.uv.xy; MaterialSTB mat = GetMaterial(uv); <span class="synStatement">if</span> (unity_MetaFragmentControl.x) { color = half4(mat.albedoColor, <span class="synConstant">1.0</span>); unity_OneOverOutputBoost = saturate(unity_OneOverOutputBoost); <span class="synComment">// d3d9 shader compiler doesn't like NaNs and infinity. </span> color.rgb = clamp(PositivePow(color.rgb, unity_OneOverOutputBoost), <span class="synConstant">0</span>, unity_MaxOutputValue); <span class="synComment">// Apply Albedo Boost from LightmapSettings.</span> } <span class="synStatement">if</span> (unity_MetaFragmentControl.y) { color = half4(mat.emitColor, <span class="synConstant">1.0</span>); } <span class="synStatement">return</span> color; } <span class="synPreProc">#endif </span><span class="synComment">//SEGATB_META</span> <span class="synComment">// ---------------------------------------------------------------------------</span> <span class="synComment">// ------------------------------------------------------------------------------------</span> <span class="synPreProc">#endif </span><span class="synComment">//SEGATB_CHS_INCLUDED</span> </pre><p></details></p><p><details><summary><span style="color: #1d4c86"><b>litChk.shader</b></span></summary></p> <pre class="code lang-c" data-lang="c" data-unlink>Shader <span class="synConstant">&quot;SegaTechBlog/lightingChecker&quot;</span> { Properties { [Header(__ Material Params __________)][Space(<span class="synConstant">5</span>)] _AlbedoColor (<span class="synConstant">&quot;Color&quot;</span>, Color) = (<span class="synConstant">0.4663</span>, <span class="synConstant">0.4663</span>, <span class="synConstant">0.4663</span>, <span class="synConstant">1</span>) _Metallic (<span class="synConstant">&quot;Metallic&quot;</span>, Range(<span class="synConstant">0.0</span>, <span class="synConstant">1.0</span>)) = <span class="synConstant">0.0</span> _Anisotropy (<span class="synConstant">&quot;Anisotropy&quot;</span>, Range(-<span class="synConstant">1.0</span>, <span class="synConstant">1.0</span>)) = <span class="synConstant">0.0</span> _Smoothness (<span class="synConstant">&quot;Smoothness&quot;</span>, Range(<span class="synConstant">0.0</span>, <span class="synConstant">1.0</span>)) = <span class="synConstant">0.5</span> [Space(<span class="synConstant">15</span>)] [Toggle(_COLMAP)] _UseColorMap (<span class="synConstant">&quot;@ Color Map&quot;</span>, Float) = <span class="synConstant">1</span> [NoScaleOffset] _MainTex (<span class="synConstant">&quot;Color(RGB), Alpha(A)&quot;</span>, 2D) = <span class="synConstant">&quot;white&quot;</span> {} [Toggle(_METMAP)] _UseMetMap (<span class="synConstant">&quot;@ Mat Map:Metallic&quot;</span>, Float) = <span class="synConstant">1</span> [Toggle(_OCCMAP)] _UseOccMap (<span class="synConstant">&quot;@ Mat Map:Occlusion&quot;</span>, Float) = <span class="synConstant">1</span> [Toggle(_SMTMAP)] _UseSmtMap (<span class="synConstant">&quot;@ Mat Map:Smoothness&quot;</span>, Float) = <span class="synConstant">1</span> [NoScaleOffset] _MetallicGlossMap (<span class="synConstant">&quot;Metal(R), Occlude(G), Smooth(A)&quot;</span>, 2D) = <span class="synConstant">&quot;white&quot;</span> {} [Toggle(_NORMALMAP)]_UseNormalMap (<span class="synConstant">&quot;@ Normal Map&quot;</span>, Float) = <span class="synConstant">0</span> [NoScaleOffset] _NormalMap (<span class="synConstant">&quot;Tangent Normal(RGB)&quot;</span>, 2D) = <span class="synConstant">&quot;bump&quot;</span> {} [Header(__ View One Element ___________)][Space(<span class="synConstant">5</span>)] [KeywordEnum(_,COLOR,DIFFUSE_COLOR,SPECULAR_COLOR,METALLIC,SMOOTHNESS,OCCLUSION)]_VMAT(<span class="synConstant">&quot;&gt; View Material Element&quot;</span>, Float) = <span class="synConstant">0</span> [Space(<span class="synConstant">5</span>)][KeywordEnum(_,LIGHT_COLOR,LIGHT_ILLUMINANCE,SHADE_LAMBERT,SHADE_SPECULAR,SHADE_SPEC_DGF,SHADE_SPEC_D,SHADE_SPEC_G,SHADE_SPEC_F)]_VSUN(<span class="synConstant">&quot;&gt; View Sun Light Element&quot;</span>, Float) = <span class="synConstant">0</span> [Space(<span class="synConstant">5</span>)][KeywordEnum(_,LIGHT_ILLUMINANCE,SHADE_LAMBERT,SHADE_REFLECTION)]_VENV(<span class="synConstant">&quot;&gt; View Environment Light Element&quot;</span>, Float) = <span class="synConstant">0</span> [Space(<span class="synConstant">5</span>)][KeywordEnum(_,LIGHT_COLOR,LIGHT_ILLUMINANCE,SHADE_LAMBERT,SHADE_SPECULAR,SHADE_SPEC_DGF,SHADE_SPEC_D,SHADE_SPEC_G,SHADE_SPEC_F)]_VPOINT(<span class="synConstant">&quot;&gt; View Sub Light Element&quot;</span>, Float) = <span class="synConstant">0</span> [Space(<span class="synConstant">5</span>)][KeywordEnum(_,TOTAL_ILLUMINANCE,TOTAL_REFLECTION)]_VGET(<span class="synConstant">&quot;&gt; View Total Light Amount&quot;</span>, Float) = <span class="synConstant">0</span> [Space(<span class="synConstant">15</span>)] [Header(__ Measure The Value __________)][Space(<span class="synConstant">5</span>)] [Toggle(_CHECKVALUE)]_CheckValue(<span class="synConstant">&quot;&gt; Measure The Output Value&quot;</span>, Float) = <span class="synConstant">0</span> [Space(<span class="synConstant">5</span>)]_ChkTargetValue(<span class="synConstant">&quot; ORANGE-GREEN-BLUE&quot;</span>, Range(-<span class="synConstant">0.1</span>, <span class="synConstant">5.0</span>)) = <span class="synConstant">0.1842</span> [Enum(x0<span class="synConstant">.01</span>,<span class="synConstant">0.01</span>, x0<span class="synConstant">.1</span>,<span class="synConstant">0.1</span>, x1,<span class="synConstant">1.0</span>, x10,<span class="synConstant">10.0</span>, x100,<span class="synConstant">100.0</span>, x1000,<span class="synConstant">1000.0</span>, x10000,<span class="synConstant">10000.0</span>)]_ChkTargetScale(<span class="synConstant">&quot; (Higher - Hit - Lower)&quot;</span>, Range( <span class="synConstant">0.001</span>, <span class="synConstant">1000.0</span>)) = <span class="synConstant">1.0</span> [Space(<span class="synConstant">8</span>)][PowerSlider(<span class="synConstant">2.0</span>)]_ChkRange(<span class="synConstant">&quot; Tolerance&quot;</span>, Range(<span class="synConstant">0.0032</span>, <span class="synConstant">10.0</span>)) = <span class="synConstant">0.045</span> [Space(<span class="synConstant">30</span>)] [Header(__ Other Options ____________)][Space(<span class="synConstant">5</span>)] [Toggle(_NOPIDIV)]_NoPiDiv(<span class="synConstant">&quot;No INV_PI as UnityStandard&quot;</span>, Float) = <span class="synConstant">0</span> } SubShader { Tags { <span class="synConstant">&quot;RenderType&quot;</span>=<span class="synConstant">&quot;Opaque&quot;</span> } LOD <span class="synConstant">100</span> Pass { Name <span class="synConstant">&quot;FORWARD&quot;</span> Tags{ <span class="synConstant">&quot;LightMode&quot;</span> = <span class="synConstant">&quot;ForwardBase&quot;</span>} ZWrite On Blend One Zero BlendOp Add HLSLPROGRAM <span class="synPreProc">#pragma target </span><span class="synConstant">3.5</span> <span class="synPreProc">#pragma multi_compile_instancing</span> <span class="synPreProc">#pragma instancing_options assumeuniformscaling</span> <span class="synPreProc">#pragma multi_compile _ VERTEXLIGHT_ON</span> <span class="synPreProc">#pragma shader_feature DIRECTIONAL</span> <span class="synPreProc">#pragma shader_feature SHADOWS_SCREEN</span> <span class="synPreProc">#pragma multi_compile _ LIGHTPROBE_SH DIRLIGHTMAP_COMBINED</span> <span class="synPreProc">#pragma multi_compile _ UNITY_USE_NATIVE_HDR UNITY_LIGHTMAP_RGBM_ENCODING UNITY_LIGHTMAP_DLDR_ENCODING</span> <span class="synPreProc">#pragma shader_feature DYNAMICLIGHTMAP_ON</span> <span class="synPreProc">#pragma shader_feature _NOPIDIV</span> <span class="synPreProc">#pragma shader_feature _COLMAP</span> <span class="synPreProc">#pragma shader_feature _METMAP</span> <span class="synPreProc">#pragma shader_feature _OCCMAP</span> <span class="synPreProc">#pragma shader_feature _SMTMAP</span> <span class="synPreProc">#pragma shader_feature _NORMALMAP</span> <span class="synPreProc">#pragma multi_compile _ _VMAT_COLOR _VMAT_DIFFUSE_COLOR _VMAT_SPECULAR_COLOR _VMAT_METALLIC _VMAT_SMOOTHNESS _VMAT_OCCLUSION _VSUN_LIGHT_COLOR _VSUN_LIGHT_ILLUMINANCE _VSUN_SHADE_LAMBERT _VSUN_SHADE_SPECULAR _VSUN_SHADE_SPEC_DGF _VSUN_SHADE_SPEC_D _VSUN_SHADE_SPEC_G _VSUN_SHADE_SPEC_F _VENV_LIGHT_ILLUMINANCE _VENV_SHADE_LAMBERT _VENV_SHADE_REFLECTION _VPOINT_LIGHT_COLOR _VPOINT_LIGHT_ILLUMINANCE _VPOINT_SHADE_LAMBERT _VPOINT_SHADE_SPECULAR _VPOINT_SHADE_SPEC_D _VPOINT_SHADE_SPEC_G _VPOINT_SHADE_SPEC_F _VGET_TOTAL_ILLUMINANCE _VGET_TOTAL_REFLECTION</span> <span class="synPreProc">#pragma multi_compile _ _VSUN__</span> <span class="synPreProc">#pragma multi_compile _ _VPOINT__</span> <span class="synPreProc">#pragma shader_feature _CHECKVALUE</span> <span class="synPreProc">#pragma vertex ChsForwardVertex</span> <span class="synPreProc">#pragma fragment ChsForwardFragment</span> <span class="synPreProc">#define SEGATB_FORWARD</span> <span class="synPreProc">#include </span><span class="synConstant">&quot;litChkLib.hlsl&quot;</span> ENDHLSL } Pass { Name <span class="synConstant">&quot;ShadowCaster&quot;</span> Tags{<span class="synConstant">&quot;LightMode&quot;</span> = <span class="synConstant">&quot;ShadowCaster&quot;</span>} ZWrite On ColorMask <span class="synConstant">0</span> HLSLPROGRAM <span class="synPreProc">#pragma target </span><span class="synConstant">3.5</span> <span class="synPreProc">#pragma multi_compile_instancing</span> <span class="synPreProc">#pragma instancing_options assumeuniformscaling</span> <span class="synPreProc">#pragma vertex DepthOnlyVertex</span> <span class="synPreProc">#pragma fragment DepthOnlyFragment</span> <span class="synPreProc">#define SEGATB_SHADOWCASTER</span> <span class="synPreProc">#include </span><span class="synConstant">&quot;litChkLib.hlsl&quot;</span> ENDHLSL } Pass { Name <span class="synConstant">&quot;META&quot;</span> Tags{<span class="synConstant">&quot;LightMode&quot;</span> = <span class="synConstant">&quot;Meta&quot;</span>} Cull Off HLSLPROGRAM <span class="synPreProc">#pragma shader_feature _COLMAP</span> <span class="synPreProc">#pragma shader_feature _METMAP</span> <span class="synPreProc">#pragma shader_feature EDITOR_VISUALIZATION</span> <span class="synPreProc">#pragma vertex MetaVertex</span> <span class="synPreProc">#pragma fragment MetaFragment</span> <span class="synPreProc">#define SEGATB_META</span> <span class="synPreProc">#include </span><span class="synConstant">&quot;litChkLib.hlsl&quot;</span> ENDHLSL } } } </pre><p></details><br />  <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122809.gif" alt="f:id:sgtech:20190422122809g:plain" title="f:id:sgtech:20190422122809g:plain" class="hatena-fotolife" itemprop="image"></span></p><br /> <p></br></p> </div> </div> <div class="section"> <h3 id="マテリアルカラーの測定"><span style="color: #607075">マテリアルカラーの測定</span></h3> <p><span style="font-size: 105%;color: #405262">さっそく、スフィアを置いて、ライティング検証用マテリアルを適用してみます。</span></p> <div class="section"> <h4 id="マテリアルを作る">マテリアルを作る</h4> <ol> <li>シーンに、プリミティブのスフィアを置く<span style="color: #ff7200"> GameObject > 3D Object > Sphere</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122847.gif" alt="f:id:sgtech:20190422122847g:plain" title="f:id:sgtech:20190422122847g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Assetsフォルダに、マテリアルを新規作成する<span style="color: #ff7200">  Assets > Create > Material</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122845.gif" alt="f:id:sgtech:20190422122845g:plain" title="f:id:sgtech:20190422122845g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>マテリアルのシェーダーを、SegaTechBlog / lightingChecker に切り替える</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122843.gif" alt="f:id:sgtech:20190422122843g:plain" title="f:id:sgtech:20190422122843g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>スフィアに、作成したマテリアルを割り当てる</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122841.gif" alt="f:id:sgtech:20190422122841g:plain" title="f:id:sgtech:20190422122841g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122839.gif" alt="f:id:sgtech:20190422122839g:plain" title="f:id:sgtech:20190422122839g:plain" class="hatena-fotolife" itemprop="image"></span></li> </ol><p></BR></p><p><span style="font-size: 105%;color: #405262">マテリアルの デフォルトカラーを見てみると、グレー 119[sRGB] となっています。 この色は、印刷物や塗装に</BR>おける 一般的な指標である、CIE L*a*b* ミドルグレー:反射率 18.42[%] に相当します。</span><a href="#f-5a24270b" name="fn-5a24270b" title="[tex:Gamma Color] は [tex:119 / 255 \fallingdotseq 0.46] , [tex:Gamma Color^{2.2} \fallingdotseq Linear Color] なので [tex:0.46^{2.2} \fallingdotseq 0.18]これは完全白色が反射率100%であるという仮定下でのL*a*b*ミドルグレーとなる。">*2</a></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122917.jpg" alt="f:id:sgtech:20190422122917j:plain" title="f:id:sgtech:20190422122917j:plain" class="hatena-fotolife" itemprop="image"></span><br /> <span style="font-size: 105%;color: #405262">このカラーが 正しい反射率になっていることを、マテリアルの 出力値測定機能を使って確認してみましょう。</span></p> </div> <div class="section"> <h4 id="マテリアルカラーを測定する">マテリアルカラーを測定する</h4> <ol> <li>マテリアルの View Material Elementプルダウンメニューから <b>COLOR</b> を選択</BR><span style="font-size: 103.5%;color: #506272"> > マテリアルカラーが単色で出力表示されます。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122915.gif" alt="f:id:sgtech:20190422122915g:plain" title="f:id:sgtech:20190422122915g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122913.gif" alt="f:id:sgtech:20190422122913g:plain" title="f:id:sgtech:20190422122913g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Measure The Output Valueチェックボックスを オン</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122910.gif" alt="f:id:sgtech:20190422122910g:plain" title="f:id:sgtech:20190422122910g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>スライダーを動かして、緑色に光るところを探す</BR><span style="font-size: 103.5%;color: #506272"> > 緑色になったとき、そのスライダーの値が、現在のマテリアル出力値となります。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122908.gif" alt="f:id:sgtech:20190422122908g:plain" title="f:id:sgtech:20190422122908g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123005.gif" alt="f:id:sgtech:20190422123005g:plain" title="f:id:sgtech:20190422123005g:plain" class="hatena-fotolife" itemprop="image"></span></BR><span style="font-size: 105%;color: #304252">測定した結果は おおよそ<b><span style="font-size: 105%">0.46</span></b>、反射率46[%]となってしまいました。</BR>これは、Unityプロジェクトのカラースペースが、初期設定では Gammaになっているからです。</span></BR><div style="border:1px solid #151515;padding:6px;border-radius:10px;width : 87%;"><span style="font-size: 90%;color: #151515">プロジェクトがGamma設定のとき、Unityは 色空間をコントロールしません。カラーの入力は sRGB(ガンマ2.2)ですが、これを そのままライティング計算に使い、ガンマ2.2用モニターに そのままの値を出力します。 結果として、入力した色は そのまま表示されるのですが、ライティング計算が 誤ったGamma色空間で行われることになるので、…なんだか…こう…濃くてギラッとしたライティング結果になりがちです。</span></div></li> </ol><p></BR></p><br /> <p><span style="font-size: 105%;color: #405262">プロジェクトのカラースペースを、Linearに切り替えます。</span></p><p></p> </div> <div class="section"> <h4 id="カラースペースを変更する">カラースペースを変更する</h4> <ol> <li>プロジェクト設定ウィンドウを開く<span style="color: #ff7200"> Edit> Project Settings</span></li> <li>Playerタブを開き、カラースペースのプルダウンメニューから<b>Linear</b>を選択</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123003.gif" alt="f:id:sgtech:20190422123003g:plain" title="f:id:sgtech:20190422123003g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>再び、マテリアルの 計測スライダーを動かして、緑色に光るところを探す<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123001.gif" alt="f:id:sgtech:20190422123001g:plain" title="f:id:sgtech:20190422123001g:plain" class="hatena-fotolife" itemprop="image"></span></BR><span style="font-size: 105%;color: #304252">今度の測定結果は 期待どおり、 おおよそ<b><span style="font-size: 105%">0.18</span></b>、反射率18[%]になりました。</span></BR><div style="border:1px solid #151515;padding:6px;border-radius:10px;width : 87%;"><span style="font-size: 90%;color: #151515">プロジェクトがLinear設定のとき、Unityは 色空間をコントロールして、ライティング計算をLinear色空間で行います。sRGB(ガンマ2.2)カラーの入力を リニアカラーに変換し、これをライティング計算に使います。最後に、ライティング結果を リニアカラーからsRGBカラーに戻した値を、ガンマ2.2用モニターに出力します。結果として、入力した色は そのまま表示され、かつ、ライティング計算も正しく行われる形になります。 つまり、カラースペース設定変更の前後で、モニターに表示されるマテリアルカラーの見た目は変化しません。シェーダー内部での値と、ライティング結果が 変化します。</BR> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122958.gif" alt="f:id:sgtech:20190422122958g:plain" title="f:id:sgtech:20190422122958g:plain" class="hatena-fotolife" itemprop="image"></span> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122956.gif" alt="f:id:sgtech:20190422122956g:plain" title="f:id:sgtech:20190422122956g:plain" class="hatena-fotolife" itemprop="image"></span></span></div></BR></li> </ol><p></BR></p><p></BR></p> </div> </div> <div class="section"> <h3 id="ライトカラーの測定"><span style="color: #607075">ライトカラーの測定</span></h3> <p><span style="font-size: 105%;color: #405262">このマテリアルで、モデルを照らしているライトのカラーも 表示, 測定することができます。</span></p> <div class="section"> <h4 id="ライトカラーを計測する">ライトカラーを計測する</h4> <ol> <li>マテリアルの View SunLight Elementプルダウンメニューから <b>LIGHT_COLOR</b> を選択</BR><span style="font-size: 103.5%;color: #506272"> > 太陽(Directional Light)のカラーが単色で出力表示されます。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123052.gif" alt="f:id:sgtech:20190422123052g:plain" title="f:id:sgtech:20190422123052g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123050.gif" alt="f:id:sgtech:20190422123050g:plain" title="f:id:sgtech:20190422123050g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>ふたたび Measure The Output Valueをオンにし、スライダーを動かして、緑色に光るところを探す</BR><span style="font-size: 105%;color: #506272"> > 測定結果は おおよそ<b><span style="font-size: 105%">0.9</span></b>になりました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123048.gif" alt="f:id:sgtech:20190422123048g:plain" title="f:id:sgtech:20190422123048g:plain" class="hatena-fotolife" itemprop="image"></span></BR></BR><span style="font-size: 105%;color: #405262">Directional Lightオブジェクトを選択してみると、Intensityが1、カラーに少し黄色が入っていて 、</BR>…だいたい0.9、合ってる!という感じがします。</span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123046.gif" alt="f:id:sgtech:20190422123046g:plain" title="f:id:sgtech:20190422123046g:plain" class="hatena-fotolife" itemprop="image"></span></BR><span style="font-size: 105%;color: #405262">もっと 大きな値も入れてみましょう。</span></BR></BR></li> <li>Directional LightのIntensityを <b>2</b> に上げる<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123044.gif" alt="f:id:sgtech:20190422123044g:plain" title="f:id:sgtech:20190422123044g:plain" class="hatena-fotolife" itemprop="image"></span></BR></li> <li>Sphereを選択し、マテリアルの測定スライダーを動かして、緑色に光るところを探す</BR><span style="font-size: 105%;color: #506272"> > 測定結果は おおよそ <b><span style="font-size: 105%">4.14</span></b> となりました。1.8になるはずが…。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123134.gif" alt="f:id:sgtech:20190422123134g:plain" title="f:id:sgtech:20190422123134g:plain" class="hatena-fotolife" itemprop="image"></span></BR></BR><span style="font-size: 105%;color: #405262">これは、ライトのIntensityがsRGB(ガンマ2.2)値として扱われているからです。ライトのColorは色なのでsRGB扱いで良いですが、Intensity</span><span style="font-size: 90%;color: #405262">(ライトの強さ)</span><span style="font-size: 105%;color: #405262">や Indirect Multiplier</span><span style="font-size: 90%;color: #405262">(ライトマップを焼くときの 強さ補正値)</span><span style="font-size: 105%;color: #405262"> にガンマが掛かってしまうのは、PBRライティング環境を設定するうえで 邪魔になります。</span></BR><div style="border:1px solid #151515;padding:6px;border-radius:10px;width : 87%;"><span style="font-size: 90%;color: #151515">この仕様、Unityとしては、Gamma設定のプロジェクトとの整合性を狙った仕様なのかもしれません。 ほかにも、HDRIイメージを天球に貼るときに使う Skybox/Cubemapマテリアルの Exposure値が、同様の仕様になっています。</span></div></li> </ol><p></BR></p><br /> <p><span style="font-size: 105%;color: #405262">Project SettingsのGraphicsタブに、ライト強度をリニア値として扱うオプション設定が存在します。</BR>が、GUI上には表示されていないので、スクリプトを使って切り替えます。<a href="#f-e0a760dd" name="fn-e0a760dd" title="[https://docs.unity3d.com/2018.3/Documentation/ScriptReference/Rendering.GraphicsSettings-lightsUseLinearIntensity.html]">*3</a></span></p><p></p> </div> <div class="section"> <h4 id="ライト強度のカラースペースを変更する">ライト強度のカラースペースを変更する</h4> <ol> <li>メニューから <span style="color: #ff7200">SegaTechBlog > LightsIntensity > Linear</span> を選択<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123131.gif" alt="f:id:sgtech:20190422123131g:plain" title="f:id:sgtech:20190422123131g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>マテリアルの測定スライダーを動かして、緑色に光るところを探す</BR><span style="font-size: 105%;color: #506272"> > 今度の測定結果は 期待どおり、 おおよそ<b><span style="font-size: 105%">1.8</span></b>になりました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123129.gif" alt="f:id:sgtech:20190422123129g:plain" title="f:id:sgtech:20190422123129g:plain" class="hatena-fotolife" itemprop="image"></span></li> </ol><p></BR></p><br /> <p><span style="font-size: 105%;color: #405262">現実世界では、ライトに照らされたとき モデル全体にライトカラーの光が届く訳ではなく、ライトに正面を向いた所は明るく照らされますが、ライトから横に90度向いた面には光が届きません。</BR></BR>ライトから投げつけた光の粒が、正面ほど 多く当たり、横向きの面には あまり当たらない というイメージです。<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122647.gif" alt="f:id:sgtech:20190422122647g:plain" title="f:id:sgtech:20190422122647g:plain" class="hatena-fotolife" itemprop="image"></span><br /> この、ライトからの光が 面に当たった量のことを、照度(illuminance)といいます。</BR>照度を出力表示してみましょう。</span><br /> </p> </div> <div class="section"> <h4 id="ライトの照度と表面の輝度を比較する">ライトの照度と表面の輝度を比較する</h4> <ol> <li>マテリアルの View SunLight Elementプルダウンメニューから <b>LIGHT_ILLUMINANCE</b> を選択</BR><span style="font-size: 105%;color: #506272"> > 太陽(Directional Light)の照度が出力表示されます。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123126.gif" alt="f:id:sgtech:20190422123126g:plain" title="f:id:sgtech:20190422123126g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123124.gif" alt="f:id:sgtech:20190422123124g:plain" title="f:id:sgtech:20190422123124g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Measure The Output Valueをオン</BR><span style="font-size: 105%;color: #506272"> > 太陽正面方向の照度が ちょうど1.8(=ライトカラーと同じ値)になっています。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123210.gif" alt="f:id:sgtech:20190422123210g:plain" title="f:id:sgtech:20190422123210g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123208.gif" alt="f:id:sgtech:20190422123208g:plain" title="f:id:sgtech:20190422123208g:plain" class="hatena-fotolife" itemprop="image"></span></BR></BR><span style="font-size: 105%;color: #405262">面に当たった光の量が照度。ですが、これが そのまま、面の 見た目の明るさになるわけではありません。</BR></BR>カメラから見て、その ライトアップされた面が見えている、ということは、面で跳ね返った光がカメラに向かって飛び込んできた、ということになります。</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122637.gif" alt="f:id:sgtech:20190422122637g:plain" title="f:id:sgtech:20190422122637g:plain" class="hatena-fotolife" itemprop="image"></span></BR></BR>いわゆる完全拡散反射面、まったくスペキュラの無い、どこから見ても おなじ明るさに見える材質があるとすると、面に当たった光を 全方向 (面の真横までくれば見えないので、半球の範囲) に分配して飛ばさなければいけません。</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122642.gif" alt="f:id:sgtech:20190422122642g:plain" title="f:id:sgtech:20190422122642g:plain" class="hatena-fotolife" itemprop="image"></span></BR></BR>面に入ってきた光が1なのに、 全方向に1ずつ跳ね返す、というのは物理的にありえません。</BR>面から 全方向に1ずつ跳ね返すためには、約3倍…ちょうど円周率&#960;倍の光が、面に当たる必要があります。</BR>逆に、面に当たった光が1だと、そこから跳ね返って 特定の方向に進み ちょうどカメラに当たる光の量は 1 / &#960; となります。</BR></BR>面で跳ね返って飛んできて カメラに当たった(見えた)光の量のことを、その面の輝度(luminance)といいます。 完全拡散面の輝度を出力表示してみましょう。</span></BR></BR></li> <li>マテリアルの View SunLight Elementプルダウンメニューから <b>SHADE_LAMBERT</b> を選択</BR><span style="font-size: 103.5%;color: #506272"> > 反射率100%, 完全拡散反射面 の輝度が出力表示されます。 …照度表示から 1 / &#960; 暗くなってるだけですが。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123206.gif" alt="f:id:sgtech:20190422123206g:plain" title="f:id:sgtech:20190422123206g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123204.gif" alt="f:id:sgtech:20190422123204g:plain" title="f:id:sgtech:20190422123204g:plain" class="hatena-fotolife" itemprop="image"></span></BR><div style="border:1px solid #151515;padding:6px;border-radius:10px;width : 87%;"><span style="font-size: 90%;color: #151515">UnityのStandardシェーダーでは、この シェーディング時に照度を&#960;で割る処理を省略しています。 旧来シェーダーとの互換性をとった判断と思われます。 明るさ 1 のライトで照らしたのに、白い面が 0.3のグレー にしかならない!というのが 馴染みにくかったのかもしれません。</BR>こういった仕様の場合、現実的な光の値を使いたい時には 手計算で&#960;で割った数字を入れて対処することで 限定的には対応できます。 この対処方法については、記事のまとめで 改めて触れます。</span></div></li> </ol><p><br /> </br></p> </div> </div> <div class="section"> <h3 id="太陽の明るさを設定する"><span style="color: #607075">太陽の明るさを設定する</span></h3> <p><span style="font-size: 105%;color: #405262">準備ができたので、ターゲットの屋外ライティング環境に合わせていきましょう。</span></p><p><span style="font-size: 105%;color: #405262">光学単位を そのまま使うには、日中屋外の数値は ケタが大きすぎるので、1/5000にしてみます。<br /> そうすると、冒頭で提示したターゲット環境テーブルは、以下のような値になります。</span></p> <table> <tr> <th>太陽に直交した面に 入ってくる光の量(照度)</th> <td>太陽から <b>17.0</b></td> <td>青空(半球)から <b>4.0</b></td> <td>合計     <b>21.0</b></td> <td>[lux/5k]</td> </tr> <tr> <th>太陽の傾斜角が66.6度。水平地面に 入ってくる光の量(照度)</th> <td>太陽から <b>15.6</b></td> <td>青空(半球)から <b>4.0</b></td> <td>合計     <b>19.6</b></td> <td>[lux/5k]</td> </tr> <tr> <th>この環境に照らされたグレー18.42%地面の明るさ(輝度)</th> <td> </td> <td>青空 =日陰   <b>0.23</b></td> <td>合計 =日向    <b>1.15</b></td> <td>[nt/5k]</td> </tr> <tr> <th>青空の明るさ(輝度)</th> <td> </td> <td> </td> <td>平均     <b>1.27</b></td> <td>[nt/5k]</td> </tr> <tr> <th></th> <td> </td> <td> </td> <td>白い雲     <b>2.0</b></td> <td>[nt/5k]</td> </tr> <tr> <th></th> <td> </td> <td> </td> <td>水平線     <b>1.6</b></td> <td>[nt/5k]</td> </tr> <tr> <th></th> <td> </td> <td> </td> <td>青い空     <b>0.8</b></td> <td>[nt/5k]</td> </tr> <tr> <th></th> <td> </td> <td> </td> <td>天頂部     <b>0.3</b></td> <td>[nt/5k]</td> </tr> <tr> <th>カメラの露出補正(相対補正値)</th> <td> </td> <td> </td> <td><b>-2.975</b></td> <td>[EV]</td> </tr> </table><p><br /> </BR><br /> <span style="font-size: 105%;color: #405262">屋外環境のライティングを整えるのに、スフィア1個では さすがに無理があるので、最低限のシーンデータを用意します。 その他、自作のモデルなどあれば インポートして配置してみてください。lightingCheckerマテリアルは Unity Standard仕様のカラーマップ,ノーマルマップ,マテリアルマップを そのまま適用できます。</span><br /> </p> <div class="section"> <h4 id="屋外環境のシーンデータを用意する">屋外環境のシーンデータを用意する</h4> <ol> <li>プリミティブの箱を置く<span style="color: #ff7200"> GameObject > 3D Object > Cube</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123202.gif" alt="f:id:sgtech:20190422123202g:plain" title="f:id:sgtech:20190422123202g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>箱にも スフィアと同じlightingCheckerマテリアルを割り当てる<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123241.gif" alt="f:id:sgtech:20190422123241g:plain" title="f:id:sgtech:20190422123241g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>プリミティブの板を 地面として置く<span style="color: #ff7200"> GameObject > 3D Object > Plane</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123239.gif" alt="f:id:sgtech:20190422123239g:plain" title="f:id:sgtech:20190422123239g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>lightingCheckerマテリアルを複製して、板に割り当てる<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123237.gif" alt="f:id:sgtech:20190422123237g:plain" title="f:id:sgtech:20190422123237g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>板をStaticに指定する</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123235.gif" alt="f:id:sgtech:20190422123235g:plain" title="f:id:sgtech:20190422123235g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>ライトプローブを置き、地面に埋まらないよう1.2m程度 持ち上げる<span style="color: #ff7200"> GameObject > Light > Light Probe Group</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123233.gif" alt="f:id:sgtech:20190422123233g:plain" title="f:id:sgtech:20190422123233g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>リフレクションプローブを置き、地面に埋まらないよう1.2m程度 持ち上げる<span style="color: #ff7200"> GameObject > Light > Reflection Probe</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123316.gif" alt="f:id:sgtech:20190422123316g:plain" title="f:id:sgtech:20190422123316g:plain" class="hatena-fotolife" itemprop="image"></span></li> </ol><p><br /> <span style="font-size: 105%;color: #405262">ごく一般的なシーンセットアップになっていると思います。</span><br /> <div style="border:1px solid #151515;padding:6px;border-radius:10px;width : 97%;"><span style="font-size: 90%;color: #151515"> Unity初めての方に このシーンデータの説明</p> <ul> <li>Staticに指定した板は、動かさない 背景モデル扱いになります。事前にGlobal Illuminationでライトマップが焼かれ、ゲーム中では このライトマップを利用して 環境光からの拡散反射(diffuse)シェーディングが表現されます。</li> <li>それ以外のモデルは、ライトプローブを利用して環境光からの拡散反射(diffuse)シェーディングを表現します。ライトプローブには、事前にGlobal Illuminationによるライティング情報が焼かれて入っています。</li> <li>リフレクションプローブには、事前に環境マップ(HDRのCubeMapテクスチャ)が焼かれて入っています。全てのモデルは、この環境マップを利用して 環境光からの鏡面反射(reflection)シェーディングを表現します。</li> <li>リフレクションプローブを置かなくても天球が鏡面反射に使われますが、それだと地面板が 実モデルの輝度で映り込まないので、リフレクションプローブを置きました。</li> <li>Global Illuminationの事前計算は、デフォルトだと エディタ上では 必要に応じて自動更新されます。自動更新が邪魔になったら、Lightingウィンドウを開いてAuto Generateチェックボックスをオフにすれば 手動更新になります。だいたい皆、邪魔になってきて切りますが、今回のようなライティング環境セットアップ中は オンのままが便利です。</li> <li>メインライトである太陽から直接のライティングは、全てのモデルにおいて、リアルタイムシェーディングで表現されます。</span></div></li> </ul><p><br /> </BR><br /> <span style="font-size: 105%;color: #405262">太陽のライトカラーには、<span style="font-size: 95%;background: #f6f6f6;border: solid 1px #dddddd"><b> 太陽に直交した面に 太陽から 入ってくる光の量(照度)</b></span><span style="font-size: 95%;border: solid 1px #dddddd"><b>17.0</b> [lux/5k] </span> を設定します。</span><br /> </p> </div> <div class="section"> <h4 id="太陽のライトカラーを設定する">太陽のライトカラーを設定する</h4> <ol> <li>箱のマテリアルの、View SunLight Elementプルダウンメニューから <b>LIGHT_COLOR</b> を選択</li> <li>Measure The Output Valueをオン、スライダーを <b>1.7</b> に設定、すぐ下の掛け数を <b>x10</b> に設定</BR><span style="font-size: 103.5%;color: #506272"> > これで、出力値が17( = 1.7x10 )のときに 緑に光る設定になりました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123314.gif" alt="f:id:sgtech:20190422123314g:plain" title="f:id:sgtech:20190422123314g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Directional Lightオブジェクトを選択し、モデルが緑に光るまで ライトのIntensityを上げていく</BR><span style="font-size: 103.5%;color: #506272"> > <b>18.67</b> で緑に光りました。(いちおう検算するとライトカラーの黄色を掛けて ちょうど17になります。<a href="#f-62c98f2a" name="fn-62c98f2a" title="ライトのデフォルト黄色は[tex:Gamma Color(255, 244, 214)/255] これは [tex:Linear Color(1.0, 0.9074, 0.6800)] , これに輝度変換係数の[tex:(0.2126729, 0.7151522, 0.072175)]を掛けて足しあわせ 黄色の輝度は[tex:0.911]。 , [tex: 18.67*0.911 \fallingdotseq 17.0]">*4</a> )</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123311.gif" alt="f:id:sgtech:20190422123311g:plain" title="f:id:sgtech:20190422123311g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123309.gif" alt="f:id:sgtech:20190422123309g:plain" title="f:id:sgtech:20190422123309g:plain" class="hatena-fotolife" itemprop="image"></span></li> </ol><p><br /> </BR><br /> <span style="font-size: 105%;color: #405262">太陽の角度を66.6度にセットし、</BR>このとき <span style="font-size: 95%;background: #f6f6f6;border: solid 1px #dddddd"><b> 水平面に 入ってくる光の量(照度)</b></span><span style="font-size: 95%;border: solid 1px #dddddd"><b>15.6</b> [lux/5k] </span> になっていることを確認してみましょう。</span><br /> </p> </div> <div class="section"> <h4 id="太陽の向きを設定する">太陽の向きを設定する</h4> <ol> <li>マテリアルの View SunLight Elementプルダウンメニューから <b>LIGHT_ILLUMINANCE</b> を選択<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123307.gif" alt="f:id:sgtech:20190422123307g:plain" title="f:id:sgtech:20190422123307g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Directional LightのRotationを <b>(90.0, 0, 0)</b> に設定</BR><span style="font-size: 103.5%;color: #506272"> > 試しに、太陽の角度を90度にセットしてみました。</BR> 箱の上面が緑になっているので、このライトで真上から照らすと照度17.0であることが再確認できました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123348.gif" alt="f:id:sgtech:20190422123348g:plain" title="f:id:sgtech:20190422123348g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123346.gif" alt="f:id:sgtech:20190422123346g:plain" title="f:id:sgtech:20190422123346g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Directional LightのRotationを <b>(66.6, 0, 0)</b> に設定</BR><span style="font-size: 103.5%;color: #506272"> > 太陽の角度を66.6度に 傾けてセットしました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123343.gif" alt="f:id:sgtech:20190422123343g:plain" title="f:id:sgtech:20190422123343g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>マテリアルのスライダーを <b>1.56</b> に設定</BR><span style="font-size: 103.5%;color: #506272"> > 箱の上面が緑になりました。66.6度から照らした時、水平面の照度15.6にできていることが確認できました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123341.gif" alt="f:id:sgtech:20190422123341g:plain" title="f:id:sgtech:20190422123341g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123339.gif" alt="f:id:sgtech:20190422123339g:plain" title="f:id:sgtech:20190422123339g:plain" class="hatena-fotolife" itemprop="image"></span></li> </ol><p><br /> </br></p> </div> </div> <div class="section"> <h3 id="空の明るさを設定する"><span style="color: #607075">空の明るさを設定する</span></h3> <p><span style="font-size: 105%;color: #405262">次に、空を調整します。 デフォルトの天球マテリアルは パラメータを 変更出来ないので、Skybox/Proceduralマテリアルを新規作成し、シーンにセットして使います。 Skybox/Proceduralマテリアルに 出力値の測定機能はありませんが、モデルに映り込んだ天球を、 lightingCheckerマテリアルで測定することができます。</BR>ただし Skybox/Proceduralマテリアルには はっきりした白い雲を表示する機能が無いので省略し、<span style="font-size: 95%;background: #f6f6f6;border: solid 1px #dddddd"><b> 空の平均 </b></span><span style="font-size: 95%;border: solid 1px #dddddd"><b>1.27</b> [nt/5k] </span> , <span style="font-size: 95%;background: #f6f6f6;border: solid 1px #dddddd"><b> 水平線 </b></span><span style="font-size: 95%;border: solid 1px #dddddd"><b>1.6</b> [nt/5k] </span> , <span style="font-size: 95%;background: #f6f6f6;border: solid 1px #dddddd"><b> 青い空 </b></span><span style="font-size: 95%;border: solid 1px #dddddd"><b>0.8</b> [nt/5k] </span> , <span style="font-size: 95%;background: #f6f6f6;border: solid 1px #dddddd"><b> 天頂部 </b></span><span style="font-size: 95%;border: solid 1px #dddddd"><b>0.3</b> [nt/5k] </span> の4つの輝度をターゲットに設定します。</span><br /> </p> <div class="section"> <h4 id="空の輝度を設定する">空の輝度を設定する</h4> <ol> <li>Assetsフォルダに、マテリアルを新規作成する<span style="color: #ff7200">  Assets > Create > Material</span></BR></li> <li>作成したマテリアルのシェーダーを、Skybox / Proceduralに切り替える</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123428.gif" alt="f:id:sgtech:20190422123428g:plain" title="f:id:sgtech:20190422123428g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>ライティング設定ウィンドウを開く<span style="color: #ff7200"> Window > Rendering > Lighting Settings</span></li> <li>Skybox Materialに、作成したSkybox/Proceduralマテリアルを割り当てる</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123425.gif" alt="f:id:sgtech:20190422123425g:plain" title="f:id:sgtech:20190422123425g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>lightingCheckerマテリアルを選択し、 View Environment Light Elementプルダウンメニューから <b>SHADE_REFLECTION</b> を選択</BR><span style="font-size: 103.5%;color: #506272"> > ボケた天球が映りました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123421.gif" alt="f:id:sgtech:20190422123421g:plain" title="f:id:sgtech:20190422123421g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123418.gif" alt="f:id:sgtech:20190422123418g:plain" title="f:id:sgtech:20190422123418g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Measure The Output Valueをオン、スライダーを <b>0.8</b> に設定、掛け数を <b>x1</b> に設定</BR><span style="font-size: 103.5%;color: #506272"> > これで、出力値0.8の部分が 緑に光る設定になりました。</span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123414.gif" alt="f:id:sgtech:20190422123414g:plain" title="f:id:sgtech:20190422123414g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Smoothnessを動かして、天球の どのあたりが0.8になっているか観察する</BR><span style="font-size: 103.5%;color: #506272"> > デフォルト天球は、水平線でも0.7くらいで かなり暗いようです。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123629.gif" alt="f:id:sgtech:20190422123629g:plain" title="f:id:sgtech:20190422123629g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Skybox/ProceduralマテリアルのExposureの値を上げて、青い空が主に0.8になるよう寄せていく</BR><span style="font-size: 103.5%;color: #506272"> > デフォの1.3から<b>6.0</b>まで上げると、青い空0.8周辺、天頂0.4で平均1.2くらいの、ほどよい値になりました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123626.gif" alt="f:id:sgtech:20190422123626g:plain" title="f:id:sgtech:20190422123626g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123621.gif" alt="f:id:sgtech:20190422123621g:plain" title="f:id:sgtech:20190422123621g:plain" class="hatena-fotolife" itemprop="image"></span></li> </ol><p><div style="border:1px solid #151515;padding:6px;border-radius:10px;width : 87%;"><span style="font-size: 90%;color: #151515">天球全体の輝度をスケールするだけの、すこし雑な調整です。 水平線が 明るめになってしまいました。<br /> Skybox/Proceduralマテリアルの Exposure以外のパラメータを変更すると、大気スキャッタ計算のバランスが変わって、空の色味がズレていくので、天球の輝度調整に使うことは お勧めしません。<br /> 白い雲の表現や、水平線付近の減衰(地表からの埃によるフォグ)などについて 細かくバランスを取るには、skyboxシェーダーのカスタマイズをしたり、シーンデータとして遠景モデルを配置していく必要があります。</span></div></p><br /> <p></BR><span style="font-size: 105%;color: #405262">空の輝度が決まったところで、今度は <span style="font-size: 95%;background: #f6f6f6;border: solid 1px #dddddd"><b> 水平地面に 青空(半球)から 入ってくる光の量(照度)</b></span><span style="font-size: 95%;border: solid 1px #dddddd"><b>4.0</b> [lux/5k] </span> を確認してみましょう。</span><br /> </p> </div> <div class="section"> <h4 id="空の照度を設定する">空の照度を設定する</h4> <ol> <li>lightingCheckerマテリアルを選択し、 View Environment Light Elementプルダウンメニューから <b>LIGHT_ILLUMINANCE</b> を選択</BR><span style="font-size: 103.5%;color: #506272"> > 環境光からの照度が表示されました。真っ白です。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123619.gif" alt="f:id:sgtech:20190422123619g:plain" title="f:id:sgtech:20190422123619g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123617.gif" alt="f:id:sgtech:20190422123617g:plain" title="f:id:sgtech:20190422123617g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Directional Lightの Indirect Multiplierを <b>0</b> に設定</BR><span style="font-size: 103.5%;color: #506272"> > 一旦、地面に反射した太陽光の照り返しを消しました。これで 空からの照度だけを計測できます。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123701.gif" alt="f:id:sgtech:20190422123701g:plain" title="f:id:sgtech:20190422123701g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123659.gif" alt="f:id:sgtech:20190422123659g:plain" title="f:id:sgtech:20190422123659g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Measure The Output Valueをオン、スライダーを <b>4.0</b> に設定</BR><span style="font-size: 103.5%;color: #506272"> > これで、出力値が4のときに 緑に光る設定になりました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123657.gif" alt="f:id:sgtech:20190422123657g:plain" title="f:id:sgtech:20190422123657g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>ライティング設定ウィンドウを開く<span style="color: #ff7200"> Window > Rendering > Lighting Settings</span></li> <li>Environment Lighting > Intensity Multiplierの値を変えて、箱の上面が緑になる値を探す</BR><span style="font-size: 103.5%;color: #506272"> > <b><span style="font-size: 105%">1.151</span></b> で、ちょうど 箱の上面が緑になりました。これで 空(半球)からの照度を4.0に設定できました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123738.gif" alt="f:id:sgtech:20190422123738g:plain" title="f:id:sgtech:20190422123738g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123655.gif" alt="f:id:sgtech:20190422123655g:plain" title="f:id:sgtech:20190422123655g:plain" class="hatena-fotolife" itemprop="image"></span></li> </ol><p><div style="border:1px solid #151515;padding:6px;border-radius:10px;width : 87%;"><span style="font-size: 90%;color: #151515"> Unityにおける 空からの環境照明は、鏡面反射(環境マップ)と拡散反射(ライトマップやライトプローブ)が 別々の仕組みで提供されています。この為、空の輝度をピッタリ決めたから 拡散反射の照度も自動で正しい値になる、という風には なかなかいきません。手動で微調整が必要です。</span></div></p><br /> <br /> <p></BR></p><p></p> </div> </div> <div class="section"> <h3 id="地面照り返しの明るさを設定する"><span style="color: #607075">地面照り返しの明るさを設定する</span></h3> <p><span style="font-size: 105%;color: #405262">最後に、さきほど一旦0にした、地面で反射した太陽光の照り返し の照度を調整しましょう。 ターゲット環境に この照度の値は無いので、ざっくり算出します。<span style="font-size: 95%;background: #f6f6f6;border: solid 1px #dddddd"><b> このライティング環境に照らされたグレー18.42%地面の、日向での明るさ(輝度)</b></span><span style="font-size: 95%;border: solid 1px #dddddd"><b>1.15</b> [nt/5k] </span> なので、これが完全拡散反射面として 下一面に広がっていた場合、下半球からの照度は 1.15 x &#960; = <span style="font-size: 95%;border: solid 1px #dddddd"><b>3.613</b> [lux/5k] </span> となります。 この値に合わせてみましょう。</span><br /> </p> <div class="section"> <h4 id="地面照り返しの照度を設定する">地面照り返しの照度を設定する</h4> <ol> <li>箱ではなく、地面板の方の lightingCheckerマテリアルを選択し、 View Total Light Amountプルダウンメニューから <b>TOTAL_ILLUMINANCE</b> を選択</BR><span style="font-size: 103.5%;color: #506272"> > 地面への、太陽や空からの照度の合計が出力表示されました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123735.gif" alt="f:id:sgtech:20190422123735g:plain" title="f:id:sgtech:20190422123735g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Measure The Output Valueをオン、スライダーを動かして、緑色に光るところを探す</BR><span style="font-size: 103.5%;color: #506272"> > 地面への照度は<b><span style="font-size: 105%">19.6</span></b>( = 1.96x10 )。ターゲット環境の、<span style="font-size: 95%;background: #f6f6f6;border: solid 1px #dddddd"><b> 太陽の傾斜角が66.6度。水平地面に 入ってくる光の量(照度)合計 </b></span><span style="font-size: 95%;border: solid 1px #dddddd"><b>19.6</b> [lux/5k] </span> に 一致していることが確認できました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123731.gif" alt="f:id:sgtech:20190422123731g:plain" title="f:id:sgtech:20190422123731g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123733.gif" alt="f:id:sgtech:20190422123733g:plain" title="f:id:sgtech:20190422123733g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>こんどは 箱のほうの lightingCheckerマテリアルを選択し、 View Environment Light Elementプルダウンメニューから <b>LIGHT_ILLUMINANCE</b> を選択</li> <li>Measure The Output Valueをオン、スライダーを <b>3.613</b> に設定<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123728.gif" alt="f:id:sgtech:20190422123728g:plain" title="f:id:sgtech:20190422123728g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>箱を下から見上げながら、Directional Lightの Indirect Multiplierを上げていき、箱の下面が緑になる値を探す</BR><span style="font-size: 103.5%;color: #506272"> > <b><span style="font-size: 105%">0.32</span></b> で、ちょうど 箱の下面が緑になりました。これで 地面照り返しの照度を 3.613に設定できました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123821.gif" alt="f:id:sgtech:20190422123821g:plain" title="f:id:sgtech:20190422123821g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123819.gif" alt="f:id:sgtech:20190422123819g:plain" title="f:id:sgtech:20190422123819g:plain" class="hatena-fotolife" itemprop="image"></span></li> </ol><p></br></p> </div> </div> <div class="section"> <h3 id="カメラの露出を設定する"><span style="color: #607075">カメラの露出を設定する</span></h3> <p><span style="font-size: 105%;color: #405262">ライティング設定は完了しましたが、画面が ほぼ真っ白です。1/5000していても、まだ、日中の屋外は眩しすぎます。 Unityの標準カメラには HDRの露出補正機能が無いので、ポストプロセスエフェクトを使って、カメラを適正露出に補正しましょう。</span><br /> </p> <div class="section"> <h4 id="Post-Processingのセットアップ">Post-Processingのセットアップ</h4> <ol> <li>Assetsフォルダに、Post-processing Profileを新規作成する<span style="color: #ff7200">  Assets > Create > Post-processing Profile</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123817.gif" alt="f:id:sgtech:20190422123817g:plain" title="f:id:sgtech:20190422123817g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>シーンに、Emptyを置く<span style="color: #ff7200"> GameObject > Create Empty</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123815.gif" alt="f:id:sgtech:20190422123815g:plain" title="f:id:sgtech:20190422123815g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Emptyに、ポスプロ設定保持用コンポーネントを追加<span style="color: #ff7200">  Add Component > Rendering > Post-process Volume</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123813.gif" alt="f:id:sgtech:20190422123813g:plain" title="f:id:sgtech:20190422123813g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Post Process VolumeコンポーネントのProfile欄に、さっき作ったPost-processing Profileをセット</BR><span style="font-size: 103.5%;color: #506272"> > これで、カメラが このEmptyに近づくと セットしたポスプロ設定が使われるようになりました。<a href="#f-b71a2737" name="fn-b71a2737" title="カメラが近づいたと見なす距離は、EmptyにBox Colliderを追加して設定する。">*5</a></span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123901.gif" alt="f:id:sgtech:20190422123901g:plain" title="f:id:sgtech:20190422123901g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Post Process Volumeコンポーネントの Is Globalをオン</BR><span style="font-size: 103.5%;color: #506272"> > これでカメラとEmptyの位置に関わらず、シーン内では常に このポスプロ設定が使われるようになりました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123859.gif" alt="f:id:sgtech:20190422123859g:plain" title="f:id:sgtech:20190422123859g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Emptyを、PostProcessingレイヤーに所属させる<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123856.gif" alt="f:id:sgtech:20190422123856g:plain" title="f:id:sgtech:20190422123856g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Main Cameraに、ポスプロ設定取得用コンポーネントを追加<span style="color: #ff7200">  Add Component > Rendering > Post-process Layer</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123854.gif" alt="f:id:sgtech:20190422123854g:plain" title="f:id:sgtech:20190422123854g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Post Process LayerコンポーネントのLayer欄に、PostProcessingレイヤーを指定</BR><span style="font-size: 103.5%;color: #506272"> > これで、PostProcessingレイヤーに置かれたPost Process Volumeを カメラが取得するようになりました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123852.gif" alt="f:id:sgtech:20190422123852g:plain" title="f:id:sgtech:20190422123852g:plain" class="hatena-fotolife" itemprop="image"></span></li> </ol><p><br /> </BR></p> </div> <div class="section"> <h4 id="手動で露出補正する">手動で露出補正する</h4> <ol> <li>Post-processing Profileに、Color Gradingエフェクトを追加<span style="color: #ff7200">  Add Effect > Unity > Color Grading</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123948.gif" alt="f:id:sgtech:20190422123948g:plain" title="f:id:sgtech:20190422123948g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Color Gradingの Post-exposureを <b>-2.975</b> に設定</BR><span style="font-size: 103.5%;color: #506272"> > ターゲット環境の<span style="font-size: 95%;background: #f6f6f6;border: solid 1px #dddddd"><b> カメラの露出設定(相対露出補正値)</b></span><span style="font-size: 95%;border: solid 1px #dddddd"><b>-2.975</b> [EV] </span> を設定し、無事に グレーな地面をグレーに表示することができました!</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123945.gif" alt="f:id:sgtech:20190422123945g:plain" title="f:id:sgtech:20190422123945g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123943.gif" alt="f:id:sgtech:20190422123943g:plain" title="f:id:sgtech:20190422123943g:plain" class="hatena-fotolife" itemprop="image"></span></BR></li> </ol><p><br /> </BR><span style="font-size: 105%;color: #405262">…これで、フォトリアルな質感や 屋外のライティングを 表現できるようになったのか、少し試してみましょう。</span><br /> </p> </div> <div class="section"> <h4 id="マテリアルにバリエーションを出してみる">マテリアルにバリエーションを出してみる</h4> <ol> <li>スフィアを複製し、新しいマテリアルを割り当てて、ゴールド のパラメータを設定<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422123939.gif" alt="f:id:sgtech:20190422123939g:plain" title="f:id:sgtech:20190422123939g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>白いモルタル のパラメータを設定</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124101.gif" alt="f:id:sgtech:20190422124101g:plain" title="f:id:sgtech:20190422124101g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>半渇きの土 のパラメータを設定</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124059.gif" alt="f:id:sgtech:20190422124059g:plain" title="f:id:sgtech:20190422124059g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>草 のパラメータを設定</BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124057.gif" alt="f:id:sgtech:20190422124057g:plain" title="f:id:sgtech:20190422124057g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124055.jpg" alt="f:id:sgtech:20190422124055j:plain" title="f:id:sgtech:20190422124055j:plain" class="hatena-fotolife" itemprop="image"></span></BR></li> </ol><p><br /> </BR><span style="font-size: 105%;color: #405262">悪くありませんが、ゴールドのハイライトの 色の飛び方が下品です。カラーグレーディングにACES色空間を使うことで、高輝度成分を上品に表現した色調調整が やり易くなります。</span><br /> </p> </div> <div class="section"> <h4 id="カラーグレーディングにACESを利用する">カラーグレーディングにACESを利用する</h4> <ol> <li>Color Gradingの Modeを <b>ACES</b> に設定</BR><span style="font-size: 103.5%;color: #506272"> > 高輝度部分のコントラストが柔らかくなり、上品な質感になりました。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124053.gif" alt="f:id:sgtech:20190422124053g:plain" title="f:id:sgtech:20190422124053g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124139.jpg" alt="f:id:sgtech:20190422124139j:plain" title="f:id:sgtech:20190422124139j:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Post-processing Profileに、Bloomエフェクトを追加。Intensityを<b>2</b>に設定</BR><span style="font-size: 103.5%;color: #506272"> > ついでにブルームを載せたところ…、画面全体が ぼんやり光ってしまいました!</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124137.gif" alt="f:id:sgtech:20190422124137g:plain" title="f:id:sgtech:20190422124137g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124135.jpg" alt="f:id:sgtech:20190422124135j:plain" title="f:id:sgtech:20190422124135j:plain" class="hatena-fotolife" itemprop="image"></span></BR></li> </ol><p><br /> </BR><span style="font-size: 105%;color: #405262">実は、Color Gradingの Post-exposureはフィルム現像段階での露出補正を模したもので、撮影時のカメラによる露出補正ではありません。ブルームやDoFエフェクトはレンズで起きる現象を模したものなので、露出補正前の輝度(ほぼ白く飛んでいる)に対して エフェクトが掛けられており、その結果 画面全体がブルームしています。<br /> 撮影段階で 適切に露出補正するには、Auto Exposureエフェクトを使います。</span><br /> </p> </div> <div class="section"> <h4 id="オートで露出補正する">オートで露出補正する</h4> <ol> <li>Color Gradingの Post-exposureをオフにする<span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124132.gif" alt="f:id:sgtech:20190422124132g:plain" title="f:id:sgtech:20190422124132g:plain" class="hatena-fotolife" itemprop="image"></span></li> <li>Post-processing Profileに、Auto Exposureエフェクトを追加。Minimumを <b>-6</b>、Maximumを <b>6</b>、Exposure Compensationを <b>0.4</b> に設定</BR><span style="font-size: 103.5%;color: #506272"> > Min,Maxには オート露出の 露出補正可動範囲を設定します。Exposure Compensationには、画面内の輝度の平均値を、どれくらいの明るさに変換して表示したいかを 設定します。</span></BR><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124127.gif" alt="f:id:sgtech:20190422124127g:plain" title="f:id:sgtech:20190422124127g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124221.jpg" alt="f:id:sgtech:20190422124221j:plain" title="f:id:sgtech:20190422124221j:plain" class="hatena-fotolife" itemprop="image"></span></BR></li> </ol><p><br /> </BR><span style="font-size: 105%;color: #405262">撮影段階で適切に露出補正が行われ、ブルームは 高輝度部分にだけ発生するようになりました。<br /> ターゲット環境で設定していた露出補正値(EV100準拠の絶対露出補正値 EV15 = 1/5000単位での輝度値に対する相対露出補正値 -2.975EV)は、事前に求めた 撮影対象の平均的輝度値を おおよそ0.1として表示するように設定(その結果 グレイ18%が 約0.18で表示される事が期待)されていますが、このAuto Exposureフィルタでは、動的に 現在の画面の平均輝度が求められ、その値が0.4として表示されるようなスケール値が 画面全体にかけられます。<br /> 結果として、画面に明るいものが多く映るほど、露出は絞られ 暗い所が より暗く表示されるようになります。</span><br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124215.gif" alt="f:id:sgtech:20190422124215g:plain" title="f:id:sgtech:20190422124215g:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124210.gif" alt="f:id:sgtech:20190422124210g:plain" title="f:id:sgtech:20190422124210g:plain" class="hatena-fotolife" itemprop="image"></span></p><br /> <br /> <p></br></p> </div> </div> <div class="section"> <h3 id="まとめ"><span style="color: #607075">まとめ</span></h3> <div class="section"> <h4 id="つくったライティング環境の活用">つくったライティング環境の活用</h4> <p>お疲れ様でした。ライティング環境のセットアップは 以上です。つくったライティング環境の活用方法ですが、まずは 主要なアセットを一ステージ分くらい用意して、仮組みしてみるのが良いと思います。<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124231.jpg" alt="f:id:sgtech:20190422124231j:plain" title="f:id:sgtech:20190422124231j:plain" class="hatena-fotolife" itemprop="image"></span></p><p>アセットが増えて 質感のバリエーションがでてくると、画面のコントラストを作るには カメラやライティングに どんなバリエーションが必要なのかが、はっきりしてきます。そして、プロジェクト内で 質感の違いを どう表現してゆくか、またカラーコレクションの方向性なども、順を追って 絵の仕様を決めていける段階になります。</p><br /> <p>最終的なゲーム画面、コンセプトアートを実現していく中では、独自表現のマテリアルを追加することがあります。<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422122623.gif" alt="f:id:sgtech:20190422122623g:plain" title="f:id:sgtech:20190422122623g:plain" class="hatena-fotolife" itemprop="image"></span><br /> ゲーム的に必要性が高ければ、天球に雲を加えたり、大気フォグ表現についても 独自で追加する必要があります。<br /> <span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124207.jpg" alt="f:id:sgtech:20190422124207j:plain" title="f:id:sgtech:20190422124207j:plain" class="hatena-fotolife" itemprop="image"></span><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190422/20190422124204.jpg" alt="f:id:sgtech:20190422124204j:plain" title="f:id:sgtech:20190422124204j:plain" class="hatena-fotolife" itemprop="image"></span><br /> こういった拡張を行った際は、ぜひ拡張後に もう一度ライティング環境のテストを行ってください。</BR>基準となる 輝度や照度の比率を、コントロールし続けることが大切です。</BR></p><br /> <p></BR><span style="font-size: 105%;color: #405262">今回のセットアップは PBRとして素直な値を設定しましたが、実際のUnityの描画フローには 多くの種類があり、それぞれに特性があります。とても全容は書ききれませんが、いくつか 代表的なものについて、対応をリストしておきます。</span><br /> </p> </div> <div class="section"> <h4 id="Standard">Standard</h4> <ul> <li>ライト直接光によるシェーディング輝度は&#960;倍明るい。 <ul> <li>この環境でフィジカルな光単位を扱う場合、手動でライトintensityに1/&#960;した値を入れる必要がある。</li> <li>lightingCheckerマテリアルの<span style="color: #ff7200">No INV_PI as UnityStandard</span>をオンにすれば、この仕様に沿った値を確認できる。</li> <li>厳密には正しくない対応である(ライト強度を手動で暗くしても、2次反射以降のシェーディング輝度が1/&#960;される訳ではない)ことに注意しつつ、仕様として飲み込む方向で。</li> </ul></li> <li>(初期設定では)ライトの強度にガンマがかかっている。</li> <li>ポイントライトの強度減衰がPBR準拠(距離自乗減衰)ではない。 <ul> <li>これも No INV_PI as UnityStandardをオン,オフして仕様の違いを確認できます。</li> </ul></li> <li>シェーディングモデルは、ローエンド機種でなければPBR準拠。</li> </ul><p></BR></p> </div> <div class="section"> <h4 id="LWRP">LWRP</h4> <ul> <li>まだPreview版を抜けたばかりで、仕様が一般化されていない。</li> <li>ライト直接光によるシェーディング輝度は&#960;倍明るい。</li> <li>ライトの強度はリニア値。</li> <li>ポイントライトの強度減衰はPBR準拠(距離自乗減衰)。</li> <li>シェーディングモデルは、ローエンド機種でなければPBR準拠。</li> </ul><p></BR></p> </div> <div class="section"> <h4 id="HDRP">HDRP</h4> <ul> <li>まだPreview版で、仕様が確定していない。</li> <li>ライト直接光によるシェーディング輝度は正しい。</li> <li>ライトの強度はリニア値で、光学単位の 大きな数値を そのまま入力できる(内部的には EV100単位のpre-exposure値を算出して事前にかけることで 値の爆発を避けている)。</li> <li>ポイントライトの強度減衰はPBR準拠(距離自乗減衰)。</li> <li>ポイントライトの 光源サイズを規定したり、ライン光源, 面光源を利用できる(距離自乗減衰ではなく エリアライトの減衰カーブが扱える)。</li> <li>ポスプロは独自仕様となる(PostProcessing V3に相当)。</li> <li>シェーディングモデルはPBR準拠、かつ SSS,Aniso,ClearCoat表現が追加されてDisney BSDF相当に近づいた。<a href="#f-2105233b" name="fn-2105233b" title="Disney BSDFについては[https://dl.acm.org/citation.cfm?id=2343493:title=Siggraph2012 - Practical physically-based shading in film and game production]のPhysically Based Shading at Disney と[https://dl.acm.org/citation.cfm?id=2787670:title=Siggraph2015 - Physically based shading in theory and practice]のExtending the Disney BRDF to a BSDF with Integrated Subsurface Scattering。また 同名やPrincipled BSDFで検索すると 様々な粒度の情報が得られる。">*6</a></li> </ul><p></BR></p> </div> <div class="section"> <h4 id="Gammaワークフロー全般">Gammaワークフロー全般</h4> <ul> <li>おおむね2Dのゲームだから Photoshopと レイヤー合成の見た目を合わせてくれ、というケース。わかります!</li> <li>とはいえ このワークフロー、実質 カラースペース管理の放棄なので、PBRライティングとの共存は 無理です。</li> <li>もしコストが割けるのであれば、Linearワークフロー内に Gammaワークフロー的な部分を作ることは可能です。</BR></li> </ul><p></p><p></BR></BR></BR><span style="font-size: 105%;color: #405262">ターゲット ライティング環境テーブルを 自分で用意してみたい時は、以下のメモを参考にしてください。</span><br /> </p> </div> <div class="section"> <h4 id="ライティング環境の求め方">ライティング環境の求め方</h4> <div class="section"> <h5 id="屋外の場合">屋外の場合</h5> <p>・まず、太陽と空からの照度を計測します。シンプルな手法が Moving Frostbite to Physically based renderingに載っています。</p> <blockquote cite="https://seblagarde.wordpress.com/2015/07/14/siggraph-2014-moving-frostbite-to-physically-based-rendering/"> <p>Measurements were taken at ground level with the light meter’s sensor angled horizontally or perpendicular to the sun (&#8869; index). Measurements were performed at various hours of a sunny day with few clouds, in Stockholm in July. The sky values were obtained by occluding the sun with a small object (i.e. casting a shadow on the sensor).</p> <cite><a href="https://seblagarde.wordpress.com/2015/07/14/siggraph-2014-moving-frostbite-to-physically-based-rendering/">https://seblagarde.wordpress.com/2015/07/14/siggraph-2014-moving-frostbite-to-physically-based-rendering/</a></cite> </blockquote> <ol> <li>照度計を使い、太陽正面向きの照度を計測 <img src="https://chart.apis.google.com/chart?cht=tx&chl=%3D%20A" alt="= A"/> [lux]</li> <li>太陽が直射する方向だけ 小さなもので隠して(=照度センサーを影にいれて)、空の照度を計測 <img src="https://chart.apis.google.com/chart?cht=tx&chl=%3D%20B" alt="= B"/> [lux]</li> <li>太陽からの照度 <img src="https://chart.apis.google.com/chart?cht=tx&chl=C%20%3D%20%28A-B%29" alt="C = (A-B)"/> [lux]</li> </ol><p>個人的に おすすめの照度計は セコニックの<a href="https://www.sekonic.co.jp/product/meter/l_478d/l_478d.html">L-478D</a>です。オプションのビューファインダーを付ければ輝度計にもなって便利です。2台欲しい!</BR></BR></p><p>・太陽の傾斜角は、場所と時間に基づいて 算出してくれるサイトが いくつもあります。 = <img src="https://chart.apis.google.com/chart?cht=tx&chl=%CE%98" alt="&Theta;"/></p><p>・グレー18%完全拡散反射面である水平地面の輝度、日向は、<img src="https://chart.apis.google.com/chart?cht=tx&chl=0.1842%20%2A%20%28%20C%20%2A%20cos%28%CE%98%29%20%2B%20B%20%29%20%2F%20%CF%80" alt="0.1842 * ( C * cos(&Theta;) + B ) / &pi;"/> [nt]<br /> ・ 同 日陰の輝度は、<img src="https://chart.apis.google.com/chart?cht=tx&chl=0.1842%20%2A%20B%20%2F%20%CF%80" alt="0.1842 * B / &pi;"/> [nt]<br /> ・空の輝度の平均は、<img src="https://chart.apis.google.com/chart?cht=tx&chl=B%20%20%2F%20%CF%80" alt="B / &pi;"/> [nt]</p><p>・空の細かいところの輝度は、輝度計で計測します。雲や空の輝度は、環境によって かなり大きい振れ幅で変化します。なるべく細かく計測して、ならした値を使いましょう。 こちらの <a href="https://www.pvlighthouse.com.au/cms/lectures/altermatt/solar_spectrum/albedo">PV Lighthouse - ALBEDO</a> 太陽光発電に関するレクチャーでは、地面の色が いかに空の輝度に影響を与えるかが説明されています。地面に雪が積もると 照り返しで空が2倍明るくなって、太陽光発電にも貢献するそうです!面白いですね。</p><p>・その他、標準反射板を持っていれば、輝度計で計測しておくことで、グレー地面輝度の検算が可能になりそうです。</p> </div> <div class="section"> <h5 id="屋内の場合">屋内の場合</h5> <p>・屋内のライティングは、もっと複雑な照明設計になってくるので、難しいところです。<br /> ・とりあえず、1/5000 lumen単位だと 数字が小さすぎて扱いにくいです。一般的な室内で300[lux] = 0.06[lux/5k]など。間をとるか、場所で切り分けるか、HDRPのような動的光学単位が必要になります。<br /> ・実在の部屋や照明器具を 計測, HDR撮影して 寄せていくのが、比較的 現実的な正攻法になるかと思います。<br /> ・屋内ライティングは、グレー18%よりも高い反射率を 部屋の標準マテリアルにして 整える必要があります。現代の建物は、手元の照度や 空間の照度、床と壁のコントラストを 省電力で実現する為に、比較的 高反射率の素材を使っている傾向があります。 <a href="http://www2.panasonic.biz/ls/lighting/plam/knowledge/document/0412.html">Panasonic - P.L.A.M. - &#x5404;&#x7A2E;&#x6750;&#x6599;&#x53CD;&#x5C04;&#x7387;</a>の表で屋内向けの建材や塗装を見てみると、自然物や屋外資材と比べて 高めの反射率が並んでいます。 この場合も、露出補正用のターゲットにはグレー18%を使います。</p> </div> <div class="section"> <h5 id="露出補正値">露出補正値</h5> <p>・EV100の値は、照度計で計測することができます。また、<a href="https://google.github.io/filament/Filament.html">Google Filament&#x306E;PBR&#x30AC;&#x30A4;&#x30C9;</a>には、ターゲットの輝度や フラット面への照度、半球への照度から EV100単位の露出補正値を算出する方法が載っています。</p> </div> <div class="section"> <h5 id="自前のシェーダーに測定機能を付けたい">自前のシェーダーに測定機能を付けたい</h5> <p>・今回のシェーダー、litChkLib.hlslに入っているCheckColorValue関数を ご覧ください。シンプルな仕組みです。<br /> ・Core RP Library使いやすそう!と思った方には、<a href="https://catlikecoding.com/unity/tutorials/scriptable-render-pipeline/">Catlike Coding - Scriptable Render Pipeline</a>チュートリアルが お勧めです。</BR></p><p></BR></p> </div> </div> <div class="section"> <h4 id="みなさんも一緒に働きませんか">みなさんも一緒に働きませんか?</h4> <p>長文、読んでくださってありがとうございました。<br /> この記事で 興味を持たれた方、セガ・インタラクティブで私たちと一緒に働いてみませんか?</p><p>アーケードゲーム開発は、ハイエンドPC相当の特定GPU構成、個性的な筐体をターゲットに、中小規模ゲーム開発が楽しめる、グラフィックDev好きには なかなか たまらない環境です!<br /> 採用情報については、以下のリンクを、是非ご確認ください。<br /> <iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="採用情報|株式会社セガ・インタラクティブ" src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fsega-interactive.co.jp%2Frecruit" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://www.sega.co.jp/recruit/index.html" onmousedown="ga('HatenaBlogUserTracker.send', 'event', 'recruit', 'sic_banner_clicked','recruit_sic_out', true);">sega-games.co.jp</a></cite></p><br /> <p>&#169;SEGA</p> </div> </div><div class="footnote"> <p class="footnote"><a href="#fn-262ea02b" name="f-262ea02b" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">Unity2019.1では Global Illminationの初期設定が変更された為、環境ライティング系の調整結果が Blogと異なる値に落ち着く。</BR>また、Unity2018.2以前のバージョンでは、シェーダー内の Core RP Libraryへのパスを書き換える必要がある。</span></p> <p class="footnote"><a href="#fn-5a24270b" name="f-5a24270b" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text"><img src="https://chart.apis.google.com/chart?cht=tx&chl=Gamma%20Color" alt="Gamma Color"/> は <img src="https://chart.apis.google.com/chart?cht=tx&chl=119%20%2F%20255%20%5Cfallingdotseq%200.46" alt="119 / 255 \fallingdotseq 0.46"/> , <img src="https://chart.apis.google.com/chart?cht=tx&chl=Gamma%20Color%5E%7B2.2%7D%20%5Cfallingdotseq%20Linear%20Color" alt="Gamma Color^{2.2} \fallingdotseq Linear Color"/> なので <img src="https://chart.apis.google.com/chart?cht=tx&chl=0.46%5E%7B2.2%7D%20%5Cfallingdotseq%200.18" alt="0.46^{2.2} \fallingdotseq 0.18"/></BR>これは完全白色が反射率100%であるという仮定下でのL*a*b*ミドルグレーとなる。</span></p> <p class="footnote"><a href="#fn-e0a760dd" name="f-e0a760dd" class="footnote-number">*3</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://docs.unity3d.com/2018.3/Documentation/ScriptReference/Rendering.GraphicsSettings-lightsUseLinearIntensity.html">https://docs.unity3d.com/2018.3/Documentation/ScriptReference/Rendering.GraphicsSettings-lightsUseLinearIntensity.html</a></span></p> <p class="footnote"><a href="#fn-62c98f2a" name="f-62c98f2a" class="footnote-number">*4</a><span class="footnote-delimiter">:</span><span class="footnote-text">ライトのデフォルト黄色は<img src="https://chart.apis.google.com/chart?cht=tx&chl=Gamma%20Color%28255%2C%20244%2C%20214%29%2F255" alt="Gamma Color(255, 244, 214)/255"/> これは <img src="https://chart.apis.google.com/chart?cht=tx&chl=Linear%20Color%281.0%2C%200.9074%2C%200.6800%29" alt="Linear Color(1.0, 0.9074, 0.6800)"/></BR> , これに輝度変換係数の<img src="https://chart.apis.google.com/chart?cht=tx&chl=%280.2126729%2C%200.7151522%2C%200.072175%29" alt="(0.2126729, 0.7151522, 0.072175)"/>を掛けて足しあわせ 黄色の輝度は<img src="https://chart.apis.google.com/chart?cht=tx&chl=0.911" alt="0.911"/>。</BR> , <img src="https://chart.apis.google.com/chart?cht=tx&chl=%2018.67%2A0.911%20%5Cfallingdotseq%2017.0" alt=" 18.67*0.911 \fallingdotseq 17.0"/></span></p> <p class="footnote"><a href="#fn-b71a2737" name="f-b71a2737" class="footnote-number">*5</a><span class="footnote-delimiter">:</span><span class="footnote-text">カメラが近づいたと見なす距離は、EmptyにBox Colliderを追加して設定する。</span></p> <p class="footnote"><a href="#fn-2105233b" name="f-2105233b" class="footnote-number">*6</a><span class="footnote-delimiter">:</span><span class="footnote-text">Disney BSDFについては<a href="https://dl.acm.org/citation.cfm?id=2343493">Siggraph2012 - Practical physically-based shading in film and game production</a>のPhysically Based Shading at Disney と<a href="https://dl.acm.org/citation.cfm?id=2787670">Siggraph2015 - Physically based shading in theory and practice</a>のExtending the Disney BRDF to a BSDF with Integrated Subsurface Scattering。また 同名やPrincipled BSDFで検索すると 様々な粒度の情報が得られる。</span></p> </div> sgtech ゲーム・アニメーション創りは面白い! hatenablog://entry/17680117126999065660 2019-03-25T15:00:00+09:00 2019-03-25T15:00:00+09:00 皆さん、はじめまして。 セガ・インタラクティブ 第一研究開発部 デザイン技術セクション テクニカルアーティストの鈴木です。モーションデザイナーとして、アーケードゲームのガンゲームをメインに10年ほど携わった後、テクニカルアーティストとしてモーション作業周りのサポートをしています。最近では「HOUSE OF THE DEAD ~SCARLET DAWN~」のサポートを行いました。また、採用活動業務も担当するようになりました。 ゲーム歴は長く、電子ゲームやファミコンなどに触れて、現在もゲームを楽しんでいます。 はじめに ゲームアニメーションとは ゲームアニメーションを創ることの面白さ 映像アニメー… <p>皆さん、はじめまして。</p> <p>セガ・インタラクティブ 第一研究開発部 デザイン技術セクション テクニカルアーティストの鈴木です。モーションデザイナーとして、アーケードゲームのガンゲームをメインに10年ほど携わった後、テクニカルアーティストとしてモーション作業周りのサポートをしています。最近では「HOUSE OF THE DEAD ~SCARLET DAWN~」のサポートを行いました。また、採用活動業務も担当するようになりました。</p> <p>ゲーム歴は長く、電子ゲームやファミコンなどに触れて、現在もゲームを楽しんでいます。</p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="ハウス・オブ・ザ・デッド ~スカーレットドーン~ | HOUSE OF THE DEAD ~SCARLET DAWN~ | セガ" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fhod.sega.jp%2F" frameborder="0" scrolling="no"></iframe></p> <ul class="table-of-contents"> <li><a href="#はじめに">はじめに</a></li> <li><a href="#ゲームアニメーションとは">ゲームアニメーションとは</a></li> <li><a href="#ゲームアニメーションを創ることの面白さ">ゲームアニメーションを創ることの面白さ</a><ul> <li><a href="#映像アニメーションを創る面白さ">映像アニメーションを創る面白さ</a></li> <li><a href="#ゲームアニメーションを創る面白さ">ゲームアニメーションを創る面白さ</a></li> </ul> </li> <li><a href="#ゲームアニメーションの難しい点">ゲームアニメーションの難しい点</a></li> <li><a href="#モノが干渉した表現当たった感じの表現と気持ちよさ">モノが干渉した表現(当たった感じの表現)と気持ちよさ</a><ul> <li><a href="#リアクション原則">リアクション原則</a><ul> <li><a href="#カメラシェイク">カメラシェイク</a></li> <li><a href="#ウエイト">ウエイト</a></li> <li><a href="#オブジェクトシェイク">オブジェクトシェイク</a></li> <li><a href="#ノックバックキャラクターが押される">ノックバック(キャラクターが押される)</a></li> <li><a href="#アニメーション">アニメーション</a></li> <li><a href="#変形形で表現する">変形(形で表現する)</a></li> <li><a href="#リアルタイム物理シミュレーション">リアルタイム物理シミュレーション</a></li> <li><a href="#ヒットエフェクト">ヒットエフェクト</a></li> <li><a href="#SE効果音">SE(効果音)</a></li> <li><a href="#スナップ">スナップ</a></li> <li><a href="#処理落ちスロー">処理落ち、スロー</a></li> <li><a href="#ハプティクス皮膚感覚フィードバック">ハプティクス(皮膚感覚フィードバック)</a></li> </ul> </li> </ul> </li> <li><a href="#どうすれば-トレーニング法">どうすれば? ~トレーニング法~</a></li> <li><a href="#最後に"> 最後に</a></li> </ul> <h3 id="はじめに">はじめに</h3> <p>さて、今回のブログの前置きですが、</p> <ul> <li>「映像アニメーション」に対応して「ゲームアニメーション」、「ゲームアニメーター」としています。</li> <li>このブログでは、ゲームのアニメーションについて、特にゲームならではの表現方法について書いています。</li> <li>ゲーム制作を勉強している、勉強しようとしている、興味がある方に向けた記事となっています。そのためプログラミングや数式、ツールは登場しません。</li> </ul> <p> </p> <p>ゲーム制作を勉強している、またはゲーム制作に興味がある皆さんは、ゲーム制作のどの部分に興味があるでしょうか?ゲームデザイン(ゲーム企画)?キャラクターデザイン?アニメーション?表示(メニュー画面のデザインやゲーム中の表示)?背景?エフェクト?それともプログラミングでしょうか?。</p> <p> 私は昔からゲームをしている中で、ゲームのアニメーションが担っている「ゲームのさわり心地」に興味があり、それをテーマに試行錯誤しています。<br /> 今回は「ゲームアニメーションと触りごこち」に焦点を絞ってブログを書きます。ゲームアニメーションの面白さ、奥深さが伝われば幸いです。</p> <p> </p> <h3 id="ゲームアニメーションとは">ゲームアニメーションとは</h3> <p>「アニメーション」という言葉について、ここでは、カートゥーンや3DCGアニメーションは「映像アニメーション」、ボタンを押すことでキャラクターが動くアニメーションを「ゲームアニメーション」と分けました。</p> <p> 考え出すと複雑になってしまうので、ゲームアニメーションとは、ここではシンプルに</p> <div><br /> <ul> <li>ボタン操作することでリアルタイムに変化するキャラクターアニメーション。<br />(<span style="-en-paragraph: true;">ボタン入力の必要ない演出的な動きと分けて考えます)</span></li> </ul> </div> <div> </div> <div>とします。補足として、これらの定義以外はゲームアニメーションではないと述べているのではありません。(ここが「考え出すと複雑になってしまう」ところです)。また、会社としての見解、取り組みを述べたものではなく、私個人の見解です。この点は誤解のないようお願い致します。<br /><br /></div> <div>ゲームアニメーター(モーションデザイナー)の仕事として求められる役割は、<br /><br /> <ul> <li><span style="color: #000000;">ゲームのアニメーション素材を制作し、実装されたゲームを遊んで確認し、アニメーションを修正。時にはディレクターやプログラマーとも相談してゲームを面白くしていく</span></li> </ul> <span style="color: #ff0000;"><br /></span>です。</div> <div> </div> <h3 id="ゲームアニメーションを創ることの面白さ">ゲームアニメーションを創ることの面白さ</h3> <p>長いことガンゲームを創りづつけて、ゲームアニメーションを創る面白さには「映像アニメーションを創る面白さ」と「ゲームアニメーションを創る面白さ」があります。それぞれ分けて考えました。</p> <h4 id="映像アニメーションを創る面白さ">映像アニメーションを創る面白さ</h4> <ul> <li>動きの重量感、しなやかさ、キャラクターの感情を動きだけで表現できる面白さ<br /><br />「演技について」考える面白さです。自分が演技しないとしても、役者としての表現追求の奥深さ<br /><br /></li> <li>時間や言語を超えて伝わる面白さ<br /><br />自分の創ったものが良ければいつまで立っても色あせない。違う文化の人にも言葉の壁を超えて伝えることができる。普遍的な魅力。</li> </ul> <h4 id="ゲームアニメーションを創る面白さ">ゲームアニメーションを創る面白さ</h4> <ul> <li>ゲームは、ボタン操作しているだけなのに、プレイヤーが重さを感じたり、爽快感を感じたりする瞬間が興味深いです。(「操作感」「さわり心地」と呼ばれるものでしょうか)<br /><br />例えば、ガンゲームであれば、ガン型コントローラーのトリガーを引いているだけなのに、弾が飛んでキャラクターに当たった感じがする。アクションゲームであれば、方向キーを押しているだけなのに、移動に加速感が感じられたり、キャラクターの疲れを感じたりする。ボタンを押しただけなのに、モノを斬っている手応えがある。といったことです。改めて考えると、「ボタンを押しただけでゲームによって感覚が変化している」と考えると不思議ですよね?<br /> さわり心地の、何年経っても変化することなく、文化や言葉の壁を超えて伝わる普遍的な点も魅力的です。例えば、ボタン操作でキャラクターが「重いブロックを押している」アクションをして、それを見たプレイヤーに重さが感じられたら、その感覚は何年経っても変わらないし、どの国の人が遊んでも、その感覚は得られるはずです。<br /> ゲームを長い期間、何度でも遊んでしまう要素の1つである「さわり心地」が追求できる点、「『ボタンを押して意図した感触が提供できているのか』といった『操作と結果』に踏み入って考える楽しさ」がこの仕事の一番興味深いところです。<br /><br /></li> <li>作成したゲームアニメーション次第でゲームが難しくなったり、簡単になったり、ゲームそのものの難易度に影響を与える<br /><br />例えば、ガンゲームのゾンビ攻撃で、「腕を振ってプレイヤーを攻撃」があるとします。腕を振るために振りかぶります。この振りかぶりのスピードが速すぎれば、プレイヤーはゾンビの攻撃に気づかず、ダメージを受けます。遅すぎれば、ゾンビは撃たれてしまい、ゲームが簡単になります。特にゾンビ攻撃については、できるだけギリギリの難易度になるよう時間をかけて調整します。自分で作成した動きでゲーム難易度に変化を与えているところが面白い点です。<br /> (HOUSE OF THE DEAD ~SCARLET DAWN~ のアニメーターは3~4人+協力会社さんでの開発です。少人数での開発のため、個人の裁量に任せられているところが大きいので、難易度調整も許されています。アニメーション調整の裁量についてはプロジェクトによって違います。特に家庭用ゲームについては厳密に仕様が決められているものもありますので、学生さんは希望する会社での個人の裁量について質問したほうが良いと思います。)<br /><br /></li> <li>ゲームの仕組みを知ることが面白い<br />仕様を「どうやって」実現するかゲームの仕組み(プログラミング)部分にもつながるパートで、ゲームの仕組みについて広く浅く理解する大変さはありますが、仕組みを知る面白さがあります。</li> </ul> <p>もし、学生さんで「自分は映像アニメーターをめざすのか、ゲームアニメーターをめざすのか」を考えるとき、これらの特徴から方向を検討しても良いかもしれませんね。</p> <p> </p> <h3 id="ゲームアニメーションの難しい点">ゲームアニメーションの難しい点</h3> <p>ゲームアニメーションを考える上で難しい点があります。それは「感覚的な部分のため人に伝えづらい」という点です。「伝えづらい」ということは、人から教えてもらうことが難しく、自分で体験して考えていかなければならないということになります。<br /> 実際に製作中のゲームレビューでも、見えにくく伝えづらい操作感や動きの気持ちよさの話になりにくく、見えやすく伝えやすいアートやゲームシステム、ゲーム性に意見が集約しがちです。もちろんこれらも重要です。しかし、先程ゲームアニメーションの魅力で挙げたとおり、時間や文化を超えて伝わる部分であるにもかかわらず、議論にならないのはもったいないと思っています。</p> <p>感覚的な部分をどう伝えるか課題ですが、海外で映像アニメーション制作している方の講演を聴いたとき、「アニメーションにはアニメーション12原則があり、それを共通言語としてコミュニケーションを取るとリテイク時に伝わりやすい」と紹介されていました。この講演から、表現のエッセンスを体系化して共通言語とすれば、感覚的なことも伝えられるのでは?というヒントをえました。</p> <p>ちなみに「アニメーション12原則」とはアニメーションを創るための基本的な要素です。言葉で説明するよりも、映像で見るとイメージしやすいのではないでしょうか。</p> <p>(音が出ます)<br /><iframe title="The illusion of life" src="https://player.vimeo.com/video/93206523?app_id=122963" width="480" height="188" frameborder="0" allowfullscreen=""></iframe><cite class="hatena-citation"><a href="https://vimeo.com/93206523">vimeo.com<br /></a></cite></p> <div class="tumblr-post" data-href="https://embed.tumblr.com/embed/post/wHHYeP7YQemk4dX9_JuLNg/84175638939" data-did="7f0bd62be3f2455c5ef0e07aded3da93fbb4f797"><a href="http://the12principles.tumblr.com/post/84175638939/appeal">http://the12principles.tumblr.com/post/84175638939/appeal</a></div> <p> <script async="" src="https://assets.tumblr.com/post.js"></script> <cite class="hatena-citation"><a href="http://the12principles.tumblr.com/">the12principles.tumblr.com</a></cite></p> <p>いかがでしょうか?基本図形が動いているだけなのに、「動きがやわらかい」「生きている感じがする」印象ではないでしょうか。12原則の要素を元にどこを修正すればよくなるのか議論したほうが修正方針が立てやすいと感じました。</p> <p> </p> <h3 id="モノが干渉した表現当たった感じの表現と気持ちよさ">モノが干渉した表現(当たった感じの表現)と気持ちよさ</h3> <p>ゲームアニメーションの感覚的な部分といっても、「モノが干渉した表現(当たった感じの表現)」「加速感の表現」「ジャンプ表現」などなど、ゲームごとに突き詰める分野が数多くあります。<br /> 今回のブログでは「モノが干渉した表現(当たった感じの表現)」にはどのようなものがあるか考えました。</p> <p>ゲームにしても、3DCGツール上にしても、現実とは違い、3D空間上では何も設定していないと、モノとモノが交差しても引っかかりもなく、すり抜けてしまいます。<br /> あなたがゲームを遊んでいて、当たった感じがするのは何らかの「仕掛け」をしているからです。<br /> 当たった感じがする「仕掛け」とは何か?私がゲーム制作の上で学んだことや、ゲームを遊びながら考えたものを、アニメーション原則のような感じで「リアクション原則」としてまとめました。</p> <h4 id="リアクション原則">リアクション原則</h4> <h5 id="カメラシェイク">カメラシェイク</h5> <p>カメラを細かく振動させるだけの古典的な方法ですが、当たった感じ、モノの重さを伝える効果があります。</p> <p>ただし、動かしすぎると3D酔いの原因になりるので、加減が難しいところです。また、カメラエフェクトのモーションブラーが入っていると、画面が汚くなってしまうことがあるので、カメラエフェクトやカメラシェイクの調整が必要です。<br /> ゲームでは、攻撃時やダメージを受けた、爆発、キャラクターが地面に倒れた、キャラクターが壁を蹴って飛び上がった、など使われていることに気づくと思います。<br /><br /></p> <p><strong>例1.「弾がカメラに当たる → 爆発して消える」</strong></p> <p>カメラシェイクが無いときは、弾が跳ね返って当たったのはわかりますが、衝撃の物足りなさがあります。<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325100959g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325100959.gif" alt="f:id:sgtech:20190325100959g:plain" /></p> <p><br />弾が当たったときと、爆発したときにカメラシェイクを追加しました。衝撃がより伝わった感じがしませんか?(この揺れでもずっと見ていると疲れてしまいますね。実際にプレイして 調整の繰り返しが必要です)<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325100918g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325100918.gif" alt="f:id:sgtech:20190325100918g:plain" /></p> <p> </p> <p><strong>例2.「キャラクターに武器が当たる」</strong></p> <p>武器がキャラクターに当たっていますが、すり抜けています。<br />これが</p> <blockquote> <p>「ゲームにしても、3DCGツール上にしても、3D空間上では何も設定していないとモノとモノが交差しても現実とは違い、引っかかりもなく、すり抜けてしまいます。」</p> </blockquote> <p>の状態です。<br />これでは物足りないので、真っ先にエフェクトを付けたくなります。しかし、動きでも解決できます。エフェクトを付けたい気持ちをグッとこらえて、カメラシェイクの効果を入れます。<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325101122g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325101122.gif" alt="f:id:sgtech:20190325101122g:plain" /><br /><br />武器の当たった感じが増していませんか?<br /> キャラクターに攻撃が当たったときの揺れは「ダメージを与えた気持ちよさを伝えるために揺らすのか」「ダメージを受けた時の痛さを伝えるために揺らすのか」プレイヤーにどちらの気持ちを与えたいのか考えて、揺れを調整する必要があります。<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325101031g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325101031.gif" alt="f:id:sgtech:20190325101031g:plain" /></p> <p><strong>例3.「2段ジャンプの踏み切り」</strong></p> <p>2段ジャンプをするキャラクターがいるとします。しかし、2段めのジャンプが分かりにくかったり、物足りなさがあります。こちらもエフェクトを付けたい気持ちをグッとこらえて、カメラシェイクを入れます。<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325100846g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325100846.gif" alt="f:id:sgtech:20190325100846g:plain" /></p> <p>「何かに当たったときだけに使うものではない」例でもあります。空中には何もありませんが、空中で踏み切った「重さ」を与えることもできます。<br /> 壁を蹴って飛び上がるときにカメラシェイクをしているゲームもありました。<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325100816g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325100816.gif" alt="f:id:sgtech:20190325100816g:plain" /></p> <h5 id="ウエイト"><span style="-en-paragraph: true; -en-clipboard: true;"><br />ウエイト</span></h5> <p>モノが当たった瞬間動きを止めて引っかかりを表現します。効果は強力で、ゲームではよく見かける表現です。当たった瞬間に動きが止まるので、プレイヤーに「当たった!」とわからせる効果があります。<br /> パズルゲームで「絵柄が揃って消える」ときの一瞬の「止め」もこちらの分類に含まれるのではないでしょうか。</p> <p>この手法もカメラシェイクに注意してゲームを遊んでいると、いろいろなところで使われていることに気づきます。</p> <p><strong>例.「キャラクターに武器が当たる」</strong></p> <p>再び武器がキャラクターに当たっているシーンです。<br />武器がキャラクターに触れたタイミングで武器の動きを止めます。<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325101735g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325101735.gif" alt="f:id:sgtech:20190325101735g:plain" /></p> <p>こちらのほうが「当たった感じ」が伝わるのではないでしょうか。<br />ゲームでは、どのタイミングで武器が当たるかわからないので、ウエイト効果はプログラミングで制御します。<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325101518g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325101518.gif" alt="f:id:sgtech:20190325101518g:plain" /></p> <h5 id="オブジェクトシェイク"> <br />オブジェクトシェイク</h5> <p>「カメラシェイク」ではカメラを動かしましたが、当たった瞬間にモノに対して細かな振動を入れることがあります。2Dゲームではよく見られる手法です。記号的な表現ですが、少ない手間で実現できるので、ゲームでは使われることが多いです。</p> <p><strong>例.「弾がドラム缶に当たる」</strong></p> <p>弾が当たっても動かなければ、プレイヤーに背景の一部と捉えられてしまいます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190325102240g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325102240.gif" alt="f:id:sgtech:20190325102240g:plain" /></p> <p>現実では重いドラム缶は跳ねる事はありませんが、ゲーム世界観によっては使える手法です。弾に当たって少しでも反応すれば、背景から独立したものである。とプレイヤーに思わせることができます。<br /> ここではドラム缶を上下に動かしましたが、左右に動かしたほうが良いでしょうか?それとも弾が当たってずれていくのが良いでしょうか?ドラム缶の反応だけでもクリエイティブ力が試されます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190325102202g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325102202.gif" alt="f:id:sgtech:20190325102202g:plain" /></p> <h5 id="ノックバックキャラクターが押される"> <br />ノックバック(キャラクターが押される)</h5> <p>格闘ゲームやアクションゲームで見られる、攻撃やガードしたキャラクターが「少し後ろにずれる動き」です。単純そうですが、実はゲーム性とも絡む、奥が深い部分ではないか、と考えています。</p> <h5 id="アニメーション"> <br />アニメーション</h5> <p>アーティストが、キャラクターが攻撃を受けてのけぞったり、よろけたり、倒れなど、キャラクターアニメーションを作成します。ゲームアニメーター(モーションデザイナー)の担当部分です。<br /> キャラクターアニメーションの弱点は「決まった動きしかしない」です。これをどう崩すかが課題で、いろいろな動きを混ぜたり、物理シミュレーションを混ぜたり、各社いろいろな取り組みをしています。</p> <p> </p> <p><strong>例.「キャラクターに武器が跳ね返される」(オブジェクトシェイク、ノックバック、キャラクターアニメーションの合わせ技)</strong></p> <p>武器がキャラクターに当たって跳ね返されるアニメーション素材に、青いキャラクターの細かな振動や後ろに下がる動きの組み込みをプログラマー、どれくらい振動して後ろに下げるのかの調整をゲームデザイナーやアーティストがそれぞれ担当し、各パートの役割の合わせ技で表現します。<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325102457g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325102457.gif" alt="f:id:sgtech:20190325102457g:plain" /></p> <h5 id="変形形で表現する"> <br />変形(形で表現する)</h5> <p>「リアクション」は動きでモノが当たった感じを表現しましたが、「変形」は形で表現します。モノが当たったタイミングで、急激に形を変化させることで、当たった感じを表現します。<br /> ゲームでは現実と同じ壊れ方や変形を再現すると、非常に手間と時間がかかるので、記号的な変形が使われることがあります。</p> <p>ゲーム中では車や壁、小物が一瞬で変形したり、シューティングゲームで敵機体が壊れていくのを確認できます。<br /><br /></p> <p><strong>例1.「ドラム缶が壊れる」</strong></p> <p>ゲーム特有の「記号的な表現」です。<br />現実では弾が当たるたびに少しづつ変形しますが、ここでは一定数弾が当たると変形する仕組みになっています。徐々に変形していくのがリアルですが、ゲームでは一気に形が変形したほうが気持ち良さが増します。<br />変形の効果だけでは当たった感じは弱いので、他の効果も合わせて表現します。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190325101405g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325101405.gif" alt="f:id:sgtech:20190325101405g:plain" /></p> <p><strong><br />例2.「キャラクターを踏み潰す」</strong></p> <p>青がプレイヤー、赤が敵のイメージです。<br />敵が踏みつけられたとき、敵がペチャンコになることで、プレイヤーに「敵をやっつけた」とわからせると同時に「気持ちよさ」を提供します。<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325101224g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325101224.gif" alt="f:id:sgtech:20190325101224g:plain" /></p> <h5 id="リアルタイム物理シミュレーション"> <br />リアルタイム物理シミュレーション</h5> <p>ゲームエンジンでは物理シミュレーションが搭載されているので、より現実的な動きを表現できるようになりました。キャラクターアニメーションの弱点「決まった動きしかしない」は克服できますが、意図する動きにするには非常に時間と手間がかかります。<br /><br /></p> <h5 id="ヒットエフェクト">ヒットエフェクト</h5> <p>当たった瞬間にヒットマークを出したり、当たったモノを点滅させたり、エフェクトを表示する、ゲームでは必ず見かける手法です。</p> <p>爆発や攻撃が当たったとき、カメラのストロボ発光のように画面をフラッシュさせる手法もありますが、<a href="https://ja.wikipedia.org/wiki/%E5%85%89%E9%81%8E%E6%95%8F%E6%80%A7%E7%99%BA%E4%BD%9C">光過敏性発作 (Wikipedia)</a>という問題があるので、使用はあまり好ましくありません。アーケードゲームでは過剰な発光をしないよう計測しながら開発しています。</p> <h5 id="SE効果音"> <br />SE(効果音)</h5> <p>「音は物質を定義する」と何かで聞いたことがあります。例えば、白い画面に■ (ただの小さい四角形) が横切る動きに、蚊やハエの羽音のSEをつければ人は■を蚊やハエと認識できます。</p> <p>ゲーム効果音にもいくつか種類があると考えています。</p> <ul> <li>質感を伝えるSE(想像系)<br />現実ではありえない音ですが、質感が伝わる音。例えば20年前の2D格闘ゲームのガード音、キャラクターが敵に触れてやられたときのSE、30年前のシューティングゲームの爆発音など、「バシッ!」や「ドカーン!」ではない音</li> <li>見た目、イメージ通りのSE(リアル系)<br />映画の効果音のようなリアルと感じられる音。</li> <li>特殊<br />攻撃ヒット時に和音を鳴らしたり、音楽にヒットSEを合わせたりしたもの。</li> </ul> <p> </p> <h5 id="スナップ">スナップ</h5> <p>アイテム欄に装備をドラッグ・アンド・ドロップした時、「カチッ」とハマる演出がこれにあたります。office製品やグラフィックソフトでも「スナップ」という機能があり、「ピタッ」とくっついた瞬間に気持ちよさと「合った!」という感覚があると思います。</p> <p><strong>例.「離れているキャラクターを引き寄せる」</strong></p> <p>あるゲームでは「キャラクターが離れていても引きつけて投げる」技があります。ゲームとして見事な手応えが感じられます。組み合った瞬間に「ウエイト」演出が含まれています。<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325104706g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325104706.gif" alt="f:id:sgtech:20190325104706g:plain" /></p> <h5 id="処理落ちスロー">処理落ち、スロー</h5> <p>格闘ゲームの最後の一撃を決めて、ゆっくり吹っ飛ぶ演出がこれにあたります。ヘッドショットが成功するとスローになる演出のゲームもあります。「ここぞ!」という時に使う事で特別な、より強い手応えを表現できます。</p> <p><strong>例1.フィニッシュブロー</strong></p> <p>キャラクターの最後の一撃をくらったやられ演出です。もう少し「やっつけた!、やられた!」という余韻を提供したいところです。<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325102814g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325102814.gif" alt="f:id:sgtech:20190325102814g:plain" /></p> <p> </p> <p>攻撃が当たった後、スローを入れました。最後の一撃の感覚を長く残すことで、やっつけた、やられたの感覚を強調することができます。<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325102642g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325102642.gif" alt="f:id:sgtech:20190325102642g:plain" /><br /> </p> <p><strong>例2.撃破</strong></p> <p>モノに当たった感じの表現とはずれますが、気持ちよさにつながる部分だと思います。<br />シューティングゲームのボス機体を破壊したイメージです。激闘の末にこの終わり方をしたら、プレイヤーはどんな気持ちになるでしょうか。<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325102554g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325102554.gif" alt="f:id:sgtech:20190325102554g:plain" /></p> <p>最後の爆発でエフェクトの動きをスローにしました。「爆発した」ことを強調することで、倒した達成感を長持ちさせる効果があります。<br /><img class="hatena-fotolife" title="f:id:sgtech:20190325110007g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190325/20190325110007.gif" alt="f:id:sgtech:20190325110007g:plain" /></p> <h5 id="ハプティクス皮膚感覚フィードバック">ハプティクス(皮膚感覚フィードバック)</h5> <p>身近なところではコントローラーの振動があります。ゲームエンジンでもコントローラーを振動させることができます。モノに当たった瞬間にコントローラーを振動させることで、当たった感じを提供します。<br /> その他、引っ張られる感覚が得られたり、圧力が感じられる装置の研究が進んでいます。(セガ・インタラクティブでも新しい感覚を伝えられる装置の調査、研究をしている部署があります)</p> <p> </p> <p> </p> <p>以上がゲームでよく見られる「当たった感じがする『仕掛け』」だと考えています。</p> <p>これらを組み合わせてゲームにしていきます。ただし、注意点があります。</p> <ul> <li>「意図したことがプレイヤーに伝わっているか?」「個々の原則は十分調整されているか」を考える<br />例えば、迫力を出そうと爆発エフェクトを大きくしたところ、キャラクターの動きが見えない、変形が見えない、などのことがあります。それぞれの要素をバランスよく考える事が大事です。とは言うものの、私も実装してから「しまった」と思ったり、指摘されて気づくことが多々ありますので、これは永遠の課題です。</li> <li>タイミング<br />モノに当たって、エフェクトやリアクションを「いつ開始するか」が重要です。タイミングがずれていると原則を組み合わせてもよくなりません。</li> </ul> <p>  </p> <h3 id="どうすれば-トレーニング法">どうすれば? ~トレーニング法~</h3> <p>「ゲームアニメーションの難しい点」でも述べたとおり、感覚的な部分なので、作例を見て「なるほど!そういえば!」と思う方もいれば、「当たり前のことじゃん」「そうなんだ」「そうなのかなぁ」と思う方もいらっしゃるかもしれません。重要なのは、これらの原則を頭の片隅に置きつつ「ゲームを遊んで、実感して、自分なりの仮設を立てて、実践(制作)していく」ことです。</p> <p>面白いと思うゲームを遊んで、なぜさわり心地がいいか考えるうちに表現力もあがる。一石二鳥ですね(笑)。</p> <p> </p> <h3 id="最後に"> 最後に</h3> <p>面接で「ゲームが好きです!」という学生さんは多いのですが、もう一歩「ゲームのどんなところに注目して遊んでいるのか」「どこが、なぜよかったのか」「(気になる点があれば)自分だったらこうしたい!」を伝えられると、より良いアピールになるのでは?と考えてブログを書かせていただきました。</p> <p>ゲームアニメーションを希望する方が増えることを願ってやみません。</p> <p> </p> <p>セガ・インタラクティブは2019年2月より<a href="https://recruit.sega.jp/environment/office/">大崎オフィス</a>に引っ越しました。コンビニや社員食堂、カフェ、バーコーナーなど充実した施設があるオフィスです。気持も新たに業務に励んでいます。</p> <p> </p> <p>ご興味ありましたら、下記の弊社グループ採用サイトをご確認ください。</p> <p><a href="http://sega-interactive.co.jp/recruit/" onmousedown="ga('HatenaBlogUserTracker.send', 'event', 'recruit', 'sic_banner_clicked','recruit_sic_out', true);">採用情報|株式会社セガ・インタラクティブ - 【SEGA Interactive Co., Ltd.】</a></p> <p> </p> <p> <strong style="color: #000000; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial;">©SEGA</strong></p> <p> </p> sgtech Tricks of Realtime VFX with Houdini詳細解説 vol.1 hatenablog://entry/17680117126979405933 2019-02-28T18:00:00+09:00 2019-03-13T14:02:16+09:00 こんにちは、セガゲームス龍が如くスタジオの伊地知です。 去年もHoudiniのお話をこのSEGA TECH Blogで掲載しており、これで二回目となります。 さる2018年12月2日にCEDEC+KYUSHU2018が開催されたのですが その時私の方で講演させていただいたTricks of Realtime VFX with Houdiniというセッションがありまして (セッションのスライドはこちらからダウンロード出来ます。) そのスライドの後半に 「実際にすぐにゲームに出して使えるエフェクトのテクニック」=「トリック」 を3つご紹介させて頂きました。 その3つのトリックを今回のSEGA TE… <p>こんにちは、セガゲームス龍が如くスタジオの伊地知です。</p> <p> 去年もHoudiniのお話をこのSEGA TECH Blogで掲載しており、これで二回目となります。</p> <p>さる2018年12月2日にCEDEC+KYUSHU2018が開催されたのですが</p> <p>その時私の方で講演させていただいたTricks of Realtime VFX with Houdiniというセッションがありまして</p> <p>(セッションのスライドは<a href="https://drive.google.com/open?id=11hpyQxoat5ZkZDpFnaqL-OapRtNFf7BT">こちら</a>からダウンロード出来ます。)</p> <p>そのスライドの後半に</p> <p>「実際にすぐにゲームに出して使えるエフェクトのテクニック」=「トリック」</p> <p>を3つご紹介させて頂きました。</p> <p>その3つのトリックを今回のSEGA TECH Blogで詳細に解説させて頂きます。</p> <p> </p> <ol> <li>加工して戻す(RestSOP) ー <a href="https://bit.ly/2DNMr0B">processAndRest01.hip</a></li> <li><span style="color: #cccccc;">独自シミュレーション(SolverSOP)</span></li> <li><span style="color: #cccccc;">最短経路探索(FindShortestPath)</span><br /><br /></li> </ol> <p>3ついっぺんにやると果てしなく長いので全部で3回に分け、</p> <p>今回は1つ目である「加工して戻す」というトリックだけを扱うことにします。</p> <p>シーンファイルもご利用頂けますしHoudiniの体験版(Apprentice版)でも開けますので</p> <p>実際にご自身のPC(Windows)、Mac、Linuxで確認しながらご覧になるとご理解いただきやすいでしょう。</p> <p>(HoudiniはいろんなOSに対応しています!) </p> <p> </p> <p>今回は初心者の方でも安心の詳細解説となっております。</p> <p>またwrangleの行数も最低限に抑えてあります。 </p> <p>操作方法や基礎知識に関しては1年前の前回のHoudiniの回でも</p> <p><iframe class="embed-card embed-blogcard" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" title="そんなことよりHoudiniやろうぜ! - SEGA TECH Blog" src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Ftechblog.sega.jp%2Fentry%2F2018%2F01%2F25%2F100000" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="http://techblog.sega.jp/entry/2018/01/25/100000">techblog.sega.jp</a></cite></p> <p>御紹介させおりますのでその辺が分からない方はそちらも合わせてご覧下さい。</p> <p> </p> <hr width="100%" /> <h4>1.加工して戻す(RestSOP)</h4> <p>では1つ目のトリックの内容から説明させて頂きます。</p> <p>Houdiniの新規シーンを開いた想定でお話をさせて頂きます。</p> <p>ダウンロードして頂いた方はシーンを上から順にデータを見ていって下さい。</p> <p>まず画面一番左下のボタン</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233230p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233230.png" alt="f:id:sgtech:20190224233230p:plain" /></p> <p>を押してGlobal Animation Optionsを開きます。</p> <p><strong>FPS</strong>を<strong>30</strong>、<strong>End</strong>を<strong>256</strong>にして<strong>SaveAsDefault</strong>ボタンを押します。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233226p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233226.png" alt="f:id:sgtech:20190224233226p:plain" /></p> <p>ネットワークエディタのオブジェクトレベルでTabキーを押しTabメニューでgeと押すと候補が出ますのでGeometryを選び作ります。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233347p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233347.png" alt="f:id:sgtech:20190224233347p:plain" /></p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233344p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233344.png" alt="f:id:sgtech:20190224233344p:plain" /></p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233340p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233340.png" alt="f:id:sgtech:20190224233340p:plain" /></p> <p>できたgeo1にダブルクリックやiキーなどでジオメトリレベルに潜ります。</p> <p>たいていの作業はこのジオメトリレベルで行う事になります。</p> <p> </p> <p>Tabメニューから<strong>Sphere</strong>を選択してPrimitiveTypeを<strong>Polygon</strong></p> <p>Frequencyを<strong>50</strong>にします。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233155p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233155.png" alt="f:id:sgtech:20190224233155p:plain" /></p> <p> </p> <p>次にTabメニューから<strong>UVTexture</strong>を出してつなげます。</p> <p>TextureTypeを<strong>Polar</strong>、<strong>Fix Boundary Seamsにチェック</strong>します。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233149p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233149.png" alt="f:id:sgtech:20190224233149p:plain" /></p> <p>この状態でビュー上で<strong>Space+5</strong>を押すとUVの状態が確認出来ます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233143p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233143.png" alt="f:id:sgtech:20190224233143p:plain" /></p> <p>UVが01の範囲内からはみ出していると都合が悪いので</p> <p>Tabメニューから<strong>UV Transform</strong>を出してUV Textureにつなげ</p> <p><strong>Scale</strong>の<strong>X</strong>の値に <strong>1/$XMAX</strong> と入力します。</p> <p>これはUV値のUの最大値で全体を割るという意味で</p> <p>こうする事によって01の範囲内に収めます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233137p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233137.png" alt="f:id:sgtech:20190224233137p:plain" /></p> <p>ビュー上で<strong>Space+1</strong>を押してPerspectiveに戻します。</p> <p>Tabメニューから<strong>PointWrangle</strong>を出してUV Transformの出力につなげます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233131p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233131.png" alt="f:id:sgtech:20190224233131p:plain" /></p> <p>ポイントアトリビュートの@rest,@Cd,@Alphaを設定します。 </p> <p>VEXpressionの欄に下記のコードを記述します。</p> <pre class="code" style="overflow: auto hidden; padding: 10px; background: #fafafa; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 0px 5px inset; font-family: Monaco, Consolas, 'Courier New', Courier, monospace, sans-serif; color: #000000; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-lang="" data-unlink="">v@rest = @P; f@Alpha = 0.0; @Cd = {1,1,1};</pre> <p>@はアトリビュートという意味でジオメトリのクラス(Point,Vertex,Primitive,Detail)自体に持たせる変数です。@の前のvやfは型を指定しておりvならベクター、fならフロートを定義します。ここではRunOverがPointになっているのでPointのクラスのアトリビュートを制御するという事になります。</p> <p>@restはポジション(@P)を保持しておく為のアトリビュート。</p> <p>頂点α(@Alpha)は0で初期化、頂点カラー(@Cd)は白で初期化という意味になります。</p> <p>Tabメニューから<strong>PointWrangle</strong>を出して先程のPointWrangleにつなげます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233244p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233244.png" alt="f:id:sgtech:20190224233244p:plain" /></p> <pre class="code" style="overflow: auto hidden; padding: 10px; background: #fafafa; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 0px 5px inset; font-family: Monaco, Consolas, 'Courier New', Courier, monospace, sans-serif; color: #000000; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-lang="" data-unlink="">f@Alpha = 1.0;</pre> <p>VEXpressionの欄にはこの様に記述します。</p> <p>再度Alphaを1にするのには訳がありますがそれはあとで解説します。</p> <p>Tabメニューから<strong>Twist( or Bend)</strong>を出して先程のPointWrangleにつなげます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233240p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233240.png" alt="f:id:sgtech:20190224233240p:plain" /></p> <p><strong>Limit Deformation to Capture Region</strong>のチェックを外し</p> <p><strong>Twist</strong>の値を<strong>360</strong>、<strong>Capture Origin</strong>のZを<strong>-1</strong>、<strong>Capture Length</strong>を<strong>2</strong>にします。</p> <p>こうする事で球がZ軸に沿って360度ねじれます。</p> <p>Tabメニューから<strong>Mountaion</strong>を出して先程のBendにつなげます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233233p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233233.png" alt="f:id:sgtech:20190224233233p:plain" /></p> <p>Mountainノードの<strong>Height</strong>を<strong>1.73</strong>、<strong>Element Size</strong>を<strong>2.18</strong>、<strong>Scale</strong>を<strong>0.06</strong>,<strong>0.16</strong>,<strong>0.06、</strong></p> <p><strong>Offset</strong>の<strong>X</strong>値を<strong>-14</strong>に設定し<strong>Y</strong>値は<strong>20</strong>に設定し<strong>1フレーム目</strong>で<strong>Altキーを押しながらクリック</strong>、<strong>256フレーム目</strong>で<strong>18</strong>と設定し<strong>Altキーを押しながらクリック</strong>。</p> <p>これでパラメータの欄が緑色になったのが分かります。</p> <p>これはアニメーションが設定されていますという事を現しています。</p> <p>ちなみにShiftを押しながらクリックでアニメーションエディタが開きます。</p> <p><strong>Max Octaves</strong>を<strong>9</strong>、<strong>Lacunarity</strong>を<strong>2.19</strong>、<strong>Roughness</strong>を<strong>0.407</strong>とします。</p> <p>この状態で再生ボタン(画面左下にあります)を押すか、カーソルキーの↑を</p> <p>押してみて下さい。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233321g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233321.gif" alt="f:id:sgtech:20190224233321g:plain" /></p> <p>球のトゲトゲが蠢きながら下に流れていくアニメーションが確認出来ます。</p> <p>確認出来たら停止ボタン(画面左下にあります)を押すか、Ctrl+↑を押して止めて下さい。</p> <p>Tabメニューから<strong>Transform</strong>を出して先程のMountainにつなげます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233317p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233317.png" alt="f:id:sgtech:20190224233317p:plain" /></p> <p><strong>Rotate</strong>の<strong>X</strong>値を<strong>31</strong>、<strong>Y</strong>値を<strong>5</strong>、<strong>Z</strong>値を<strong>5</strong>とし少し回転させます</p> <p>Tabメニューから<strong>Clip</strong>を出して先程のTransformにつなげます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224234332p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224234332.png" alt="f:id:sgtech:20190224234332p:plain" /></p> <p>先程と同じ要領で<strong>Distance</strong>の<strong>1フレーム目</strong>に<strong>-1.25</strong>、<strong>256フレーム目</strong>に<strong>1.36</strong>とキーを打ちます。</p> <p>この状態で再生させると下半分が削れた状態が段々と上に上がっていって</p> <p>トゲトゲの球が消えていくのが分かります。</p> <p>Tabメニューから<strong>PointWrangle</strong>を出して先程のClipにつなげます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224234328p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224234328.png" alt="f:id:sgtech:20190224234328p:plain" /></p> <pre class="code" style="overflow: auto hidden; padding: 10px; background: #fafafa; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 0px 5px inset; font-family: Monaco, Consolas, 'Courier New', Courier, monospace, sans-serif; color: #000000; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-lang="" data-unlink="">@P = @rest;</pre> <p>VEXPressionの欄にこの1行を入力すると歪められていたポイントのポジションが元に戻ります。</p> <p>この挙動を不思議に思う方もいらっしゃるかもしれませんがこれは</p> <p>単純に@restに保持していた座標で元の位置に戻っただけなのです。</p> <p>しかし消されたポイントは戻りません。</p> <p>歪んだ状態で水平に切るという事は座標を戻すと水平では無く歪んだ状態で削れていくのです。</p> <p>↑キーで再生させるとこの様に動作しているのが確認出来るでしょう。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224234240g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224234240.gif" alt="f:id:sgtech:20190224234240g:plain" /></p> <p>映像の表現ならここまでで良いですがゲームの場合</p> <p>ゲーム中で表現する為に工夫が必要です。</p> <p> CEDEC+KYUSHU2018では私はテクスチャパターンアニメーションでやりましょうと言ってしまいましたが実はもっと良いαカットオフを用いた手法があります。</p> <p>シェーダ側でαしきい値を用いて透明にするのですが</p> <p>そのαをどう出すのかがこのトリックの鍵になります。</p> <p>2つ目のトリックで紹介するSolverというノードをもうここで使います。</p> <p>毎フレーム値を加工して蓄積させていく事が出来るノードで評価した結果を</p> <p>キャッシュしておくことが出来ます。</p> <p>Tabメニューから<strong>Solver</strong>を出して上から4つ目のpointwrangle1から</p> <p>左から1番目のところにつなげて左から二番目の入力にpointwrangle3をつなげます。</p> <p> </p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224234238p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224234238.png" alt="f:id:sgtech:20190224234238p:plain" /></p> <p>ダブルクリックしてsolver1の中に潜ります。</p> <p> Tabメニューから<strong>AttributeTransfer</strong>を出してPrev_Frameを第一入力に</p> <p>Input_2を第二入力につなげPointsにチェックを付けAlphaを指定します。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224234234p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224234234.png" alt="f:id:sgtech:20190224234234p:plain" /></p> <p>AttributeTransferは第一入力に対し第二入力のアトリビュートを近いものから転写していくノードです。MayaであればTransferAttribute、Softimageをお使いだった方ならGATORを御存知だと思いますがその万能版だと思って頂ければ理解が早いかと思います。(Softimageユーザーの方ならMayaのTransferAttributeなんかと比べられるのは屈辱だと思いますがHoudiniのAttributeTransferからすればどちらも五十歩百歩です。)</p> <p>SolverSOPの中でこの様なつなぎ方をすると前のフレームの結果に対し現在のフレームの第二入力のアトリビュートを転写するという意味を持ちます。</p> <p>Tabメニューから<strong>PointWrangle</strong>を出して第一入力にPrev_Frame、第二入力にAttributeTransferをつなげます</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233439p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233439.png" alt="f:id:sgtech:20190224233439p:plain" /></p> <p>VEXpressionの欄には </p> <pre class="code" style="overflow: auto hidden; padding: 10px; background: #fafafa; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 0px 5px inset; font-family: Monaco, Consolas, 'Courier New', Courier, monospace, sans-serif; color: #000000; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-lang="" data-unlink="">@Alpha += @opinput1_Alpha/256;</pre> <p> と記述します。</p> <p>このコードと接続の意味は前のフレームの結果のアルファに対し</p> <p>第二入力のアルファを256で割った数値を加算するという意味になります。</p> <p>つまりこの2つのノードの意味は毎フレーム現在のアルファ値の1/256を</p> <p>加算し続けるということになります。</p> <p> </p> <p>uキーで1つ上の階層に戻って256フレーム目まで進めます。</p> <p>すると球がこの様に見えているはずです。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233435p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233435.png" alt="f:id:sgtech:20190224233435p:plain" /></p> <p>毎フレームアルファ値を累積して256フレーム分貯めた結果がこれです。</p> <p>これをUV座標に基づいてテクスチャに書き出してやります。</p> <p>GameDevelopmentToolsetのSimpleBakerを使うやり方が最も簡単でしょう。</p> <p>GameDevelopmentToolsetのインストールの最も簡単な方法は左上の</p> <p>GameDevelopmentToolsetタブのUpdateToolsetボタンを押すことです。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233432p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233432.png" alt="f:id:sgtech:20190224233432p:plain" /></p> <p>ゲーム会社や映像スタジオ、CGスクールなどでプロキシ環境下であれば</p> <p>この機能がうまくいかない場合があります。</p> <p>その際は<a href="https://github.com/sideeffects/GameDevelopmentToolset/tree/Development">公式のgithub</a>からダウンロードして手動でインストールして下さい。</p> <p>GameDevelopmentToolsetがインストールされた状態になったら</p> <p>Tabメニューから<strong>GameDev Simple Baker</strong>を出して下さい。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233430p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233430.png" alt="f:id:sgtech:20190224233430p:plain" /></p> <p>ここで普通に考えればアルファにチェックを入れれば出力出来るはずなんですが</p> <p>何故か真っ白になってしまうので一旦@Cdに@Alphaを移して</p> <p>basecolorとして出力する事になります。</p> <p> simple bakerの1つ前に<strong>PointWrangle</strong>を足して</p> <pre class="code" style="overflow: auto hidden; padding: 10px; background: #fafafa; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 0px 5px inset; font-family: Monaco, Consolas, 'Courier New', Courier, monospace, sans-serif; color: #000000; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-lang="" data-unlink="">@Cd = @Alpha;</pre> <p> 記述して頂点カラーにアルファを移してからsimple baker でテクスチャを焼きます。</p> <p>すると</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233426p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233426.png" alt="f:id:sgtech:20190224233426p:plain" /></p> <p>この様なテクスチャが焼き上がりますのでPhotoshop上でレベル補正かけたり</p> <p>トーンカーブで補正かけたりして1~254くらいの値の範囲にしておくと</p> <p>シェーダに食わせた時の見た目が良い様です。</p> <p> </p> <p>モデルの方も同時に出力しておきます。</p> <p> UVを設定したuvtransform1から出すと良いのですがそのままだと</p> <p>25,000頂点もありかなりメモリを食ってしまいます。</p> <p>uvtransform1の下に<strong>PolyReduce</strong>を作ってつなげます。</p> <p> <strong>Percent To Keep</strong>を<strong>1</strong>に<strong>Vertex Attribute Seams</strong>を<strong>0.4</strong>にして頂点数を252にまで</p> <p>落とします。ゲーム内で綺麗に見える最低限の頂点数であれば Percent To Keepを</p> <p>いろいろ試してみても良いでしょう。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190224233533p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190224/20190224233533.png" alt="f:id:sgtech:20190224233533p:plain" /></p> <p>Tabメニューから<strong>ROP FBX Output</strong>を出してつなげます。</p> <p> <strong>Output File</strong>を指定して<strong>Save to Disk</strong>ボタンを押します。</p> <p>これでモデルファイルも出力出来ました。</p> <p> ではUnity上で確認してみましょう。</p> <p>普通のスタンダードシェーダでは両面に対応していないので</p> <p><strong>Create -&gt; Shader -&gt; Standard Surface Shader</strong></p> <p>で作ったものにちょい足ししたシェーダで表示してみましょう。</p> <pre class="code" style="overflow: auto hidden; padding: 10px; background: #fafafa; border-radius: 3px; box-shadow: rgba(0, 0, 0, 0.2) 0px 0px 5px inset; font-family: Monaco, Consolas, 'Courier New', Courier, monospace, sans-serif; color: #000000; font-size: 13px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;" data-lang="" data-unlink="">Shader "Custom/doubleSidedCutOff" { Properties { _Color ("Color", Color) = (1,1,1,1) _Cutoff ( "Cutoff", Range(0, 1) ) = 0.5 _MainTex ("Albedo (RGB)", 2D) = "white" {} _Glossiness ("Smoothness", Range(0,1)) = 0.5 _Metallic ("Metallic", Range(0,1)) = 0.0 _BumpMap ( "Normal Map" , 2D ) = "bump" {} _BumpScale ( "Normal Scale" , Range(0,1) ) = 1.0 } SubShader{ Tags { "Queue" = "AlphaTest" "RenderType"="TransparentCutout" } LOD 200 Cull Off CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Standard fullforwardshadows alphatest:_Cutoff // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; sampler2D _BumpMap; struct Input { float2 uv_MainTex; }; half _Glossiness; half _Metallic; half _BumpScale; fixed4 _Color; // Add instancing support for this shader. You need to check 'Enable Instancing' on materials that use the shader. // See https://docs.unity3d.com/Manual/GPUInstancing.html for more information about instancing. // #pragma instancing_options assumeuniformscaling UNITY_INSTANCING_BUFFER_START(Props) // put more per-instance properties here UNITY_INSTANCING_BUFFER_END(Props) void surf (Input IN, inout SurfaceOutputStandard o) { // Albedo comes from a texture tinted by color fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // Metallic and smoothness come from slider variables o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; fixed4 n = tex2D( _BumpMap, IN.uv_MainTex); o.Normal = UnpackScaleNormal(n, _BumpScale); } ENDCG } FallBack "Transparent/Cutout/VertexLit" }</pre> <p>このシェーダをアサインしたマテリアルを用意して適当なテクスチャを貼ってあげます。</p> <p>その際テクスチャのアルファに先程生成したテクスチャを入れ込んでおきます。</p> <p>するとこの様に表示されます。</p> <p><iframe src="https://www.youtube.com/embed/t3i5Ditl0cw?feature=oembed" width="640" height="360" frameborder="0" allowfullscreen=""></iframe><cite class="hatena-citation"><a href="https://youtu.be/t3i5Ditl0cw">youtu.be</a></cite></p> <p> </p> <p>@restに座標を保持して戻す時に削れたpointが戻らないのは当然としても</p> <p>生成されたpointがちゃんと良い感じの場所に戻ってくれるのは凄いと思います。</p> <p>中で一体どういう処理が走ってるんでしょうか?気になります。 </p> <p>累積アルファのカットオフはテクスチャパターンアニメーションでやるより</p> <p>遥かに質も向上しメモリも削減出来る賢いやり方なので</p> <p>覚えておいて損は無いでしょう。</p> <p> </p> <p>さて今回はここまでです、いかがでしたでしょうか?<br />ゲームに出力する部分は様々な手法を考慮し工夫する必要があります。</p> <p>現状ビルボードが主流のゲームエフェクトですがこんなトリックを用いる事で思いがけない表現をプレイヤーの方々にお見せし感動体験を演出する事も可能になるのです。</p> <p>ゲームエンジン側の知識もフル動員すればもっと凄いものが表現出来るでしょう。</p> <p>勉強する事は山程ありますし考えなければいけない事もいっぱいあります。</p> <p>ですがやりたい表現が達成出来た時の喜びもまたひとしおです。</p> <p>次回のHoudiniの記事もお楽しみに。 </p> <p> </p> <p>この記事に興味を持って頂けた方は弊社で私達と一緒に働いてみませんか?</p> <p>弊社ではHoudiniに興味を持って取り組めるような人を募集しています!<br />我こそはという方、興味のある方は以下のリンクを是非クリックしてみてください。</p> <p> <br /><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="採用情報|株式会社セガゲームス -【SEGA Games Co., Ltd.】" src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fsega-games.co.jp%2Frecruit%2Findex.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="http://sega-games.co.jp/recruit/index.html" onmousedown="ga('HatenaBlogUserTracker.send', 'event', 'recruit', 'games_banner_clicked','recruit_games_out', true);">sega-games.co.jp</a></cite></p> <p> </p> <p><span style="color: #000000; font-family: 'Segoe UI', 'Helvetica Neue', 'Apple Color Emoji', 'Segoe UI Emoji', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">©SEGA</span></p> <p> </p> sgtech Are you readyyy to Deep Learning!? hatenablog://entry/10257846132710571438 2019-01-25T10:00:00+09:00 2019-02-24T23:49:47+09:00 セガゲームス第4事業部第4開発1部TA(テクニカルアーティスト)セクション*1 宮下です。2019年が始まって早1カ月がたとうとしてますが、あなたにとって2018年はどんな年でしたか?(少々時期外れな質問なのですが…) Readyyy! 私は2019年2月1日にリリースされたスマホタイトル「Readyyy!」に携わっており、とても忙しい1年でした。このタイトルは、プレイヤーが新人プロデューサー兼寮長として、男子高校生アイドル18人を育成するスマホゲームで、ゲームエンジンUnity*2を使って開発しています。 Readyyy! キービジュアル TAとして、3Dによるチビメンや「Live2D*3」… <p> セガゲームス第4事業部第4開発1部TA(テクニカルアーティスト)セクション<a href="#f-14bd32fd" name="fn-14bd32fd" title="1月に組織改編がありまして部署名が変わりました。">*1</a> 宮下です。2019年が始まって早1カ月がたとうとしてますが、あなたにとって2018年はどんな年でしたか?(少々時期外れな質問なのですが…)</p> <h3>Readyyy!</h3> <p> 私は2019年2月1日にリリースされたスマホタイトル<span style="color: #d32f2f;"><strong>「Readyyy!」</strong></span>に携わっており、とても忙しい1年でした。このタイトルは、プレイヤーが新人プロデューサー兼寮長として、男子高校生アイドル18人を育成するスマホゲームで、ゲームエンジンUnity<a href="#f-6df46c26" name="fn-6df46c26" title="https://unity3d.com/jp">*2</a>を使って開発しています。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="Readyyy! キービジュアル"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190120235301p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120235301.png" alt="f:id:sgtech:20190120235301p:plain" /></p> <figcaption>Readyyy! キービジュアル</figcaption> </figure> <p> TAとして、3Dによるチビメンや「Live2D<a href="#f-84d50e50" name="fn-84d50e50" title="ここではLive2D Cubismのこと。2Dイラストに擬似3D的な滑らかなアニメーションを追加することのできるソフト。Spineという海外の競合ソフトがある。また、最近はVTuberにも良く使われている。https://www.live2d.com/ja/products/cubism3">*3</a>」の立ち絵をはじめとする「Readyyy!」の技術的なグラフィック表現の根幹を担っています。特に立ち絵については、ライティングという結構面白いことしているんですよ。</p> <p> 昼間、夕方、逆光などの環境によるライティングを実現するための仕組みの設計と、それに関連するシェーダーやコンポーネント<a href="#f-3520c89b" name="fn-3520c89b" title="Unityにおいてオブジェクトの振る舞いを記述するためのスクリプトのこと。">*4</a>を作りました。そのデータを「Photoshop」や「Live2D」から出力するためのツール整備もしています。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="昼間順光の表現"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190120235043j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120235043.jpg" alt="f:id:sgtech:20190120235043j:plain" /></p> <figcaption>昼間順光の表現</figcaption> </figure> <figure class="figure-image figure-image-fotolife mceNonEditable" title="夕焼け逆光の表現"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190120235101j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120235101.jpg" alt="f:id:sgtech:20190120235101j:plain" /></p> <figcaption>夕焼け逆光の表現</figcaption> </figure> <center><center><iframe src="https://www.youtube.com/embed/LGMrZ5DfXOs" width="600" height="338" frameborder="0" allowfullscreen=""></iframe></center> <p> ご興味あれば、ぜひ遊んでみてください!</p> <center> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="TOP(トップ) - 『Readyyy!』公式サイト" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fready.sega.jp%2F" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://ready.sega.jp/">ready.sega.jp</a></cite></p> </center></center> <h3>CEDEC+KYUSHU2018</h3> <p> 実はこのセガテックブログのおかげで、昨年12月に「CEDEC+KYUSHU2018」での講演という、貴重な体験をさせていただきました。おかげというのは、「CEDEC+KYUSHU2018」の関係者の方が、2017年に私の書いた記事、</p> <center> <p><iframe class="embed-card embed-blogcard" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" title="Ruby on Railsでアセットライブラリを作ろう! - SEGA TECH Blog" src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Ftechblog.sega.jp%2Fentry%2F2017%2F12%2F25%2F100000" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="http://techblog.sega.jp/entry/2017/12/25/100000">techblog.sega.jp</a></cite></p> </center> <p>をご覧になって、講演を依頼してくださったのです。</p> <p> 今回は、そのとき講演した5つの自動化効率化のお話<a href="#f-94c5c29f" name="fn-94c5c29f" title="https://cedil.cesa.or.jp/cedil_sessions/view/1972">*5</a>の中から、ディープラーニングをテーマにしたものにプラスアルファしてお届けします。</p> <p> 「CEDEC+KYUSHU2018」での講演をお聞きになった方も復習を兼ねてご覧いただければと思います。説明も、より丁寧になっていますので!</p> <h3>ディープラーニングで自動的にサムネイルを作れないか!?</h3> <p> 前置きが大変長くなりました。それでは始めましょう!</p> <p> なお、ディープラーニングを勉強するのに<a href="https://www.amazon.co.jp/%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E4%BD%9C%E3%82%8BDeep-Learning-%E2%80%95Python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%81%AE%E7%90%86%E8%AB%96%E3%81%A8%E5%AE%9F%E8%A3%85-%E6%96%8E%E8%97%A4-%E5%BA%B7%E6%AF%85/dp/4873117585/ref=sr_1_1?ie=UTF8&amp;qid=1547523207&amp;sr=8-1&amp;keywords=%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0">「</a><span id="productTitle"><a href="https://www.amazon.co.jp/%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E4%BD%9C%E3%82%8BDeep-Learning-%E2%80%95Python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%81%AE%E7%90%86%E8%AB%96%E3%81%A8%E5%AE%9F%E8%A3%85-%E6%96%8E%E8%97%A4-%E5%BA%B7%E6%AF%85/dp/4873117585/ref=sr_1_1?ie=UTF8&amp;qid=1547523207&amp;sr=8-1&amp;keywords=%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0">ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装」</a>という本を使っています!難しいですがとてもいい本です。</span></p> <h4>アニメ顔検出</h4> <p> 2016年ごろ、とあるデザイナーさんからこのような相談を受けました。</p> <p><span style="font-size: 150%;">「サムネイルを自動的に作れませんか?」</span></p> <center> <div class="images-row mceNonEditable"> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20190120234116j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120234116.jpg" alt="f:id:sgtech:20190120234116j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20190120234114j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120234114.jpg" alt="f:id:sgtech:20190120234114j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20190120234112j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120234112.jpg" alt="f:id:sgtech:20190120234112j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20190120234110j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120234110.jpg" alt="f:id:sgtech:20190120234110j:plain" /></div> <div class="images-row-item"><img class="hatena-fotolife" title="f:id:sgtech:20190120234107j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120234107.jpg" alt="f:id:sgtech:20190120234107j:plain" /></div> </div> </center> <p> サムネイルとは縮小した画像のことですが、このように顔など特徴的な箇所をクローズアップしてトリミングするケースもあります。ちなみに彼らは、「Readyyy!」の「SP!CA」というユニットのアイドルたちです。</p> <p> そのデザイナーさんが所属しているプロジェクトのプラットフォームはスマホでした。スマホタイトルは運営を長く続けていくため、新規要素をどんどん追加していきます。その要素を一覧で表示させたりするために、サムネイルが必要となるのです。</p> <p> また、ご存知とは思いますがゲーム開発ではアニメ顔が使われることが多く、そのプロジェクトでもアニメ顔が採用されていました。</p> <p> これを自動的に作成…何か良い方法はないものか…。検索すると…出てきました!「OpenCV」を使ったものです。</p> <center> <p><iframe class="embed-card embed-blogcard" style="display: block; width: 100%; height: 190px; max-width: 500px; margin: 10px 0px;" title=" OpenCVによるアニメ顔検出ならlbpcascade_animeface.xml - デー" src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fultraist.hatenablog.com%2Fentry%2F20110718%2F1310965532" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="http://ultraist.hatenablog.com/entry/20110718/1310965532">ultraist.hatenablog.com</a></cite></p> </center> <p> 多くの人がこれを使ってアニメ顔検出しているようですね。勉強も兼ねて「Photoshop」のプラグインという形で実装してみました。一から実装すると大変なので、サンプルのプラグインに間借りする感じで作りました。<br /> 余談ですが、「Photoshop」プラグインのAPIって独特というか、なんとも難しいですよね…。下のgif動画は、プラグインを動作させたときのものです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="Photoshopプラグイン"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190120234252g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120234252.gif" alt="f:id:sgtech:20190120234252g:plain" /></p> <figcaption>Photoshopプラグイン</figcaption> </figure> <p> どうですか!?素晴らしい性能ですね!ただ、おしいのが誤検出(下の半透明で赤く塗り潰した部分)です。</p> <center> <p><img class="hatena-fotolife" title="f:id:sgtech:20190120234339p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120234339.png" alt="f:id:sgtech:20190120234339p:plain" /></p> </center> <p> このOpenCV(lbpcascade_animeface)を使った手法は検出精度の調整ができるのですが、精度を上げすぎると、顔ではない部分も検出してしまい、精度を下げると、顔を検出しづらくなってしまうという現象が発生します。そのちょうどよいバランスを見つければいいのかもしれませんが、その設定で絶対大丈夫と言い切る自信がありません。残念ながら、これでは自動生成するツールとして、信頼性が足りませんよね…。</p> <h4>顔なのか?顔ではないのか?</h4> <p> しばらくして、1つのアイデアが閃きました。OpenCV(lbpcascade_animeface)が検出した画像の、<span style="color: #d32f2f;"><strong>「顔」「顔ではない」をディープラーニングで学習させて、判断させるようにすればいいのではないか…と</strong></span>。ここではディープラーニングの代表的な手法、畳み込みニューラルネットワーク(Convolutional Neural Network、以下CNNと呼びます)を用います。本来なら切り出した顔などの特徴量から誰なのかを判定できる素晴らしい手法なのですが、今回は贅沢(?)に、「顔」「顔ではない」の2種類の判定のためだけに使います。</p> <p> 後で知ったのですが、この物体検出後にCNNで分類する手法は<strong>「R-CNN」</strong>という立派な名前がついていました。</p> <h4>Keras</h4> <p> ディープラーニングのフレームワークには、簡単で分かりやすいという評判の<strong>Keras</strong><a href="#f-280b49dd" name="fn-280b49dd" title="https://keras.io/ja/">*6</a>を使いました。KerasはPythonによるフレームワークで、TensorFlowやTheanoなどのディープラーニングライブラリをバックエンドとして選択できます。今回バックエンドには、CPU版TensorFlowを使いました。</p> <p> KerasやCNNについては、こちらの記事を参考にしています。</p> <center> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="Kerasでキルミーアイコン686枚によるキルミー的アニメ絵分類 - Qiita" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fqiita.com%2Fdomkade%2Fitems%2F760b433a1749a3287b1d" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://qiita.com/domkade/items/760b433a1749a3287b1d">qiita.com</a></cite></p> </center> <h4>教師データ</h4> <p> ディープラーニングを始めるにあたって、まず教師データというものを<strong>大量に</strong>用意します。ここでは「顔」と「顔ではない」画像ファイル群ですね。実は、この教師データを用意するところに1つのハードルがあります。個人で用意する場合<strong>「大量に」</strong>という点が大変だと思うのですが、セガでは複数のタイトルを開発していますので、他のプロジェクトから画像を提供してもらいました。これに先ほどのOpenCV(lbpcascade_animeface)を使ったアニメ顔検出をさせて、「顔」と「顔ではない」画像群を、比較的簡単に用意できました。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="顔 700枚"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190120234423j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120234423.jpg" alt="f:id:sgtech:20190120234423j:plain" /></p> <figcaption>顔 700枚</figcaption> </figure> <figure class="figure-image figure-image-fotolife mceNonEditable" title="顔ではない 1000枚"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190120234420j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120234420.jpg" alt="f:id:sgtech:20190120234420j:plain" /></p> <figcaption>顔ではない 1000枚</figcaption> </figure> <p> これで準備が整いました。100回学習させてみると、7時間ほどかかりました。</p> <p> 学習させた成果のことをモデルと呼びます。モデルは基本的に学習回数が多いほど、性能が良くなります。ただし、特定の教師データにだけ過度に対応した状態、<span style="color: #d32f2f;"><strong>過学習(overfitting)</strong></span>になってしまうことがあります。未知のデータに対応できない状態ですね。</p> <p> 下の図は今回学習させたモデルの性能を表しています。</p> <center> <p><img class="hatena-fotolife" title="f:id:sgtech:20190120234336p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120234336.png" alt="f:id:sgtech:20190120234336p:plain" /></p> </center> <p> <span style="color: #ff0000;"><strong>「acc」</strong></span>は正答率、<span style="color: #0000cc;"><strong>「loss」</strong></span>は性能の悪さを示す指標で、教師データに対してどれだけ一致していないかを表しています。横軸は学習回数で、多いほど性能が良くなる傾向を示しているのがお分りいただけると思います。</p> <p> また、実は教師データの全てを学習に使っているわけではなく、教師データの一部は未知のデータに対応できるかどうかのテストに使っており、そのテスト結果が、<span style="color: #cc00cc;">「<strong>val_acc」</strong></span>と<span style="color: #286f2c;">「<strong>val_loss」</strong></span>です。</p> <p> 緑のグラフ<span style="color: #286f2c;">「<strong>val_loss」</strong><span style="color: #000000;">は、</span></span>学習を繰り返すたびに上昇していく傾向にありますが、これは<span style="color: #d32f2f;"><strong>過学習</strong></span>状態であることを示しています。なので100回ではなく、30回ぐらいで止めておいたほうが良いモデルと言えそうですが、今回はこのまま100回学習したモデルで話を進めます。</p> <p> では、このモデルを切り出した画像に適用してみましょう。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="学習の成果は!?"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190120234332j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120234332.jpg" alt="f:id:sgtech:20190120234332j:plain" /></p> <figcaption>学習の成果は!?</figcaption> </figure> <p> 「Readyyy!」のキービジュアルでの判定の成果はこのようになりました。7番だけ99%顔と判断して失敗してしまいましたが、この手法は有効そうです。</p> <h4>デザイナーが使えるようPhotoshopで動作させてみる</h4> <p> では、この顔検出+顔判定のシステムを、「Photoshop」から使えるようにしてみましょう。システムはPythonで動作しているので、「Falcon<a href="#f-59820e8a" name="fn-59820e8a" title="https://falconframework.org/">*7</a>」というフレームワークを使って、WebAPIとしてアクセスするようにしてみます。手順としては、</p> <ol> <li><span style="color: #1464b3;"><strong>Photoshop上でドキュメントを一時的にファイル(JPEG等)保存する。</strong></span></li> <li><span style="color: #1464b3;"><strong>Photoshop上でそのファイルを読み込んで、WebAPIを使ってアップロードし、応答を待つ。</strong></span></li> <li><strong><span style="color: #d32f2f;">画像を受け取ったWebサーバー側で、アニメ顔を検出する。</span></strong></li> <li><strong><span style="color: #d32f2f;">引き続きWebサーバー側で、「顔」か「顔ではない」かを判定し、「顔」の矩形の座標を返す。</span></strong></li> <li><span style="color: #1464b3;"><strong>Photoshop上でその結果を受け取り、選択範囲として反映する。</strong></span></li> </ol> <p>となります。</p> <p> 今回は「Photoshop」上での動作には、プラグインではなくスクリプト(JavaScript)を使います。<span style="color: #1464b3;">青い文字が「Photoshop」スクリプトでの処理</span>。<span style="color: #d32f2f;">赤い文字がWebサーバーでの処理</span>となります。</p> <p> 「Photoshop」スクリプトでバイナリデータをアップロードする方法は、ここに良いコードがありますので、参考にしてみてください。</p> <center> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="HTTP Upload file with Socket | Adobe Community" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fforums.adobe.com%2Fthread%2F2111611" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://forums.adobe.com/thread/2111611">forums.adobe.com</a></cite></p> </center> <p> 「Falcon」を使ったWebAPIも簡単に実装できます。今回はこちらを参考しました。</p> <center> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="Python軽量フレームワークFalconでAPI開発 入門(その1) - Qiita" src="https://hatenablog-parts.com/embed?url=https%3A%2F%2Fqiita.com%2Fshimakaze_soft%2Fitems%2F166071b17dd286e8913b" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="https://qiita.com/shimakaze_soft/items/166071b17dd286e8913b">qiita.com</a></cite></p> </center> <figure class="figure-image figure-image-fotolife mceNonEditable" title="WebAPI+Photoshopスクリプトによる実装サンプル"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190120234223g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120234223.gif" alt="f:id:sgtech:20190120234223g:plain" /></p> <figcaption>WebAPI+Photoshopスクリプトによる実装サンプル</figcaption> </figure> <p> 対象の画像内に複数人いる場合は最初に見つかった人の顔の矩形を返します。上の動画では、左から2番めの茶色の髪の比呂君が選択されてますね。</p> <p><span style="color: #d32f2f; font-size: 150%;"><strong> これで、「Photoshop」スクリプトを使って、画像から自動的にサムネイルを作りだせるようになりました。</strong></span></p> <p><span style="color: #000000;">  ここまでが、「CEDEC+KYUSHU2018」</span><span style="color: #000000;">でディープラーニングについて講演した内容です。</span></p> <h4>ツールと連携させる(プラスアルファ)</h4> <p> <span style="color: #000000;">ここから先が今回追加する内容で、「Readyyy!」で試みた★1と★2フォトの自動生成をご紹介します。</span>人間並みの高い精度でアニメ顔を矩形選択できるのであれば、いろいろ応用できそうですよね。</p> <p> ちなみにフォトというのは、「Readyyy!」内で手に入るアイドルの写真のことです。★5フォトは、このような豪華なフォトです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="★5フォト"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190120235131j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120235131.jpg" alt="f:id:sgtech:20190120235131j:plain" /></p> <figcaption>★5フォト</figcaption> </figure> <p> ★1と★2のフォトは、アイドル画像と汎用的な背景画像を組み合わせたシンプルなフォトです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="★1フォト"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190120235139j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120235139.jpg" alt="f:id:sgtech:20190120235139j:plain" /></p> <figcaption>★1フォト</figcaption> </figure> <p> なお、連携させるツールのフローは以下のようなもので、全て「Photoshop」上での操作です。</p> <ol> <li>アイドル画像を読み込み、あとでデザイナーが位置調整しやすいように、スマートオブジェクト化しておく。</li> <li><strong><span style="color: #d32f2f;">アイドル画像の顔の部分を選択範囲として囲む。</span></strong></li> <li>背景画像を読み込む。</li> <li>その背景画像にあらかじめ指定してある基準位置と、先ほどのアイドル画像の選択範囲の大きさが一致するように調整して、アイドル画像をコピー&ペーストする。</li> <li>完成した画像を書き出す。</li> </ol> <p> 2番(赤い文字の部分)にアニメ顔検出判定システムを組み込んで、自動化を試みます。では実行してみますね。動画の左側が「Photoshop」、右側が出力フォルダの様子です。また20倍速で再生しており、本来はもっとゆっくりとした動作となります。 </p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="ツールへの組み込み"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190121133210g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190121/20190121133210.gif" alt="f:id:sgtech:20190121133210g:plain" /></p> <figcaption>ツールへの組み込み</figcaption> </figure> <p> よし!どんどん生成されている!結構いい感じです!</p> <center> <figure class="figure-image figure-image-fotolife mceNonEditable" title="顔の大きさが違う…"> <p><img class="hatena-fotolife" title="f:id:sgtech:20190120235152j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190120/20190120235152.jpg" alt="f:id:sgtech:20190120235152j:plain" /></p> <figcaption>顔の大きさが違う…</figcaption> </figure> </center> <p> ただ極端な例なのですが、このあたりを比較してみるとアイドルの顔の大きさがそろっていません。このあたりの微調整は、デザイナーさんにがんばってもらいました…。さらなる自動化を目指すには、工夫が必要そうです。</p> <p> 今回は検出にOpenCV(lbpcascade_animeface)を使いましたが、検出自体をDeepLearningで行う手法(Faster R-CNN<span style="color: #3c4858; font-family: Roboto, Helvetica, Arial, sans-serif; font-size: 18px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; float: none; display: inline !important;">)</span>もあるので、次はこちらも試したいと思っています。</p> <h4><strong>まとめ</strong></h4> <ul> <li>アニメ顔検出は、OpenCV(lbpcascade_animeface)が使える</li> <li>誤検出には、ディープラーニング(CNN)で対応</li> <li>検出されたアニメ顔のトリミングに課題あり</li> </ul> <h3>最後に…</h3> <p> ここまで読んでくださり、ありがとうございました。課題も見つかり今回は道半ばという結果になってしましたが、いかがだったでしょうか?今後も継続的に改良を積み重ねて、またここでお伝えできればなぁと思っています。</p> <p> TAセクションではこのようにデザイナーの制作に役立つ環境を提供できるよう力を注いでおります。Unityの登場でTAの活躍できるフィールドは格段に広がり、シェーダーやポストエフェクトなど面白い表現を生み出せないかと日々格闘中です。</p> <p> そんな中でお仕事したい方は、ぜひ下記の弊社グループ採用サイトをご確認ください。いっしょに働いてみませんか?</p> <center> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="採用サイト|株式会社セガゲームス -【SEGA Games Co., Ltd.】" src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fsega-games.co.jp%2Frecruit%2Findex.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="http://sega-games.co.jp/recruit/index.html" onmousedown="ga('HatenaBlogUserTracker.send', 'event', 'recruit', 'games_banner_clicked','recruit_games_out', true);">sega-games.co.jp</a></cite></p> </center><center> <p><iframe src="https://www.youtube.com/embed/w95IVAFbdnQ" width="600" height="338" frameborder="0" allowfullscreen=""></iframe></p> </center> <p> そして、「Readyyy!」、よろしくお願いします!</p> <p> </p><div class="footnote"> <p class="footnote"><a href="#fn-14bd32fd" name="f-14bd32fd" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">1月に組織改編がありまして部署名が変わりました。</span></p> <p class="footnote"><a href="#fn-6df46c26" name="f-6df46c26" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://unity3d.com/jp">https://unity3d.com/jp</a></span></p> <p class="footnote"><a href="#fn-84d50e50" name="f-84d50e50" class="footnote-number">*3</a><span class="footnote-delimiter">:</span><span class="footnote-text">ここではLive2D Cubismのこと。2Dイラストに擬似3D的な滑らかなアニメーションを追加することのできるソフト。Spineという海外の競合ソフトがある。また、最近はVTuberにも良く使われている。<a href="https://www.live2d.com/ja/products/cubism3">https://www.live2d.com/ja/products/cubism3</a></span></p> <p class="footnote"><a href="#fn-3520c89b" name="f-3520c89b" class="footnote-number">*4</a><span class="footnote-delimiter">:</span><span class="footnote-text">Unityにおいてオブジェクトの振る舞いを記述するためのスクリプトのこと。</span></p> <p class="footnote"><a href="#fn-94c5c29f" name="f-94c5c29f" class="footnote-number">*5</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://cedil.cesa.or.jp/cedil_sessions/view/1972">https://cedil.cesa.or.jp/cedil_sessions/view/1972</a></span></p> <p class="footnote"><a href="#fn-280b49dd" name="f-280b49dd" class="footnote-number">*6</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://keras.io/ja/">https://keras.io/ja/</a></span></p> <p class="footnote"><a href="#fn-59820e8a" name="f-59820e8a" class="footnote-number">*7</a><span class="footnote-delimiter">:</span><span class="footnote-text"><a href="https://falconframework.org/">https://falconframework.org/</a></span></p> </div> sgtech 龍が如くにおけるキャラクター制作ワークフロー hatenablog://entry/10257846132689248523 2018-12-26T10:00:00+09:00 2019-07-31T09:59:37+09:00 初めまして。セガゲームス 第1CSスタジオの有賀千陽です。キャラクターデザインの業務に10年以上携わったのち、現在は新設されたデザインサポートチームでデザイナーの作業を支援するツールを制作しています。 「龍が如くスタジオ」で制作されているタイトルにはたくさんの実在の人物が登場します。今回のSEGA TECH Blogでは「龍が如くスタジオ」キャラクター班流のリアルなキャラクターを作成するフローを皆さまにご紹介させていただきます。 【目次】 短時間でリアルなキャラを沢山作らないといけない! 「龍が如く」シリーズにおける3Dスキャンの歴史 光学式スキャナー 投影式の3Dスキャナー PhotoSca… <p>初めまして。<br />セガゲームス 第1CSスタジオの有賀千陽です。<br />キャラクターデザインの業務に10年以上携わったのち、現在は新設されたデザインサポートチームでデザイナーの作業を支援するツールを制作しています。</p> <p> </p> <p>「龍が如くスタジオ」で制作されているタイトルにはたくさんの実在の人物が登場します。<br />今回のSEGA TECH Blogでは「龍が如くスタジオ」キャラクター班流のリアルなキャラクターを作成するフローを皆さまにご紹介させていただきます。</p> <p>【目次】</p> <ul class="table-of-contents"> <li><a href="#短時間でリアルなキャラを沢山作らないといけない">短時間でリアルなキャラを沢山作らないといけない!</a><ul> <li><a href="#龍が如くシリーズにおける3Dスキャンの歴史">「龍が如く」シリーズにおける3Dスキャンの歴史</a><ul> <li><a href="#光学式スキャナー">光学式スキャナー</a></li> <li><a href="#投影式の3Dスキャナー"> 投影式の3Dスキャナー</a></li> </ul> </li> <li><a href="#PhotoScanの導入">PhotoScanの導入</a><ul> <li><a href="#3Dデータ生成用の写真撮影の様子"> 3Dデータ生成用の写真撮影の様子</a></li> <li><a href="#画像の現像"> 画像の現像</a></li> </ul> </li> <li><a href="#秘訣は-龍が如くスタジオ独自のドラゴンエンジン">秘訣は 「龍が如くスタジオ」独自の「ドラゴンエンジン」</a></li> </ul> </li> <li><a href="#キャラクター制作ワークフロー">キャラクター制作ワークフロー</a><ul> <li><a href="#3Dメッシュ生成">3Dメッシュ生成</a></li> <li><a href="#メッシュ生成-フロー">メッシュ生成 フロー</a></li> <li><a href="#顔モデル作成フロー">顔モデル作成フロー</a></li> <li><a href="#テクスチャ作成">テクスチャ作成</a></li> <li><a href="#テクスチャについて">テクスチャについて</a><ul> <li><a href="#アンビエントオクリュージョンマップ">アンビエントオクリュージョンマップ</a></li> <li><a href="#トランスミッタンスマップ">トランスミッタンスマップ</a></li> <li><a href="#F0マップ">F(0°)マップ</a></li> </ul> </li> <li><a href="#テクスチャ作成フロー">テクスチャ作成フロー</a><ul> <li><a href="#タンジェントノーマルマップ">タンジェントノーマルマップ</a></li> <li><a href="#シャイニネスマップ">シャイニネスマップ</a></li> <li><a href="#トランスミッタンスマップ-1">トランスミッタンスマップ</a></li> <li><a href="#架空のキャラクター">架空のキャラクター</a></li> <li><a href="#顔のしわ">顔のしわ</a></li> </ul> </li> <li><a href="#キャラ作成をサポートするツール群">キャラ作成をサポートするツール群</a><ul> <li><a href="#WrapX"> WrapX</a></li> <li><a href="#LODの作成"> LODの作成</a></li> <li><a href="#そのほかのツール">そのほかのツール</a></li> </ul> </li> </ul> </li> </ul> <p> </p> <p>まずは「龍が如く」シリーズのキャラクターの特徴から説明しましょう。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190313135651j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190313/20190313135651.jpg" alt="f:id:sgtech:20190313135651j:plain" width="388" /></p> <ul> <li>プラットフォームはPS4などハイエンド機である</li> <li>開発期間が短い※おおよそ一年</li> <li>芸能人とタイアップし、ご本人がゲーム中でキャラクターを演じている</li> <li>沢山のユニークなキャラクターが登場する</li> </ul> <p>などが挙げられます。</p> <p> </p> <p>そのリアルなキャラクターたちを短い期間にどれくらいのクオリティで、どれくらいの顔の数を作らないといけなかったのか?</p> <p>クオリティはもちろん<span style="font-size: 150%;"><strong>写真のようなクオリティ</strong></span>です。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20190313135644j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20190313/20190313135644.jpg" alt="f:id:sgtech:20190313135644j:plain" /><br /><br /></p> <p>タイアップキャストになると誰が見てもそっくりに作らなくてはなりません。</p> <p> </p> <p>次に数の話ですが…</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="1プロジェクトで使用したキャラ(男性のみ)"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005946j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005946.jpg" alt="f:id:sgtech:20181224005946j:plain" /></p> <figcaption>1プロジェクトで使用したキャラ(男性のみ)</figcaption> </figure> <p>『龍が如く6 命の詩。』の男性NPC<a href="#f-ae2e193e" name="fn-ae2e193e" title="「龍が如く」プロジェクトの方言で簡易的なフェイシャルアニメーションが適用されるスペックのキャラクター">*1</a>の顔だけで上記の画像ぐらいです。</p> <p> </p> <p>これに加えて女性NPC・重要キャラクター・キャバ嬢のタイアップキャラなどを含めると、</p> <ul> <li>男性の顔:約200種 </li> <li>女性の顔:約70種 </li> </ul> <p>あいかわらずたくさん作ってますね…。まとめると、</p> <h3 id="短時間でリアルなキャラを沢山作らないといけない">短時間でリアルなキャラを沢山作らないといけない!</h3> <p>リアルなキャラを大量に作成するに当たり活躍してくれたのが、これから説明するフォトグラメトリーを活用した制作フローでした。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005310p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005310.png" alt="f:id:sgtech:20181224005310p:plain" /></p> <p> </p> <p>まずは、フォトグラメトリーの説明と、フォトグラメトリーによる3Dの自動生成、Maya等のDCCツールに持っていくまでのフローの説明をします。</p> <blockquote> <p><br />フォトグラメトリーとは?<br />------------------------------------------------------------------------------------<br />3次元の物体を複数の観測点から撮影して得た2次元画像から、<br />視差情報を解析して寸法・形状を求める写真測量のこと。 <br /><br /></p> </blockquote> <p>小難しくてよくわかりませんね…</p> <p>要は<strong>撮った写真から自動で3Dデータを生成してくれる技法のことです。</strong><br />この文言だけで、かなり<span style="font-size: 13pt;">簡単に作れるように感じられるのではないでしょうか?</span></p> <p> </p> <p>フォトグラメトリーを本格的に導入したのは『龍が如く6 命の詩。』の開発中でした。</p> <p>ではそれ以前はどうしていたのか?</p> <p><br />「龍が如くスタジオ」で行っていた3Dスキャンの歴史を簡単に説明します。</p> <h4 id="龍が如くシリーズにおける3Dスキャンの歴史">「龍が如く」シリーズにおける3Dスキャンの歴史</h4> <ol> <li>リアリティの追及</li> <li>制作スピードの向上</li> </ol> <p>この2つの要求を満たすために、「龍が如く」シリーズでは2007年PS3対応が始まった『龍が如く 見参!』の制作から3Dスキャンによるワークフローが導入されました。</p> <p>PS2世代までは写真を見てモデリングを行っていました。いわゆる目コピーです。つまり制作クオリティはデザイナーのスキル頼りだったのです。</p> <p>PS3世代になってゲーム機のスペック向上に伴い、リアリティのあるゲームモデルの必要性が高まり、さらに『龍が如く 見参!』から実在の俳優を登場させることにもなり、リアリティとクオリティの追及がさらに重要視されるようなりました。</p> <h5 id="光学式スキャナー">光学式スキャナー</h5> <p>2007年の『龍が如く 見参!』以降『龍が如く3』『龍が如く4 伝説を継ぐもの』『<span style="color: #333333; font-family: Meiryo; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: #ffffff; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">龍が如く OF THE END</span>』まで社外のスタジオで役者さんを撮影し、メッシュデータもそのスタジオで生成されたものを使用していました。<br />3Dスキャンを行うようになりキャラクターのモデリング時間は40%削減でき、クオリティも上がりました。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="外部スタジオを利用していたころのスキャンメッシュ"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005306p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005306.png" alt="f:id:sgtech:20181224005306p:plain" /></p> <figcaption>外部スタジオを利用していたころのスキャンメッシュ</figcaption> </figure> <p>そのスタジオでは当時としては最新式だった光学式(ヘリウムネオンレーザー)の3Dスキャナーを使用していましたが、スキャンメッシュの精度はごらんの通り、なんとなく誰だか認識できる程度で細かいディテールは撮れていません。</p> <h5 id="投影式の3Dスキャナー"> 投影式の3Dスキャナー</h5> <p>以下の画像は『龍が如く OF THE END』の途中から導入が始まった社内撮影スタジオでスキャンされた3Dモデルです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="投影式3Dスキャナを利用してキャプチャされた3Dモデル"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005302p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005302.png" alt="f:id:sgtech:20181224005302p:plain" /></p> <figcaption>投影式3Dスキャナを利用してキャプチャされた3Dモデル</figcaption> </figure> <p> </p> <p>この頃から社内に撮影専用スタジオを設け、テクスチャはカメラ1台(手持ち)での撮影からスタートし、後にカメラ5台(+三脚・ストロボ)でシャッターを同期させて撮影する方法に移行。より精度の高いテクスチャを撮影できるようになりました。</p> <p>3DモデルのキャプチャにはWhite-Light (走査型白色)方式<a href="#f-9965286b" name="fn-9965286b" title="プロジェクターから発する光のパターン画像をデジタルカメラで撮影するという技術">*2</a>の3Dスキャナーを導入しました。プロジェクターを用い撮影対象に画像を投影して専用ソフトウェアで解析して3Dメッシュを生成するという方法です。</p> <p>社内に専用スタジオを設け新しい3Dキャプチャのシステムを導入したことにより、メッシュの精度が以前より向上し時間面でも費用面でも社外スタジオの利用時に比べて大幅なコストカットを達成しました。</p> <p> ただ、暗室で5秒程度息を止めて動かないでいる必要があるため、まばたきや体が動いてしまうだけでメッシュの精度が低下するなど正確な3Dモデルのキャプチャは非常に難しく、撮影されている人の負担も大きかったのです。</p> <p>さらに、社外スタジオのスキャンデータも社内スタジオのスキャンデータも、どちらもテクスチャの生成ができなかった為、3Dメッシュを生成した後撮影した画像をメッシュにベイクしてテクスチャを自分たちで作成する必要がありました。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005259p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005259.png" alt="f:id:sgtech:20181224005259p:plain" /></p> <p><br />その頃のテクスチャ作成方法は、DCCツール内部に画角が同一となるカメラを作成し、位置を合わせてカメラプロジェクションUVを作成しテクスチャベイクしていたのですが、この作業だけで数時間かかっていました。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005255p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005255.png" alt="f:id:sgtech:20181224005255p:plain" /></p> <p>また、社外スタジオのスキャンデータも社内スタジオのスキャンデータもそのままではノーマルマップベイクのソースにできるほど精細にキャプチャできるわけではなく、Zbrushでのスカルプトによるディテールの追加作業は必須でした。</p> <p> </p> <h4 id="PhotoScanの導入">PhotoScanの導入</h4> <p>そんななか、フォトグラメトリーの技術を使い3Dメッシュを生成するPhotoScanというソフトウェアがプロジェクトに導入されました。</p> <h5 id="3Dデータ生成用の写真撮影の様子"> 3Dデータ生成用の写真撮影の様子</h5> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005401p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005401.png" alt="f:id:sgtech:20181224005401p:plain" /></p> <p>上の写真は2015年から2018年現在まで使用している社内フォトスタジオです。<br /><br />事業所移転前の羽田にあった旧スタジオの様子なので手作り感あふれる仕上がりですが、ここで沢山の芸能人の方々をスキャンしてきた見た目にそぐわずできるヤツなんです・・・が、なんと!現在大崎の新オフィス内に「龍が如くスタジオ」キャラクター班こだわりの新スタジオを構築中なのです!<br />今年度中に完成予定ですのでお楽しみに。<br /><br /></p> <p>話は戻って、カメラのスペックは以下のようになっています。</p> <ul> <li><strong>台数 : 30台</strong></li> <li><strong>機種 : CanonX7i</strong></li> <li><strong>レンズ : 標準ズームレンズ</strong></li> <li><strong>焦点距離 : 55mm</strong></li> </ul> <p>基本設計や機材の調達は社外の専門家に委託し、その後の運用、撮影のオペレーション、メンテナンスなどはキャラクター班が行っています。<br /><br /></p> <h5 id="画像の現像"> 画像の現像</h5> <p>X-Rite社のColorCheckerPassportと一緒に撮影した画像からカメラプロファイルを作成し全ての現像に使用します。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005357p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005357.png" alt="f:id:sgtech:20181224005357p:plain" /></p> <p> </p> <h4 id="秘訣は-龍が如くスタジオ独自のドラゴンエンジン">秘訣は 「龍が如くスタジオ」独自の「ドラゴンエンジン」</h4> <p>「龍が如く」シリーズは常に部内開発のゲームエンジン上で制作されてきました。そうすることでレスポンスが良く柔軟なゲーム開発が可能になり、デザイナーの時には無茶な要求にも短時間で実装することができるのです。<br />『龍が如く6 命の詩。』の開発時にアップデートされた内製ゲームエンジン「ドラゴンエンジン」は、それまでのゲームエンジンよりシームレスでリアルな表現が可能になりました。</p> <p>部内でゲームエンジンを開発できるような高い技術力を持ったプログラマがたくさんいるのも、「龍が如くスタジオ」がクオリティの高いゲームを素早く作れる要素の一つとなっています。</p> <h3 id="キャラクター制作ワークフロー">キャラクター制作ワークフロー</h3> <p>前置きがだいぶ長くなってしまいましたが、本題のキャラクターワークフローの解説に移ります。<br />今回は「龍が如く」シリーズ関連のプロモーションでおなじみ島野さんの顔制作に沿ってお伝えします。</p> <h4 id="3Dメッシュ生成">3Dメッシュ生成</h4> <p>3Dメッシュの生成にはAGISoft社のPhotoScanというソフトウェアを使用しています。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="PhotoScanの操作画面"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005951j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005951.jpg" alt="f:id:sgtech:20181224005951j:plain" /></p> <figcaption>PhotoScanの操作画面</figcaption> </figure> <p>このソフトウェアの導入により3Dメッシュの生成と同時にテクスチャも生成できるようになったことから、テクスチャをMaya上でベイクしていた数時間の作業が削減されテクスチャ作成時間が大幅に短縮できました。</p> <p><br />この一連のフローにより、デザイナーのスキルに依存していたクオリティの向上と制作時間が短縮し安定して高水準なクオリティがアウトプットできるようになったのです。</p> <h4 id="メッシュ生成-フロー">メッシュ生成 フロー</h4> <p>では実際に3Dメッシュを生成する過程を紹介しましょう。</p> <ol> <li>始めに現像した撮影画像をツールに読み込みカメラ位置を計測</li> <li>ポイントクラウド(点群データ)を生成</li> <li>3Dメッシュを生成</li> <li>最後にテクスチャベイクで終了</li> </ol> <p>PhotoScnanは各画像のカメラの位置や画角を画像解析により取得し、ソフトウェア上で撮影環境を再現しますが、ソースにしている写真の点数が少ないと各画像の位置関係が予測できずカメラの位置情報が取得できなくなります。</p> <p>現在弊社スタジオは30台のカメラで構成されており、横の耳から後ろの首回りまで360度カバーできるようになりました。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="高密度クラウド"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005825j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005825.jpg" alt="f:id:sgtech:20181224005825j:plain" /></p> <figcaption>高密度クラウド</figcaption> </figure> <p>上記の画像はポイントクラウド(点群)です。</p> <p>この状態では点群と認識できないくらい高密度なので寄ってみます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005822j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005822.jpg" alt="f:id:sgtech:20181224005822j:plain" /><br />更に寄ってみます</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005818j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005818.jpg" alt="f:id:sgtech:20181224005818j:plain" /></p> <p> 小さい点が見えるのがわかりますか…?</p> <p> </p> <p>このポイントクラウドを元にメッシュとテクスチャを生成します。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="PhotoScanで生成したポリゴンメッシュ"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005948j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005948.jpg" alt="f:id:sgtech:20181224005948j:plain" /></p> <figcaption>PhotoScanで生成したポリゴンメッシュ</figcaption> </figure> <p><br /><br /></p> <p>上の画像は生成したメッシュデータです。1000万ポリゴンで生成しています。</p> <p> </p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="テクスチャ表示とUV"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005815j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005815.jpg" alt="f:id:sgtech:20181224005815j:plain" /></p> <figcaption>テクスチャ表示とUV</figcaption> </figure> <p>上の画像はテクスチャです。<br />PhotoScanが生成したポリゴンメッシュとUVに写真がベイクされます。</p> <p>これらを任意の形式でエクスポートしてR3DS社のWrapXというツールでPhotoScanからエクスポートした3Dメッシュにベースメッシュをシュリンクラップします。<br />この工程の詳細は後ほど解説しますね。</p> <p> </p> <h4 id="顔モデル作成フロー">顔モデル作成フロー</h4> <p>PhotoScanやWrapXで得たソースを元に実際にどのようにゲームのデータに落としこむのでしょうか。</p> <p>まずはスキャンメッシュとゲームメッシュを合わせるという作業になります。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005353p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005353.png" alt="f:id:sgtech:20181224005353p:plain" /></p> <p>これはPhotoScanで生成したメッシュです。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005350p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005350.png" alt="f:id:sgtech:20181224005350p:plain" /></p> <p>これがWrapXで生成したメッシュです。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005346p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005346.png" alt="f:id:sgtech:20181224005346p:plain" /></p> <p>実際に合わせてみるとこうなります。</p> <p>わかりにくいですが目の周りのエッジフローが少し歪んでいますね。</p> <p>ゲームメッシュのエッジのラインがきちんとスキャンメッシュの特徴に沿うように修正していきます。</p> <p>目の周りはまつ毛や二重や粘膜の部分など細かい造形が多くPhotoScanでは再現しきれません。口の周りも唇の内側など写真には写らない部分はメッシュが生成されないので、その二か所はどうしても手作業で修正する必要があります。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005536p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005536.png" alt="f:id:sgtech:20181224005536p:plain" /></p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005533p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005533.png" alt="f:id:sgtech:20181224005533p:plain" /></p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005529p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005529.png" alt="f:id:sgtech:20181224005529p:plain" /></p> <p>これらの作業は非常に重要で、メッシュの法線情報を正しく作ることによりクオリティを上げるという目的もありますが、「龍が如く」シリーズではフェイシャルモーションが複雑に動くためエッジフローが実際の筋肉の流れに沿っていないと後々イベントムービーシーンで思わぬ破たんを生みだす原因となってしまいます。</p> <p>この作業に関してはWrapXの導入でかなり効率化されました。</p> <h4 id="テクスチャ作成">テクスチャ作成</h4> <p>次はテクスチャ作成なのですが、その前に簡単に描画周りを説明しておきます。</p> <p>「龍が如く」ではいわゆる主流ではない、f0値を扱ったPBRを採用しています。</p> <p>この理由は、「龍が如く」というプロジェクトがゴリゴリのフォトリアル指向ではないことと、ゲームに妖怪や怪物<a href="#f-16985940" name="fn-16985940" title="河童や小野ミチオなど">*3</a>など現実にいないキャラクターが登場する可能性を加味し、ある程度振り切った表現ができる今の形に収まりました。</p> <p> </p> <h4 id="テクスチャについて">テクスチャについて</h4> <p>次は「ドラゴンエンジン」で使われているテクスチャについてです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="顔一つの表情に沢山の種類のテクスチャが使われています"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005954j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005954.jpg" alt="f:id:sgtech:20181224005954j:plain" /></p> <figcaption>顔一つの表情に沢山の種類のテクスチャが使われています</figcaption> </figure> <p>上記の画像にあるような8枚<a href="#f-8f819b62" name="fn-8f819b62" title="シェーダーによって前後します">*4</a>のテクスチャをキャラクター班で作成して使用しています。<br />DiffuseMap、NormalMap、ShinnessMap、AmbientOccrusionMapは、おそらく大体のプロジェクトでお馴染みだと思いますので説明は割愛します。</p> <h5 id="アンビエントオクリュージョンマップ">アンビエントオクリュージョンマップ</h5> <p>アンビエントオクリュージョンマップをわざわざ1枚のマップで持っているのは、キャラ単体では画面を占める割合は低くスクリーンスペースのアンビエントオクリュージョンが充分に乗らないので個別でベイクしキャラごとに用意しているからです。</p> <h5 id="トランスミッタンスマップ">トランスミッタンスマップ</h5> <p>肌透過用のトランスミッタンスマップは、肌の薄い部分を表現するために使っています。逆光を当てられた時の耳や、指などに効果的です。</p> <h5 id="F0マップ">F(0°)マップ</h5> <p>黒い画像ですが、F(0°)マップと呼んでいます。<br />F(0°)とは屈折率の比から求まる、0度のフレネル反射率という意味らしいです。<br />屈折率0度、法線方向から見たときの、鏡面反射率、スペキュラーの総量です。<br />mayaにあったmental_rayのマテリアルでは、IOR(屈折率)と書かれていることからリフレクションの強さにも影響します。値が高いほど正面から見ても環境が映りこみます。</p> <p>キャラクター班としては素材ごとに担当プログラマーに用意してもらった値で作業するという認識です。</p> <h4 id="テクスチャ作成フロー">テクスチャ作成フロー</h4> <p>次にテクスチャの作成フローです。</p> <p>龍のテクスチャワークフローは、タンジェントノーマル、AO、シャイニネスの順番に一連の流れで制作しています。<br />ディフューズは状況によって前後いたしますが、スキャンメッシュと生成された画像をソースに、ゲームメッシュでベイクすればほぼ終了です。</p> <h5 id="タンジェントノーマルマップ">タンジェントノーマルマップ</h5> <p>まずは16bit高解像度テクスチャを利用してディスプレイスメントマップを作成します。</p> <p>そのディスプレイスメントマップをZbrush上でスキャンメッシュにアサインしてゲームメッシュにベイクするのが目的です。</p> <p>PhotoScanにより自動で生成されたテクスチャがコレです。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="PhotoScanで生成したテクスチャ"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005905j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005905.jpg" alt="f:id:sgtech:20181224005905j:plain" /></p> <figcaption>PhotoScanで生成したテクスチャ</figcaption> </figure> <p>ご覧のとおりバラバラです。</p> <p> </p> <p>ほくろやシミなどの余計な凹凸情報になりえるものは先にフラットにしておきます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224010044j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224010044.jpg" alt="f:id:sgtech:20181224010044j:plain" /></p> <p> </p> <p>前処理が済んだらPhotoshop上でハイパス等を使いディスプレイスメントマップを作成します。</p> <p><br />次にZbrush上での作業にうつります。<br /><br /></p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005812j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005812.jpg" alt="f:id:sgtech:20181224005812j:plain" /></p> <p>右側がZbrush上で、スキャンメッシュにディスプレイスメントマップを適用した状態です。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005526p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005526.png" alt="f:id:sgtech:20181224005526p:plain" /></p> <p>ディスプレイスをかける前よりかなり細かい凹凸が表現できているのがわかりますでしょうか。</p> <p>先ほど調整したゲームメッシュをインポートし、レイヤー分けしてからスキャンメッシュにディスプレイスメントを適応します。その凹凸情報を、projectALLを使って転写します。</p> <p>スキャンメッシュにはエラーも多いので、この作業の前に事前にモーフターゲットを登録しておきprojectALLで投影したくない部分をマスクしてするなどして都合の悪い部分をフィルタリングしています。</p> <p>その後、キャラクターによってはさらにスカルプトしてディティールアップを図ります。</p> <p>後はSubdivisionの一番上と一番下をエクスポートし、XnormalやSubstance等のテクスチャベイカーを使ってタンジェントノーマルとAOを生成します。<br />人によってはディフューズもこの段階でスキャンメッシュからベイクします。</p> <p>生成したテクスチャが…</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005902j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005902.jpg" alt="f:id:sgtech:20181224005902j:plain" /></p> <p>これですね。ちゃんとバラバラだったUVが繋がっています。</p> <p>スキャンメッシュからベイクによって得たデータとなります。</p> <p>ディフューズマップはベイクしたままというわけにはいかないのでさらに手を入れて調整します。</p> <p>テクスチャの撮影時に陰影を消すようにはしているものの、どうしても取りきれない陰影が入ってしまいますので手作業で余計な陰影を除去します。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224010047j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224010047.jpg" alt="f:id:sgtech:20181224010047j:plain" /></p> <p>少しわかりづらいかもしれませんが、除去前と除去後で陰影の差が少し緩和されています。<br />消しすぎると単調に見えるのでさじ加減に多少経験が必要な作業です。</p> <h5 id="シャイニネスマップ"> <br />シャイニネスマップ</h5> <p>シャイニネスマップは、ノーマルマップをキャビティマップに変換するアクションを使い作成したマップをオーバレイで5枚重ね共通のトーンカーブを適用した後、光って欲しいところ、欲しくないところを既定の値で塗り完成です。</p> <p>すべてのキャラクターはUVが共通なので、実際はキャビティレイヤーの差し替えと個人で違う位置になる唇周りと眉毛周りの塗りの調整のみ行っています。</p> <p>Substanceでも同様に上の一連の作業が組んであります。</p> <h5 id="トランスミッタンスマップ-1">トランスミッタンスマップ</h5> <p>つづいて肌透過用のトランスミッタンスマップの作成も紹介しましょう。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005522p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005522.png" alt="f:id:sgtech:20181224005522p:plain" /></p> <p>顔モデルにスムースをかけた後に、白黒反転をしてアンビエントオクリュージョンをベイクしたものです。<br />このフロー自体が正しいものなのかは正直わかりませんが、コストと効率を鑑みて、最も効果的なフローでした。</p> <p>処理軽減のため全てのキャラが同じテクスチャを使っています。</p> <p>以上ですべてのテクスチャ作成が完了です。</p> <p> </p> <p>仕上げにテクスチャの中間データはDDSを採用しているのでDDSで書き出します。</p> <p>その際のインターフェイスが煩雑で多くの設定ができてしまうので、デザイナーが迷わないようにツールを用意しました。</p> <p>リサイズのアルゴリズムとDDS保存形式を任意で選ぶことができます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005737p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005737.png" alt="f:id:sgtech:20181224005737p:plain" /></p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005943j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005943.jpg" alt="f:id:sgtech:20181224005943j:plain" /></p> <p>元々はガンマ補正、レベル補正の設定や、ラップモード設定、ミップマップ設定など細かく分かれていたのですが、それらの仕様が確定されてからは、混乱を避けるため全て非表示にして触れないようにしてあります。</p> <p>細かいことですが、これによりかなりミスも少なくなりかなり効率的に作業できるようになりました。</p> <p>その後いろいろ微調整<a href="#f-7651c6a3" name="fn-7651c6a3" title="企業秘密★">*5</a>して、完成したモデルですが…</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="顔"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005912j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005912.jpg" alt="f:id:sgtech:20181224005912j:plain" /></p> <figcaption>顔</figcaption> </figure> <figure class="figure-image figure-image-fotolife mceNonEditable" title="全身"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005909j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005909.jpg" alt="f:id:sgtech:20181224005909j:plain" /></p> <figcaption>全身</figcaption> </figure> <p>どうでしょう、島野さんに見えますか?</p> <p>「龍が如くスタジオ」流のフローでこのクオリティの顔モデルが今では1日もあれば誰でも制作できるようになりました!</p> <p> </p> <h5 id="架空のキャラクター">架空のキャラクター</h5> <p>ついでに架空キャラクターのフローについてもすこし触れてみましょう。</p> <p>基本的に弊社の社員に協力してもらい、リアルなキャラクターを作成する場合のフローでほぼそのまま再現します。</p> <p>その後、キャラクターの設定に合わせて修正します。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224010040j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224010040.jpg" alt="f:id:sgtech:20181224010040j:plain" /></p> <p>このキャラクターは眉毛の角度や目つきの修正ぐらいしか行っていません。</p> <p>設定によっては元の風貌からは別人になるケースもあり、特に重要度の高いキャラになるとコンセプト画で用意した顔に近づけるために原形をとどめなくなります。</p> <p>その場合は、ほとんど肌のディフューズ以外は、使用しないのでデザイナーの腕の見せ所でしょうか。</p> <p> </p> <p>次は顔モデリング以外の話を簡単にご紹介します。</p> <p> </p> <h5 id="顔のしわ">顔のしわ</h5> <p>各キャラクターには顔の表情が変わったときに表出する皺を表現するための皺マップが用意されています。</p> <p>下の画像はとあるキャラの顔の皺マップです。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005734p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005734.png" alt="f:id:sgtech:20181224005734p:plain" /></p> <p>用意するマップはノーマルマップのみです。</p> <p>皺用のディフューズやシャイニネス等は用意しておらず、頂点カラーの塗分けによってノーマルマップの表出を制御しています。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="皺表出用の頂点カラー"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224010212j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224010212.jpg" alt="f:id:sgtech:20181224010212j:plain" /></p> <figcaption>皺表出用の頂点カラー</figcaption> </figure> <p>イベントムービー班が設定した表情のパターンに合わせて表出するようになっており、</p> <p>デザイナーの作業負担軽減の為全キャラクター設定はほとんど同じです。</p> <h4 id="キャラ作成をサポートするツール群"> <br />キャラ作成をサポートするツール群</h4> <p>ここまでモデルを作成するフローを説明してきましたが、ここからはそのフローの作業を軽減するツールについてお話したいと思います。</p> <p>まずウェイトのセットアップツールです。DCCツールをSoftimage<a href="#f-dc2138a0" name="fn-dc2138a0" title="つい最近まで「龍が如く」シリーズのキャラクター班はSoftimageで開発していました">*6</a>からMayaに切り替えた経緯上、Softimageと同じ感覚でMayaでのウェイト編集を出来るようにする必要がありました。</p> <p>そこでまずはデザインサポートチームでウェイトのエディタを作成することになりました。</p> <p>顔のポリゴンメッシュはWrapXによって生成されたものを使っていれば全て同じUV・同じ頂点番号なので、ウェイトセットアップは頂点番号かUVのポジションでウェイトをアサインします。</p> <p>これで殆どの場合うまくいくのですが、目の形によって目を閉じた時に破綻したり眉毛の位置によっては眉毛が付いてこない、あるいは瞬きしたときに眉毛もついてくる等のバグが発生します。</p> <p>Maya用のウェイトエディターを使って修正していきます。</p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005731p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005731.png" alt="f:id:sgtech:20181224005731p:plain" /></p> <p>ウェイトのスムースや、ジョイントのロック、ウェイトを保持したままのエッジ切り直し、スキンモデルのデュプリケート、スキンモデルのコンバインなど沢山の便利なツールが用意されています。<br />このエディタが用意されてからはコンポーネントエディターの数倍速くウェイトの修正ができるようになりました。</p> <h5 id="WrapX"> <br />WrapX</h5> <p>上記でチラホラ名前の挙がっていたツール、WrapXを紹介します。</p> <p>WrapXとは大抵はDCCツール上で行うシュリンクラップを、高精度で行うスタンドアロンのアプリケーションです。<br />今は多機能な新バージョンもリリースしている古いツールですが、スクリプトで操作できるのが決め手でこのツールを長らく使用しています。</p> <p>「龍が如く」プロジェクトでは、PhotoScanで取得した高精細なポリゴンモデルを、リトポロジも兼ねて一定のトポロジのメッシュに落とし込む目的で使用しています。</p> <p>Pythonでスクリプトを書かないとカスタマイズができないのでデザイナーからしてみれば使いにくいツールですが、このツールを導入しあえてデザイナーが触れないようにしてリトポロジやポリゴンの削減をWrapXで吸収してしまえば、こだわりがちなデザイナーの工数も増えづらいのではないかという狙いもあります。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="WrapXでシュリンクラップを行います"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005858j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005858.jpg" alt="f:id:sgtech:20181224005858j:plain" /></p> <figcaption>WrapXでシュリンクラップを行います</figcaption> </figure> <p>左がベースメッシュで約5000頂点あります。<br />ベースメッシュとは、「龍が如く」プロジェクトにおいて素体として最初に作られるモデルで、ほぼすべてのキャラクターモデルはこのベースモデルを基準に作られています。<br />右がスキャンメッシュです。</p> <p>まず、既存のPhotoScanで生成した顔のメッシュやテクスチャ、トポロジを共通にするためのベースモデルを読み込み、最初は三点、両目頭と人中にポイントを指定して大まかに頭部の位置とスケールを合わせます。</p> <p>次に、詳細にシュリンクラップを行うため、位置合わせのためのポイントをPhotoScanのメッシュとベースモデル両方に指定していきます。</p> <p>計算を除外するポリゴンも指定する事ができるので、ソースのメッシュが大きく欠けている場合も、ベースのモデルを大きく変形させる事なくシュリンクラップを行う事ができます。</p> <p>設定が完了したら計算を行います。</p> <p>その過程をGifにしてみました。</p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="シュリンクラップの様子(約40倍速)"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224010051g:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224010051.gif" alt="f:id:sgtech:20181224010051g:plain" /></p> <figcaption>シュリンクラップの様子(約40倍速)</figcaption> </figure> <p>最後にスキャンメッシュをシュリンクラップしたベースメッシュと、それに位置とスケールを合わせたスキャンメッシュをエクスポートして完了です。 </p> <figure class="figure-image figure-image-fotolife mceNonEditable" title="WrapXをMayaから操作するツール"> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224010206j:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224010206.jpg" alt="f:id:sgtech:20181224010206j:plain" /></p> <figcaption>WrapXをMayaから操作するツール</figcaption> </figure> <p>最初はWrapXのみでシュリンクラップの作業を行っていましたが、現在では手軽にシュリンクラップや編集が行えるようにMayaからコントロールできるツールを用意してあります。</p> <p>こちらのツールでは、WrapXの鬼門であったフローの途中で指定していたポイントの編集を行う機能も追加しました。</p> <p>顔のハイメッシュは、このWrapXのフローを採用することでまだ技術的に未熟なデザイナーでも比較的ハイスピード&ハイクオリティに作成できるようになり、トポロジを共通化することで面倒なウェイト関連の作業もストレスなく行う事ができるようになりました。</p> <h5 id="LODの作成"> LODの作成</h5> <p>ゲーム制作の辛いところはここからLODを作成しないといけないところですが、LOD作成もツール側である程度自動化してあります。 </p> <p>現在既成のLOD作成ツールは「龍が如く」プロジェクトでは使用せず、クオリティ重視で手作業によりLODを作成しています。</p> <p>ですが顔のLODは先ほどのトポロジの共通化によりボタン一つでクオリティを維持したまま生成できるツールが使えるのでLOD制作の時間はほとんどかかっていません。</p> <h5 id="そのほかのツール">そのほかのツール</h5> <p>「龍が如く」プロジェクトではほかにもリアルなキャラモデルを短時間で作り上げる為に、いろいろなフローを取り入れています。</p> <p>しかし、「リアルにする為のフローを取り入れる=工数の増大につながる」ことが多いため、フローの採用とその際に増える工数の圧縮の為のツールの制作はセットで行うようにしています。</p> <p>たとえばMarvelousDesignerで作成したデータのリトポロジ用のツールなどがあります。</p> <p> </p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005728p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005728.png" alt="f:id:sgtech:20181224005728p:plain" /></p> <p><img class="hatena-fotolife" title="f:id:sgtech:20181224005725p:plain" src="https://cdn-ak.f.st-hatena.com/images/fotolife/s/sgtech/20181224/20181224005725.png" alt="f:id:sgtech:20181224005725p:plain" /></p> <p>MarverousDesignerは衣服などの3Dデータの作成や、シミュレーションを行えるアプリケーションです。<br />リアリティのある衣服の3Dモデルを作成するには最適なアプリケーションでしたがリトポロジが大きな課題でした。<br />この問題もデザインサポートチームでリトポロジーツールを作成し、さらにゲームエンジンにすぐに組み込めるようウェイトやマテリアルの設定、各種テクスチャの焼きつけなども簡易的に行えるようにしました。<br /><br />他には</p> <ul> <li>今まで作成した大量の顔データをブレンドして新しい顔を作るツール</li> <li>写真を撮影するだけでPhotoScanにより全自動でスキャンメッシュが生成されるツール</li> <li>そのPhotoScanで生成したスキャンメッシュを短時間でゲーム用のデータに落とし込むツール</li> </ul> <p>など沢山あります。<br /><br />Mayaはスクリプトを覚えてツールを作れるようになるとあちこち自動化・高速化ができてとても楽しいツールです。<br />私はデザイナーとしてセガに入社しましたが、今ではPythonでMayaのツールを作るのにすっかりハマっています。<br /><span style="color: #000000; font-family: 'Segoe UI', 'Helvetica Neue', 'Apple Color Emoji', 'Segoe UI Emoji', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">このブログを読んでいるデザイナーなのにツールを作って自動化するのが大好きな方!クオリティの高い作品作りに懸命に取り組む弊社デザイナーたちの作業効率化に向けた環境づくりに、共に取り組んでいただけませんか?<br />もちろん、そうではない方も「龍が如くスタジオ」であんな芸能人やこんな有名人の方々と一緒にお仕事してみませんか?<br />「龍が如くスタジオ」は一緒にゲームを作ってくれる仲間を募集中です!</span></p> <p><iframe class="embed-card embed-webcard" style="display: block; width: 100%; height: 155px; max-width: 500px; margin: 10px 0px;" title="採用情報|株式会社セガゲームス -【SEGA Games Co., Ltd.】" src="https://hatenablog-parts.com/embed?url=http%3A%2F%2Fsega-games.co.jp%2Frecruit%2Findex.html" frameborder="0" scrolling="no"></iframe><cite class="hatena-citation"><a href="http://sega-games.co.jp/recruit/index.html">sega-games.co.jp</a></cite></p> <p><span style="color: #000000; font-family: 'Segoe UI', 'Helvetica Neue', 'Apple Color Emoji', 'Segoe UI Emoji', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">それでは皆さま、よいお年をお迎えください!</span></p> <p><span style="color: #000000; font-family: 'Segoe UI', 'Helvetica Neue', 'Apple Color Emoji', 'Segoe UI Emoji', Helvetica, Arial, sans-serif; font-size: 14px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;"><br />©SEGA</span></p> <p> </p><div class="footnote"> <p class="footnote"><a href="#fn-ae2e193e" name="f-ae2e193e" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">「龍が如く」プロジェクトの方言で簡易的なフェイシャルアニメーションが適用されるスペックのキャラクター</span></p> <p class="footnote"><a href="#fn-9965286b" name="f-9965286b" class="footnote-number">*2</a><span class="footnote-delimiter">:</span><span class="footnote-text">プロジェクターから発する光のパターン画像をデジタルカメラで撮影するという技術</span></p> <p class="footnote"><a href="#fn-16985940" name="f-16985940" class="footnote-number">*3</a><span class="footnote-delimiter">:</span><span class="footnote-text">河童や小野ミチオなど</span></p> <p class="footnote"><a href="#fn-8f819b62" name="f-8f819b62" class="footnote-number">*4</a><span class="footnote-delimiter">:</span><span class="footnote-text">シェーダーによって前後します</span></p> <p class="footnote"><a href="#fn-7651c6a3" name="f-7651c6a3" class="footnote-number">*5</a><span class="footnote-delimiter">:</span><span class="footnote-text">企業秘密★</span></p> <p class="footnote"><a href="#fn-dc2138a0" name="f-dc2138a0" class="footnote-number">*6</a><span class="footnote-delimiter">:</span><span class="footnote-text">つい最近まで「龍が如く」シリーズのキャラクター班はSoftimageで開発していました</span></p> </div> sgtech