murnana's diary

プリントの裏に書くとか、そんな感じです

久々に何か書こうかなと思ったら、前回記事から230日経っていたらしい

今日なんとなく、最近自分の中で起こったことを書こうかなと思ったのですが、何を書くのか忘れてしまいました。

情熱が青春より冷めやすくなった気がします。そういう年頃ですかね(わー、そんなはずない!原動力なのに!)

murnana.hatenablog.com

雑談も入れるつもりだったのですが、技術系ばっかりですね。

技術系記事はQiitaに移そうかな、なんてぼんやり考えていた矢先に、いままでの「いいね」の概念とはとか思ったり勝手にユーザーデータを公開したりした辺りで疲れてしまったのでしょう。書く気力も。

ブログのコメント機能を切らせていただきました

予め書いておくと、荒らしにあったとか、他人の意見が怖いとか、そんなんじゃないです。

あまりにもコメントの反応がないので、いっそ無いほうが管理する必要がなくなるからいいかな、というところです。

よくよく考えてみると、ブログのコメント機能って結構古くからあるけれど、機能として全然更新されませんね。

Twitterのようにタイムリーなコメントが飛んでくる(過去のツイートはタイムラインで流され、忘れ去られるので)わけではありませんし、とはいえ字数制限があるので長い文章は書けないですし。

そういう意味ではTumblrって画期的ですね。一時期移動しようかなと思ったけれど、当時Tumblrのページってちょっと重たくて使い勝手がなんとなく悪かったので、やめた覚えがあります。

お、これは…また移動を考える時期が来たか…?

NotImplementedException クラス

[NotImplementedException クラス (System) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/api/system.notimplementedexception?view=netframework-4.8)

C#の例外クラスって何があるのかが知りたいのです。いっぱいあってどれ選べばいいんでしょうか…

# 効用

switch分で仕方なく未実装にするときなんかの例外として。
或いは、継承したはいいがこの関数が呼ばれるとまずいというときに。

※ 例外処理は用法・用量を守って正しくお使いください。

```csharp
switch(name)
{
case "りんご":
// ...
break;
case "ナシ":
// ...
break;
default:
throw new NotImplementedException($"'{name}' is not implemented.");
}
```

macOSにVSCode + C#(.Net Core SDK)を入れる

macOSでダウンロードするじゃろ? * Download .NET (Linux, macOS, and Windows)

$dotnet コマンド叩いて確認するじゃろ?

VSCode開くじゃろ?

「The .NET Core SDK cannot be located. .NET Core debugging will not be enabled. Make sure the .NET Core SDK is installed and is on the path.」

と言われてしまうのじゃ。


VSCodeを起動したまま、.Net Core SDKをダウンロードしてコマンドを確認しても、 VSCodeそのものを再起動しないといけないです。というオチでした。

参考

CoreData使った時に、ログに「Failed to load model named」 何たらと出る

以下の記事と同じ原因でした。

qiita.com

NSPersistentContainer を生成する際に、モデル名を指定します。 このモデル名は xcdatamodeld (CoreDataモデルのファイル名)と同じ名前でなければなりません。

developer.apple.com

勉強会「【はじめてのUnityShader】君の手でキャラクターの見た目を彩ろう!」に行ってきた

supporterzcolab.com

まんてらさんによるUnityシェーダー講座。内容は Unity上でのシェーダーが初心者の方 向けでした。

この記事の趣旨

「講演内容を見直したい」「もうちょっと詳しく知りたい」人向けです。

著者知識も混ぜつつ書きます。あと、分からなかったらマニュアル読めよ という暴力をふるう プログラマなので、ちまちまマニュアルのリンクを貼ります。

判りやすいのと正確さは別の話ですが、正確さに欠けていたら…マサカリください。私も知りたいです。

記事で書くこと

  • Unityでのシェーダーの構造(ShaderLabをざっくりと)
  • 頂点シェーダとフラグメントシェーダーで、モデルを1色に染める方法

記事で書かないこと

前提知識
  • Unityとは
  • Unityの基本的な使い方
  • UnityのHierarchyについて
  • コンピューターグラフィックスで使用される座標変換
そのほか
  • Properties について (次回内容のはずなので書きません)
  • テクスチャの貼り方 (次回内容なので書きません)
  • 開発環境の構築手順
  • 講演内容の再現手順
  • 宣伝

Unityシェーダー事始め

シェーダーは 画面に映像を出力する為の設計図です。本村・クリストファー・純也 さん曰く、料理のレシピに似ている

  • https://cgworld.jp/feature/1607-gtmf2016.html
  • カレーを作る手順は料理のレシピ
  • コンピュータグラフィックを描く手順はシェーダー
    • 正確には シェーダーを交えたレンダーパイプラインがレシピあたると思うがそんな細かいことはおいておこう

