"そこ"から這い上がるブログ

プログラミングと電子工作が趣味でそこら辺のことを備忘録的に書きつつ這い上がっていこうといったブログ。そこ這い。

GBCの液晶を交換した

先日、GB USB SMART CARD 64M という書き込みができるゲームボーイのカセットの存在を知りまして、これを使えば自分でゲームボーイ用のソフトが作れるらしい。

ということで、押し入れから当時使っていたゲームボーイカラーを引っ張り出したところ……

ブックオフで100円だったグランデュエル

全然画面見えないし、なんか割れてるような状態でした。実際には割れてはいなくてフィルムがシワシワになって周りが黒くなっている感じです。
どうやらこれはビネガーシンドロームという現象で、液晶の偏光フィルムが加水分解してこうなってしまうようです。湿気たところにずっと放置されてましたからね……

偏光板を剥がして交換することで復活するらしいのですが、どうせならバックライト化してみたくて、Aliexpress でバックライト付き液晶を買いました。

まずはY字型のドライバーでケースを開けて、液晶を取り外します。

一枚目の写真左(本体の頭側)のリボンケーブルが液晶と繋がっている

新しい液晶は元のやつよりサイズが大きいので、それに合わせてケースを削る必要があります。

削る前とあと

彫刻刀で傷をつけてペンチで割っていきました。
フレームを広げるのと画面下の出っ張りを取り除きます。

新しい液晶。写真右の基盤は中心のリボンケーブルを折って液晶の上に重ねます。

そうして新しい液晶を取り付けた結果……

綺麗になったグランデュエル

めっちゃ綺麗に映るようになりました。バックライト付きなので明るい。
タッチセンサが液晶の基盤についていて、本体の右上辺りを触ると明るさの調整もできます。

肝心のGBCソフト作りはHelloWorldを出すまでやった後、開発は止まってしまっていますが……

 

・・・

3年ぶりのブログ更新、といってもあまり中身のないものですが。
3年前も1月に書いたきりなので、今年こそはブログを更新していきたいー
それとゲーム制作も進めているのでそちらも出せるように頑張ります。

2023年もよろしくお願いいたします。

 

ポケモソの近づくと透明になるシェーダーを再現してみた

明けましておめでとうございます!


……というわけでポケモンの近づくと透明になるシェーダーを再現してみました。

f:id:knasa:20200114224925g:plain

 

ちなみに元ネタ

f:id:knasa:20191226004800j:plainf:id:knasa:20191226004803j:plain

ゲームボーイカラー以来のポケモンに「3Dだー!」「捕まえるだけでみんな経験値もらっていいんですか⁈」なんて思いながら遊んでたのですが、カメラに近づくと透明になる柱に気づきましてこれは作れそうじゃないかと思った次第です。

まずは分析

カメラが近づくと半透明になる代わりに、徐々に透明になるピクセルがあるパターンで消えています。透明になるピクセルは形状に関係なくスクリーンスペースで決められているっぽい。というのはわかったんですが、この透明にしていくパターンがわからない……ググってどうやらこれはBayerマトリックスと呼ばれるパターンのようです。

 

これは一体......?

ディザ抜きといわれる半透明に見せかけるための手法で、実際に半透明にするよりも処理負荷が軽いとのこと。ドットをわざと見せてるあたりポケモンでは処理負荷より演出の意味合いが強そう。

 作ったコードはこんな感じ
名前をDitheringTransparentにしようと思ったら、どうやら英語ではScreenDoorっぽい

gist.github.com

 

そしてマテリアルの設定

f:id:knasa:20200114230156p:plain

BayerTexのところにはBayerMatrixをもとにした4ⅹ4ピクセルのグレースケール画像を入れます。
{\displaystyle {\frac {1}{16}}\times {\begin{bmatrix}0&8&2&10\\12&4&14&6\\3&11&1&9\\15&7&13&5\\\end{bmatrix}}}

画像はWikipediaさんより
この行列に255をかけてあげればおk
画像は

f:id:knasa:20200114231000p:plain←これ(4x4なのでとても小さい)

ただこの時注意なのが、ImportSettingsでCompressionを"High Quality"にすること。
そうしないと、量子化されてしまうようでちょっと物足りなくなります。

