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

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

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

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

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

Q&A

解決済

1回答

4947閲覧

Unityのfragmentシェーダーの色の出力について質問です

shauni

総合スコア13

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

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

0グッド

0クリップ

投稿2018/12/13 08:38

編集2018/12/14 14:38

前提・実現したいこと

Unityのfragmentシェーダーの色の出力について質問です
0~255の整数で256段階に表現された色をfloatもしくはfixedに戻して出力したいのですがそのまま256で割るだけだとうまくいきませんでした
出力した色をスクショしてペイントソフトで調べてみたところ、元のfloatの値が0.1だったら89だったり、0.01だったら25だったり、どのような規則があるのかわかりませんでした

intの色とfloatかfixedの色を相互に変換するにはどうすれば良いのでしょうか

unityのバージョンは2017.4.15f1です

Shader "Unlit/color test" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } float4 frag (v2f i) : SV_Target { float4 col; col.rgb = 0.0; //128になってほしいがスクショすると188になる col.r = float(128.0 / 255.0); //25になってほしいがスクショすると88になる // col.r = float(25 / 255.0); col.a = 1.0; col.gb = 0.0; return col; } ENDCG } } }

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

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

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

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

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

Bongo

2018/12/14 07:08

シェーダーのコードやC#スクリプトのコードもご提示いただけると参考になるかもしれません。また、ちょっと気になるのですが、メニューの「Edit」→「Project Settings」→「Player」の「Other Settings」の「Rendering」の「Color Space」はどのような設定になっているでしょうか?
shauni

2018/12/14 08:53 編集

回答ありがとうございます ColorSpaceは Linerでした シェーダーはUnlitのシェーダーの色の出力を固定して適当なオブジェクトのマテリアルに設定しているだけなので、C#のスクリプトはありません ``` Shader "Unlit/color test" { Properties { _MainTex ("Texture", 2D) = "white" {} } SubShader { Tags { "RenderType"="Opaque" } LOD 100 Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) float4 vertex : SV_POSITION; }; sampler2D _MainTex; float4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } float4 frag (v2f i) : SV_Target { float4 col; col.rgb = 0.0; //128になってほしいがスクショすると188になる col.r = float(128.0 / 255.0); //25になってほしいがスクショすると88になる // col.r = float(25 / 255.0); col.a = 1.0; col.gb = 0.0; return col; } ENDCG } } } ```
shauni

2018/12/14 08:54

見づらくて申し訳ないです コードブロックというものは返信では使えないのでしょうか
Bongo

2018/12/14 09:33

おお、ありがとうございます。今はUnityが手元にないのでのちほどよく見てみようと思います。何だかガンマ補正が関係しているように見えますね。((128.0/255.0)^(1.0/2.2)*255.0 = 186.4、((25.0/255.0)^(1.0/2.2)*255.0 = 88.7といった具合にまずまずの一致があるようです。先ほど申し上げた「Color Space」の「Linear」と「Gamma」を切り替えてみて比較すると何かわかるかもしれませんね。 コードの投稿についてですが、質問文は後から編集することも可能なはずですので、最初の質問文の下に追記していただく形にしますと、コードブロックも使えますので好都合かと思います。残念ながら追記依頼欄やコメント欄ではコードブロックは使えないようですね...
guest

回答1

0

ベストアンサー

確認してみましたところ、おそらくColor Spaceの設定によるのではないかと思われます。もし「Linear」になっているようでしたら、「Gamma」に切り替えればご質問者さんご提示のコードそのままで意図通りのスクリーンショットになりそうです。
Linearモードだと「シェーダー内ではリニア色空間を想定して計算を行っており、最後にガンマ補正を加える必要がある」と判断され、シェーダーから0.5の色を出力しても自動的に中間階調が持ち上げられて、最終結果が128よりも明るい188になったのだろうと考えられます。

下記のようにUV座標のxをそのまま出力するマテリアル(LinearGradient)と...

ShaderLab

1Shader "Unlit/LinearGradient" 2{ 3 Properties 4 { 5 _MainTex ("Texture", 2D) = "white" {} 6 } 7 SubShader 8 { 9 Tags { "RenderType"="Opaque" } 10 LOD 100 11 12 Pass 13 { 14 CGPROGRAM 15 #pragma vertex vert 16 #pragma fragment frag 17 18 #include "UnityCG.cginc" 19 20 struct appdata 21 { 22 float4 vertex : POSITION; 23 float2 uv : TEXCOORD0; 24 }; 25 26 struct v2f 27 { 28 float2 uv : TEXCOORD0; 29 float4 vertex : SV_POSITION; 30 }; 31 32 sampler2D _MainTex; 33 float4 _MainTex_ST; 34 35 v2f vert (appdata v) 36 { 37 v2f o; 38 o.vertex = UnityObjectToClipPos(v.vertex); 39 o.uv = TRANSFORM_TEX(v.uv, _MainTex); 40 return o; 41 } 42 43 fixed4 frag (v2f i) : SV_Target 44 { 45 return fixed4(i.uv.xxx, 1.0); 46 } 47 ENDCG 48 } 49 } 50}

UV座標のxの値をsRGB逆変換して出力するマテリアル(GammaGradient)を作り...

ShaderLab

1Shader "Unlit/GammaGradient" 2{ 3 Properties 4 { 5 _MainTex ("Texture", 2D) = "white" {} 6 } 7 SubShader 8 { 9 Tags { "RenderType"="Opaque" } 10 LOD 100 11 12 Pass 13 { 14 CGPROGRAM 15 #pragma vertex vert 16 #pragma fragment frag 17 18 #include "UnityCG.cginc" 19 20 struct appdata 21 { 22 float4 vertex : POSITION; 23 float2 uv : TEXCOORD0; 24 }; 25 26 struct v2f 27 { 28 float2 uv : TEXCOORD0; 29 float4 vertex : SV_POSITION; 30 }; 31 32 sampler2D _MainTex; 33 float4 _MainTex_ST; 34 35 v2f vert (appdata v) 36 { 37 v2f o; 38 o.vertex = UnityObjectToClipPos(v.vertex); 39 o.uv = TRANSFORM_TEX(v.uv, _MainTex); 40 return o; 41 } 42 43 inline float3 srgbToLinear(float3 c) 44 { 45 return lerp(c / 12.92, pow((c + 0.055) / 1.055, 2.4), step(0.04045, c)); 46 } 47 48 inline float3 linearToSrgb(float3 c) 49 { 50 return lerp(c * 12.92, 1.055 * pow(c, 1.0 / 2.4) - 0.055, step(0.0031308, c)); 51 } 52 53 fixed4 frag (v2f i) : SV_Target 54 { 55 return fixed4(srgbToLinear(i.uv.xxx), 1.0); 56 } 57 ENDCG 58 } 59 } 60}

両モードでどのように表示されるか比較しました。

LinearGradient、Gammaモード
linear-gamma

GammaGradient、Linearモード
gamma-linear

LinearGradient、Linearモード
linear-linear

GammaGradient、Gammaモード
gamma-gamma

Linearモードのままで0.5の値が128として得られるようにしたい場合、GammaGradientに例示したような感じで、シェーダーから色を出力する直前に中間階調を暗くしてやる必要があるでしょう。こうするとその後のガンマ補正で中間階調が明るくなり、GammaモードでLinearGradientを使ったときとほぼ同等の見た目になるかと思います。
ただし、計算精度の問題で白周辺・黒周辺は多少ずれてしまうかもしれません。Linearモードはシェーダー内の計算をリニア空間で行いたい(光の伝搬をより物理的に正確に計算し、リアルな映像を作りたい...など)場合には好都合でしょうが、今回のようなケースはGammaモード前提でやった方がよさそうです。

投稿2018/12/14 18:00

Bongo

総合スコア10807

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

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

shauni

2018/12/15 11:54

ありがとうございました ガンマ補正というものを知らなかったのでとても参考になりました  自分のUnityでもgammaにすると意図した通りになりました ただ環境がVRChatというゲーム上で利用したくてLinerから変更することができないので Bongoさんの提示された関数を使わせて頂くことにします
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問