質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

2789閲覧

ドットシェーダーの適用後画像で色がブレンドされてしまう

Qicken

総合スコア6

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2020/12/17 13:37

編集2020/12/17 13:42

前提・実現したいこと

Unityにて、ドットシェーダーを作成したい。
(ただし、実際はソースコードはただのモザイクシェーダーです。)
ドット絵らしくボヤけないように解像度を落としたいのですが、背景色とブレンドされてしまいボヤけた印象になってしまっています。コレを回避したいです。

発生している問題・エラーメッセージ

シェーダー適用後の画像の一部が背景色とブレンドされてしまっている。

該当のソースコード

Shader "Custom/DotEffect" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _PixelNumber ("PixelNum", float) = 100 } SubShader { Pass { Tags { "RenderType"="Opaque" } CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" sampler2D _MainTex; float _PixelNumber; struct v2f { half4 pos : POSITION; half2 uv : TEXCOORD0; }; float4 _MainTex_ST; v2f vert(appdata_base v) { v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); return o; } half4 frag(v2f i) : COLOR { half2 uv = floor(i.uv * _PixelNumber) / _PixelNumber; fixed4 col = tex2D(_MainTex, uv); return col; } ENDCG } } }

試したこと

まずプロジェクトセッティングからアンチエイリアスを切りました。シェーダー適用前のカメラの画像はエッジの部分が背景色とブレンドされていない状態なのですが、ポストプロセス適用後にブレンドされてしまいます。
ソースコード上はブレンドするような実装がないはずなのですが...適用前適用後

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こちらでも試してみたところ、おっしゃる通り背景色漏れが観察されました。
通常は下図のように描画されるシーンにおいて...

図1

カメラ用スクリプトとして下記のようなコードを使用し...

C#

1using UnityEngine; 2 3[RequireComponent(typeof(Camera))] 4[ExecuteAlways] 5public class DotEffect : MonoBehaviour 6{ 7 [SerializeField] private Material effectMaterial; 8 9 private void OnRenderImage(RenderTexture src, RenderTexture dest) 10 { 11 if (this.effectMaterial == null) 12 { 13 Graphics.Blit(src, dest); 14 } 15 else 16 { 17 Graphics.Blit(src, dest, this.effectMaterial); 18 } 19 } 20}

effectMaterialにはご質問者さんのシェーダーコードを使ったマテリアルをセットしたところ、下図のようにオブジェクトの縁に背景のマゼンタ色が混じったドットが出現しました。
なお、ドットをある程度大きくして見やすくするため、マテリアルのPixelNumは40に設定しています。

図2

これはおそらくhalf2 uv = floor(i.uv * _PixelNumber) / _PixelNumber;によって求めた結果のUVが、必ずしもぴったり処理前映像のテクセル中心を指しているとは限らないことによるのだろうと思います。
サンプリング位置がテクセル中心からずれていると、ずれに応じて近傍のテクセルの色と線形補間された色が取得され、結果として背景色が混ざり込んだ状態になってしまったのでしょう。

そこでカメラ用スクリプトを下記のように変更して、線形補間をオフにしたところ...

C#

1using UnityEngine; 2 3[RequireComponent(typeof(Camera))] 4[ExecuteAlways] 5public class DotEffect : MonoBehaviour 6{ 7 [SerializeField] private Material effectMaterial; 8 9 private void OnRenderImage(RenderTexture src, RenderTexture dest) 10 { 11 if (this.effectMaterial == null) 12 { 13 Graphics.Blit(src, dest); 14 } 15 else 16 { 17 src.filterMode = FilterMode.Point; 18 Graphics.Blit(src, dest, this.effectMaterial); 19 } 20 } 21}

下図のように背景色漏れが起こらなくなりました。

図3

余計なお世話かもしれませんが、ドット化したときの映像が元の映像に対して斜めにずれたり、個々のドットの形が画面のアスペクト比に応じた長方形になるのが気にならないでしょうかね?

図4

ずれはfloorの代わりにroundで丸めてやればいいでしょうし、ドットを正方形にする場合はアスペクト比に応じて縦横のピクセル数を調整してやるといいでしょう。
シェーダーコードを下記のように改変したところ...

ShaderLab

1Shader "Custom/DotEffect" 2{ 3 Properties 4 { 5 _MainTex ("Base (RGB)", 2D) = "white" {} 6 _PixelNumber ("PixelNum", float) = 100 7 } 8 9 SubShader 10 { 11 Pass 12 { 13 Tags { "RenderType"="Opaque" } 14 15 CGPROGRAM 16 #pragma vertex vert 17 #pragma fragment frag 18 #include "UnityCG.cginc" 19 20 sampler2D _MainTex; 21 float _PixelNumber; 22 23 struct v2f 24 { 25 half4 pos : POSITION; 26 half2 uv : TEXCOORD0; 27 }; 28 29 float4 _MainTex_ST; 30 31 v2f vert(appdata_base v) 32 { 33 v2f o; 34 o.pos = UnityObjectToClipPos(v.vertex); 35 o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); 36 return o; 37 } 38 39 float4 _MainTex_TexelSize; 40 41 half4 frag(v2f i) : COLOR 42 { 43 float2 pixelNumber = float2(_MainTex_TexelSize.z * _MainTex_TexelSize.y * _PixelNumber, _PixelNumber); 44 half2 uv = round(i.uv * pixelNumber) / pixelNumber; 45 fixed4 col = tex2D(_MainTex, uv); 46 return col; 47 } 48 ENDCG 49 } 50 } 51}

下図のようになりました。

図5

投稿2020/12/18 19:20

Bongo

総合スコア10811

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Qicken

2020/12/22 02:32

返答遅れた事をまずお詫びします。なんらかの理由で線形補完されているであろう事は結果から推測が経ちましたが原因と解決策が全く分からず随分悩んだのでとてもスッキリしました。roundの件も勉強になりました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問