f:id:knasa:20200114231538p:plain

f:id:knasa:20200114231638p:plain←"Normal Quality"だと四色ぐらいになってしまう
それとこれは結果には関係ないですが、Filter Modeを"Point(no filter)"にしておくと見やすいです。
そうじゃないと拡大時にボケてしまってInspectorでみるときにちょっとわかりにくくなります。

後のパラメータは
BlockSize : この数で割った分のピクセルがBayerMatrix一枚分になる
Radius : 透明化を始める距離
BlockSizeは見やすいようにちょっと大きめにしてます。

おしまい

何とか今年初記事を書きました。(ほんとは去年書くつもりだった)
シェーダーをいじる機会が増えてて、ちょうどこれはいい勉強になりそうだったのでやってみた次第です。
カメラに近づくと透明になるシェーダーってなんて名前なんですかね?
「カメラに近づくと透明になるシェーダー」なんですかね?

 

と、こんなところでガラルに帰ろうかと思います。
まだバッジ集め終わってないんですよ……

参考サイト様




 

ベクトルを同じ向きにするための回転行列の求め方

ある方向を示すベクトルAがあって、他のベクトルBをその方向に向けたい場合に

回転行列の求め方に悩んだのでメモ。

やり方としては

  1. AとBの内積からなす角( 回転量 )を求める。
  2. AとBの外積から 回転軸 を求める。
  3. 回転量回転軸 から回転行列を作る。

といった感じです。

// toVec, fromVecは正規化されているVector3f
// 二つのなす角( 内積を求める )
float angle = acos( fromVec.dot( toVec ) );
// 回転軸( 外積を求めて正規化 )
Eigen::Vector3f axis = fromVec.cross( toVec ).normalized();
// 回転量と回転軸から回転行列を生成
Eigen::Matrix3f rotateMat = Eigen::AngleAxisf( angle, axis ).matrix();

Eigenを使った例ですが、考え方自体はUnityなどでも使えるはずです。

回転量と回転軸から行列を求めるのにEigen::AngleAxisfクラスを使用して楽をしてしまっていますが、

ロドリゲスの回転公式 を使うと求められるはず

EigenではAffineクラスを使って移動(+拡大)も含めたアフィン変換の行列の生成もできます。

// クォータニオン
Eigen::Quaternionf quat( Eigen::AngleAxisf( angle, axis ) );
// アフィンクラス
Eigen::Affine3f affine;
// 移動量
Eigen::Translation3f translation( Eigen::Vector3f( 0.5f, 1.5f, 0 ) );
// 移動と回転の合成
affine = translation * quat;
// 行列の取得
Eigen::Matrix4f affineMat = affine.matrix();

にしてもベクトルってのはすごい便利だなぁ

参考先

自作DLLのリンカエラーについて

本題と関係ないところで長時間詰まったので、もうしないように(何度かしてる)メモ

DLLを作成し、それを別のプロジェクトで利用しようとした際に、リンカエラー(LNK2019)が出てしまう。

DLLが配布されているようなもの場合はまず自分のプロジェクト設定を疑って、対象DLLの.libファイルがちゃんとリンクされているかを確認する。

ちゃんとリンクはされている&自作の場合疑うべきは
__declspec(dllexport)  の付け忘れ
自分の場合は大体これが原因

そして、それをつけてリンカエラーは消えるけども、別のエラー(C2280)が出る場合があり、
今回はそれも当たってしまった。

std::unique_ptrを使ったstd::vectorなどのコンテナクラスを含んでいる場合に起きるエラーの様で
以下のリンク先によると

c++ - DLL exporting causing issues with unique pointers - Stack Overflow

機械翻訳

declspec(dllexport)でクラスを宣言する場合、コンパイラは、インポートモジュールに必要なものがわからないため、デフォルトのコンストラクター、コピー割り当てなどの関数を含む、クラスのすべてのメンバー関数を生成する必要があります。

これについては、C ++クラスでのdllimportおよびdllexportの使用で説明されています。 unique_ptrはコピーできないため、そのコピーコンストラクターとコピー割り当て演算子は削除され、ベクターオブジェクトがそれらを使用しようとすると、C2280エラーが発生します。

