4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

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

Last updated at Posted at 2022-10-06

はじめに

 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」となる。

 "defaults": 
        {
        "experimental.pixelShaderPath": "C:\\Users\\ユーザー名\\適当なファイルパス\\sample.hlsl"
        },

HLSLと画像の事例

事例1:赤一色

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

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

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

事例3:背景色が赤

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

事例4:グラデーション

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

事例5:背景色を縦に領域分け

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

事例6:背景色を横に領域分け

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

事例7:赤の縦線を引く

sample7.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//1ベクトル=スカラー値
  float  Scale;//1ベクトル=スカラー値
  float2 Resolution;//2✕1ベクトル
  float4 Background;//4✕1ベクトル
};

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

事例8:赤の横線を引く

sample8.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//1ベクトル=スカラー値
  float  Scale;//1ベクトル=スカラー値
  float2 Resolution;//2✕1ベクトル
  float4 Background;//4✕1ベクトル
};

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

事例9:赤の斜め線を引く

sample9.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//1ベクトル=スカラー値
  float  Scale;//1ベクトル=スカラー値
  float2 Resolution;//2✕1ベクトル
  float4 Background;//4✕1ベクトル
};

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

事例10:放物線

sample10.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//1ベクトル=スカラー値
  float  Scale;//1ベクトル=スカラー値
  float2 Resolution;//2✕1ベクトル
  float4 Background;//4✕1ベクトル
};

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

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

sample11.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//1ベクトル=スカラー値
  float  Scale;//1ベクトル=スカラー値
  float2 Resolution;//2✕1ベクトル
  float4 Background;//4✕1ベクトル
};

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
感想:なんだかオシロスコープみたいだな

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

sample11_2.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//1ベクトル=スカラー値
  float  Scale;//1ベクトル=スカラー値
  float2 Resolution;//2✕1ベクトル
  float4 Background;//4✕1ベクトル
};

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

事例12:恒例のドット絵

sample12.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//1ベクトル=スカラー値
  float  Scale;//1ベクトル=スカラー値
  float2 Resolution;//2✕1ベクトル
  float4 Background;//4✕1ベクトル
};

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

事例13:ドット絵その2

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

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

HLSLはif文(条件分岐)が鬼門

 sample13.hlslを実行したら、パソコンのファンがうなりをあげ、操作もカクカクした。パソコンの負荷が高い様だ。
 タスクマネージャーを見たらGPU負荷が100%あった。これは悲しい。
image.png

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

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

事例14:ドット絵その3(if文の低減版)

sample14.hlsl
Texture2D shaderTexture;
SamplerState samplerState;


cbuffer PixelShaderSettings {
  float  Time;//1ベクトル=スカラー値
  float  Scale;//1ベクトル=スカラー値
  float2 Resolution;//2✕1ベクトル
  float4 Background;//4✕1ベクトル
};

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

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

image.png

負荷を減らした際のポイント

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

蛇足:ドット文字との比較

image.png

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

HLSLでつまづいたメモ

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

その1

 float型を存在する一方、「float2」や「float3」が存在する。「float」はわかる。Go言語やC#を経験してたので、「float32」が32ビット、「float64」が64ビットを意味するのは理解できる。しかし「float2」ってなんだ!「float3」ってなんなんだ!

float2  fVector = { 0.2, 0.3};

その2【数字の後ろの「f」について】

 よく、数字の後ろに「f」が付くサンプルのプログラムを見るが、float型を意味する様です。しかし「f」がなくてもプログラムが動く。不思議だ。魔物だ。

float3  fVector = { 0.2f, 0.3f, 0.4f };

その3【行列(マトリックス)の型は「float2x2」が存在する】

 なんだそれは!

float2x2 fMatrix = { 0.0f, 0.1, // 1行目
                     2.1f, 2.2f // 2行目
                   };   

その4【4行4列の行列の型】

float4x4 変数名 = float4( {0,0,0,0}, {1,1,1,1}, {2,2,2,2}, {3,3,3,3} );

その5【5行6列の行列の型】

 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

 マトリックスは、次の構文で宣言することもできる。しかし4行4列を超えるとエラーが出た。限界?

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

その7 ベクトルの配列数の上限

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

float4 aiueo_kakikukeko[64][64]//限界

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

他のページからの参考

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

ref1.hlsl
Texture2D shaderTexture;
SamplerState samplerState;

cbuffer PixelShaderSettings {
  float  Time;//1ベクトル=スカラー値
  float  Scale;//1ベクトル=スカラー値
  float2 Resolution;//2✕1ベクトル
  float4 Background;//4✕1ベクトル
};
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

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

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

感想

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

Link集

参考にしたYouTube

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

参考リンク

HLSLリファレンスまとめ
GLSL/HLSL/Metal 命令対応表

Qiitaの記事

GLSLをHLSLに書き換え

マイクロソフトのページ

上位レベル シェーダー言語 (HLSL)
組み込み関数 (DirectX HLSL)

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?