手書き風シェーダーの作成方法を調べる上で結構使えそうだなと思ったのでDeeplにて翻訳してみました。前半36P分です。
(翻訳面倒だよって人には使える記事かもです)
翻訳ガバガバなところがありますので、実際に卒論みながらやるのをお勧めします
多分この記事まででポストエフェクトでアウトライン、セルシェーダーを実装することくらいまではできてるかなと思います。
実際に私もUE5.3.2で同じものを実装してみながら翻訳しています。
画像は実装結果やBPです。
4ページ 8行目から
Translating the effect and feel of a 2D style onto a functioning real-time 3D environment is a challenge that sparked my interest tremendously. This topic was approved and granted to me on the condition that I would research a way to automate a big part of this process. Because of that, I will explore how a 2D style can be achieved in 3D, what is key in selling the look and how several automated systems can be implemented to speed up the workflow.
2Dスタイルの効果や感触を、機能するリアルタイムの3D環境に変換することは、私の興味を大いにかきたてる挑戦だ。
このテーマは、私がこのプロセスの大部分を自動化する方法を研究するという条件で承認され、私に与えられた。そのため、2Dのスタイルを3Dでどのように実現できるのか、ルックを売り込むために何が重要なのか、そして3Dに対応するいくつかの方法を探っていく。
また、ワークフローをスピードアップするために、いくつかの自動化システムをどのように導入できるかを探ってみたい。
この記事の概要↓
In this article, I will explore in depth how post-processing materials can be used to alter the general look of a scene to fit a 2D style. However, altering the general look of a game is not enough to achieve an art style. Textures and materials need to be tailored to it. For this, I will explore how the layered material system in Unreal Engine can be used for the texturing of a 2D style. These aspects will be put to the test by recreating a specific concept. In doing so, I will attempt to formulate an answer to the following questions:
この記事では、2Dスタイルに合わせてシーンの全体的な外観を変更するために、ポスト処理マテリアルをどのように使用できるかを詳しく説明します。しかし、ゲームの一般的な外観を変更するだけでは、アートスタイルを達成するのに十分ではありません。テクスチャとマテリアルをそれに合わせる必要があります。そこで、Unreal Engine のレイヤー マテリアル システムを使用して、2D ゲームのテクスチャリングをどのように行うことができるかを探ります。これらの側面は、特定のコンセプトを再現することで試されます。
そうすることで、以下の質問に対する答えを導き出すことを試みます:
• How effective are these systems for an artist?
For this I will review how well the set-up went and how time efficient, user-friendly and reusable
it is.
• How well does the style run in a game setting?
I will review shader complexity and performance in-game.
• What could make or break this auto-generated look for a player?
I will review what the shaders do well and where there is room for improvement.
- アーティストにとって、これらのシステムはどれほど効果的なのだろうか?
この点については、セットアップがどの程度うまくいったか、また、時間効率がよく、使い勝手がよく、再利用が可能かどうかを検証してみたい。 - そのスタイルはゲーム環境でどの程度動作するのか?
シェーダーの複雑さとゲーム内でのパフォーマンスについてレビューする。 - 選手にとって、この自動生成ルックの良し悪しを決めるものは何か?
シェーダーがうまく機能している点と、改善の余地がある点をレビューします。
The goal of this project is to get as close to the concept as possible with these systems. Another goal is to expand these systems so they can become customizable for a user to the point where it’s possible to quickly create a variety of 2D hand drawn looks, applicable to any kind of 3D scene in Unreal Engine. I do want to mention this project was only possible because other artists explored it and were willing to share their workflows. They are credited throughout this paper and in the bibliography section. I hope this paper and the artists mentioned can motivate and help artists dive into this topic. It certainly is an interesting part of the field and so many styles are still untouched and waiting to be translated.
このプロジェクトの目標は、これらのシステムで可能な限りコンセプトに近づけることだ。もうひとつの目標はこれらのシステムを拡張して、Unreal Engine のあらゆる種類の 3D シーンに適用可能なさまざまな 2D 手描きルックをすばやく作成できるところまで、ユーザーがカスタマイズできるようにすることです。
このプロジェクトが実現できたのは、他のアーティストがこのプロジェクトを探求し、そのワークフローを喜んで共有してくれたからに他なりません。これらのアーティストの名前は、本稿全体および参考文献のセクションにクレジットされています。この論文と言及したアーティストが、このトピックに飛び込むアーティストのモチベーションを高め、手助けになることを願っています。それは確かに多くのスタイルがまだ手つかずで、翻訳されるのを待っている。
5ページ
RESEARCH AND RELATED WORK
研究および関連業務
- PBR VS NPR
The translation of 2D art styles in a 3D environment has been a hot topic in the gaming industry for quite some time.
Because of its aesthetic, certain styles have become very popular. For example, Guilty Gear, which fits into the anime style, and The Walking Dead, which is more a western comic. These games provide evidence that 2D styles can be achieved in 3D and can succeed in selling the look. However, I found that more experimental art styles are usually the path less traveled in the industry and it’s harder to find examples of those in the game industry.
3D環境における2Dアートスタイルの翻訳は、かなり以前からゲーム業界で話題になっている。
その美的センスから、特定のスタイルが大人気となっている。例えば、ギルティギアはアニメのスタイルにフィットしています。また、西部劇コミックに近い『ウォーキング・デッド』など(がそうです)。これらのゲームは、2Dのスタイルが3Dでも実現でき、そのルックを売り込むことに成功できるという証拠を示している。しかし、より実験的なアートスタイルというのは、通常ゲーム業界ではそのような例を見つけるのは難しい。
In the 3D industry a distinction is made between physically based or photo-realistic rendering (PBR) and non-photorealistic rendering (NPR). PBR is a computer graphics approach that renders out light in the same way as the real world. Many PBR techniques thus aim to achieve realism. However, since some of the previous examples of games don’t want to achieve realism, but more the recreation of a certain art style, an alternative approach to rendering light and shading is needed. Then we come into the field of NPR. NPR is an area of computer graphics that aims to shade in a way that a variety of expressive art styles become possible. NPR has appeared in many video games and movies under its most common and popular example: the cel shader. The cel shader is designed to make 3D graphics appear to be flat by using less shading.
3D業界では、物理ベースまたはフォトリアリスティック・レンダリング(PBR)と非フォトリアリスティック・レンダリング(NPR)を区別している。PBRは、現実世界と同じ方法で光をレンダリングするコンピュータグラフィックスのアプローチです。そのため、多くのPBR技術はリアリズムの実現を目指している。しかしゲームでは、リアリズムの実現ではなく、特定のアートスタイルの再現を目的としているため、光と陰影をレンダリングするための別のアプローチが必要となります。次に、NPRの分野に入ります。NPRとは、コンピュータグラフィックスの一分野である。
NPRとは、コンピュータグラフィックスの一分野で、さまざまな表現が可能になるように陰影をつけることを目的としている。NPRはゲームや映画に登場する。3Dグラフィックスは、シェーディングを少なくすることで、平面的に見えるように設計されています。
2 UNITY VS UNREAL ENGINE
Learning about the distinction between PBR and NPR made it clear that, first and foremost, an alternative way of rendering light would need to be implemented to flatten out a 3D scene. While exploring the workflow of existing games (Guilty Gear) and personal work of artists online (definitely check them out - Nick Carver, Dermott Burns, Kamil Hepner,...), I discovered this was mostly approached by making custom shaders. In Unity through Shadergraph
and in Unreal Engine through Post-Processing Materials. It’s important to note it’s also possible to script effects into these engines. Because the focus of this paper is Unreal Engine and Post-Processing Materials, I won’t discuss Shadergraph.
PBRとNPRの違いについて学んだことで、何よりもまず、3Dシーンをフラットにするために、光をレンダリングする別の方法を実装する必要があることがはっきりした。
既存のゲーム(ギルティギア)やネット上のアーティストの個人的な作品(ニック・カーヴァー、ダーモット・バーンズ、カミル・ヘプナーなど)のワークフローを探るうちに、3Dシーンを平坦化するためには、まず第一に、ライトのレンダリングに代わる方法を実装する必要があることが明らかになった、
カミル・ヘプナーなど)、カスタムシェーダーを作成することでアプローチしていることを発見しました。
UnityではShadergraph、Unreal EngineではPost-Processing Materialsを使用します。これらのエンジンにエフェクトをスクリプトすることも可能です。本稿では、Unreal EngineとPost-Processing Materialsにフォーカスしているため、以下の説明は省略します。
3 POST-PROCESSING MATERIALS IN UNREAL ENGINE
As the word suggests, post-processing is the work that happens after the initial frame is fully rendered. Another pass is then added to that image, applying all the settings from your post-processing volumes. Settings like these could include color adjustments, screen-space ambient occlusion, bloom,...
言葉通り、post-processingは最初のフレームが完全にレンダリングされた後に行われる作業だ。その後のすべての設定を適用します。このような設定には、色調整、スクリーン空間アンビエントオクルージョン、ブルームなどが含まれます。
Post-processing materials are materials you can make and use within a post-processing volume to alter the look of a scene beyond the typical settings of the volume. With these materials, you can add in custom alterations like screen
effects, area type effects, or adjust the general visuals of your game without the implementation of scripts. These materials can be stacked in the volume. Each material you add to the stack adds another pass on top of the final render and thus also adds to the performance cost. The performance cost depends on the complexity of the material made. It’s good practice to combine passes and only activate the ones needed. It’s also good practice to use the existing image adjustments settings within the post-process volume as much as possible for what you want to achieve before creating any custom materials as these are most optimized.
ポストプロセッシングマテリアルとは、ポストプロセッシングボリューム内で作成・使用できるマテリアルのことです。シーンの外観をボリュームの一般的な設定以上に変更できます。これらのマテリアルを使用すると、スクリーンエフェクトやエリアタイプエフェクトのようなカスタム変更を追加したり、ゲームのビジュアル全般を調整したりすることができます。これらの マテリアルはボリュームにスタックできます。スタックにマテリアルを追加するたびに、最終的なレンダリングの上にもう1パスが追加されます。レンダリングの上にもう1パス追加されるため、パフォーマンスコストも増加します。パスを組み合わせ、必要なものだけをアクティブにするのは良い習慣です。
また、カスタムマテリアルを作成する前に、ポストプロセスボリューム内の既存の画像調整設定を可能な限り使用するのも良い方法です。
Post-processing is thus part of the render pipeline. The default renderer in Unreal Engine is the deferred renderer.
This means that all lights are applied deferred. This is achieved by first rendering the scene using shaders designed to output basic attributes of geometry such as position, normal, and diffuse color. Other attributes might include per-pixel specular values and other material properties. These are stored in full screen render targets, collectively
このように、Post-processingはレンダー パイプラインの一部です。Unreal Engine のデフォルト レンダラーはディファード レンダラーです。つまり、すべてのライトはディファードで適用されます。これは、まず、位置などのジオメトリの基本属性を出力するように設計されたシェーダーを使用してシーンをレンダリングすることによって実現されます。
ジオメトリの基本アトリビュート (位置、法線、ディフューズ カラーなど) を出力するように設計されたシェーダーを使用してシーンをレンダリングします。
その他のアトリビュートには ピクセルごとのスペキュラ値やその他のマテリアル・プロパティなどが含まれます。これらは、フルスクリーン・レンダー・ターゲットに格納されます。
6ページ
known as the G-buffer. Once the G-buffer has been generated, it’s possible to compute a fully lit result for any pixel on the screen (StackExchange, 2010). With post-processing materials, you can use the SceneTexture node to access the different render targets in the G-Buffer used to compose the ultimate image. These render targets can be used in your calculation steps for your post-processing effect. A typical example is using the render target Scene Depth to create outlines around an object, which is something we will tackle later for the style.
Gバッファが生成されると、画面上の任意のピクセルに対して、完全に照明された結果を計算することが可能になります(StackExchange、2010)。ポスト処理マテリアルを使用すると、SceneTexture ノードを使用して、究極のイメージを構成するために使用される G-Buffer 内のさまざまなレンダーターゲットにアクセスできます。これらのレンダーターゲットは計算ステップで使用できます。典型的な例は、レンダーターゲット Scene Depth を使用してオブジェクトの周りにアウトラインを作成することです。
8ページ
4 THE LAYERED MATERIAL SYSTEM IN UNREAL ENGINE
Altering the general look of a game is not enough to achieve an art style. Textures and materials need to be tailored to it and will also play a significant role in selling the look. While looking for a way to automate and speed up this part of the pipeline, I came across the game “The Cycle” by developer YAGER and their benefits of using the layered material system in Unreal Engine. This workflow was also researched and explored by Silke van der Smissen to completely texture a stylized scene in-engine.
アートスタイルを実現するには、ゲームの外観を変えるだけでは不十分です。テクスチャやマテリアルも テクスチャやマテリアルもそれに合わせる必要があり、ルックを売り込む上で重要な役割を果たします。パイプラインのこの部分を自動化し、スピードアップする方法を探していたところYAGER社のゲーム「The Cycle」に出会いました。マテリアル システムを使用する利点に出会いました。このワークフローは、Silke van der Smissen氏によって研究・探求され、エンジン内でスタイル化されたシーンに完全にテクスチャを適用することができました。
Layered materials are an extension of the material functions in Unreal Engine. As mentioned before, a material function is a self-contained node network that lets you package a part of a material into a reusable asset. You can then insert this asset into the node network of any master material you want. Any adjustments you make to these functions then gets automatically propagated to the master materials and instances that are using it. The goal of these functions is mostly to create a material library of which you can easily pick functions you need, like glass, moss, dirt, metals,... and insert wherever you want.
レイヤーマテリアルは、アンリアル エンジンのマテリアル関数の拡張機能です。前述のとおり、マテリアル関数は、マテリアルの一部を再利用可能なアセットにパッケージ化できる、自己完結型のノード ネットワークです。このアセットを、任意のマスター マテリアルのノード ネットワークに挿入することができます。これらのファンクションに加えた調整は、それを使用しているマスターマテリアルやインスタンスに自動的に反映されます。これらの関数の主な目的は、マテリアルライブラリを作成し、ガラス、コケ、土、金属など、必要な関数を簡単に選んで、好きな場所に挿入できるようにすることです。
The difference between material functions and the layered material system is that layered materials provide a user interface in which you can easily add, swap or remove layers from their stack. In contrast, with material functions you need to get into your node network and adjust it to add or remove what you want. This also results in a lot more master materials if you need variation.
マテリアル関数とレイヤーマテリアル・システムの違いは、レイヤーマテリアルがユーザー・インターフェイスを提供することです。スタックからレイヤーを簡単に追加、交換、削除できるユーザーインターフェイスを提供することです。スタックからレイヤーを簡単に追加、交換、削除できるユーザーインターフェイスを提供することです。対照的に、マテリアルファンクションでは では、ノードネットワークに入り、必要なものを追加したり削除したりするために調整する必要があります。また、バリエーションが必要な場合は マテリアルが必要になります。
Underneath, we can see an example of the layered materials stack from the game “The Cycle” by developer YAGER.
They used the layered material system to make assets fit in more with their environments. The workflow was as follows: they cleanly textured assets in Substance Designer and then used the system to build up wear and tear to adapt the assets to their respective environments. Because they had a material library consisting of different wear and grime based on environment, they could easily swap out certain weathering.
その下に、開発会社YAGERのゲーム「The Cycle」のレイヤーマテリアルスタックの例を見ることができる。彼らはレイヤーマテリアルシステムを使用して、アセットをより環境に適合させた。ワークフローは次のとおりです。彼らはSubstance Designerでアセットにきれいなテクスチャを施し、次にこのシステムを使ってアセットをそれぞれの環境に適合させるために損耗を積み重ねました。環境に応じて異なる磨耗や汚れで構成されたマテリアルライブラリを持っていたため、特定のウェザリングを簡単に入れ替えることができた。
9ページ
Working with this system proved very beneficial for them. Some of its key benefits were:
このシステムでの作業は、彼らにとって非常に有益であることが証明された。主な利点は以下の通りである:
• Reduced complexity:
The system has the power of material functions but without the complexity of the traditional workflow
(complex graph of material functions in a master material
- 複雑さの軽減:
従来のワークフローのような複雑さはなく、材料関数の力を発揮します。
(材料マスターの材料機能の複雑なグラフ)
• Manageability:
The system offers more control and is much more manageable. Especially with the UI
- 管理性:
システムはより多くのコントロールを提供し、より管理しやすくなっています。特にUI
• Flexibility:
The stack, layers and blends are much more editable in the future in comparison with the traditional
workflow: It’s easy to create a new layer and add it to the stack vs creating a new function and adding it to
the existing graph of a master material
- 柔軟性:
スタック、レイヤー、ブレンドは、従来のものと比較して、将来的に編集可能です。
• Clean base materials:
There’s less work to be done in the base material. Most of the work goes into the assets (layers and blends
ワークフロー: 新しいレイヤーを作成してスタックに追加するのは簡単です。
新しい関数を作成してマスターマテリアルの既存のグラフに追加するのと比較して、新しいレイヤーを作成してスタックに追加するのは簡単です。
• Instancing:
You can instance material layers and blends. You can stack the same layer with different inputs multiple
times without overriding their inputs
- インスタンス化:
マテリアルレイヤーとブレンドのインスタンス化が可能です。同じレイヤーを異なる入力で複数回スタックできます。
• Consistency:
Since the system works with decals as well, the same wear and tear can be used for both assets and
decals. This creates a more coherent and consistent look of a level.
- 一貫性:
システムはデカールでも機能するため、アセットとデカールの両方に同じ磨耗と破損を使用できます。これにより、レベルのより首尾一貫した一貫性のある外観が作成されます。
Epic Games also created their own version similar to the system and experienced certain benefits by using this for Gears of War. For example, artist no longer had to “guess” how a fully externally textured asset would look in-engine. By being able to build up certain effects in-engine, they could receive that feedback immediately.
エピック・ゲームズもまた、このシステムに類似した独自のバージョンを作成し、これを『Gears War』に使用することで一定の効果を得ている。例えば、アーティストは、完全に外部テクスチャ化されたアセットがエンジン内でどのように見えるかを「推測」する必要がなくなりました。エンジン内で特定のエフェクトを作り上げることができるため、そのフィードバックを即座に受け取ることができるのです。
Seeing these workflows and the benefits experienced made me wonder how I could apply this research to my topic.
これらのワークフローと経験した利益を目の当たりにして、私はこの研究を自分のテーマにどう応用できるかを考えた。
When looking at the concept for the case study, I noticed that the objects were all build- up of different layers of effects. Take the robot: it has a base watercolor layer, on top of that another watercolor layer, then hatching, a white rim light and moss patches. I also noticed that some objects only had a
few of these layers, meaning that not every object needed the same amount of layers.
ケーススタディのコンセプトを見たとき、オブジェクトがすべて異なるエフェクトのレイヤーで構成されていることに気づいた。ロボットを例にとると、ベースとなる水彩レイヤーがあり、その上に別の水彩レイヤー、さらにハッチング、白いリムライト、コケのパッチがある。オブジェクトによっては、これらのレイヤーがつまり、すべてのオブジェクトに同じ量のレイヤーが必要なわけではないのだ
This warmed me up to the idea of implementing a similar system and creating a small material library to texture assets for a highly illustrative art style in-
engine.
これによって、同じようなシステムを実装し、小さなマテリアル・ライブラリを作成して、高度なイラストレーション・アート・スタイル用のアセットにテクスチャを貼り付けるというアイデアを思いついた。
エンジンで使用することができます。
10ページ
5 MAKING 3D LOOK 2D
When looking at how Guilty Gear approached their style, they often stressed that the key to achieving 2D in 3D is the artists intentionality. Since nothing in the world is perfect, the eye immediately senses something as off if it is.
Adding intentional imperfections will be key to making or breaking the look you’re going for. Certain examples could be adding inconsistent line weight, thickness and distortion to make it feel hand drawn. These are just some examples to illustrate the importance of further alterations of math calculations so they don’t seem perfect and thus extremely CGI.
ギルティギアがどのように自分たちのスタイルに取り組んでいるかを見てみると、3Dで2Dを実現する鍵はアーティストの意図性にあるとよく強調されていた。この世に完璧なものなど存在しないのだから、そうであれば目はすぐに何かを感じ取る。
意図的に不完全さを加えることが、目指すルックを作るか壊すかの鍵になる。例えば、手描き感を出すために、線の太さやゆがみを不揃いにすることなどが挙げられる。これらはほんの一例に過ぎず、完璧なCGIと思われないように、計算をさらに変更することの重要性を説明するためのものである。
CASE STUDY
1 BREAKING DOWN THE ARTSTYLE
While achieving 2D in 3D is a popular subject in the industry, recreating more experimental styles seems to be the path less traveled. That is exactly the reason I chose this specific concept by Oswaldo KATO. Its watercolors, subtlety and soft look will prove to be an interesting challenge.
2Dを3Dで実現することは業界で人気のあるテーマだが、より実験的なスタイルを再現することは、あまり知られていないようだ。私がオズワルド加藤のこの作品を選んだ理由はまさにそこにある。その水彩画、繊細さ そして柔らかな表情は、興味深い挑戦であることを証明してくれるだろう。
https://twitter.com/ozoztv/status/1488089680172269569
11ページ
Before any other actions, it’s important to first and foremost analyze the art style and pinpoint the key characteristics that will have to be recreated.
他のアクションの前に、何よりもまずアートスタイルを分析し、再現しなければならない重要な特徴を突き止めることが重要だ。
The key elements for implementation are:
実施のための重要な要素は以下の通りである:
• The usage of watercolors
o There’s a “spottiness”, which could also be because of the paper being used.
o Certain areas are subtly bleeding into each other.
o While the pigment intensity is quite consistent, now and then there’s a slight fluctuation.
• There’s a paper texture
o There’s a graininess to the drawing.
• All silhouettes have an outline
o The outlines are wavy because it’s hand drawn.
o There’s a slight inconsistency in the line weight.
o The lines have a subtle a pencil texture to them.
• Interaction between light and shadow
o There’s a clear division between light and shadow, there are no gradients.
o The shadow is a darker color of the main base color of an object.
• Hatching
o Hatching is used to accentuate volumes.
o Hatching is also used for shadow areas and the ambient occlusion.
• There’s a white rimlight
o This reacts with light: it’s brighter in lit areas and darker in shadow areas.
• Not a lot of detail in the geometry, only focus on the silhouette of shapes
o Most of the detail comes from the texturing process.
-
水彩絵の具の使い方
・「不均一な分布」があるが、これも使用されている紙のせいかもしれない。
・ある領域は微妙に互いに滲み合っている。
・色素の濃さは非常に安定しているが、時々わずかな変動がある。 -
紙の質感がある
・描画に粒状感がある。 -
すべてのシルエットには輪郭がある
・手描きなのでアウトラインが波打っている。
・線の太さに若干の不一致があります。
・線に微妙に鉛筆のような質感がある。 -
光と影の相互作用
・光と影の間には明確な区分があり、グラデーションはありません。
・影は、オブジェクトのメイン・ベース・カラーの暗い色です。 -
ハッチング
・ハッチングはボリュームを強調するために使われます。
・ハッチングは影の部分やアンビエントオクルージョンにも使われます。 -
白いリムライトがある
・これは光に反応し、明るい場所ではより明るく、影の場所ではより暗くなります。 -
ジオメトリのディテールはあまりなく、形状のシルエットのみにフォーカスしている。
・ ディテールのほとんどは、テクスチャリングのプロセスから生まれる。
12ページ
AUTOMATING THE MAIN LOOK WITH POST-PROCESSING MATERIALS
メインルックをPOST-PROCESSING MATERIALSで自動化する
2.1 SETTING UP A POST-PROCESSING MATERIAL
Creating a post-processing material is done by first creating a normal material. You can then transform a regular material in UE to a post-process material by changing its material domain to “Post Process”. It’s also important to set its blendable location from the default “After Tonemapping” to “Before Tonemapping”. In essence, we’re telling the material to apply this pass earlier (before tonemapping) then it normally does (after tonemapping). This setting avoids the jittering of the silhouette because of temporal anti-aliasing, which often occurs when working with the scene depth. There’s also an option to set the blendable priority of the material. When having multiple post-processing materials, in here you can manually define in which order the passes should be processed. I will leave it at 0 for my shader. An instance is then made to be used within the post-processing volume.
ポストプロセスマテリアルを作成するには、まず通常のマテリアルを作成します。
その後、UEで通常のマテリアルを、そのマテリアルドメインを "ポストプロセス "に変更することでポストプロセスマテリアルに変換できます。また、ブレンド可能な場所をデフォルトの "After Tonemapping "から "Before Tonemapping "に設定することも重要です。要するに、このパスを通常(トーンマッピング後)より早く(トーンマッピング前)適用するようにマテリアルに指示するのです。
この設定により、シーン深度を扱うときによく発生する、時間的アンチエイリアスによるシルエットのジッタリングを回避できます。
マテリアルのブレンド可能な優先順位を設定するオプションもあります。複数のポストプロセッシングマテリアルがある場合、ここでどの順番でパスを処理するかを手動で定義できます。私のシェーダーでは0にしておきます。その後、ポストプロセッシングボリューム内で使用されるインスタンスが作成されます。
13ページ
Post Process volumes have boundaries, but can be set to boundless. Within the volume, under the tab “Rendering
Features” post-processing materials can be added. The tab holds an array in which you can drop your post-process materials. This is the post-processing stack I was referring to. Notice that, when inserting a material, the value “1” appears next to it. This signifies a slider that goes from 0 (fully disabled) to 1 (fully enabled). You can think of it like the opacity slider on a layer in Photoshop, though it’s best to stick to a value of either 0 or 1 since any value in between doesn’t mean the pass becomes more transparent, instead it can give an unpredictable result depending on the nodes. As mentioned previously, you can manually define the priority of a post-process material. If you don’t do that, it will follow the order of the materials in the stack. You can add in as many post-processing materials to the stack as you want, but it’s best to combine post-processes into one whenever possible.
ポストプロセスのボリュームには境界があるが、無限に設定することができる。ボリューム内のタブ「レンダリング
機能」タブでポストプロセスマテリアルを追加できます。このタブには、ポストプロセス素材をドロップできる配列があります。これがポストプロセススタックです。
マテリアルを挿入すると、その横に "1 "という値が表示されます。これは、0(完全に無効)から1(完全に有効)までのスライダーを意味します。Photoshopのレイヤーの不透明度スライダーのようなものだと思えばいいですが、0か1のどちらかの値で固定するのがベストです。その中間の値を指定しても、パスがより透明になるわけではなく、ノードによっては予測できない結果になる可能性があるからです。前述したように、ポストプロセスマテリアルの優先順位を手動で定義することができます。そうしないと、スタック内のマテリアルの順番に従います。スタックにpost-processing materialsを好きなだけ追加できますが、可能な限りpost-processingを1つにまとめるのがベストです。
2.3 OUTLINES SHADER
2.2.1 SETTING UP
The first key characteristic of the art style are the outlines. While there are a lot of different ways to approach outlines in 3D (inverted hull, fresnel, dot product,...), I decided to do them in a post-processing material since I need the effect globally and want to support normal detail of textures. To approach this, a Sobel operation will be performed on the Scene Depth, which is extracted from the G-buffer (Kris Kaufman, 2022 and Kamil Hepner, 2022).
アートスタイルの最初の特徴は、アウトラインです。3Dでアウトラインにアプローチする異なる方法はたくさんあるが(反転ハル、フレネル、ドット積など)、私はグローバルな効果が必要であり、テクスチャの法線ディテールをサポートしたいので、post-processing materialで行うことにした。これにアプローチするために、Gバッファから抽出されるScene Depthに対してSobel演算が実行されます(Kris Kaufman, 2022 and Kamil Hepner, 2022)。
A Sobel operation, also known as the Sobel-Feldman operator, is an edge detection algorithm used in image-processing and computer vision. This operation takes a render and shifts it by one pixel in multiple directions: up and down vertically and left and right horizontally. Each of these results get subtracted from the original render. This subtraction detects discrepancies, which represent the lines. When all of these are then added together, they create the fully outlined image. The effect can be recreated in Photoshop to better illustrate how it works. By duplicating an image, offsetting it by one pixel in any direction and then setting the blend mode to “Subtract”, lines will start to
show up.
ソーベル・フェルドマン演算とも呼ばれるソーベル演算は、画像処理やコンピュータビジョンで用いられるエッジ検出アルゴリズムである。この演算は、レンダリングを複数の方向(上下方向、左右方向)に1ピクセルずつずらす。これらの結果はそれぞれ、元のレンダリングから減算される。この減算によって、線を表す不一致が検出される。これらをすべて足し合わせると、完全にアウトライン化された画像ができあがる。この効果をPhotoshopで再現すると、その仕組みがよくわかる。画像を複製し、任意の方向に1ピクセルずつオフセットし、ブレンドモードを "減算 "に設定すると、線が現れ始めます。
14ページ
To recreate the effect in Unreal Engine, a SceneTexture node is used in the previous created Post-Process material.
This SceneTexture is then set to Scene Depth. When the color output of this node is connected with the emissive slot of the material, you can see in the viewport a black and white version of the scene. The Scene Depth node returns a value between 0 and 1 which tells us how close or far away an object is from the camera. When the pixels gets darker (closer to 0), it means the object is near. When the pixels get brighter (closer to 1), it means the object is further away. This information can be used to generate outlines even on objects that are far away.
Unreal Engine でエフェクトを再現するには、前回作成した Post-Process マテリアルで SceneTexture ノードを使用します。
この SceneTexture は、Scene Depth に設定されます。このノードのカラー出力がマテリアルのエミッシブ スロットに接続されると、ビューポートにシーンの白黒バージョンが表示されます。Scene Depthノードは0と1の間の値を返し、オブジェクトがカメラからどれくらい近いか遠いかを教えてくれます。ピクセルが暗くなる(0に近づく)と、オブジェクトが近くにあることを意味します。ピクセルが明るくなる(1に近づく)と、オブジェクトが遠くにあることを意味します。この情報を使って、遠くにある物体でも輪郭を生成することができる。
Since the scene depth is in grayscale, we only need to work with one channel from the color output. A component mask is used to disable the G, B and A channel. This will be the render to offset.
シーンの深度はグレースケールなので、カラー出力から1つのチャンネルだけを扱う必要がある。コンポーネントマスクを使用して、G、B、Aチャンネルを無効にする。これがオフセットへのレンダーとなる。
To offset the render, another Scene Depth is necessary. To get each pixel, we need to use the InvSize output which divides the U (1) and V (1) of the viewport by the width and the height of the window. To create the shift, we multiply the InvSize, which is a 2D vector for the UVs, by the direction we want to offset it. This is also a 2D vector so we can manipulate the U and V individually. The first direction we will offset it in will be the negative U or -1,0.
レンダリングをオフセットするには、別の Scene Depth が必要です。各ピクセルを取得するには、ビューポートのU(1)とV(1)をウィンドウの幅と高さで割ったInvSize出力を使用する必要があります。シフトを作成するには、UVの2DベクトルであるInvSizeにオフセットしたい方向を掛けます。これも2Dベクトルなので、UとVを個別に操作できます。最初にオフセットする方向は、負のUまたは-1,0になります。
Now that we have created the shift, we need to add it to the picture. To offset the picture, a Texture Coordinates node is needed. The multiplication can then be added to this node. This result is then used to offset the UV’s of the initially created scene depth.
シフトを作成したので、それを画像に追加する必要があります。ピクチャをオフセットするには、Texture Coordinatesノードが必要です。乗算はこのノードに追加できます。この結果は、最初に作成されたシーンデプスの UV をオフセットするために使用されます。
※オフセットするとは→https://wa3.i-3-i.info/word11923.html
15ページ
Last, we need to subtract this offset render from the original image to detect lines in that direction. To create the original image, another scene depth node is added.
最後に、このオフセットレンダリングを元の画像から減算して、その方向のラインを検出する必要がある。元の画像を作成するには 元の画像を作成するために、別のシーン深度ノードが追加されます。
Outputting this will result in outlines mostly on one side of the objects. That’s because edges were detected in that specific direction.
これを出力すると、アウトラインはほとんどがオブジェクトの片側になります。これは、エッジが検出されたからです。
16ページ
The next step is to do this for all other directions: U right [1,0], V down [0,1] and V up [0,-1]. By adding all of these results together, outlines will show up on all sides of the objects. Since we are reusing the same function for every direction, later in this paper I will optimize this by putting the main calculation in a material function and then reusing the material function instead.
次のステップは、他のすべての方向についてこれを行うことである: Uは右に[1,0]、Vは下に[0,1]、Vは上に[0,-1]。これらの結果をすべて足し合わせることで、オブジェクトのすべての面にアウトラインが表示される。すべての方向に対して同じ関数を再利用しているため、本論文の後半では、主な計算をマテリアル関数に置き、その代わりにマテリアル関数を再利用することで、これを最適化します。
17ページ
The range of the outlines goes too far and even draws outlines on polygons that shouldn’t have them. This can be fixed by multiplying our additions by a scalar. Then, a power node can be added to make the outlines stronger. It’s best to clamp this result so all values stay between 0 and 1 and the values don’t become burned by further calculations.
アウトラインの範囲が広すぎて、アウトラインを描くべきでないポリゴンにもアウトラインを描いてしまう。これは、足し算にスカラーを掛けることで修正できる。次に、パワーノードを追加してアウトラインを強くすることができます。すべての値が0と1の間にとどまるように、この結果をクランプするのがベストです。
左右のピクセル、上下のピクセルと計算していきます。
その後上下左右の計算結果を足してClampして、エミッシブカラーにつなげます
18ページ
Overlaying the outlines on the original scene can be done with a lerp (linear interpolate) node. This node allows you to transition from one component to another based on an alpha/mask. The mask will be our outlines. We can then go from our initial render to a flat color (for the lines).
元のシーンにアウトラインを重ねるには、lerp(線形補間)ノードを使います。このノードを使うと、アルファ/マスクに基づいて、あるコンポーネントから別のコンポーネントに移行できます。マスクはアウトラインになります。そして、最初のレンダリングから(ライン用の)フラットカラーに移行できます。
To get the original scene back, another Scene Texture node is needed. This needs to be set to Post-ProcessingInput0.
PostProcessingInput0 is the original scene after the image has been fully rendered and before any post-processing materials are applied, except the build-in settings from the post-processing volume if you’ve adjusted those. It’s worth to note that when you blend something on top of the Post-ProcessingInput0 and output that, in the next material, Post-ProcessingInput0 will have been overridden with what you previously created.
元のシーンを取り戻すには、別のScene Textureノードが必要です。これは、Post-ProcessingInput0に設定する必要があります。
PostProcessingInput0は、画像が完全にレンダリングされた後、後処理マテリアルが適用される前のオリジナルシーンです。Post-ProcessingInput0の上に何かをブレンドして出力すると、次のマテリアルでは、Post-ProcessingInput0は以前に作成したもので上書きされることに注意してください。
2.2.2 ADDING NORMAL LINES
To add in normal detail, we will need to perform the same Sobel operation as before, but this time on the world normal instead of the scene depth. We can copy and paste the same nodes until the addition from the previous operation and change the SceneTexture from Scene Depth to World Normal. Since anything normal-related uses R G and B values, we need to adjust the component mask and enable those channels again.
ノーマルのディテールを追加するには、前と同じ Sobel オペレーションを実行する必要がありますが、今回はシーンデプスの代わりにワールドノーマルに対して実行します。前の操作の追加まで同じノードをコピー&ペーストして、SceneTextureをScene DepthからWorld Normalに変更します。法線に関連するものはすべてR G B値を使用するので、コンポーネントマスクを調整し、これらのチャンネルを再度有効にする必要があります。
19ページ
After all the versions are added together, we will put the result in an AddComponents node. It will add all channels into one channel, outputting one value and thus making a grayscale result. Then the same multiplication and power node can be used to further adjust the lines.
すべてのバージョンが足し合わされた後、その結果をAddComponentsノードに置く。これはすべてのチャンネルを1つのチャンネルに加算し、1つの値を出力して、グレースケールの結果を作ります。その後、同じ乗算と累乗ノードを使用して、さらに線を調整することができます。
To combine the normal lines with the outlines, a max node was used. The max node will always output the highest value out of the two inputs it gets. This will make sure that, out of the two masks we just created (the outlines and the normal lines), it will always pick the most prominent value to draw a line on screen. For example, where the outlines don’t register anything but the normal lines do, the normal lines value will be used. Where the normal lines don’t register anything but the outlines do, the outlines value will be used. This result needs to be clamped again.
通常のラインとアウトラインを組み合わせるために、maxノードが使われた。maxノードは、取得した2つの入力のうち、常に最も高い値を出力する。これにより、先ほど作成した2つのマスク(アウトラインとノーマルライン)のうち、常に最も目立つ値を選んで画面に線を描くようになる。たとえば、アウトラインには何も登録されないが、法線には登録される場合、法線の値が使われる。通常線は何も登録されないが、アウトラインは登録される場合、アウトラインの値が使用される。この結果を再度クランプする必要がある。
If you want to apply the same color to both the normal lines and the outlines, you can use the blend we previously created after this max node. Otherwise, you can use a different lerp for outlines and normal lines and blend them together afterwards.
ノーマルラインとアウトラインの両方に同じ色を適用したい場合は、このmaxノードの後に、以前に作成したブレンドを使用できます。そうでない場合は、アウトラインと法線に別のlerpを使い、後でそれらをブレンドすることができます。
・先ほどまでSceneTexture:SceneDepthノードで作成していたアウトラインノードたち(Addまで)をコピペする
・コピペしたノードたちの SceneTexture:SceneDepthノードをSceneTexture:WorldNormalノードに変更、Mask(R)をすべてMask(RGB)に変更
・コピペした方のノードたちの計算結果が3つの値になっているため、AddComponentsで1つの値に集約
・集約した値に可変の値をかけたり、累乗したりして調整できるようにする
・同じようにSceneTexture:SceneDepthノードで作成していたアウトラインノードたちの計算結果にも任意の値をかけたり累乗したりする
20ページ
2.2.3 ADDING LINE THICKNESS
To add in line thickness, the directional offset needs to be multiplied with a scalar value that represents the line thickness. This way, we’re telling our shader how many extra pixels it needs to take to do the offset and draw the outline. This multiplication is done for every direction and uses the same scalar. It’s the same operation for the normal outlines, though here I wanted to control the thickness of the normal outlines separately, so I created a new scalar for that.
線の太さを追加するには、方向オフセットに線の太さを表すスカラー値を乗算する必要があります。こうすることで、シェーダに、オフセットを行い輪郭を描画するために必要な余分なピクセル数を伝えることになります。この乗算はすべての方向に対して行われ、同じスカラーを使用します。通常のアウトラインも同じ操作ですが、ここでは通常のアウトラインの太さを個別に制御したかったので、そのために新しいスカラーを作成しました。
SceneDepthノードの方4つにだけラインの太さ分の値をかけてみた結果になります
21ページ
2.2.4 CHANGING THICKNESS OVER DISTANCE
You might notice that the further away from the scene you are, the more the lines become dense and cluttered because they stay the same pixel size as up close.
シーンから離れれば離れるほど、線が密集して乱雑になることに気づくかもしれない。
We can adjust our thickness based on the distance of an object with the scene depth and a RemapValueRange node.
This method was discovered in Kamil Hepner’s stylized lines and outlines. We could say:
シーン深度とRemapValueRangeノードを持つオブジェクトの距離に基づいて、太さを調整することができます。
この方法は、Kamil Hepnerのスタイル化されたラインとアウトラインで発見されました。こうも言えます:
・For every object within 600 units range of the camera, we want the thickness to be 4.
The closer, the thicker we want the lines.
カメラから600ユニット以内のすべてのオブジェクトについて、太さを4にしたい。
近ければ近いほど、線は太くしたい。
・For every object between 600-1000 units range, we want the objects to gradually transition from thickness 4 to 1. So, the further away, the less thick the lines become.
600~1000ユニットの範囲内のすべてのオブジェクトについて、オブジェクトが厚さ4から1へと徐々に変化するようにしたい。つまり、遠ければ遠いほど、線の太さは細くなる。
・Every object that’s beyond 1000 units’ distance can be capped at 1 pixel line thickness.
1000単位以上の距離のオブジェクトは1ピクセルの線の太さに制限される。
If we cap the value that the scene depth node returns to a lower threshold of 600 and an upper threshold of 1000, we will already have completed the first and last condition. That means any value below 600 will be capped at its lower threshold and everything above 1000 will be capped at its higher threshold. This capped value can then be used as the main input for the RemapValueRange node to take care of all the values in between. The RemapValueRange remaps a value from its two original thresholds (600-1000) to two new thresholds (4-1). We can use this remapped value as the scalar to multiply all the directional offsets with. You can use the same remapped value for the normal lines or create a new one if you want different thresholds.
シーン深度ノードが返す値を下限しきい値600、上限しきい値1000に設定すれば、すでに最初と最後の条件が完了したことになります。つまり、600以下のすべての値は、その低い閾値でキャップされ、1000以上のすべては、その高い閾値でキャップされます。このキャップされた値はRemapValueRangeノードのメイン入力として使用され、その間の全ての値を処理します。RemapValueRangeは2つの元の閾値(600-1000)から2つの新しい閾値(4-1)に値をリマップします。このリマップされた値を、すべての方向オフセットに乗算するスカラーとして使うことができます。異なる閾値が必要な場合は、同じリマップ値を通常の線に使用するか、新しい値を作成することができます。
22ページ
2.2.5 DISTORTING THE LINES
In traditional, hand drawn art, we never really see any straight or perfect lines. That gives a lot of character to a drawing. It’s important to mimic traits like these to make 3D feel like 2D. In that sense, distortion can be added to the outlines to make it feel as if it’s hand drawn.
伝統的な手描きアートでは、直線や完璧な線を見ることはない。それが絵に個性を与えている。3Dを2Dのように感じさせるためには、このような特徴を模倣することが重要です。その意味で、輪郭線に歪みを加えることで、手描きのように感じさせることができる。
This can be achieved by adding a texture used to distort the thickness of the lines and is a method I saw Dermott Burns use in their 2D stylized shader. Another option is to make a custom node which holds a few lines of code generating a random number between certain thresholds. It’s important to note that it’s best practice to use a texture as opposed to lines of code since this greatly increases shader complexity and compilation times.
これは、線の太さを歪ませるためのテクスチャを追加することで実現でき、Dermott Burnsが2Dスタイルシェーダーで使っているのを見た方法です。もう1つの方法は、特定のしきい値の間で乱数を生成する数行のコードを保持するカスタムノードを作ることです。これはシェーダの複雑さとコンパイル時間を大幅に増加させます。
A grayscale noise texture returns a certain value per pixel. By adding these values to the value of our line thickness,
we can make some lines thicker and thus create some irregularity. Depending on the texture size and the strength of the black and white values, this effect can be even more exaggerated. To have that control, a scalar is added to manipulate the tiling of the node and a multiplication to strengthen the values of the texture. This operation gets added to the line thickness, determined by the RemapValueRange, and gets used as the new input for the offset multiplication. If you want the normal lines to be distorted as well, they will need the same operation.
グレースケールのノイズテクスチャは、ピクセルごとに一定の値を返します。これらの値を線の太さの値に加えることで、いくつかの線を太くすることができます。この値を線の太さの値に加えることで、いくつかの線を太くし、不規則性を作り出すことができます。テクスチャのサイズと黒と白の値の強さによっては、この効果をさらに誇張することができます。この制御を行うために、ノードのタイリングを操作するスカラーと、テクスチャの値を強化する乗算が追加されます。この操作は、RemapValueRangeによって決定された線の太さに追加され、オフセット乗算の新しい入力として使用されます。ノーマルラインも歪ませたい場合は、同じ操作が必要になります。
To give the user a choice whether to apply distortion or not, a Static Switch Parameter was added. This functions as a Boolean does. Then, in the true input, you plug in what it needs to output if it’s true and in the false output what it needs to output if it’s false.
歪みを適用するかどうかをユーザーに選択させるために、Static Switch Parameterが追加された。これはブール値として機能する。そして、true入力にはtrueの場合に出力する必要があるものを、false出力にはfalseの場合に出力する必要があるものを差し込む。
23ページ
2.2.7 CLEANING UP WITH MATERIAL FUNCTIONS
A material function is a self-contained node network that lets you package a part of a material into a reusable asset.
You can then insert this asset into the node network of any master material you want. Any adjustments you make to these functions then gets automatically propagated to the master materials and instances that are using it.
マテリアル・ファンクションは、マテリアルの一部を再利用可能なアセットにパッケージすることができる自己完結型のノード・ネットワークです。
このアセットを任意のマスターマテリアルのノードネットワークに挿入することができます。これらのファンクションに加えた調整は、それを使用しているマスターマテリアルやインスタンスに自動的に反映されます。
Since it’s possible to use material functions in a post-processing material, and since we are using the same parts of code multiple times, we can create a new material function which does this part of the code for us so we can call it whenever we need it later.
post-processing materialでマテリアル関数を使用することが可能で、同じ部分のコードを何度も使用することになるので、この部分のコードを実行する新しいマテリアル関数を作成し、後で必要なときにいつでも呼び出せるようにします。
We want this function to have an input for the directional offset and the line thickness so we can pass along the information from the main material to the function to do its calculations. To do that, we need to swap out our vector 2 and scalar with a FunctionInput vector 2 and FunctionInput scalar.
この関数に方向オフセットと線の太さの入力を持たせて、メインマテリアルから関数に情報を渡して計算できるようにしたい。そのためには、ベクトル2とスカラーをFunctionInputベクトル2とFunctionInputスカラーに入れ替える必要がある。
You’ll see the error “SceneTexture expressions cannot be used in opaque materials”. This can be dismissed. The SceneTexture nodes of this function will be able to access theirinformation if the function is used in the right material domain, namely post-process. You can call this function by dragging it from your content browser into your material.
「SceneTexture expressions cannot be used in opaque material」というエラーが表示されます。これは却下できます。この関数の SceneTexture ノードは、関数が正しいマテリアルドメイン、つまりポストプロセスで使用される場合、その情報にアクセスできます。コンテンツブラウザからマテリアルにドラッグすることで、この関数を呼び出すことができます。
You can also enable “Expose to Library” in the material function properties. Then, you will be able to look it up like you would with any other node in the material editor.
マテリアル機能のプロパティで「ライブラリに公開」を有効にすることもできます。そうすれば、マテリアルエディタで他のノードと同じように検索できるようになります。
24ページ
For normal lines, the same can be done. You could even take this a step further by creating a new material function in which you call your outline offset for each direction and add them all together. You can also create a material function in which you paste the entire operation for all directions like we did in the beginning. Using material functions will make your post-process material a lot cleaner, easier to look at and work with.
通常のラインについても同じことができます。さらに一歩進んで、新しいマテリアル関数を作成して、各方向のアウトラインオフセットを呼び出し、それらをすべて足し合わせることもできます。また、冒頭で行ったように、すべての方向に対して操作全体を貼り付けるマテリアル関数を作成することもできます。マテリアル関数を使用することで、ポストプロセスのマテリアルがよりすっきりとし、見やすく、作業しやすくなります。
25ページ
2.5 CEL SHADER
Another key characteristic of the artwork is that the lighting creates a clear division between lit areas and shadow areas. There are no gradients, which is the case with normal lighting and is the normal way of rendering light (photo-realistic rendering). This means we need to adjust the way our lighting gets rendered. This can be achieved by implementing a cel shader. Cel shading, also known as toon shading, is a non-photorealistic rendering technique designed to make 3D objects appear to be flat by using less shading color. The shading is done in a number of bands of different flat colors. This technique is often used to make 3D look like 2D and is often chosen as a style for games for its aesthetic.
作品のもうひとつの大きな特徴は、照明によって光の当たっている部分と影の部分が明確に分かれていることだ。グラデーションはありません。これは通常の照明の場合で、通常の光のレンダリング方法(フォトリアリスティック・レンダリング)です。つまり、照明のレンダリング方法を調整する必要があります。これは、セルシェーダーを実装することで実現できます。セルシェーディングはトゥーンシェーディングとも呼ばれ、3Dオブジェクトをより少ないシェーディングカラーで平坦に見せるように設計された非フォトリアリスティックレンダリング技術です。シェーディングは、異なるフラットカラーのいくつかのバンドで行われます。この技法は、3Dを2Dのように見せるためによく使用され、その美的感覚からゲームのスタイルとしてよく選ばれる。
When discussing the key to their art style, the company behind Guilty Gear mentioned that cel shading is often tricky to pull off well. They said: “In cel shading, everything is either lit or unlit, there’s no in between. This is one of the reasons cel shading is so hard to get right. In a drawing an artist can choose the most convincing distribution of light and darkness but in shaders it’s all math with unforgiving thresholds mercilessly split between light and dark. The slightest difference in the surface normal may end up in a huge blot. This is why precise control is required.”.
ギルティギアの制作会社は、アートスタイルの鍵について語る際、セルシェーディングをうまく表現するのは難しいことが多いと述べている。彼らは言う: 「セルシェーディングでは、すべてが光るか光らないかのどちらかであり、その中間はありません。これが、セルシェーディングをうまくやるのが難しい理由のひとつです。ドローイングでは、アーティストは最も説得力のある明暗の配分を選ぶことができますが、シェーダーでは、容赦のない閾値で容赦なく明暗を分ける、すべてが数学です。サーフェス法線のわずかな違いが、大きなしみになってしまうかもしれない。だからこそ、正確なコントロールが求められるのです」。
There were many elements they implemented to get precise control, one of them being adjusting the normal of a mesh so it would render more aesthetically pleasing.
彼らが正確なコントロールを得るために実装した要素はたくさんあり、そのひとつがメッシュの法線を調整して、より美しくレンダリングできるようにすることだった。
For the cel shader for this concept a lot of different approaches will be explored, discussed and reviewed based on their procedurality. While for this style it is not needed to go as far as the Guilty Gears approach, it’s great to keep in mind in case we run into objects that don’t get cel shaded well.
このコンセプトのためのセルシェーダーでは、プロシージャル性に基づいて、さまざまなアプローチを検討し、議論し、レビューする。このスタイルでは、「ギルティギア」のようなアプローチは必要ありませんが、セルシェーディングがうまくいかないオブジェクトに遭遇したときのために、覚えておくといいでしょう。
26ページ
2.5.1 USING A DOT PRODUCT
The most common method to implement cel shading is by using a dot product to compare the normals of a surface with the direction of the light. In essence, we want to know whether the surface normals and the direction of the light are pointing towards each other or not. If they do, it means the surface is lit. The more they point away from each other, the less lit.
セルシェーディングを実装する最も一般的な方法は、サーフェスの法線と光の方向をドット積で比較することである。要するに、サーフェスの法線と光の方向が互いに向いているかどうかを知りたいのだ。もしそうであれば、サーフェスが照明されていることを意味する。それらが互いに離れているほど、光が当たっていないことを意味する。
The dot product gives a certain value of the angle between the two and by thresholding the dot product, you can create multiple bands. For example, you can assign a darker color if the dot product is higher than -0.8. If the dot product is lower than -0.8, assign a light color. This will create a two band cel shader (Tommy Tran, 2018).
ドットプロダクトは、2つの角度の間のある値を与え、ドットプロダクトを閾値処理することによって、複数のバンドを作成することができます。例えば、ドット積が-0.8より高ければ、暗い色を割り当てることができる。ドット積が-0.8より小さい場合は、明るい色を割り当てます。これで2バンドのセルシェーダーができる(Tommy Tran, 2018)。
When a cel shader is to be implemented in a surface material, this seems to be the common way to do it. This method was initially tried to have more control over the way of shading per-object. However, there are some limitations with this method that were also some of the factors that drove me towards a global, post-processing cel shader.
セルシェーダーをサーフェスマテリアルに実装する場合、この方法が一般的なようです。この方法 は当初、オブジェクトごとのシェーディング方法をより自由にコントロールするために試みられました。しかし、この方法にはいくつかの制限があります。この方法にはいくつかの制限があり、それが私をグローバルなポスト処理セルシェーダーへと向かわせた要因でもありました。
One limitation is that only a directional light can affect the cel shading and only from the directional light can the color be extracted (using the AtmosphericLightColor node). Al other lights like spot, point and area lights have no effect or need hard-noding/hard-coding per light to take them into account. Another one is that other objects can’t cast shadows on cel shaded objects. This is because, even though another object might be in between the light and the main object, their normals are still pointing at each other and thus the calculations above still count for them.
1つの制限は、指向性ライトだけがセルのシェーディングに影響を与えることができ、(AtmosphericLightColorノードを使用して)色を抽出できるのは指向性ライトだけです。スポットライト、ポイントライト、エリアライトのような他のライトは効果がないか、それらを考慮するためにライトごとにハードコーディングが必要です。もう1つは、他のオブジェクトがセルシェーディングされたオブジェクトに影を落とせないことです。これは、ライトとメインオブジェクトの間に別のオブジェクトがあったとしても、それらの法線はお互いを向いているため、上記の計算がそれらのオブジェクトに対してカウントされるからです。
27ページ
Because of these limitations and the fact that the scene doesn’t require per-object control, I went for a cel shader in a post-processing material. Mind you, with a post-process material it is also possible to create a per object effect by masking objects out from the scene to apply the effect on them. This will be discussed later in the paper. Since post-processing materials gives us access to the G-buffer, we can calculate how lit a surface is instead of using a dot product. This means all light and shadow will be considered and then this value can be used to threshold and create different bands with. Post-processing materials also offer some work-around for implementing light color.
これらの制限と、シーンがオブジェクトごとの制御を必要としないという事実から、私はポストプロセスマテリアルのセルシェーダーを採用しました。ポストプロセスマテリアルを使えば、シーンからオブジェクトをマスクして、オブジェクトごとにエフェクトを適用することも可能です。これについては後述します。ポストプロセスマテリアルではGバッファにアクセスできるので、ドット積を使用する代わりにサーフェスの明るさを計算できます。つまり、すべての光と影が考慮され、この値を使って閾値を設定し、異なるバンドを作成することができます。ポスト処理マテリアルはまた、ライトカラーを実装するためのいくつかの回避策を提供します。
ポストエフェクトでセルシェーディング
2.5.2 USING AN IF NODE TO DETERMINE A BAND
To implement a cel shader we first need to extract the light information from our unaltered scene. Because of how the G-buffer works, there is no render target that has this information for us, so we need to calculate it ourselves with the render targets we have. In essence, we will divide our black and white unaltered scene, which includes the lighting, by a black and white diffuse color of the scene, which has no light. This will output a new black and white render containing all the light information (PrismaticaDev, 2020). You could put the light calculation into a material function as well, since this will be reused. In this phase, it’s extra important that your post-process material is set to “Before Tonemapping” so you can get the original light values from the scene and not the remapped ones.
セルシェーダを実装するには、まず、変更されていないシーンから光情報を抽出する必要があります。Gバッファの仕組み上、この情報を持っているレンダーターゲットはないので、今あるレンダーターゲットを使って自分で計算する必要があります。要するに、ライティングを含む白黒のシーンを、ライティングのないシーンの白黒の拡散色で分割します。これにより、すべてのライト情報を含む新しい白黒レンダリングが出力されます(PrismaticaDev, 2020)。これは再利用されるので、光の計算をマテリアル関数に入れることもできます。この段階では、ポストプロセスのマテリアルを「トーンマッピング前」に設定し、シーンからリマップされた値ではなく元の光の値を取得できるようにすることが特に重要です。
We can then plug this information into an if node to create the first band of the cel shader. An if node compares two values to each other. You can then specify what it needs to do/output if one value is bigger than the other, smaller, or if they’re equal to each other. In this case, we want to compare the value of each pixel of the light information we just calculated to a threshold we choose ourselves, for example 0.5. This will be our shadow threshold or shadow depth. If the light value is bigger than the shadow threshold of 0.5, we want it to output the diffuse color of the scene. If it’s smaller or equal, we want it to output a darker version of the diffuse color, representing the shadows. We can achieve a darker version of the diffuse by multiplying it with a scalar. This will influence the tint of the scene. If you want to have some control over the color of the shadow, you can also multiply the diffuse with a color.
次に、この情報を if ノードに差し込み、セルシェーダの最初のバンドを作成します。ifノードは2つの値を比較します。一方の値が他方より大きい場合、小さい場合、あるいは等しい場合に、何をするか、何を出力するかを指定できます。この場合、先ほど計算した光情報の各ピクセルの値を、たとえば0.5など、自分で選んだしきい値と比較したい。これが影のしきい値または影の深さになります。光の値が影のしきい値0.5より大きければ、シーンの拡散色を出力したい。0.5より小さいか等しい場合は、シャドウを表す拡散色を暗く出力します。ディフューズにスカラーを乗算することで、ディフューズをより暗くすることができます。これはシーンの色合いに影響します。影の色をある程度コントロールしたい場合は、ディフューズに色を乗算することもできます。
28ページ
2.5.3 ADDING EXTRA BANDS
To create an extra band, an extra if node is needed. We need to do another value check with the light information, but this time with a lower threshold, for example 0.3. If the value extracted from the light is bigger than 0.3, it can render the band we created with our previous if node. If it’s smaller or equal to 0.3, we can output a newly multiplied version of our diffuse scene. If you want to create another band for a highlight, then the light information needs to be checked with a way higher threshold. That’s the general workflow for adding bands. This gives you control over every band’s depth and color but also has the downside of being hard coded and thus limited to how many bands you code in. This shader is completely dynamic and will thus change along when you adjust your lights.
余分なバンドを作るには、ifノードが必要です。ライトの情報を使って別の値チェックをする必要があるが、今回はしきい値を低くして、例えば0.3にする。光から抽出された値が0.3より大きければ、前のifノードで作成したバンドをレンダリングできます。0.3より小さいか等しい場合、ディフューズシーンの新しく乗算されたバージョンを出力することができます。ハイライト用に別のバンドを作成したい場合は、ライト情報をもっと高いしきい値でチェックする必要があります。これが、バンドを追加する一般的なワークフローです。これは、すべてのバンドの深さと色をコントロールできますが、ハードコードされているため、コードするバンドの数に制限があるという欠点もあります。このシェーダーは完全にダイナミックなので、あなたがライトを調整するときに一緒に変化します。
2.5.4 CEL SHADER WITH PROCEDURAL BANDS
If you want a system where the user can specify how many bands they want, there are multiple ways to approach it depending on how much you want to customize each band. Next up is a version in which, in the material instance, you can specify how many bands you want. For this, the lighting information needs to be multiplied by a scalar for the amount of cels desired. This is reduced to a whole number, posterizing the light information based on the scalar. This is then divided back to the 0-1 range to get normal light and shadow values (Martin Widdowson, 2020).
ユーザーがバンド数を指定できるシステムにしたい場合、各バンドをどの程度カスタマイズしたいかによって、複数のアプローチ方法があります。次は、マテリアルのインスタンスで、バンド数を指定できるバージョンです。この場合、ライティング情報に希望するセル数のスカラーを掛ける必要があります。これを整数にして、スカラーに基づいて照明情報をポスタライズします。これを0~1の範囲に戻して分割し、通常のライトとシャドウの値を得る(Martin Widdowson, 2020)。
29ページ
If you want further customization of each band, it can be an option to implement a “custom” node. A custom node
allows you to write any lines of HSLS code you want your material to perform without having to create and integrate scripts from programming software. In essence, you could write a for-loop that, for the amount of bands that the user wants, checks the light value, tells the system how to render the bands and gives different outputs so the user can have control over each bands depth and color. However, this method was not put to the test since this would definitely increase shader complexity.
各バンドをさらにカスタマイズしたい場合は、「カスタム」ノードを実装することも可能です。カスタムノード を使用すると、プログラミングソフトウェアからスクリプトを作成して統合することなく、素材に実行させたい HSLS コードの任意の行を記述することができます。要するに、ユーザーが望むバンドの量に対して、光の値をチェックし、バンドをレンダリングする方法をシステムに伝え、ユーザーが各バンドの深さと色をコントロールできるように異なる出力を与えるforループを書くことができます。しかし、この方法は、シェーダーの複雑さを確実に増大させるので、テストには使われませんでした。
2.5.5 MAKING A CEL SHADER USING CURVES AND LUTS
Another way to approach the cel shader is using curves to determine the bands. This provides full control over the amount of bands, as well as the width and color of a band (Tommy Tran, 2018).
セルシェーダーにアプローチするもう1つの方法は、カーブを使ってバンドを決定することです。これにより、バンドの量だけでなく、バンドの幅や色も完全に制御できる(Tommy Tran, 2018)。
Curves are data containers that hold a set of values interpolated over a range. Curves can be vectors, floats, and colors. To create a curve, go to Add New>Miscellaneous>Curve and choose CurveLinearColor, since we will be using colors for our cel shader. By default, it will give you a grayscale gradient curve to start with. A Curve Linear Color asset can store interpolated RGBA colors. If you double click on the created curve, the curve editor shows up. Since the curve only used the B channel, and since it is interpolated between 0 (black) and 1 (white), it outputs a grayscale gradient.
カーブは、ある範囲にわたって補間された値のセットを保持するデータ・コンテナである。カーブには、ベクトル、浮動小数点数、および 色である。カーブを作成するには、Add New>Miscellaneous>Curveと進み、CurveLinearColorを選択します。を選択します。デフォルトでは、グレースケールのグラデーションカーブが作成されます。カーブ線形カラー アセットには、補間されたRGBAカラーを保存できます。作成したカーブをダブルクリックすると、カーブエディタが表示されます。このカーブでは カーブはBチャンネルのみを使用し、0(黒)と1(白)の間で補間されているので、グレースケール グラデーションが出力される。
30ページ
The editor holds 3 main windows:
エディターには3つのメインウインドウがある:
・The curve graph in which you can add, subtract and adjust any keys for the RGBA channels (similar to the timeline in blueprints, if you’re familiar with that).
RGBAチャンネルのキーを追加、減算、調整できるカーブグラフです(ブループリントのタイムラインに似ています)。
・The curve gradient result of the keys from the curve graph. You can also only work with this part of the graph. Then the color keys you add here will automatically create the RGBA keys in the curve graph.
カーブ・グラフのキーのカーブ・グラデーションの結果。グラフのこの部分だけを扱うこともできる。ここで追加した色キーは、自動的にカーブグラフのRGBAキーを作成します。
・The color panel, which gives you some post-processing options that affect all the keys.
カラーパネルでは、すべてのキーに影響するpost-processingオプションをいくつか選択できる。
We can’t just use curves like these in the material editor. Only Curve Atlases can do that and so we need to store our curves in there. Then, we can call that atlas and specify which curve it needs to use for our cel shader. To create a Curve Atlas, go to Add New>Miscellaneous>Curve Atlas. Open the Curve Atlas and in the details panel under “Gradient Curves” press the + button to add your created curve into it.
このようなカーブは、マテリアル・エディタで使うことはできません。それができるのはカーブアトラスだけなので、そこにカーブを保存する必要があります。そして、そのアトラスを呼び出して、セルシェーダーに使用するカーブを指定します。カーブアトラスを作成するには、Add New(新規追加)>Miscellaneous(その他)>Curve Atlas(カーブアトラス)と進みます。カーブアトラスを開き、詳細パネルの "グラデーションカーブ "の下にある+ボタンを押して、作成したカーブをアトラスに追加します。
We want our curve to remap the values from the extracted light to the values of the curve. So, if a value from the extracted light is underneath a certain value of a key in the curve, it will be mapped to that. If it’s above a certain value of a key in the curve, it will be mapped to the key above that. Because of the remapping, it’s very important that the extracted light info is clamped from 0 to 1. In the post-processing material, a “CurveAtlasRowParameter” node needs to be added in. This allows us to call our Atlas and thus use curves in materials. In the node, make sure you choose the atlas we just created and choose our example curve as the default curve. Since this node is a parameter, you can always choose a different curve in instances (as long as you make sure the curve is part of the atlas).
抽出された光の値をカーブの値にリマップさせたい。つまり、抽出された光の値がカーブのキーのある値の下にあれば、その値にマッピングされる。カーブのキーのある値より上にある場合は、その上のキーにマッピングされます。リマッピングのため、抽出されたライト情報が0から1にクランプされることが非常に重要です。ポスト処理マテリアルでは、"CurveAtlasRowParameter "ノードを追加する必要があります。これにより、アトラスを呼び出し、マテリアルでカーブを使用することができます。このノードで、先ほど作成したアトラスを選択し、デフォルトカーブとして例のカーブを選択してください。このノードはパラメータなので、(カーブがアトラスの一部であることを確認すれば)インスタンスでいつでも別のカーブを選択できます。
All we need to do to remap the values from the extracted light, is plug that info into this parameter and the node will take care of the rest. If you output this result, you will see the scene as if it is photo realistically rendered. That is because our curve is a gradient and thus the values of the light are remapped to this gradient. For a cel shader we don’t want it to interpolate between this many values, we want fewer and clear divisions between values.
抽出されたライトの値をリマップするために必要なのは、その情報をこのパラメータに差し込むことだけで、あとはノードが処理してくれます。この結果を出力すると、シーンがフォトリアリスティックレンダリングされたように見えます。これは、カーブがグラデーションであるため、ライトの値がこのグラデーションにリマップされるからです。セルシェーダでは、これほど多くの値の間を補間してほしくありません。
32ページ
Let’s create another curve to make the cel shader. It needs to be added to the atlas. Then, in the instance of the material, you can choose this new curve to be used. In this curve, we will mainly work with the color result graph. If you double click above the graph, you can add in a color key. If you double click underneath, you can add in an opacity key, though we won’t be using this. Add a few more versions of gray colors in the color graph. For example, for light value 0 to 0,2, we want it to render completely black. From 0,2 to 0,8 we want it to render one version of gray and from 0,8 onwards we want it to render white. This will create a 2 band cel shader. You can make more bands by adding in more color keys. The closer or further apart you put these values, the smaller or broader a band.
セルシェーダーを作るために、別のカーブを作りましょう。アトラスに追加する必要があります。そして、マテリアルのインスタンスで、この新しいカーブを選択して使用します。このカーブでは、主にカラー結果グラフを扱います。グラフの上をダブルクリックすると、カラーキーを追加できます。グラフの下をダブルクリックすると、不透明度キーを追加できます。カラーグラフにグレーの色をいくつか追加します。例えば、ライトの値が0から0,2の場合、真っ黒にレンダリングしたい。0,2から0,8まではグレーの1つのバージョンをレンダリングし、0,8以降は白をレンダリングします。これで2バンドのセルシェーダができます。さらにカラーキーを追加してバンドを増やすことができます。これらの値を近づけたり離したりするほど、バンドは小さくなったり広くなったりします。
キーを増やすとき、赤い四角のどこかをダブルクリックすると追加される
We can then use these remapped values to multiply on top of our base color and thus add the cel shader on top of our scene.
次に、これらのリマップされた値を使ってベースカラーに乗算し、シーンにセルシェーダーを追加します。
33ページ
You’re not limited to black and white. You can use any kind of color for the cel shader. If you want different values of shadows, you just have to make sure the values of the colors fit. In the material instance of the post-processing material we are making, you can double click on the curve being used. You can then directly adjust this curve and immediately see the changes in the viewport. Let’s add some color to the curve.
白黒に限定されることはありません。セルシェーダーにはどんな色でも使えます。影の値を変えたい場合は、色の値が合うようにすればよい。後処理のマテリアルのインスタンスで マテリアルのインスタンスで、使用するカーブをダブルクリックします。このカーブを直接調整して ビューポートで変更をすぐに確認できます。カーブに色を追加してみましょう。
34ページ
If you find it a bit too dark, you can either use lighter color values for the curve, adjust the brightness for all keys in the color panel of the curve or in the material multiply the node by a scalar so the user has control over it in the material instance.
少し暗すぎると感じる場合は、カーブに明るいカラー値を使用するか、カーブのカラーパネルですべてのキーの明るさを調整するか、マテリアルのインスタンスでユーザーがコントロールできるように、マテリアルでノードにスカラーを乗算します。
2.5.6 ADDING IN AMBIENT OCCLUSION
To add in the post-processing ambient occlusion the cel shader needs to be multiplied with the SceneTexture:AmbientOcclusion. That’s really all there is to it. Then, the AO settings within the post-processing volume will work again (PrismaticaDev, 2020).
post-processingでアンビエントオクルージョンを追加するには、セルシェーダーにSceneTexture:AmbientOcclusionを乗算する必要があります。本当にそれだけです。その後、ポストプロセッシングボリューム内のAO設定が再び機能します(PrismaticaDev, 2020)。
35ページ
2.5.7 ADDING IN LIGHT COLOR
As mentioned earlier, extracting the color of lights used in the scene can be a tricky for cel shading and is often where a basic cel shader falls short. If you don’t want to deep dive into scripting, then the following method can offer a global node-based workaround for this. The method is not perfect and is best to be implemented early in a project so all texture colors can be coordinated with this effect since it does alter colors a bit. Because of this reason, light color has been left out for the final scene. Another reason is that this method then discards the color of the different bands created in previous versions because, to take light color into account, it will use the scene color instead.
前述したように、シーンで使用されるライトの色を抽出することは、セルシェーディングにとって厄介であり、基本的なセルシェーダがしばしば不足するところです。スクリプティングに深入りしたくない場合は、次の方法でグローバルノードベースの回避策を提供できます。この方法は完璧ではなく、プロジェクトの初期に実装するのがベストです。このような理由から、ライトカラーは最終的なシーンでは除外されています。もう1つの理由は、この方法では、以前のバージョンで作成されたさまざまなバンドのカラーが破棄されるため、ライトカラーを考慮するために、代わりにシーンカラーを使用するからです。
To add light color to the scene, we take our final unaltered render from the scene and condense it to just its color information. The reason we can’t use diffuse or base color is because this is an unlit version of the scene with only the color information of each mesh. However, by neutralizing the complete unaltered render, which holds all lighting information, including the light color, we can create a somewhat similar diffuse version of the scene. This is done by normalizing the SceneTexture:PostProcessingInput0. We can then correct this normalized version a bit by multiplying it by a certain number, like 1. You could make this a scalar if you want to influence it in instances. To then get our previous cel shader back on top of this diffuse color, we need to desaturate the result of the cel shader and multiply it by the diffuse of the scene. This is the inverse version of our light extraction we’ve been using (dividing the unaltered scene with the diffuse color): adding the light information (now cel shaded) back on top of the diffuse version (PrismaticaDev, 2020).
シーンにライトカラーを追加するために、シーンから最終的に変更されていないレンダーを取り出し、それをカラー情報だけに凝縮する。ディフューズやベースカラーを使用できない理由は、これが各メッシュの色情報のみを持つシーンのアンライトバージョンだからです。しかし、ライトカラーを含むすべてのライティング情報を保持する、完全な変更前のレンダーを中和することで、シーンの多少似たディフューズバージョンを作成できます。これは SceneTexture:PostProcessingInput0を正規化します。次に、この正規化されたバージョンを少し補正します。インスタンスで影響を与えたい場合は、これをスカラーにすることもできます。そして 前のセルシェーダーをこのディフューズカラーの上に戻すには、セルシェーダーの結果を脱色して、ディフューズと掛け合わせる必要がある。これは、これまで使ってきたライト抽出の逆バージョンです(変更前のシーンをディフューズで割る)。これは,これまで使用してきた光源抽出の逆バージョンです(変更前のシーンを拡散色で分割する)。バージョン(PrismaticaDev, 2020)の上にライト情報(今はセルシェーディングされたもの)を追加します。
2.5.8 BLENDING IT INTO OUR EXISTING NODES
To blend our cel shader with our previously created outlines, we will go back to the lerp that blended our lines on top of our unaltered scene. Instead of blending it with our unaltered scene, we now want it to blend with our cel shader. I’ve added a Boolean (StaticSwitchParameter) in between so the user can choose whether they want the lines on the unaltered scene or the cel shaded one.
セルシェーダを以前に作成したアウトラインとブレンドするには、変更前のシーンの上に線をブレンドしたレープに戻ります。変更前のシーンとブレンドする代わりに、今度はセルシェーダとブレンドします。間にブール値(StaticSwitchParameter)を追加したので、ユーザーは、変更されていないシーンとセルシェーディングされたシーンのどちらにラインを表示させたいかを選択できます。
36ページ
I also implemented an option that allows the user to choose between blending the cel shader on top of the diffuse or blending it on top of a flat background color. Since my shader uses the version with the if nodes, we need to adjust it a bit to do that. Between the ComponentMask of the SceneTexture:DiffuseColor and the multiply, we need to insert another Boolean (StaticSwitchParameter). This one will decide whether to output the diffuse color of the scene or a flat background color on which the bands get multiplied.
また、セルシェーダーをディフューズの上にブレンドするか、フラットな背景色の上にブレンドするかを選択できるオプションも実装しました。私のシェーダはifノードを使ったバージョンを使っているので、そのようにするには少し調整する必要があります。SceneTexture:DiffuseColorのComponentMaskとmultiplyの間に、別のBoolean (StaticNode)を挿入する必要があります。別のブール値 (StaticSwitchParameter) を挿入します。これは、シーンのディフューズカラーを出力するか、それとも シーンの拡散色を出力するか、バンドが乗算されるフラットな背景色を出力するかを決定します。
一旦半分終わったのでこの記事は終わりです。
後半は模様付けるところから始まるかと思います。