declspec(dllexport)を含めない場合、コンパイラは実際に使用される関数のみを生成し、問題のあるコピーは回避されます。この問題を回避する1つの方法は、個々のクラスメンバー関数をエクスポートすることです。

これは、それらの一部をデフォルトとして指定することを意味する場合があります。仮想関数はvtableによって処理されるため、エクスポートする必要はありません。

別の回避策は、コピーコンストラクタとコピー割り当て演算子を明示的に削除することです。これにより、デフォルトコンストラクターの作成が妨げられ、コンストラクター/割り当て関数が移動されるため、これらをデフォルト設定する必要がある場合があります。

 

class UNIQUEPTRISSUE_API ClassB {
public:
    ClassB(const ClassB &) = delete;
    ClassB &operator=(const ClassB &) = delete;
    // You may need to explicitly default these if they are used
    ClassB() = default;
    ClassB &operator=(ClassB &&) = default;
    ClassB(ClassB &&) = default;
private:
    std::vector<std::unique_ptr<ClassA>> x;
};

説明にある二つ目の方法が以上のコードで、これで自分の場合は無事解決しました……
よくわかってないで使うからこういうことになるんだなぁとしみじみ

PCLで関数の実行速度を測りたい時の便利関数

新年初記事です。明けましておめでとうございます。
Looking Glassがですね去年届きまして、動画の作り方でも記事にしようと思っていましたが、
それはまた別の機会に(早く書こうという気持ち)

毎度わすれるので、備忘録として
特に大した説明もないのでコードを

#include <pcl/common/time.h>

void hoge()
{
    pcl::ScopeTime scopetime( "hoge_func" );
    // なんか処理
}

出力

hoge_func took 〇ms

pcl::ScopeTime scopetime( string );
これだけでその関数内の実行時間がわかっちゃいます。一行で済むの便利。
確認してないですが、名前的にスコープ内の時間がわかる感じなので
正確には関数内というよりは、スコープ内の時間測定ですかね。

pixiv SUMMER BOOT CAMP 2018 に参加してきました

今年のサマーインターンピクシブさんに行ってきました。
そのレポというか体験談のようなものをまとめたいと思います。

応募時

この夏、ピクシブで圧倒的猛者になる

 という力強いキャッチフレーズのインターンシップ募集ページの中に見慣れない「3D・VRコース」という文字が。この時はまだ6月でVRoidも発表されていない時期だったので、何をするんだろう?という興味が強くエントリーをすることに決めました。通常の専攻の他にGitHub専攻なるものもありましたが、自分の貧弱なリポジトリでは到底無理だろうと思い通常で応募しました。

参加前

面接の後にVRoid Studioの発表があり、「3D・VRってこれのことか!」となり参加への期待が高まっていました。そして、参加させていただけるとのメールが届き、うきうきで参加日を迎えるわけです。

1日目

なぜか開始が水曜日の1日目、インターン生同士の自己紹介を簡単に済ませ、次に向かったところは全社会(名前は記憶が曖昧)なる社員全員が集まっての事業報告などの会でした。ピクシブさんの数多くのサービスの売り上げから予定まで、学生が参加していいものなのかと驚かされつつ、全社員の皆さんの前でも自己紹介を行いました。

全社会が終わると今度は各チームごとに分かれての社内ランチが、ピクシブさんのカラフルなオフィスに使われているテーブルには名前(種類名?)がついており四季のテーブルのうち夏秋冬のテーブルでVRoidチームの方たちとお弁当を頂きました。なおこの後のお昼は一日を除きチームの方たちに外に連れて行って頂きました。

お昼が終わるとまずは環境設定から、ゲーミングノートを貸していただき春のテーブルでもう一人のインターン生の方と向かい合っての作業となりました。チームの方たちにサポートしてもらい準備が終わると、手元のEditorで動くVRoid Studioが!ほぉぉ……
はぁぁこんな風に動いているのかーなんて思いながら中を見つつ、課題を考えます。
他のコースでは元々何を課題とするのか決まっている場合もあるようですが、3Dコースではメンターさんと一緒に何をするかを考えました。
結果として自分の課題は「VRoid Studioの撮影機能の強化」となりました。これまでの撮影機能では2kの正方形の画像での撮影のみとなっていて、エディタ画面の横縦幅と必ずしも一致した写真ではないというところを改善したいというのが課題を考えたきっかけです。

