HLSLで描く画像（Pixel Shaders）をWindows Terminal の背景に出来るようになった。HLSLと画像の事例メモ



# はじめに
　HLSLは「High Level Shading Language」の頭文字となるが、マイクロソフトの説明サイトでは「上位レベルシェーダー言語」と訳されている。適当な漢字で表せば「高級着色像素言語」的な感じだ。
　HLSLはシェーダー言語（＝シェーディング言語＝着色像素言語）に属し、他のシェーダー言語には、GLSLやCGが存在する。
　このシェーダー言語を使えば光の反射、乱反射、空気感を含んだ「高級な画像（動画）」が作成できる。
　画像の計算は、画面にあるドット（＝画素。フルハイビジョンなら1920×1080画素）一つ一つ毎に計算をする為、大量の計算が必要なる。そのため、CPUではなく、GPUを使って画面全体の総ドットを並列計算で処理していく。

　そして今回大切なことは、HLSLで作成した画像は、Windows Terminalの背景にできる！

　本来であれば、HLSLはUnity(ゲームエンジン、ゲーム開発環境)と、C++言語やC#言語等プログラム言語と一緒にして活用する様だが、自分はUnityを一度も使ったことがないので、HLSLをVisual Studio Codeでポチポチ打ちながらWindows Terminal画面で画像が出たら一喜一憂した。
　ちなみにBlender (3DCGアニメ作成の為の統合開発環境)は、HLSLではなくGLSLです。


# パソコン環境
- Windows10
- Windows Terminal : 1.15.2712.0
- Visual Studio Code

# 【初期設定】Windows Terminalの設定
　Windows Terminalの背景にHLSLで作成した画像を表示する為には、Windows Terminalの設定ファイル「settings.json」内の「Profiles」以下の「defaults」以下に「experimental.pixelShaderPath」とHLSLファイルのアドレスを示す行を追加する。
 HLSLの拡張子は「.hlsl」となる。
```json
 "defaults": 
        {
        "experimental.pixelShaderPath": "C:\\Users\\ユーザー名\\適当なファイルパス\\sample.hlsl"
        },
```



# HLSLと画像の事例

## 事例1:赤一色

```HLSL:sample1.hlsl
float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
    //SV_POSITION:均質空間内の頂点位置らしい。よくわからん
    //TEXCOORD　:テクスチャー座標らしい。よくわからん
    //SV_Target　レンダー ターゲットの配列らしい。全然わからん

    return float4(1,0,0,1);//赤
    //return float4(0,1,0,1);//緑
    //return float4(0,0,1,1);//青
    //return float4(1,0,0,1)+float4(0,1,0,1)+float4(0,0,1,1);//白
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/3aae3805-e9ca-deec-ceff-d0bb1dc30d7e.png)


## 事例2:変数を使った緑一色

```HLSL:sample2.hlsl
float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
    float3 g = float3(0,1,0);
    return float4(g,1.0);
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/28a6c2ca-039d-ecd0-bf75-d8fbe6913bab.png)


## 事例3:背景色が赤
```HLSL:sample3.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
    float4 t = shaderTexture.Sample(samplerState, float2(1.0, 1.0));
    float4 color = shaderTexture.Sample(samplerState, tex);
    color.xyz += float3(1, 0.0, 0.0);
    return color;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/fc6c4d90-14cf-1969-3d9c-9a724f7734e4.png)


## 事例4:グラデーション
```HLSL:sample4.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
    float4 t = shaderTexture.Sample(samplerState, float2(1.0, 2.0));
    float4 color = shaderTexture.Sample(samplerState, tex);
    color.xyz += float3(t.x * 8 + (tex.x + tex.y) / 4, 0.0, 0.6); 
    return color;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/03ebacfc-f952-20b4-87c6-3e6a1fce8459.png)


