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

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

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

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

GLSL

GLSL (OpenGL Shading Language) はC言語をベースとしたシェーディング言語です。

HLSL

HLSLは、米マイクロソフト社によって開発された Direct3D APIで使われるプロプライエタリなシェーディング言語です。

Q&A

解決済

1回答

3204閲覧

HLSLでの「<」単体の演算について

santaro

総合スコア18

OpenGL

OpenGLは、プラットフォームから独立した、デスクトップやワークステーション、モバイルサービスで使用可能な映像処理用のAPIです。

GLSL

GLSL (OpenGL Shading Language) はC言語をベースとしたシェーディング言語です。

HLSL

HLSLは、米マイクロソフト社によって開発された Direct3D APIで使われるプロプライエタリなシェーディング言語です。

0グッド

0クリップ

投稿2020/07/02 03:54

UnityのHLSLを読んでいると

HLSL

1 float sw = uv.x < _Config.x;

という式がありました。uv.x_Config.xがfloatの値だとするならば、上記の式の「<」はどのような演算でswにはどのような結果がはいるのでしょうか?

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

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

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

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

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

guest

回答1

0

ベストアンサー

おそらく「uv.x < _Config.xの結果はbool型となり、それをfloatに変換することでsw1.00.0のいずれかになる」...つまり、uv.x_Config.x未満ならsw1.0、そうでなければ0.0ということでいいんじゃないかと思います。

リファレンスに載っているに違いない...と思ったのですが、Comparison Operatorsの節を見てみても「比較演算の結果の型は○○である」と明言している文章はなさそうに見えました。ですが...

To use comparison operators with vector and matrix types, use the all or any intrinsic function.

This operation fails because the if statement requires a single bool but receives a bool4:

if (A4 < B4)

These operations succeed:

if ( any(A4 < B4) ) if ( all(A4 < B4) )

ベクトル型や行列型に対して比較演算子を使いたい場合、組み込み関数のallanyを使用してください。

この演算は、if文に対しては単一のboolが必要であるのに反して、bool4が与えられているため失敗します:

if (A4 < B4)

これらの演算なら成功します:

if ( any(A4 < B4) ) if ( all(A4 < B4) )

といった文章がありました。
A4B4はたぶん4成分の値なんでしょう。4成分同士の比較演算の結果がbool4になると解釈できますので、類推すると1成分同士の比較演算を行なった場合にはboolが得られると考えるのが自然じゃないかと思います。
また他にも、節の最初の方ではスカラー同士の比較演算の例が挙げられていますが、先ほど引用しました「if文に対しては単一のboolが必要」という文章と矛盾しないためには、スカラー同士の比較演算結果はbool型であるべきだと思います。

そしてCasting and Conversion - Win32 apps | Microsoft Docsの記事では、bool型をint型やfloat型に移そうとするとfalseは0に、trueは1に変換されるとの記述がありました。DXSASの記事ではありますが、たぶんHLSLでもこのルールに従うだろうと思います。

念のための確認として、Unity上で下記のマテリアルを作成して...

ShaderLab

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

Quadに割り当てたところ、UV座標が0.5以下になる左半分は黒く、0.5よりも大きい右半分は赤くなりました。

図

コンパイル結果のフラグメントシェーダー部分を抜粋すると...

-- Hardware tier variant: Tier 1 -- Fragment shader for "d3d11": // Stats: 2 math, 1 temp registers Shader Disassembly: // // Generated by Microsoft (R) D3D Shader Disassembler // // // Input signature: // // Name Index Mask Register SysValue Format Used // -------------------- ----- ------ -------- -------- ------- ------ // TEXCOORD 0 xy 0 NONE float x // SV_POSITION 0 xyzw 1 POS float // // // Output signature: // // Name Index Mask Register SysValue Format Used // -------------------- ----- ------ -------- -------- ------- ------ // SV_Target 0 xyzw 0 TARGET float xyzw // ps_4_0 dcl_input_ps linear v0.x dcl_output o0.xyzw dcl_temps 1 0: lt r0.x, l(0.500000), v0.x 1: and o0.x, r0.x, l(0x3f800000) 2: mov o0.yzw, l(0,0,0,1.000000) 3: ret // Approximately 0 instruction slots used

となっており、ltによる大小比較(真なら0xFFFFFFFF、偽なら0x0000000)の結果に対してandによる0x3f800000とのビット積をとることで、比較結果が真なら0x3f800000(浮動小数点数に直すと1.0)、偽なら0x0000000(浮動小数点数に直すと0.0)の値を得ているようです。

投稿2020/07/03 20:46

Bongo

総合スコア10807

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

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

santaro

2020/07/05 04:39

ありがとうございます!! 初心者なので解読には時間がかかりそうですが、「sw」の演算の仕方はなんとなくわかりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問