2日目

課題が決まり、作業開始です。

まずは現状の撮影機能がどのようになっているかの調査をしました。
コードを読んだり実際に色々と撮影をしながらどのように手を加えていけばいいのかを考えていきました。
VRoid StudioのGUIにも手を加えることになるので、その部分のXAMLは特に教えてもらいつつ作業を進めていきました。
この日はほとんどがコード読みと動作確認でした。

3日目

作業開始から2日目になるわけですが、5日目の午後は成果発表会となっており、午前中はそのプレゼン資料の作成となるため、実質作業日は残り2日。
前日に撮影画像の解像度の変更の機能を実装する方法の検討はしていたものの、いざ実装しようとすると元々あったコードにうまく合わせることが出来ませんでした。「これを継承すれば……」「ここと構造が似ているから……」という見当はつくもののそれが上手くいかない……このままではまずいと思い、まずは動くようにしようというコードの書き方に切り替えました。この判断は結果的には動きはしたので良かったものの、それでよかったのかという部分では心残りではあります……
夜には会社内での食事会があり、手巻き寿司を頂きました。
9月入社の方の歓迎会なども兼ねていたようで大いに盛り上がっていました。

4日目

実質作業最終日です。

・撮影解像度の変更(高解像度化や縦長横長画像など)
・撮影カメラ映像のプレビュー表示
・撮影時のアニメーション(スマホのスクショの時のような)
・撮影カメラのポストエフェクト追加
を結果的に今回のインターン期間で実装を行いました。
最後はポストエフェクトの種類追加に費やし、Bloom,Vignette,Motion Blur, 被写界深度の四種類のポストエフェクトが使えるようになりました。

5日目

発表のためのスライドと、見せるための写真の撮影を行っていました。
我ながら撮影の時に色々といじれるのは楽しく、機能の追加が出来てよかったなと感じました。ユニティちゃんの回転蹴りモーションにモーションブラーの相性が良かったです。
発表はトップバッターでドキドキでしたが、何とか終えることができその後は安心して他のインターン生の発表を聞くことが出来ました。みんなすごい……

全体的な感想

5日間という短い間でしたが、とても良い経験が出来たように思います。

自分のコース以外でもそうですが、実際の開発の現場に入って一緒に作業をすることが出来るので、VRoid Studioの更新スピードを知っている方は想像がつくかもしれませんが、どんどん開発が進んでいる様子を目の前で感じることが出来ました。機能をどうすべきかでの意見を交わしている様子などを実際に前にするのは一週間という短いインターンではなかなかない経験ではないでしょうか。

自分の開発した機能は前述したように周りのコードに合わせることが出来ていない部分が多く結局全部書き直しなのでは……、またUnityのバージョンが違うということもあり、すぐには反映されることはないように思いますが、自分の作成した部分が少しでもお役に立てていれば嬉しいです。

圧倒的猛者になれたかはともかく、今回のインターンは反省点も多く、自分を見直すきっかけとしても、実際に仕事として働く時の経験を知ることが出来る良い機会としても、参加できて本当に良かったと思います。
メンターののりおさんをはじめ、VRoidチームの皆さん、ピクシブのみなさん、ありがとうございました!

PCL1.8.1 Normalの表示が出来ないときの改善策

PCLでNormalを使いたいけど表示しようとすると実行時エラーが出る現象の解決

コードは
Normal Estimation Using Integral Images
↑のを使用

そのままビルド……は通る
けど、実行するとダメ
vtksmartpointer辺りのエラーが出るはず

解決策は以下を追加

#include <vtkAutoInit.h>

VTK_MODULE_INIT( vtkRenderingOpenGL );

それとOpenGL32.Libへのリンクが必要です。
自分の場合は「C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x64\」にありました。
8.1はVisualstudioのバージョンに合わせて(自分は2017)になるようです。


こんなんどこで教えてもらえるの……
なんでサンプルには書いてないの……cmakeビルドだといらないとか......?
めげそう

参考サイト
PCL 1.8.0 (Point Cloud Library) のプロパティシート (Visual Studio 2017版)
はじめてのVTK - Mugichoko’s blog