## 事例5:背景色を縦に領域分け
```HLSL:sample5.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
    float4 t = shaderTexture.Sample(samplerState, float2(1.0, 1.0));
    float4 color = shaderTexture.Sample(samplerState, tex);   
    if (tex.x > 0.1 ){
        color.xyz += float3(1.0, 0.0, 0.5);
    }
    return color;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/eee36f1e-a6e5-4f93-091f-51d027c0d3ec.png)



## 事例6:背景色を横に領域分け
```HLSL:sample6.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
    float4 t = shaderTexture.Sample(samplerState, float2(1.0, 1.0));
    float4 color = shaderTexture.Sample(samplerState, tex);   
    if (tex.y > 0.1 ){
        color.xyz += float3(1.0, 0.0, 0.5);
    }
    return color;
}

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/31d65272-b1fa-9fd1-df3b-9ffdb6c1a17b.png)


## 事例7:赤の縦線を引く
```HLSL:sample7.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//１ベクトル＝スカラー値
  float  Scale;//１ベクトル＝スカラー値
  float2 Resolution;//２✕１ベクトル
  float4 Background;//４✕１ベクトル
};

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
    float4 t = shaderTexture.Sample(samplerState, float2(1.0, 1.0));
    float4 color = shaderTexture.Sample(samplerState, tex);   
    if (tex.x * Resolution.x > 200 && tex.x * Resolution.x < 201 ){
        color.xyz += float3(1.0, 0.0, 0.0);   
    }
    return color;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/05e9d693-e871-afca-a854-f3655f4df26a.png)


# 事例8:赤の横線を引く
```HLSL:sample8.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//１ベクトル＝スカラー値
  float  Scale;//１ベクトル＝スカラー値
  float2 Resolution;//２✕１ベクトル
  float4 Background;//４✕１ベクトル
};

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
    float4 t = shaderTexture.Sample(samplerState, float2(1.0, 1.0));
    float4 color = shaderTexture.Sample(samplerState, tex);   
    if (tex.y * Resolution.y > 110 && tex.y * Resolution.y < 111 ){
        color.xyz += float3(1.0, 0.0, 0.0);   
    }
    return color;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/0c475445-8ca1-5da5-6b60-f07a711c7aa3.png)


## 事例9:赤の斜め線を引く
```HLSL:sample9.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//１ベクトル＝スカラー値
  float  Scale;//１ベクトル＝スカラー値
  float2 Resolution;//２✕１ベクトル
  float4 Background;//４✕１ベクトル
};

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
    float4 t = shaderTexture.Sample(samplerState, float2(1.0, 1.0));
    float4 color = shaderTexture.Sample(samplerState, tex);   
    if (tex.y * Resolution.y >  tex.x * Resolution.x -0.5 && tex.y * Resolution.y <  tex.x * Resolution.x+0.5   ){
            color.xyz += float3(1.0, 0.0, 0.0);      
    }
    return color;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/813cd9a4-cf6c-1997-613c-65e25c2cc6e5.png)

## 事例10:放物線
```HLSL:sample10.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//１ベクトル＝スカラー値
  float  Scale;//１ベクトル＝スカラー値
  float2 Resolution;//２✕１ベクトル
  float4 Background;//４✕１ベクトル
};

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
    float4 t = shaderTexture.Sample(samplerState, float2(1.0, 1.0));
    float4 color = shaderTexture.Sample(samplerState, tex);   
  const  float y_add = 800.0;
  const  float x_add = 30.0;
  float yy =    tex.y * Resolution.y -  y_add ;
  float xx =    tex.x * Resolution.x/10 - x_add;
  
  if (yy> - (xx)*(xx)  - 1.0 && yy <  -(xx )*(xx ) +1.0){
      color.xyz += float3(1.0, 1.0, 1.0);  
    }
    return color;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/02721db5-77cc-f5fd-047f-d2c9de48252d.png)


## 事例11:Sinカーブ（線が不連続になってしまった）

