ことれいのもり

0から学ぶHLSLシェーダーの読み方 第2回~ピクセルシェーダー~

はじめに

この記事はDirectX11で使っている、シェーダー言語のHLSLを読めるようになるために私が学んだことの備忘録です。

実際のHLSLコードを書いて表現するといった内容ではなく、HLSLという言語の見方がさっぱり分からない人がある程度読めるようになることを目的としています。

第2回はピクセルシェーダーのコードの説明をします。

前提

言語

  • C++
  • HLSL

参考リンク

ピクセルシェーダー Pixel Shader

ピクセルシェーダーの入力と出力のおさらいです。

入力:ピクセルごとにわけられたデータ

出力:ピクセルの色情報

厳密にはラスタライザーから送られた値が入力になります。

ピクセルシェーダーの書き方は頂点シェーダーと同じです。

最初に入力・出力の構造体定義を、main部分にピクセルシェーダーで行なう処理を記述します。

今回のコードは、入力された色をそのまま出力するだけです。

// 入力部分の構造体定義
struct PixelInput
{
    float4 position : SV_POSITION; // ラスタライザから受け取った頂点の座標
    float4 color : COLOR;          // 頂点の色
};

// 実際の処理
// PixelInput型で受け取り、float4型で出力する
// SV_Targetで出力した値をどこにするか決定
float4 main(PixelInput input) : SV_Target
{
    // 受け取った色をそのまま返す
    return input.color;
}

一つずつ説明します。

入力部分の構造体定義

// 入力部分の構造体定義
struct PixelInput
{
    float4 position : SV_POSITION; // ラスタライザから受け取った頂点の座標
    float4 color : COLOR;          // 頂点の色
};

ピクセルシェーダーの入力部分を定義する構造体で、頂点の座標と色の情報を持っています。

頂点シェーダーの出力部分で記述した内容と全く同じことに気がついたでしょうか?

ラスタライザは自動で処理が行なわれるので、コードを書く上では無視できます。

そのため、頂点シェーダーの出力部分 = ピクセルシェーダーの入力部分 といってもいいです。

positionのセマンティクスが POSITION ではなく、SV_POSITIONになっているのは、ラスタライザから受け取った座標だからです。

出力部分の構造体定義

最初の説明で入力・出力部分の構造体定義を書くといいましたが、今回は必要ないです。

というのも、出力結果は色の情報ですが、float値で表現できるからです。

強いて言えば float4 ですが、元から定義されているので省きます。

main部分

// 実際の処理
// PixelInput型で受け取り、float4型で出力する
// SV_Targetで出力した値をどこにするか決定
float4 main(PixelInput input) : SV_Target
{
    // 受け取った色をそのまま返す
    return input.color;
}

main部分でピクセルシェーダーの処理内容を記述します。

受け取った色をそのまま返すだけなので、見れば分かると思います。

頂点シェーダーと違う点として、mainの引数の後ろに : SV_Targetと書かれている部分があげられます。

これは、出力した値をどこに使うか?を指定する部分です。

今回の SV_Targetだと、「画面に描画するピクセルの色」という意味になります。

もしSV_Targetを指定せずに return input.color; をしても、「この値をどこに出力したら良いんだろう?」と迷ってしまいます。

ピクセルシェーダーを書く際には、出力結果を示すセマンティクスが必要であるということを覚えておきましょう。

おわりに

第1回と合わせて頂点シェーダー・ピクセルシェーダーの書き方は終わりです。

ここからは表現したい事に応じてHLSLコードを追加していくだけです。

第3回以降はいろんな表現をコードにしていきます!