tsumikiseisaku.com
Open in
urlscan Pro
219.94.128.186
Public Scan
URL:
https://tsumikiseisaku.com/blog/sculpting/
Submission: On June 13 via manual from JP — Scanned from JP
Submission: On June 13 via manual from JP — Scanned from JP
Form analysis
2 forms found in the DOMPOST https://tsumikiseisaku.com/blog/wp-comments-post.php
<form action="https://tsumikiseisaku.com/blog/wp-comments-post.php" method="post" id="commentform" class="comment-form">
<p class="comment-notes"><span id="email-notes">メールアドレスが公開されることはありません。</span> <span class="required">*</span> が付いている欄は必須項目です</p>
<p class="comment-form-author"><input id="author" name="author" placeholder="Name" type="text" value="" size="30"></p>
<p class="comment-form-email"><input id="email" name="email" placeholder="E-Mail(任意)" type="text" value="" size="30"></p>
<p class="comment-form-cookies-consent"><input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes"> <label for="wp-comment-cookies-consent">次回のコメントで使用するためブラウザーに自分の名前、メールアドレス、サイトを保存する。</label></p>
<p class="comment-form-comment"><textarea id="comment" name="comment" placeholder="Comment" aria-required="true"></textarea></p>
<p class="form-submit"><input name="submit" type="submit" id="submit" class="submit" value="送信"> <input type="hidden" name="comment_post_ID" value="1574" id="comment_post_ID">
<input type="hidden" name="comment_parent" id="comment_parent" value="0">
</p>
<p class="tsa_param_field_tsa_" style="display:none;">email confirm<span class="required">*</span><input type="text" name="tsa_email_param_field___" id="tsa_email_param_field___" size="30" value="">
</p>
<p class="tsa_param_field_tsa_2" style="display:none;">post date<span class="required">*</span><input type="text" name="tsa_param_field_tsa_3" id="tsa_param_field_tsa_3" size="30" value="2024-06-13 06:11:45">
</p>
<p id="throwsSpamAway">日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)</p>
</form>
GET https://tsumikiseisaku.com/blog/
<form role="search" method="get" id="searchform" class="searchform" action="https://tsumikiseisaku.com/blog/">
<div>
<input value="" name="s" id="s" type="text">
<div>
<i class="icon-search"></i>
<input class="icon-search" id="searchsubmit" value="" type="submit">
</div>
</div>
</form>
Text Content
TSUMIKI TECH TIMES * * > * シェーダー * > * 簡易スカルプト機能の作り方 簡易スカルプト機能の作り方 2023.9.7 シェーダー 積木製作の北村です。 先日、コンクリートをプレイヤーの自由な操作で削りたいという相談を受けました。 今回はUnityで簡易的なスカルプト機能を実装してこの表現を作ってみます。 今回作ったもの 先に完成図をお見せすると、こんな感じです。 メッシュの準備 今回削っていくコンクリートのモデルはこちらです。 今回は中央手前の赤枠で囲われた角の部分を削っていきます。 Что предлагает Vavada мобильный сайт и десктопная версия. Как открыть счет и начать делать ставки на деньги. Особенности каталога и актуальные методы для снятия средств. スカルプトで表現する都合上、削る範囲のメッシュはポリゴンを細かく分割しておく必要があります。 UVも通常のアセット制作時と同様に開いておきましょう。 また、今回は切削範囲の境界を目立たせたくない為、 スカルプトを適用する強度をメッシュの頂点カラーに記録しておきます。 メッシュの変形は赤い部分に強く適用され、黒い部分には適用されません。 メッシュの変形 では、実際にメッシュの変形を行いましょう。 基本的な処理の流れとしては、 1. 頂点同士のつながり方を取得 2. 操作部位から一定の範囲内の頂点のみ操作部位から遠ざける 3. 動かした頂点に対し、頂点同士のつながり方を利用してスムージングを行う 4. 移動後の頂点の位置関係とつじつまが合うように法線を再計算する となります。 1については、クラスの初期化の段階でC#で頂点の状況をチェックして、 得られた結果をComputeShaderに渡します。 2は頂点の位置から移動の方向を取得できるのでシンプルです。 This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters Show hidden characters // displace vertex float3 Displce(float3 position) { // NOTE: displace calculation is done in LOCAL SPACE! // displace mesh // direction to displace / x can be displaced both directions float3 displaceDir = float3(0, -1, 1); // position and distance seem object space float dist = distance(position, _sculptPos); if (dist > _sculptRadius) return position; float angleWeight = dot(normalize(_sculptDir), normalize(position - _sculptPos)); angleWeight = max(saturate(angleWeight), 0.3); float offset = _intensity * smoothstep(_sculptRadius, 0, dist) * angleWeight; float3 dir = normalize(position - _sculptPos); // constrain y-axis displace direction dir.y = sign(dir.y) * displaceDir.y < 0 ? -dir.y : dir.y; // constrain z-axis displace direction dir.z = sign(dir.z) * displaceDir.z < 0 ? -dir.z : dir.z; // disable to offset along x-axis //dir.x = 0; float3 newPos = position + dir * offset; return newPos; } view raw ConcreteSculpting_Displace.compute hosted with ❤ by GitHub 今回はメッシュが必ず決まった方向に凹むので、頂点の移動の方向に制限を掛けています。 3については、操作中の頂点と繋がっている複数頂点の位置の加重平均を取ることにします。 操作中の頂点に近い頂点ほど計算結果に与える影響が強くなります。 以下の資料のLaplacian Smoothingについての解説を参考に実装しました。 https://graphics.stanford.edu/courses/cs468-12-spring/LectureSlides/06_smoothing.pdf This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters Show hidden characters // relax mesh; weighted average float3 RelaxMesh(uint index) { // iterate through the connected points float3 thisPos = LoadVertex(index); float3 midPos = float3(0, 0, 0); int count = 0; float dist = distance(thisPos, _sculptPos); if (dist > _sculptRadius) return thisPos; Topology topology = _topologyBuffer[index]; // sum of distance between the points float distSum = 0; for (uint j = 0; j < 10; j++) { int otherVertice = GetTopologyIndex(topology, j); if (otherVertice == -1) continue; float3 otherPos = LoadVertex(asuint(otherVertice)); distSum += distance(thisPos, otherPos); } // calculated relaxed position float weightSum = 0; for (uint i = 0; i < 10; i++) { int otherVertice = GetTopologyIndex(topology, i); if (otherVertice == -1) continue; float3 otherPos = LoadVertex(asuint(otherVertice)); float weight = 1.0 - distance(thisPos, otherPos) / distSum; midPos += otherPos * weight; weightSum += weight; count++; } // avoid 0 division midPos = count > 0 ? midPos / weightSum : thisPos; // direction to displace / x can be displaced both directions float3 displaceDir = float3(0, -1, 1); // constrain y-axis displace direction midPos.y = sign(midPos.y - thisPos.y) * displaceDir.y < 0 ? thisPos.y : midPos.y; // constrain z-axis displace direction midPos.z = sign(midPos.z - thisPos.z) * displaceDir.z < 0 ? thisPos.z : midPos.z; return midPos; } view raw ConcreteSculpting_Smoothing.compute hosted with ❤ by GitHub 4については、以下の記事を参考に三角ポリゴン単位で計算を行います。 https://qiita.com/aa_debdeb/items/486456e8352070055fac This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters Show hidden characters float3 CalculateNormal(float3 p0, float3 p1, float3 p2) { float3 d10 = p1 - p0; float3 d20 = p2 - p0; return normalize(cross(d10, d20)); } view raw ConcreteSculpting_Normal.compute hosted with ❤ by GitHub これらの処理をComputeShaderで実装していきます。 テクスチャの適用 今回はコンクリートの破砕の表現なので、削った部分のテクスチャの切り替えも併せて実装します。 テクスチャの切り替えを実装するには、どのような切り替え方をしたいかをRenderTextureに記録する必要があります。 今回はスカルプトのComputeShaderの中で、操作対象の頂点付近のピクセルを断面用のテクスチャの領域として記録します。 処理の流れは以下のようになります。 1 操作対象の頂点からUV座標を取得 ComputeShaderに渡した頂点の情報から、動かす頂点のUV座標を取得します。 2 取得したUV座標の周囲のピクセルをテクスチャ変更範囲として記録 RenderTexture上で、1で取得したUV座標の周囲のピクセルの値を変更します。 以下にメッシュのUVレイアウトのイメージで図を書いてみました。 図の中央の頂点が操作対象で、その周囲の赤い部分がテクスチャを差し替える範囲になるイメージです。 以下は実際に記録されたRenderTextureの例です。 黒以外の色になっている領域がテクスチャを断面用の物に差し替える範囲です。 3 断面のテクスチャを更新の度にオフセットさせる為、そのオフセット値をランダムに生成 オフセット値はRenderTextureのR, Gチャンネルに記録します。 テクスチャを横にずらす際のオフセット値はR、縦にずらす場合はGチャンネルに記録しています。 4 コンクリートのシェーダーでRENDERTEXTUREを読み込み、テクスチャを切り替え シェーダー内での個々のテクスチャのマッピングは、今回の場合Triplanarを使うのが便利です。 実装例 実際にテストシーンで使ったComputeShaderはこちらです。 ConcreteSculpting.compute 上記のComputeShaderを呼び出すC#スクリプトは以下の物を使いました。 SculptManager.cs KernelParamsHandler.cs 描画されるメッシュの変形にはGraphicsBufferとRWByteAddressBuffer、ByteAddressBufferを使用しております。 インタラクションに使用するためのMeshColliderの更新にも同じ方法を使いたかったのですが、うまくMeshColliderが更新されませんでした… その為、代わりにRWStructuredBufferから取得した値を配列に入れてMeshCollider用のメッシュに代入しています。 その他、テストシーンでの入力取得に以下のスクリプトも使用しています。 ConcreteBreakTrigger_Demo.cs ConcreteSculptManager.cs ControllerInputHandler.cs ここに各種シェーダーやテクスチャ、パーティクル等を加えて完成すると以下のようになります。 参考 今回は以下のページを参考に実装しました。 ・Stanford University: Mesh Smoothing ・UC Davis: Mesh Smoothing ・Game Dev Bill: How to Calculate Shader Graph Normal ・【Unity】Advanced Mesh APIでメッシュの頂点をCompute Shaderで動かす キャンセル メールアドレスが公開されることはありません。 * が付いている欄は必須項目です 次回のコメントで使用するためブラウザーに自分の名前、メールアドレス、サイトを保存する。 email confirm* post date* 日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策) * Share * Tweet * +1 * LINE * Hatena * Pocket * RSS * feedly シェーダー Previous Post 一筆書きの簡易表現 Company * * * * Category * アセット 1 * イベント 1 * サウンド 2 * シェーダー 23 * システム 6 * モーション 1 * モデリング 1 * ライティング 1 * リリース 2 * 日記 1 * 画作り 11 Search Archive * 2023年9月 2 * 2021年4月 1 * 2020年9月 1 * 2020年7月 1 * 2020年6月 1 * 2019年12月 1 * 2019年9月 6 * 2019年6月 1 * 2019年3月 1 * 2019年2月 1 * 2019年1月 1 * 2018年12月 1 * 2018年8月 2 * 2018年5月 1 * 2018年4月 1 * 2018年3月 1 * 2018年2月 1 * 2018年1月 1 * 2017年8月 1 * 2017年5月 2 * 2017年4月 3 * 2017年3月 2 * 2017年2月 2 * 2017年1月 5 * 2016年12月 3 * 2016年11月 3 Recent Posts * 2023.9.7 線をなぞる表現の作り方 (進捗判定付き) * 2023.9.7 簡易スカルプト機能の作り方 * 2021.4.30 一筆書きの簡易表現 * 2020.9.1 Questハンドトラッキングを実案件で使ってみた所… * 2020.7.7 ライトマップを再利用して 遮蔽箇所の反射を抑える * 2020.6.1 Alpha Test を綺麗に見せる方法 * 2019.12.17 Quest用シーン制作で気を付けている事 * 2019.9.26 Unity Japan Office メイキング… * 2019.9.26 Unity Japan Office メイキング… * 2019.9.26 Unity Japan Office メイキング… * 2019.9.26 Unity Japan Office メイキング… * 2019.9.26 Unity Japan Office メイキング… * 2019.9.26 Unity Japan Office メイキング… * 2019.6.14 Unityシェーダーチュートリアル ポストプロセ… * 2019.3.26 3dsMaxにおける便利UV展開 ▲ * * > * シェーダー * > * 簡易スカルプト機能の作り方 * * * * © 2018 TSUMIKISEISAKU