```HLSL:sample11.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//１ベクトル＝スカラー値
  float  Scale;//１ベクトル＝スカラー値
  float2 Resolution;//２✕１ベクトル
  float4 Background;//４✕１ベクトル
};

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
    float4 t = shaderTexture.Sample(samplerState, float2(1.0, 1.0));
    float4 color = shaderTexture.Sample(samplerState, tex);   
  const  float y_add = 200.0;
  const  float x_add = 30.0;
  float yy =    tex.y * Resolution.y -  y_add ;
  float xx =    tex.x * Resolution.x/10 - x_add;
//ここがサインカーブ
  if (yy > - 100*sin(xx)  - 1.0 && yy <  -100*sin(xx ) +1.0){
      color.xyz += float3(1.0, 1.0, 1.0);
    }
    return color;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/16f048b3-3337-84e8-086d-a41dd3ed4c70.png)
感想：なんだかオシロスコープみたいだな


## 事例11-2:Sinカーブ（不連続な線を、連続に修正）

```HLSL:sample11_2.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//１ベクトル＝スカラー値
  float  Scale;//１ベクトル＝スカラー値
  float2 Resolution;//２✕１ベクトル
  float4 Background;//４✕１ベクトル
};

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
  float4 t = shaderTexture.Sample(samplerState, float2(1.0, 1.0));
  float4 color = shaderTexture.Sample(samplerState, tex);   
  
  const  float y_add = 200.0;
  const  float x_add = 150.0;
  float yy =    tex.y * Resolution.y - y_add ;
  float xx =    tex.x * Resolution.x - x_add;
  
  for (float i=1;i<10;i++){
    float xi = xx + i/10;
    if (yy > - 100*sin(xi/31.4)  - 1.0 && yy <  -100*sin(xi/31.4) +1.0){
      color.xyz += float3(1.0, 1.0, 1.0)  ;
    }
  }
  return color;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/86faa027-d7c2-46a5-8ead-9f4632992aef.png)


## 事例12:恒例のドット絵
```HLSL:sample12.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//１ベクトル＝スカラー値
  float  Scale;//１ベクトル＝スカラー値
  float2 Resolution;//２✕１ベクトル
  float4 Background;//４✕１ベクトル
};

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
  float4 t = shaderTexture.Sample(samplerState, float2(1.0, 1.0));
  float4 color = shaderTexture.Sample(samplerState, tex);   
 
//アルファベットのAのドット絵情報
 int dot_color[5][6] ={{1,0,0,0,1,1},{0,1,0,1,1,1},{1,0,0,0,1,1},{1,1,1,1,1,1},{1,1,1,1,1,1}};

  for (float x_d=0.0;x_d<6.0;x_d++){
    for (float y_d=0.0;y_d<6.0;y_d++){
      if (tex.x  > x_d/20   && tex.x  < (x_d+1)/20){
        if (tex.y  > y_d/20   && tex.y  < (y_d+1)/20){
              color.xyz += float3(1.0, dot_color[x_d][y_d], 0.0)  ;
        }
      }
    }
  }
  return color;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/a2b4852e-5bc2-aa34-68bf-e7ebc5e29096.png)


## 事例13:ドット絵その２
```HLSL:sample13.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
  float4 t = shaderTexture.Sample(samplerState, float2(1.0, 1.0));
  float4 color = shaderTexture.Sample(samplerState, tex);   

//[横][縦][RGB]

