BETA

HLSLで草

投稿日:2019-01-19
最終更新:2019-01-20

草生やしたい

HLSLで。
ツイッタで草生やした刈ったっていうの見てやりたくなりました。
IndieVisualLabさんのやつよりだいぶ見た目悪いです。わかめだこれ
IndieVisualLabさんのは見た目いいのでそっちを見ましょう。
実装時間ですが自分の場合平日帰ってきて4時間を4日でした。目安にしていただければ。

参考

Unityのシェーダの本を書いていらっしゃる方々がいらっしゃいます。
それ見ながらやりました。
https://github.com/IndieVisualLab
なんとソースファイルというかプロジェクト一式?なのでUnityインストールしてプロジェクト開くで動いてしまいます。
すごい。

↑のはプログラムだけですが、理論的な部分を知りたいという人は本買いましょう。
図があるとわかりやすくていいっすね。
vol.1~vol.3まで買っちゃいました。1つ2000円です。(すてま)
https://indievisuallab.stores.jp/items/59edf11ac8f22c0152002588
https://indievisuallab.stores.jp/items/5ae077b850bbc30f3a000a6d
https://indievisuallab.stores.jp/items/5bc08f64a6e6ee273e000e4b

数学と物理?が必要なものとかはさっぱりですが、今回のはいらないので
そういうのに手出していきたいですね。
今回のはvol1の6章です。
2枚ディスプレイで電子版片方に開いて片方VSで書くとはかどります。


HLSLで

おれおれフレームワークで。
ユニティのシェーダさっぱりなので触ったことあるHLSLで
見たところユニティのとほぼほぼ変わらないので9割コピペで動いちゃいます。
以下変更点です。以下コードはコピペしても動かないですごめんなさい。

変更部分: プレーンの代わり

ユニティのプレーンを置く代わりに頂点を適当に配置

    // .cpp  
    std::srand(static_cast<u32>(std::time(nullptr)));  
    constexpr int div     = 64; // プレーンの一辺の頂点数  
    constexpr float dist = 10; // 面積広さスケール  
    for(int i=0; i<div; ++i)  
    {  
        for(int j=0; j<div; ++j)  
        {  
            Vertex add;  
            add.position                   = math::CVector::set( 1.0f/div*i-0.5f, 0.0f, 1.0f/div*j-0.5f, 1.0f ) * dist;  
            add.uv0                         = math::CVector::set(  1.0f/div*i, 1.0f/div*j, 1.0f, 1.0f  ) ;  
            add.uv1.data.rand_seed  = randf();  
            list.emplace_back(add);  
        }  
    }

値はお好みで
distを1にすると1x1の四角になります。


変更部分: ジオメトリシェーダにわたすポリゴン形式変更

    // .cpp  
    device_context.IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_POINTLIST ) ;

1つの点に対しジオメトリシェーダで草一本生やすのでポイントにしました。


変更部分: ジオメトリシェーダのインプット部分

    //geometry_shader.hlsl  
void main(  
    point GS_IN input[1],   
    inout TriangleStream< GS_OUT > output

D3D11_PRIMITIVE_TOPOLOGY_POINTLISTに合わせての変更です。


変更部分: HLSLで構造体の配列使えない問題

    //geometry_shader.hlsl  

    // 面を伸ばす方向  
    float4 width_dir       = float4( sin(rot_rad), 0.0f, cos(rot_rad), 0.0f) * 0.03;  
    // 位置を少しランダムに  
    float4 rand_pos_offset = float4( sin(rot_rad_2), 0.0f, cos(rot_rad_2), 0.0f) ;  

    // 根っこの頂点1  
    GS_OUT g2p0     = (GS_OUT)0;  
    g2p0.pos            = rand_pos_offset+float4(input[0].pos.xyz, 1.0f)-width_dir;  
    g2p0.normal       = input[0].normal;  
    g2p0.uv0            = input[0].uv0;  
    g2p0.color           = _BottomColor;  

    // 根っこの頂点2  
    GS_OUT g2p1     = (GS_OUT)0;  
    g2p1.pos            = rand_pos_offset+float4(input[0].pos.xyz, 1.0f)+width_dir;  
    g2p1.normal       = input[0].normal;  
    g2p1.uv0            = input[0].uv0;  
    g2p1.color          = _BottomColor;  
     ・  
     ・  
     ・

これ知らなかった。
float var[4];とかだとOKなんだけど構造体の配列駄目なんだね。


変更部分: SampleLevel

    //geometry_shader.hlsl  

    // 高さマップから高さ取得  
    float height_rand   = height_tex.SampleLevel(sample_height , input[0].uv0.xy, 0).r;

よくつかうSample関数使えなかった。ジオメトリシェーダだと駄目らしい。
かわりにSampleLevel関数で代用。


変更部分: プロパティ?をstatic constに

    //geometry_shader.hlsl  

    // 値は適当  
static const float _BottomHeight  = 2.0f;  
static const float _MiddleHeight   = 0.2f;  
static const float _TopHeight       = 0.2f;  
static const float4 _BottomColor  = float4(0.0f, 0.0f, 1.3f, 0.1f);  
static const float4 _TopColor       = float4(0.0f, 1.0f, 0.0f, 0.1f);  
static const float _BottomBend    = 1.0f;  
static const float _MiddleBend      = 1.2f;  
static const float _TopBend          = 2.0f;  
static const float _WindPower      = 0.3f;

const bufferにいれて変更できるようにしてもいいと思う。
自分は面倒だったのでやってない。


変更部分: フレーム数

    //geometry_shader.hlsl  
cbuffer TIME    : register(b1)  
{  
    float   time : TIME; // フレーム数  
};  

     ・  
     ・  
     ・  

    float  wind_pow = sin(radians(time));  
    g2p2.pos += wind_dir  
                        * (_WindPower * wind * _BottomBend )  
                        * wind_pow;

ユニティにはデフォであるみたいですが、こっちは作んなきゃですね。
毎フレーム+1したのを入れてます。

感想

せっかくHLSLなので頂点置くんじゃなくてハルシェーダとかで頂点増やしてみたい

技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
駆け出しエンジニアからエキスパートまで全ての方々のアウトプットを歓迎しております!
or 外部アカウントで 登録 / ログイン する
クランチについてもっと詳しく

この記事が掲載されているブログ

@esYgFPm2miKw4VJBの技術ブログ

よく一緒に読まれる記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる
技術ブログをはじめよう Qrunch(クランチ)は、プログラマの技術アプトプットに特化したブログサービスです
or 外部アカウントではじめる
10秒で技術ブログが作れます!