Unity の Matreialについて

https://docs.unity3d.com/Manual/class-Material.html

とりあえず、モデルにシェーダーを適用させるために必要なモジュールくらいでOK。

Shaderファイルについて

https://docs.unity3d.com/Manual/SL-Reference.html

Unityのシェーダーは「ShaderLab」言語で書かれています。
https://docs.unity3d.com/Manual/SL-Shader.html

ShaderLabはだいたい以下の形をとります。

Shader "MannteraSample" {
    SubShader {
        Pass {
            CGPROGRAM   // Cg言語で書く
            ENDCG
        }
    }
}
Shader

マテリアルの名前みたいなものです。アッパーキャメルで名前を付けると、大文字部分で区切るみたいです。これスラッシュじゃなかったっけ…? スラッシュで階層区切りができます。大文字区切りなんてないんや

e.g. `ManteraSample/Shader` だと、Materialは「ManteraSample > Shader」で選択可能。

なーんにも書かれていないシェーダーファイルは、「Not supported」から選択できます。

SubShader

https://docs.unity3d.com/Manual/SL-SubShader.html

Pass をまとめている親玉です。

同じシェーダーでもGraphics の設定やデバイスによって分けたい時などに、SubShader を複数作って分けることができます。

Pass

レンダーパイプライン内で実行される、シェーダ-プログラム本体です。 ここに、頂点シェーダーやフラグメントシェーダーを書きます。

Cgで書く - Cg、HLSLとは

まんてらさんはCgって言ってたけど、どっちでもいいっぽいです。
https://docs.unity3d.com/Manual/SL-ShaderPrograms.html

補足:

まじかー 書くならHLSLがよさそうですね。

Pass 内に書かれたマクロ CGPROGRAM ENDCG 内で書ける、シェーダー言語の一種です。

OpenGL には GLSLDirectX には HLSL という言語が使われます。CgNVIDIAが開発したシェーダー言語だそうです(でも古いって聞いたゾ)。

シェーダーに入力する頂点データの宣言

まず、Vertex Shader に頂点データを流し込みます。

頂点データは複数の引数で受け取ることもできますが、長くなりがちなので 構造体 として宣言を行い、1つの構造体を引数として受け取る事が多いです。

今回は以下の形で受け取ります。

struct appdata {
  float4 vertex : POSITION;
};

頂点の座標のみを受け取る構造体です。

float4 は4次元ベクトルであることを表します。 3次元ではない理由は、行列計算の都合があるためです。
(この辺のことは座標変換についての別記事を書く予定です)

POSITION は頂点座標である事を表します。この部分は セマンティクス ( Semantics ) といいます。 セマンティクスは色々ありますが、今回は説明を省きます。

頂点シェーダーからの出力と、フラグメントシェーダーが受け取るデータの宣言

もう一つ、頂点シェーダーが出力し、フラグメントシェーダーが受け取る構造体も宣言します。

正確にはフラグメントシェーダーが受け取るかもしれないデータ、ですが。

struct v2f
{
    float4 pos : SV_POSITION;
};

SV_POSITION は座標変換後の座標が入ります。

シェーダーのエントリーポイントを宣言

一つのシェーダーファイルに2つのシェーダーを収める為、宣言が必要です。

##pragma vertex vert
##pragma fragment frag

公式ドキュメント にある「HLSL snippets」を読むとわかる人は何となくつかめると思います。

##pragma vertex が頂点シェーダーの宣言 (vert がエントリーポイント)、##pragma fragment がフラグメントシェーダーの宣言(frag がエントリーポイント)です。

頂点シェーダー を書く

ここで、座標変換などを行います。

v2f vert(appdata v)
{
  v2f _out = (v2f)0;
  _out.pos = UnityObjectToClipPos(v.vertex);
  return _out;
}

appdatav2f は先ほど宣言した構造体です。

UnityObjectToClipPos 関数は、ざっくりいうと3次元の情報である頂点座標を、2D画面につぶしてくれる関数です。
詳しい話は https://docs.unity3d.com/Manual/SL-BuiltinFunctions.html で、どうぞ。

フラグメントシェーダー を書く

ここで最終的な色を決めます。

float4 frag(v2f _in) : SV_Target
{
  float4 col=(float4)0;
  col=float4(1,1,1,1);
  return col;
}

SV_Target は出力するデータを表すセマンティックスです。

今、これは単色(白色)を出力しています。
col=float4(1,1,1,1) の部分を変えれば色が変わります。


講演はここまででした。
テクスチャ貼ったりするのは次回だそうです。