float dot4_color[16][15][3] ={
{{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{1.0,0.6,0.0},{0.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,1.0,0.0},{0.0,0.0,0.0},{1.0,0.6,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{1.0,0.6,0.0},{0.0,0.0,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.0},{1.0,0.6,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,0.0,0.5},{1.0,0.6,0.0},{0.0,1.0,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,1.0,0.0},{1.0,0.6,0.0},{0.0,0.0,0.5},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,0.0,0.5},{1.0,0.6,0.0},{0.0,0.0,0.5},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,0.0,0.5},{1.0,0.6,0.0},{0.0,0.0,0.5},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,0.0,0.5},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,0.0,0.5},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5}},
{{0.0,0.0,0.5},{0.0,0.0,0.5},{1.0,0.6,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{1.0,0.6,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5}},
{{0.0,0.0,0.5},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5},{1.0,0.6,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,1.0,0.0},{0.0,1.0,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,0.0,0.5}},
{{0.0,0.0,0.5},{0.0,0.0,0.5},{1.0,0.6,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{1.0,0.6,0.0},{0.0,1.0,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0}},
{{0.0,0.0,0.5},{0.0,0.0,0.5},{1.0,0.6,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{1.0,0.6,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{1.0,0.6,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{1.0,0.6,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,0.0,0.5},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.5},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0}},
};

  for (float y_d=0.0;y_d<16.0;y_d++){
    for (float x_d=0.0;x_d<16.0;x_d++){
      if (tex.x  > x_d/100   && tex.x  < (x_d+1)/100){
        if (tex.y  > y_d/100   && tex.y  < (y_d+1)/100){
          color.xyz += float3(dot4_color[y_d][x_d][0], dot4_color[y_d][x_d][1], dot4_color[y_d][x_d][2]) ;
        }
      }
    }
  } 
  return color;
}
```



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/3fc40c56-986a-e1e3-1713-7b209003ccea.png)

　実行したら、パソコンのファンがうなりをあげた

# HLSLはif文(条件分岐)が鬼門
　sample13.hlslを実行したら、パソコンのファンがうなりをあげ、操作もカクカクした。パソコンの負荷が高い様だ。
　タスクマネージャーを見たらGPU負荷が100%あった。これは悲しい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/5b6bd486-9f54-be2d-46b2-45574cbe9d1f.png)

　Webで調べたら、HLSLはif文（条件分岐）が遅くなる要因と書いてあった。

https://qiita.com/HnniTns/items/9b0e18d52117d327d9c4

https://light11.hatenadiary.com/entry/2018/07/08/134440

https://nanka.hateblo.jp/entry/2018/05/09/124405

　sample13.hlslの本文を見るとif文を256回（=16×16）使っているのがダメなようだ。


## 事例14:ドット絵その3(if文の低減版)
```HLSL:sample14.hlsl
Texture2D shaderTexture;
SamplerState samplerState;


cbuffer PixelShaderSettings {
  float  Time;//１ベクトル＝スカラー値
  float  Scale;//１ベクトル＝スカラー値
  float2 Resolution;//２✕１ベクトル
  float4 Background;//４✕１ベクトル
};

const static float3 dot4_color[16][15] ={

{{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{1.0,0.6,0.0},{0.0,0.0,0.0},{0.0,1.0,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.0,1.0,0.0},{0.0,0.0,0.0},{1.0,0.6,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{1.0,0.6,0.0},{0.0,0.0,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.0,0.0,0.0},{1.0,0.6,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.44,0.26,0.16},{1.0,0.6,0.0},{0.0,1.0,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,1.0,0.0},{1.0,0.6,0.0},{0.44,0.26,0.16},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.44,0.26,0.16},{1.0,0.6,0.0},{0.44,0.26,0.16},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.44,0.26,0.16},{1.0,0.6,0.0},{0.44,0.26,0.16},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.44,0.26,0.16},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.44,0.26,0.16},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16}},
{{0.44,0.26,0.16},{0.44,0.26,0.16},{1.0,0.6,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{1.0,0.6,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16}},
{{0.44,0.26,0.16},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16},{1.0,0.6,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.0,1.0,0.0},{0.0,1.0,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.44,0.26,0.16}},
{{0.44,0.26,0.16},{0.44,0.26,0.16},{1.0,0.6,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{1.0,0.6,0.0},{0.0,1.0,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0}},
{{0.44,0.26,0.16},{0.44,0.26,0.16},{1.0,0.6,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{1.0,0.6,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{1.0,0.6,0.0},{0.0,0.0,0.0}},
{{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{1.0,0.6,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,1.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{1.0,0.6,0.0},{0.44,0.26,0.16},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0}},
{{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.44,0.26,0.16},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0},{0.0,0.0,0.0}},
};

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
  float4 t = shaderTexture.Sample(samplerState, float2(1.0, 1.0));
  float4 color = shaderTexture.Sample(samplerState, tex);   
  
int div_num = 8;
int left = 40;
int top = 4;
int x_int = trunc((tex.x * Resolution.x - div_num*left)/div_num);
int y_int = trunc((tex.y * Resolution.y - div_num*top)/div_num);

if (x_int  > left - 16  &&x_int  < left &&  y_int  > top && y_int  < top + 16){
  color.xyz += float3(dot4_color[y_int-top][x_int-left][0], dot4_color[y_int-top][x_int-left][1], dot4_color[y_int-top][x_int-left][2]);
}
  return color;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/8b8a27d5-6fc3-3996-db94-f0a8cc2e9df0.png)

　パソコンのファンは停止し、GPUの負荷率も20%代に減った。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/c2fa72cc-6cbd-e0a1-e897-a1751dc01b6a.png)

