C#(WPF)とDLLでシステムコマンドをグローバルフックする
先日、BUFFALO製のマウスやキーボードを他の機器にBlueToothを飛ばせる製品を購入しました
BlueTooth製品の入力を別のBlueToothとして飛ばしたりできて非常に面白いし使いやすい商品!
・・・・だった・・のですが!
飛ばす元でAltキーを単発で押すとメニューにフォーカスが移ってしまい、
気付かないうちに設定を変更してしまうという問題に直面しました
「その動きだけ制約加えるソフト作成してみよっかな」と思い立って作り始めたのですが
・どうもグローバルフックが必要 しかもDLL化しないとダメ。言語はもう忘れ気味のC++
・資料が古いものばかり DEFファイルなんてほとんど作ったことないよ・・・
・APP側がC#で作成されているサンプルが少ない
・フック横取りして無効化しているのはキー入力ばかりでシステム系のものが見当たらない
ということでブログに書くことにしました!
製作環境はVS2015の無料のやつです
まずはDLLから始めます
新規作成 > C++のWin32プロジェクト > 名前はHook > OK > 次へ >DLLにチェック > 完了
dllmain.cppを以下に書き換える(ヘッダー追加するまでエラーでてるけど気にしない)
次にソリューションのヘッダーファイルを右くり > 追加 > 新しい項目 > Hook.h を作成
中身は以下
ビルドしたらDLL完成
次にC#側でAPPを作成開始!
新規作成 > WPFアプリケーション > LockAltMenuという名前で作成
常駐ソフトにするので、まずはソリューションにあるMainWindowsを削除
App.xaml内 の StartupUri="MainWindow.xaml" という部分も削除
App.xaml.csを以下に書き換える
参照にSystem.Windows.FormsとSystem.Drawingを追加
プロジェクト右クリック > プロパティ > リソース > icon.ico という適当な画像をドラッグしてアイコンリソースを作成
最後に先ほど作ったDLLを実行ファイルと同じ場所に移動※!これで完成!!
※ 同じ断層に作成してある場合はプロジェクトプロパティのビルド前イベントに
Copy "../../../../Hook\Debug\Hook.dll" $(TargetDir)Hook.dll と追加しておくと便利
【解説らしきもの】
ソースがすべてですが、注意点だけ抜き出しておきます
・フック内容を書き換えたい場合はSetWindowsHookExの第一引数に気をつけろ!
・グローバルフックDLLをC#で扱う場合、DllImportはエントリポイントまで記入しないと動作しない
・似たような方法でDLLインジェクション+サブクラス化を検討している場合は、SetWindowLongPtr(GWL_WNDPROC指定)で拾えるシステムコマンドの種類は少ないので実装前に確認したほうが無駄な時間を食わずに済むよ!
・操作したいターゲットが決まっている場合はSetWindowsHookExの第3,4引数を変えてローカルフックにする(コメント参照)
・実験に失敗したらOS再起動しないと治らなくなるので注意されたし!
技術が古いためか動作しないサンプルもチラホラあり、簡単にできると思ったのに意外に大変だった orz
誰かのお役に立てば幸いです
SmartMaterialについて
SmartMaterialの機能を知ってかなり感動したんですが、日本語の記事がほとんどヒットしないという悲しさ。
SPの基本的な考え方は
素材を割り当て→マスクして隠す
です
マスクの部分にはペイントだけではなくジェネレータを利用できます。
ジェネレーターは非常に強力なのですが、PositionMapやAOMap、ThicknessMap等、モデルから抽出した固有の情報が必要になります。(ジェネレーターによって種類が異なります)
SPはこの情報をモデルごと(正確にはTextureSetごと)に記憶することしました。
(どの情報も好きなタイミングでMeshからベイクできます。)
これにより「ジェネレータと必要情報の自動紐づけ」が可能となり、
モデルにより異なる情報は無視して、ジェネレータ(エフェクト)を含む素材をテンプレートとして保存できる仕組みが完成しました。
これが「SmartMaterial」です。
PositionMap等が必要な複雑な素材であってもテンプレートとして保存できるのは非常に強力で、時間短縮に繋がります。
現時点ではSmartMaterialを読み込んだ時に必要なマップがベイクされていない状態でもそのまま読み込めます。
警告のようなものが出るか、読み込み時に必要マップが確認できる仕組みがあってもいい気がします。
SubstancePainter1.5を試してみた
半年以上SubstancePainterアップデートしていなかったので早速アップデートしてみた。
相変わらず日本語情報が少ないので公式の動画を三つくらい視聴。
変わったところや気になった機能をまとめてみた。
SmartMaterialがやばい!
後述します。
sbsarファイルの管理が楽になった。
SettingのShelfの項目にフォルダを指定するとMaterialなどのカテゴリごとにフォルダを自動生成してくれるので、そのフォルダの中にsbsarファイルをぶち込めばOK。フォルダが断層になっていても問題なく参照してくれるのがGood!
日本語に対応。
NormalMapが「通常マップ」ってΣ
「法線マップ」でしょ!
日本の代理店とかから指摘がいかないのかなぁ・・・。
レイヤーやマスクにエフェクトがかけられるようになった。
SDの強力なジェネレーターがかけられるのもやばいんだけど、その上からペイントエフェクトで手軽に手直しできるのがかなり便利ですねこれ。以前だとレイヤー構造が複雑になりがちだったので便利です。
あとColorSectionEffectが神です。SDでMultiMaterialBlendノードを利用する必要がなくなりました。というかSubstancePainter一本でテクスチャを作成するワークフローに変更できそうです。
以前できなかった複数マテリアル(UVマップ)を持ったモデルのサポートや、ベイク種類の増加、テクスチャの合成方法も増えてるし、ビューアの強化等 ほんと至れり尽くせり。
全体を通して機能がかなり増えていて別ソフトになってましたが、流石はAllegorithmic社さん UIが洗練されているのでほとんどマニュアルなしで使えました。(3D初心者の方やDesignerの方を触ったことない人がいきなり操作できるかどうかと聞かれると疑問ではありますが・・・。)
今後も期待できる内容で大満足のアップデートだったと思います。
なんか思ったより長くなったのでSmartMaterialについては明日書きます。
PBRShader for UnityTerrain
結論から言うと恐らく現状ではPBR対応のサーフェイスシェーダーをTerrainのCustomShaderとして利用することはできない
http://forum.unity3d.com/threads/terrain-pbr.276734/
Unity Technologiesによると公式にて近日中に対応予定。とのこと。
PBRに拘らなければCustomShaderを適用したMaterialをTerrainの設定画面から指定することができた。
以下は角度によってテクスチャを自動で切り替えるシェーダーを適用した例
ただしTangentVectorが取得できない等Terrain特有の癖が分かるまではUnity上で細かくデバッグしながら作成したほうが良さそう。
シェーダーからTerrainのInspector内の PaintTexture にアクセスしたい場合は以下を記述する。
(4つのテクスチャが登録されていると過程)
プロパティ内
[HideInInspector] _Splat3("Layer 3 (A)", 2D) = "white" {}
[HideInInspector] _Splat2("Layer 2 (B)", 2D) = "white" {}
[HideInInspector] _Splat1("Layer 1 (G)", 2D) = "white" {}
[HideInInspector] _Splat0("Layer 0 (R)", 2D) = "white" {}
[HideInInspector] _Normal3("Normal 3 (A)", 2D) = "bump" {}
[HideInInspector] _Normal2("Normal 2 (B)", 2D) = "bump" {}
[HideInInspector] _Normal1("Normal 1 (G)", 2D) = "bump" {}
[HideInInspector] _Normal0("Normal 0 (R)", 2D) = "bump" {}
入力部分の構造体の例
struct Input {
float2 uv_Sample;
float2 uv_Main : TEXCOORD0;
float2 uv_Splat0 : TEXCOORD1;
float2 uv_Splat1 : TEXCOORD2;
float2 uv_Splat2 : TEXCOORD3;
float2 uv_Splat3 : TEXCOORD4;
};
変数宣言部でサンプラーを利用できるようにする
uniform sampler2D _Splat0,_Splat1,_Splat2,_Splat3;
サーフェイスシェーダー内部でのアクセス方法
tex2D(_Splat0, IN.uv_Splat0)
グーグル上で資料が増えたこともあって、シェーダーまわりの知りたいことは一通り調査が終わった!
次はずっとしたかったのにできなかったSubstanceDesignerとPainterのアップデートをやっていこうと思う~
Unity5のサーフェイスシェーダー
昨日の続きでUnity5のサーフェイスシェーダー内部を覗いてみた。
PBRに対応するため内部で面倒なことをしていると思い込んでいたら、まるごとすっきりとリメイクされている模様。
よってほとんど説明する内容が無い・・・。
Shader "Custom/NewShader" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
_Glossiness ("Smoothness", Range(0,1)) = 0.5
_Metallic ("Metallic", Range(0,1)) = 0.0
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200
CGPROGRAM
// Physically based Standard lighting model, and enable shadows on all light types
#pragma surface surf Standard fullforwardshadows
// Use shader model 3.0 target, to get nicer looking lighting
#pragma target 3.0
sampler2D _MainTex;
struct Input {
float2 uv_MainTex;
};
half _Glossiness;
half _Metallic;
fixed4 _Color;
void surf (Input IN, inout SurfaceOutputStandard o) {
// Albedo comes from a texture tinted by color
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;
o.Albedo = c.rgb;
// Metallic and smoothness come from slider variables
o.Metallic = _Metallic;
o.Smoothness = _Glossiness;
o.Alpha = c.a;
}
ENDCG
}
FallBack "Diffuse"
}
Vertex/FragmentシェーダーをPBRで書く必要が無い限りは物理ベースの計算を隠蔽したままコーディングができそうな気配!
これはありがたい・・・。
Unity5のCustomShaderの互換性
昨日の記事に引き続き、まずはPBRの部分を無視してShader機能の互換性について調査。
アップデート時の注意点をまとめてみた。
・ライトの光の強度が2倍になったよ
・サーフェイスシェーダのインタポレーターと命令数の増加でSM2.0だと命令数リミットにより動作しない可能性があるよ→問題が出たらSM3.0にしてみたら?
・ノンユニフォームメッシュはCPUの段階で事前スケールされなくなったことにより NormalやTangentベクトルのNormalizeの必要性がでたよ(サーフェイスシェーダーの場合は生成してくれる)
・フォグの描画タイミングを変更 #pragmaにnofogと表記することで明示的にフォグのサポート状況を管理できるようになったよ
・サーフェイスシェーダーのAlphaチャンネルにデフォルトで1.0が出力されるようになったよ
・パフォーマンス改善のためForward描画中にマテリアルインデックス順に描画していた仕様を変更→ソートは行わないためインデックスに依存した仕様だった場合は注意ね
・見たこともないいくつかの固定関数シェーダーの廃止(使ったら警告がでる)
・プログラマブルシェーダーと固定関数シェーダーの併用ができなくなったよ
・シェーダーコンパイラが変更され少し速くなったよ
・変数「unity_Scale」は廃止するから 今後はWorldスペースに変換してスケール行列を適用してね
・Forwardで描写された影のEffectPass(ShadowCollectorパス)の処理は移動したので古いパスは削除して問題ないよ
結構深いことをしていないとクリティカルな問題は生じなそうな変更点ですね。
UnityからGPUに渡す部分をシンプルにしたい思惑が見て取れます。
Unity5のCustomShader
Unity5でPBRが導入されてカスタムシェーダの書き方に関する最新の記事を探していたんですが
Unity5の公開当初はまったくといっていいほど情報がありませんでした。
情報が出るのを待っていたんですが、仕事が忙しくなってしまいなかなかチェックができていませんでした。
ようやく時間がとれるようになってきたのでネットサーフィンしてみると以前全く見つからなかった情報がチラホラと。
http://docs.unity3d.com/Manual/UpgradeGuide5-Shaders.html
http://www.alanzucconi.com/2015/06/24/physically-based-rendering-and-lighting-models-in-unity3d/
相変わらず日本語資料は皆無です。
PBRのシェーディングの概要は理解しているつもりなのですが、計算部分まで学習してしまうか悩ましいところです。
(覗いてもいないのでどのくらいのハードルなのか分からないし怖い・・・。)
まだ資料は読んでないのですが、Terrain専用のカスタムシェーダーの作成を目標に動き出すことにしました。
(以前、サークルのレベルデザイナー担当の方が、Terrainの思索段階で何度もテクスチャペイントを使って雰囲気を出しては作り直して~という作業を行っていたのを見て、TerrainShaderを書いてみたいと思っていました。)
UnityのTerrainはシェーダの構造が特殊でマテリアルのものを移植できないみたいなので、そのあたりも資料を集めねば。