## 負荷を減らした際のポイント
- 大小のif文（条件分岐）は、割り算の答えの整数部で判断した。
- 変数をconst（定数）にすると多少、負荷が減った。
- 変数をmain関数の外に出した場合、「static」が必要になる。

## 蛇足：ドット文字との比較
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/e9e69f9c-15b4-8457-95bf-e5bae4a6ca19.png)

　文字データは横の黒線が入るので、やはりHLSLが綺麗。


# HLSLでつまづいたメモ
以下を読解してメモします。ちなみに私はマイクロソフトのページが分かりにくいです。

https://learn.microsoft.com/ja-jp/windows/win32/direct3dhlsl/dx-graphics-hlsl-per-component-math


## その1
　float型を存在する一方、「float2」や「float3」が存在する。「float」はわかる。Go言語やC#を経験してたので、「float32」が32ビット、「float64」が64ビットを意味するのは理解できる。しかし「float2」ってなんだ！「float3」ってなんなんだ！
```HLSL
float2  fVector = { 0.2, 0.3};
```

## その2【数字の後ろの「f」について】
　よく、数字の後ろに「f」が付くサンプルのプログラムを見るが、float型を意味する様です。しかし「f」がなくてもプログラムが動く。不思議だ。魔物だ。
```HLSL
float3  fVector = { 0.2f, 0.3f, 0.4f };
```

## その3【行列(マトリックス)の型は「float2x2」が存在する】
　なんだそれは！
```HLSL
float2x2 fMatrix = { 0.0f, 0.1, // 1行目
                     2.1f, 2.2f // 2行目
                   };   
```

## その4【４行４列の行列の型】
```HLSL
float4x4 変数名 = float4( {0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} );
```

## その5【５行６列の行列の型】
```HLSL
 int dot_color[5][6] ={{1,0,0,0,1,1},{0,1,0,1,1,1},{1,0,0,0,1,1},{1,1,1,1,1,1},{1,1,1,1,1,1}};
```


## その6
　マトリックスは、次の構文で宣言することもできる。しかし４行４列を超えるとエラーが出た。限界？
```HLSL
matrix <Type, Number> VariableName
```

```HLSL
//↓こんな感じ
matrix <float, 2, 2> fMatrix = { 0.0f, 0.1, // row 1
                                 2.1f, 2.2f // row 2
};
```

## その7　ベクトルの配列数の上限
　配列数を増やして確かめた結果、要素が４つのfloat4等のベクトルの配列の上限は最大4096個までであった。
　配列数が4096を超えると、HLSLのコンパイルが失敗する。
　4096の配列数は合計が上限であり、例えば2048┼2048┼１はエラーとなる。
```HLSL
float4 aiueo_kakikukeko[64][64]//限界
```

https://twitter.com/SebAaltonen/status/1493944392389963782

　ちなみに、4096を超える方法もあるようだが、よくわからない。(4096×16=65526)
　そうなると、ドット絵は64×64が上限になってしまうが、一つのfloat4中に、情報を詰めればもう少しドット絵を増やせるだろう。
　


# 他のページからの参考

## 参考1：格子状の線を色のグラデーションを付けて引く

```HLSL:ref1.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//１ベクトル＝スカラー値
  float  Scale;//１ベクトル＝スカラー値
  float2 Resolution;//２✕１ベクトル
  float4 Background;//４✕１ベクトル
};
float3 hsv2rgb(float3 hsv){
    // ref. https://gist.github.com/iUltimateLP/5129149bf82757b31542
    float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);

    //frac(x)	x の小数部を返します。
    //abs(x)	絶対値
    float3 p = abs(frac(hsv.xxx + K.xyz) * 6.0 - K.www);
    
    //lerp(x,y,a)	xとyの間の線形補間。
    //clamp( x, min, max )	xがmin以下ならmin, max以上ならmax
    return hsv.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), hsv.y);
}

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET
{
    float4 t = shaderTexture.Sample(samplerState, float2(0.0, 0.0));
    float4 color = shaderTexture.Sample(samplerState, tex);
    if (tex.x * Resolution.x % 20 < 1.0 || tex.y * Resolution.y % 20 < 1.0)
    {
       color.xyz += hsv2rgb(float3(t.x * 8 + (tex.x + tex.y) / 4, 1.0, 0.6));
    }
    return color;
}

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/a5d845b1-9156-3ca1-d291-a8f98648df87.png)


## 参考2：複数のグラデーション

```HLSL:ref2.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;
  float  Scale;
  float2 Resolution;
  float4 Background;
};

float4 main(float4 pos : SV_POSITION, float2 tex : TEXCOORD) : SV_TARGET{
    float4 color = shaderTexture.Sample(samplerState, tex);
    float4 ocolor = shaderTexture.Sample(samplerState, tex+2.0*Scale*float2(-1.0, -1.0)/Resolution.y);

    const float thickness = 0.1;

    float ny = floor(tex.y/thickness);
    float my = tex.y%thickness;
    const float pi = 3.141592654;

    float cola = ny*2.0*pi;
    float3 col = 0.75+0.25*float3(sin(cola*0.111), sin(cola*0.222), sin(cola*0.333));

    float brightness = 1.0-smoothstep(0.0, thickness*0.5, abs(my - 0.5*thickness));
    float3 rasterColor = col*brightness;

    float3 final = rasterColor;
    final = lerp(final, float(0.0), ocolor.w);
    final = lerp(final, color.xyz, color.w);
    return float4(final, 1.0);
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/157498/eb21a1e7-95ad-9a8f-5bef-f964c4c8942c.png)


# 感想
　HLSLは線や曲線が書くのが苦手な気がする。


# Link集

## 参考にしたYouTube
↓「Windowsターミナル用のカスタムピクセルシェーダーを作成する方法を探る。」内容は英語ですが、画面内のHLSLは参考になった。

https://www.youtube.com/watch?v=YF50axsb-cA


## 参考リンク

http://mirichi.github.io/dxruby-doc/tutorial/shader.html#AUTOINDEXANCHOR_5

[HLSLリファレンスまとめ](https://hlslref.wiki.fc2.com/)
[GLSL/HLSL/Metal 命令対応表](https://dench.flatlib.jp/opengl/glsl_hlsl)


## Qiitaの記事
[GLSLをHLSLに書き換え](https://qiita.com/kitasenjudesign/items/89297f239059662cd38e)

## マイクロソフトのページ
[上位レベル シェーダー言語 (HLSL)](https://learn.microsoft.com/ja-jp/windows/win32/direct3dhlsl/dx-graphics-hlsl)
[組み込み関数 (DirectX HLSL)](https://learn.microsoft.com/ja-jp/previous-versions/direct-x/bb509611(v=vs.85)?redirectedfrom=MSDN)