Three.js: UVオフセット/リピートはテクスチャではなくマテリアルの一部である必要があります

作成日 2015ĺš´01月10日  Âˇ  73コメント  Âˇ  ソース: mrdoob/three.js

UVオフセットとリピート(およびおそらく他のテクスチャプロパティのいくつか)は、テクスチャからマテリアルに奇妙に渡される均一であり、必要に応じてマテリアルごとにテクスチャを複製する必要がある(大量のメモリを浪費する)という問題が発生します。 -マテリアルのオフセット/リピート、または独自のカスタムシェーダーをロールします。 人々にこれを強制することは非常に非効率的です。最も良いケースは、適用されるオブジェクトのサイズに基づいてサーフェス全体にテクスチャを並べて表示する場合、またはテクスチャをアニメーションのスプライトシートとして使用する場合です。 「共有」テクスチャで共有UVオフセット/リピートが必要になる可能性は低く、通常はマテリアルを共有する方が適切であるため、現在のシステムは実際の利点のない障害としてしか見ることができません。 いずれにせよ、テクスチャからユニフォームを更新することは奇妙です。なぜなら、それは実際にはテクスチャの一部であるビジネスを持たず、エンドユーザーを混乱させることになります。 たとえば、マテリアルに複数のマップが適用されている場合にオフセット/リピートを変更すると、たとえば、diffuse + normalmapは、ディフューズマップのオフセット/リピートのみを使用するため、法線マップのオフセット/リピートの値は、そのコンテキストではまったく役に立ちません。 、それが法線マップのオフセット/リピートに影響を与えるはずだと本当に示唆している場合。 それはすべて混乱しています。

「refreshUniformsCommon」関数で変更が必要であると確信していますが、おそらくそれ以上のものがあります。 スプライトプラグインにもいくつかの変更が必要です。 これはおそらく多くの人々のプロジェクトを壊すでしょうが、それはテクスチャ/マテリアルAPIのかなり大きな矛盾です。 マテリアルでは通常はnullであるオーバーライドを作成することをお勧めします。設定すると、テクスチャの値が無視されるため、すべての人が壊れることはありません。

Suggestion

最も参考になるコメント

このスレッドは私にとってTL; DRです。 しかし、私はちょうど今、r68でこのコードを発見しました(古いプロジェクト、うん):

        // uv repeat and offset setting priorities
        //  1. color map
        //  2. specular map
        //  3. normal map
        //  4. bump map
        //  5. alpha map

        var uvScaleMap;

        if ( material.map ) {

            uvScaleMap = material.map;

        } else if ( material.specularMap ) {

            uvScaleMap = material.specularMap;

        } else if ( material.normalMap ) {

            uvScaleMap = material.normalMap;

        } else if ( material.bumpMap ) {

            uvScaleMap = material.bumpMap;

        } else if ( material.alphaMap ) {

            uvScaleMap = material.alphaMap;

        }

        if ( uvScaleMap !== undefined ) {

            var offset = uvScaleMap.offset;
            var repeat = uvScaleMap.repeat;

            uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );

        }

だから、ええ...

ここで提案したような根本的な変更をライブラリに提案する場合は、その変更について明確で説得力のある議論を提供する必要があります。

拡散反射光マップと法線マップで異なるリピートを設定しようとしていて、機能しなかったために髪を抜いてみました。 APIはこの設定をテクスチャに配置するので、私はそれができると思いました。 そうです、説得力のある議論のために私の髪を保存するのはどうですか? このチケットはまだ開いており、3jsはまだテクスチャにこの設定を持っており、テクスチャの1つに対してのみ尊重されます=これは事実上、すでにマテリアルごとの設定です。

これを所属する場所に移動しない場合は、少なくともドキュメントでは効果がないと言いますか?

全てのコメント73件

関連記事: https :

マテリアルごとにテクスチャを複製する必要があります(大量のメモリを浪費します)

大量のメモリが無駄になっているのはどのような意味ですか?

「共有」テクスチャで共有UVオフセット/リピートが必要になる可能性は低いです

それはどういう意味ですか?

現在のアプローチを維持する場合、変更が必要なことの1つは、テクスチャのクローンを作成するときに、共有イメージをGPUに1回だけ渡す必要があることです。

フレーム/シートの数が多いオブジェクトがある場合、作成される役に立たないオブジェクトがたくさんあり、あなたが述べたように、画像は非常に無駄なGPUに複数回コピーされます。 さらに無駄なことに、異なるアニメーションの異なるポイントに配置する必要のある複数のオブジェクトがある場合、固有のマテリアル/オブジェクトごとに固有のテクスチャセットを作成する必要があるため、マテリアルのユニフォームが発生する可能性がある場所での処理がすぐに面倒になります。これらの余分なテクスチャオフセット/リピートデータ構造を使用せずに、はるかに簡単に操作できます。これは、APIを機能させるためだけに、よく考えられていないAPIを中心に構築されています。 アプリケーションの特定のユースケースでは、これらの一意のテクスチャグループをどこにでも作成する必要があり、この単一の問題を回避するために使用するすべてのストックマテリアルをシェーダーマテリアルに置き換えることが唯一の解決策であると感じています。または、THREE.jsバージョンをフォークして、必要な変更を加えます。

2番目のステートメントに関して:

現在のパラダイムは、同じUVオフセット/リピートで同じテクスチャを適用したい場合にのみ作業を容易にすることを意味しましたが、これを他のように定義したい可能性がはるかに高いため、一般的にはまれなケースですユニフォーム、マテリアルごと、テクスチャだけでなくマテリアルを共有します。

現在のシステムに関する主な注意点。 オフセット/リピートは、シェーダー内のすべてのテクスチャに影響を与える単一のユニフォームとしてのみ実際に存在しますが、3つにアタッチされているという事実です。テクスチャは、ユニフォームとして適切に使用できないことを意味し、オフセット/リピートを考えるように人々を騙します。ストックマテリアルに適用できるさまざまなテクスチャに対して異なる方法で選択できます(つまり、異なる拡散オフセットと法線マップオフセットを定義できますが、異なるテクスチャに一意に設定できても、実際には不可能です)。 キャンバスレンダラーの残骸である可能性がありますが、それを大いに利用しているwebGLrender / GLSLマテリアルシステムでは意味がありません。

mrdoobは、材料ごとにそれを使用することに反対する理由として、次の形式である必要があると述べました。

material.map
material.mapOffset
material.mapRepeat
material.env
material.envOffset
material.envRepeat
... NS。

しかし、繰り返しになりますが、オフセット/リピートは現在でもマップタイプごとに機能しないため、これは実際には有効な引数ではありません。 とにかく多くのユニフォームを無駄にしてマップタイプごとに配置することはできません(言うまでもなく、通常は1セットのUVのみを使用するため、法線マップ/バンプマップ/ディフューズマップ/スペキュラーマップに複数のオフセットはありません)。 すべてのオプションを妥当なものとして検討する場合、それは実際にはテクスチャプロパティではなくマテリアルプロパティである必要があると思います。 現在のシステムには何のメリットもないと思います。 UVオフセットを介してマテリアルをアニメートすることが、プロパティをまったく持たない主な理由であり、そのために適切に使用することさえできないと感じています。 言うまでもなく、これらのユニフォームが必要ない場合は、シェーダーのコンパイルから省略できますが、マップが存在する限り、ユニフォームは存在します。

@QuaziKb敬意を払って、ここで提案したようなライブラリへの根本的な変更を提案する場合は、その変更について明確で説得力のある議論を提供する必要があります。 あなたの特定のアプリケーションの参照のフレームから議論することはそれをカットするつもりはありません。

そうは言っても、私もオフセット/リピートがTextureからマテリアルに移動することを望んでいます。

次のマップが同じオフセット/リピート値を持っていると仮定するのは合理的だと思います。

specularMap
normalMap
bumpMap
alphaMap
aoMap (future)
glossMap (future)
displacementMap (future)

唯一の例外は


これが現在の実装方法です。 各マップには独自のオフセット/リピート値がありますが、それらは尊重されません。

したがって、 MeshPhongMaterial 、 MeshLambertMaterial 、 MeshBasicMaterial 、およびSpriteMaterialに追加できます。

mapOffset // or mapTranslate
mapRepeat // or mapScale

Textureからoffsetとrepeatを削除します。

このように、スプライトシートの実装は簡単です。 各スプライトにはマテリアルがあり、それらのマテリアルは単一のテクスチャを共有します。 テクスチャにはイメージがあります。 テクスチャを複製する必要がなくなりました。 GPU側では、マテリアルは単一のシェーダープログラムを共有します。

私見、これはより自然なAPIです。

APIが以前のように実装された理由を思い出そうとしています。 正当な理由があったと思います。

申し訳ありませんが、それが私の例に特有であることを示唆するつもりはありませんでした。単に、現在のAPIを使用すると、スプライトシート/一意のオブジェクト/マテリアルごとのオフセットをアニメーション化するときに大幅な肥大化が発生し、実際の解決策はありません。 当然、オフセット/リピートをモデルの頂点UVに単純にベイクするのではなく、これをユニフォームとして使用する主な目的は、オフセットをアニメーション化することです。これは、APIを回避してユニフォームを作成しないと実行できないことを示唆していました。テクスチャにアタッチすることは、マテリアルにアタッチする場合よりもはるかに有用ではありません。

次のマップが同じオフセット/リピート値を持っていると仮定するのは合理的だと思います。
地図
..。
alphaMap

FWIW、この動作(現在の実装)は、現時点で私に重大なフラストレーションを引き起こしています。 メッシュマテリアルのalphaMapオフセットを、その拡散マップ(固定されたまま)とは独立してトゥイーンすることにより、メッシュのリビールをアニメートしようとしています。 いくつかの欲求不満の後、私はhttps://github.com/mrdoob/three.js/pull/4987を介して発見し、このバグはこれが不可能であることを発見しました。

@jcarpenterあなたが言及している「バグ」とは何ですか? 改善のためのあなたの提案は何ですか?

訂正:「バグ」とは、この問題を意味していました。 Bugzillaカルチャーでの過度の時間による混乱。 :pこれはバグではなく、意図した動作であることを理解しています。

Cinema 4Dのような従来の3Dコンテンツ作成アプリでの私の経験に基づいて、改善のためのWRTは、ユーザーが次の両方を実行できると想像しています。

  • 他のテクスチャとは関係なく、マテリアル内の各テクスチャのオフセット/スケール/リピートを定義します。
  • 親マテリアルのオフセット/スケール/リピートを定義します

あるいは、私が取り組んでいるユースケース(「メッシュの表示をアニメーション化しようとしている」)の場合、まったくラップしないwrapSとwrapTのオプションがあると便利です。 Cinema4Dから添付されたGIFごとに、UVWマッピングのタイリングを完全に無効にするオプションがあります。 既存のwrapSおよびwrapTメソッドを使用したかなり広範なテストに基づくと、このようなことは不可能です。 three.jsのアイテムの表示をアニメーション化するための私のオプションは、メッシュ全体のトゥイーン位置と不透明度に制限されているようです...何かが足りない場合を除きます。

c4d-tile-2

同意しました。 計画は、これらすべてを単純化し(シェーダーで単一のmatrix3を使用)、テクスチャごとにオフセット/リピート(または変換/スケール)を行うことです。

これを手伝いたい人は誰でも大歓迎です!

@jcarpenter

残念ながら、現時点でこれを行う唯一の方法は、異なるマテリアルを使用した複数のメッシュ、またはカスタムシェーダーマテリアルを使用することです。 どちらも、three.jsワークフローに飛び込んだばかりのユーザーにとっては一種の関与です。

使いやすさ、パフォーマンス、拡張性の間には常にトレードオフがあります。 私の提案は、テクスチャとマテリアルが現在APIで機能する方法を書き直して、テクスチャが厳密にプラグインするパラメータであり、オフセット/リピート/ラップモードのようなシェーダーで実際に均一である値が特ににリンクされるようにすることです。材料。 場合によっては、変更する必要のないテクスチャのUVの制御にユニフォームを無駄にしたくない場合があります(拡散にのみ必要な場合は、フォンマテリアルに4 * 5の余分なユニフォームを含めるのは非常に無駄です)、したがって、特定のUVが必要かどうかを検出し、それらの要求を満たすためにテクスチャが再構築されるかどうかを検出する魔法が舞台裏にある場合、または必要な調整可能なUVの数と内容を指定するためにオプションでパラメータを渡すことができる場合はクールです。それらがオフセットするマップとその方法ですが、解決するのは難しい問題です。

計画は、これらすべてを単純化し(シェーダーで単一のmatrix3を使用)、テクスチャごとにオフセット/リピート(または変換/スケール)を行うことです。

@mrdoob

  1. _per material.map_を意味するので、テクスチャ変換はマテリアルに含まれますか? 残念ながら、マテリアルマップはたくさんあります。 ライトマップを除いて、すべてのテクスチャ変換が同じであると引き続き想定できます。
  2. ローテーションもサポートしますか? その場合は、回転中心も追加する必要があります。ただし、回転中心をテクスチャの中心に配線する必要がある場合を除きます。

これは非常にありがたい変更です。 テクスチャを一意の繰り返し値にするためだけにテクスチャのクローンを作成する必要があるのは、非常に面倒です。 これは他の図書館がそれを行う方法ですか?

  1. _per material.map_を意味するので、テクスチャ変換はマテリアルに含まれますか? 残念ながら、マテリアルマップはたくさんあります。 ライトマップを除いて、すべてのテクスチャ変換が同じであると引き続き想定できます。

マップごとにmat3必要であり、 Textureプロパティから構成されている必要があると思います。

  1. ローテーションもサポートしますか? その場合は、回転中心も追加する必要があります。ただし、回転中心をテクスチャの中心に配線する必要がある場合を除きます。

回転はい。 中央にあるかどうか...わかりませんが、私が理解している限り、これはすべて、シェーダー用の単一のmat3にエンコードできます(マップごと)。

これは、 Matrix3をシェーダーに渡し、 offsetX 、 offsetY 、 repeatX 、 repeatY定義される変換を表す方法を示すプロトタイプです。 rotation 、 rotationCenterX 、およびrotationCenterY 。

centerがオプションとして許可されていない場合は、 ( 0.5, 0.5 )ハードワイヤードする必要があります。

コメントを歓迎します。

編集:デモを更新

rotateuvs

これは素晴らしい! :+1 :: + 1:

ただし、( offsetとrepeat代わりに) translationとscaleを使用すると思います。

正確には、新しい材料特性はどうあるべきですか? マテリアルマップはたくさんあります。

テクスチャプロパティから何を削除する必要がありますか?

wrapS/Tはテクスチャに残っているはずだと思います。

texture.offsetとtexture.repeatを削除する必要があると思います。

新しいプロパティは... texture.translation 、 texture.rotation 、 texture.scale 、 texture.center 、 texture.matrix必要があると思います。 おそらく、レンダリング時に呼び出されるtexture.updateMatrix()メソッドも必要になります。 もちろん、これには、テクスチャが再利用されている場合でも、一度だけ実行するようにするという課題があります。

この投稿のタイトルとhttps://github.com/mrdoob/three.js/issues/5876#issuecomment-69483293の議論を参照して、ポイントはこれらのプロパティをマテリアルに移動することだと思いました。

コメントは/ ping @ bhouston 。

私の考えでは、テクスチャのオフセット/リピートは可能な限りUVにベイクする必要があります。 それは容易です。 これは、UE4 / Unity5がほとんどの場合それを行う方法です。

例外は、Unity 5には、すべてのテクスチャで共有されるマテリアルごとに1つのグローバルオフセット/リピートを指定する機能があることです。ただし、ライトマップやアンビエントオクルージョンマップなどのベイク処理されたマップと見なされるものには影響しません。調整しても意味がありません。)

ここで多くの柔軟性を主張しない理由は、プロが作成したモデルには適切なUVがあるため、これは通常必要ありません。コンテンツ作成ツールにはこれをベイク処理する方法があります。 もう1つの問題は、WebGLのフラグメントユニフォームの下限が途方もなく低いことです(16 Vec4)。 マップごとに繰り返し/オフセットが必要で、すぐに多くのマップを取得する場合は、フラグメントユニフォームをほとんど価値のないものとして無駄にしています。

最近、Clara.ioにリピート/オフセットを追加してから、テクスチャごとに明るさ/ゲインコントロールを追加しました。これは、すべてのApple iOSデバイスなどのローエンドデバイスでフラグメントユニフォームがオーバーフローする原因となるため、これらの変更を元に戻します。 リピート/オフセットと明るさ/ゲインを持つことはNVIDIA980sを搭載したデスクトップでうまく機能しますが、ハイエンドマシンではなく、すべての人のために設計する必要があります。 ;)

フラグメントユニフォームは敬意を持って扱い、必要な場合にのみ使用する必要があります。 これはそのようなケースの1つではないと私は信じています。

例外は、Unity5にはマテリアルごとに1つのグローバルオフセット/リピートを指定する機能があることです。

これは基本的にthree.jsが現在行っていることですが、ディフューズマップからオフセット/リピートを取得し、他のすべてのマテリアルテクスチャはそのマップの設定を使用します。

提案は、テクスチャからオフセット/リピートを削除し、代わりにそれをマテリアルに追加することです-おそらく名前を変更します。 繰り返しになりますが、すべてのマテリアルテクスチャは同じ設定を共有します(一部のユーザーはそれに満足していませんが)。 これにより、均一な使用量を低く抑えることができます。

残念ながら、これについてはあまりコンセンサスが得られていません。

Unity5が行っていることを行うことは良い考えです。 テクスチャの代わりに素材にも貼っています。 あなたは私のサポートがあります。

マップごとは実際には理想的ではありませんが、必要に応じて、マテリアルの作成時にフラグ/キーで指定することで解決できます。

一般に、シェーダーでUVを変更する唯一の理由は、UVをアニメートするためです。 UVを静的に変換したいだけの場合は、この機能を追加するためにシェーダーを変更するべきではありません。

シェーダーに提案されている唯一の変更は、置き換えることです

vUv = uv * offsetRepeat.zw + offsetRepeat.xy;

と

vUv = ( uvTransform * vec3( uv, 1 ) ).xy;

Ok。 これはどうですか... texture.dynamic (デフォルトではfalse )を追加すると、次のようになります。

vUV = uv;

ユーザーがtexture.dynamicをtrue texture.matrixすると、 texture.translation 、 texture.rotation 、 texture.scale 、およびtexture.center texture.matrix計算されます。 texture.center 、それをプログラムに渡し、以下を生成します。

vUv = ( uvTransform * vec3( uv, 1 ) ).xy;

もちろん、 texture.dynamicが変更された場合は、プログラムを再コンパイルする必要があります。

そうすれば、両方の長所を活かすことができますか?

@mrdoob

  1. あなたの見解では、 scaleはテクスチャのプロパティですか、それともtexture.scaleはマテリアルのプロパティですか? それがこのスレッドのすべてであるため、後者であることを願っています。
  2. .matrixプロパティは必要ありません。 新しいMatrix3は、マテリアルユニフォームoffsetRepeatを置き換えるユニフォームです。 レンダラーの他のパラメーターから計算され、他のユニフォームと同じようにGPUに渡されます。
  1. あなたの見解では、 scaleはテクスチャのプロパティですか、それともtexture.scaleはマテリアルのプロパティですか? それがこのスレッドのすべてであるため、後者であることを願っています。

私はこのスレッドに同意しません。 mapMatrix 、 envMapMatrix 、...またはmapTranslation 、 mapRotation 、 mapScale材料を汚染するべきではないと思います。 THREE.Textureにtranslation 、 rotation 、 scale 、そしておそらくcenterあれば、もっときれいだと思います。

  1. .matrixプロパティは必要ありません。 新しいMatrix3は、マテリアルユニフォームoffsetRepeatを置き換えるユニフォームです。 レンダラーの他のパラメーターから計算され、他のユニフォームと同じようにGPUに渡されます。

そのようなものが必要です。 異なるマップで同じテクスチャを再利用するとします。 すべてのインスタンスについてMatrix3を計算する必要はありません。

私はこのスレッドに同意しません。 mapMatrix、envMapMatrix、...またはmapTranslation、mapRotation、mapScaleでマテリアルを汚染するべきではないと思います。 THREE.Textureに平行移動、回転、スケール、そしておそらく中央があると、よりクリーンになると思います。

異なる繰り返しプロパティを持つために、テクスチャを複製する必要がありますか? 小さなシーンでは、これはおそらく大したことではありませんが、すでに40以上のテクスチャが存在する大きなシーンでは、これは記憶の悪夢です。

@titansoftime imageはTHREE.Textureから切り離す必要があります。 理想的には、1つのTHREE.Image 、それぞれ異なるtranslation 、 rotation 、...構成の異なるTHREE.Texture使用できます。

@titansoftime画像は

それは理にかなっている。 texture.clone()はすでにこのように機能しますか、それとも手動で設定する必要がありますか?

texture.clone()はそのように機能しますが、 WebGLRendererは画像が同じであることを認識できないため、テクスチャのアップロードは不要です...

私はこのスレッドに同意しません。 mapMatrix、envMapMatrix、...またはmapTranslation、mapRotation、mapScaleでマテリアルを汚染するべきではないと思います。 THREE.Textureに平行移動、回転、スケール、そしておそらく中央があると、よりクリーンになると思います。

これは基本的に私たちが今していることです。 各テクスチャには独自のoffsetプロパティがあり、個々のオフセットは尊重されません。レンダラーは、マテリアルの各マップに同じオフセットを使用します。

FWIW、 https: //github.com/mrdoob/three.js/issues/5876#issuecomment-69483293で言ったことを実行する必要があると思います。

APIが@jcarpenterがやりたいことを実行できない理由がalphaMapのオフセットをアニメーション化する一方で、 mapは同じままです)。 キャンバスでそれを行うこともできますが、それは代わりにGPUのタスクだと思います。

さまざまなマップのオフセットで遊ぶことでできることはたくさんあります... alphaMapのみをオフセットする、 normalMapスケーリングするなど

マテリアルごとにuvTransform 1つしかないことは、非常に制限されているようです。

あ、ちょっと待って。 なぜ皆さんが素材ごとに好むのか理解できたと思います。 このようにして、フラグメントシェーダーでピクセルごとのUVを計算する代わりに、頂点シェーダーで単一のvUvが計算されます。 右?

オフセットは実際にはマテリアルのユニフォームを使用して実装され、テクスチャとは関係がないため、マテリアルごとが理想的です。したがって、作成する必要のあるマテリアルごとのユニフォームを変更する必要がある場合は、無意味な回避策になります。大量の新しいオブジェクト/テクスチャ(JSではかなり悪い/ WebGLではひどい)は、ユーザーから隠されているマテリアルユニフォームの単なる機能である何かを制御するためだけのものです。 テクスチャの一部を有利、効率的、またはさらに明確にすることは決してありません。これは、実行時に変化するUVを指定する1つの実際のアプリケーションであるアニメーションが、APIのために遅く非効率的にレンダリングされることを意味します。

テクスチャは、画像、およびその画像に関連するすべてのものを指定する必要があります。 UVオフセットは、画像/画像のプロパティとは関係がなく、テクスチャを表示するマテリアルと関係があります。マテリアルの一部でない場合でも、この機能を使用するのは意味がありません。インスタンス、および多くの場合、実際に機能を使用したい場合は、同時に多くのテクスチャを更新します。

アニメーションタイルのフレームごとに異なる画像があり、そのタイルのオフセット/リピートを制御したいとします。 彼らはすべての着信フレームをオフセットで更新する必要があり、そのタイルを使用するマテリアルの一意のインスタンスごとにすべてのフレームのコピーを持っている必要があります。実際には制御しているだけの何かのために、数百の新しいオブジェクトと追加の割り当てにすばやく雪だるま式になります。正当な理由もなく、これらすべてのオブジェクトを使用して、舞台裏でマテリアルごとにいくつかのフロートがあります。

マップごとの変換については、それは良いことですが、変換を一意にするか、共有するか、動的にするかを制御する複雑なAPIがある場合を除いて、ほとんどの場合、均一なコストは理由もなく高すぎます。IMOその制御を行うことは良いことですが、慎重に検討する必要があります。

あ、ちょっと待って。 なぜ皆さんが素材ごとに好むのか理解できたと思います。 このようにして、フラグメントシェーダーでピクセルごとのUVを計算する代わりに、頂点シェーダーで単一のvUvが計算されます。 右?

いいえ。UVはいつものように頂点シェーダーで計算されます。

スプライトシートと20個のスプライトを想像してみてください。 現在、 http://threejs.org/examples/misc_ubiquity_test2.htmlのように、20個のクローンマテリアルと20個のクローンテクスチャが必要SpriteMaterial.rotationがあることに注意してください。)

オフセットをマテリアルに移動すると、20個のクローンマテリアルと1個のテクスチャが必要になります。

実際、オフセットをスプライトに移動するには、1つのマテリアルと1つのテクスチャが必要になります。

スプライトシートと20個のスプライトを想像してみてください。 現在、20個のクローンマテリアルと20個のクローンテクスチャが必要です。

ああ、私はこのユースケースを考慮していませんでした。 ありがとう!

これについて考えます...

私はテクスチャのUV変換ではないことを提唱しています。

2つの理由:(1)混乱している、(2)伝播するイベントが多い、(2)無駄である。

混乱:理由は、メインマップにUV変数が1つしかないためですが、テクスチャの1つにUV変換がある場合、このUV変換が最初のUVを使用するすべてのマップに適用される可能性があることは混乱を招きます。他のテクスチャに変換があるかどうかに関係なく、チャネル。 各マップがマテリアルに独自のUV変換を持つことを許可した場合、テクスチャに関連付けられたUV変換でより問題ありませんが、フラグメントが均一に使用されるため、これを行うのは困難です。

その他のイベント伝播:Clara.ioで遭遇したもう1つの問題は、テクスチャパラメータをアニメーション化しようとしたときのイベント伝播です。 各テクスチャを使用している各マテリアルを追跡し、それらのマテリアルに汚れているため再計算する必要があることを伝えるために、各テクスチャが必要です。 これを行うことは不可能ではありません、ただより多くの仕事。

無駄:もう1つの問題は、3Dモデルまたはスパイトのインスタンスが複数あり、それらがすべて同じアニメーションテクスチャを持っている場合です。 その場合、テクスチャデータ自体が同じであっても、異なるアニメーションを作成するために、メモリ内にテクスチャの個別のコピーを用意する必要があります。 その意味で、UV変換データをマテリアルに配置するのに比べて少し無駄です。

したがって、マテリアルごとに許可されるUV変換が1つしかない場合は、それをマテリアル自体に配置します。 Unity 5モデルに従い、UVオフセット、マテリアルの回転があります。 ゲーム開発者はすでにこのアプローチに精通しています。

スプライトは、マテリアルのUV変換によっても適切に処理されると思います。これは、上記の3Dモデルの場合と非常によく似ています。

Having only one uvTransform per material seems very very limiting.

ここで完全に同意します。 この機能がないことは非常に制限されます。 ここで提供できる素晴らしい効果がありますが、すべてのオフセットが一緒にロックされているためではありません。

しかし、クローンを窒息させることなく、この機能をどのように利用できるようにすることができますか?

テクスチャではなくマテリアルに値を設定することは、すべてのテクスチャが一致する一般的なユースケースにとって意味があると思います。

ここで完全に同意します。 この機能がないことは非常に制限されます。 ここで提供できる素晴らしい効果がありますが、すべてのオフセットが一緒にロックされているためではありません。

しかし、クローンを窒息させることなく、この機能をどのように利用できるようにすることができますか?

THREE.ShaderMaterialまたはTHREE.RawShaderMaterialはこの機能を提供します。現在、通常のマテリアルでは機能しないため、このルートを使用する必要があります。

もっとファンキーなことをしているのなら、マップのリピートとオフセットを個別に調整するよりもファンキーだと思うので、とにかくこのように傾くでしょう。

+1、みんな。

巨大なスプライトシート(別名アトラス)があり、そのテクスチャを複数のTHREE.Spriteインスタンスで再利用したい場合に非常に便利です。

これに関するニュースはありますか? この問題はまだAPIのかなり明白な欠陥です。 ほとんどのマップタイプには未使用のオフセット/リピートがあり、イベントの伝播により、平面上のアニメーションスプライトのようなものが必要以上に遅くなり、メモリが重くなります。

アニメーションマップの柔軟性は、現在のシステムには存在しません。 設定を素材に結び付けることで柔軟性を低下させるという議論が続いています。 この柔軟性は現在のシステムには存在しないため、この議論は議論の余地があります。 マテリアルのオフセット/リピートはグローバルにのみ設定でき、拡散マップ(?)から取得されます。 これにより、使用中のほとんどのマップに冗長な「オフセット」/「リピート」設定があり、アニメーションのテクスチャを共有できない場合は常にクローンを作成する必要があるため、柔軟性が大幅に向上するというさらに悪い問題が発生します。削減。 各テクスチャ/マップに一意のオフセットがあることを期待しますが、現状ではこれは不可能です。ほとんどの場合、法線/スペックでオフセットを同じものに設定するのは面倒なので、実際には1セットのUVオフセットが必要です。 / diffuse(固定された拡散マップ上で法線マップをスクロールすることは、シェーダーマテリアルを使用できるニッチな用途です)。

構築されている実際のシェーダーを見ると、テクスチャオフセット/リピートはマテリアルに関連付けられていますが、1つのマップから奇妙にコピーされており、決して制御することはできません。 材料は、冗長性なしに高速でエレガントであるために、これを制御する必要があります。

両方の長所は、たくさんの追加のフラグで可能ですが、これらの種類の特定のエッジケースの代わりにシェーダーマテリアルを使用するようにユーザーに指示するよりも、これが優れたソリューションだとは思いません。

これに対する解決策は、 @ sunagのNodeMaterialところでです。

また、これに私の+1を追加します! スプライトシートでの作業がはるかに良くなります。

:+1:これは驚くべきことだと思いました。 繰り返されるすべてのスプライトが互いにアニメーション化されていたため、ゲーム内の各スプライトのテクスチャの複製を開始する必要がありました。 このように聞こえますが、冗長なスプライトデータをGPUにロードしていますか?

この問題の回避策はありますか? テクスチャインターフェイスをバイパスして、シェーダーにユニフォームを直接設定することで、UVオフセットを操作することは可能でしょうか?

これに対する解決策は、 @ sunagのNodeMaterialところでです。

@bhouston 、リンクを@sunagのアカウントの下に公開リポジトリはありません。

@ rhys-vdwこれはdevブランチにのみあります:

https://github.com/mrdoob/three.js/tree/dev/examples/js/nodes

これは新しいため、スプライトで使用する準備ができているかどうかはわかりませんが、完全にグラフベースのシェーダーシステムであるため、テクスチャアクセスを任意に変更できる柔軟性が得られます。

これは新しいため、スプライトで使用する準備ができているかどうかはわかりませんが、完全にグラフベースのシェーダーシステムであるため、テクスチャアクセスを任意に変更できる柔軟性が得られます。

@bhouston Nodeを使用して例を作成できますが、これは良さそうです。

THREE.SpriteMaterialについては、オフセット/スケールにアクセスしてspritesheetを作成できます。たとえば、次のようになります。

var offsetX = frameX / mapWidth;
var scaleX = mapWidth / frameWidth;

sprite.material.map.offset.x = offsetX;
sprite.material.map.repeat.x = scaleX;

https://github.com/mrdoob/three.js/blob/master/src/renderers/webgl/plugins/SpritePlugin.js#L53

ノードベースのシステムは修正されていません...それでもAPIの問題に対処していません。 マテリアルプロトタイプにオフセット/リピートを追加し、レンダラーにテクスチャの代わりにそれを読み取らせるには2秒かかります。 私は自分のプロジェクトですでにそれを行っていますが、APIに明らかな欠陥が残っているため、一般的なことをしようとした場合にこの問題が発生する新しいユーザーの頭痛の種を防ぐために、正式に変更する必要があります。

...したがって、テクスチャアクセスを任意に変更できる柔軟性が得られます。

tbhそれが何を意味するのかわかりません。 マテリアルごとに「オフセット」と「リピート」の個々のセットシェーダーユニフォームをアニメートします。

THREE.SpriteMaterialについては、オフセット/スケールにアクセスして、たとえばこれを使用してスプライトシートを作成できます...

@sunag 、おそらく問題は明確ではありません。 共有したコードは、そのマテリアルのすべてのインスタンスで共有されるテクスチャを変更します。 つまり、2つのマテリアルでテクスチャを共有することは不可能ですが、一意のオフセットがあります。たとえば、2つの敵のスプライトが異なるアニメーションフレームを表示します。

私は自分のプロジェクトですでにそれを行っていますが、APIに明らかな欠陥が残っているため、一般的なことをしようとした場合にこの問題が発生する新しいユーザーの頭痛の種を防ぐために、正式に変更する必要があります。

@QuaziKbプロジェクトのターゲットにできるPRはありますか?

@WestLangleyが言ったように、次のことが当てはまる場合、このすべてが問題になることはありません。

現在のアプローチを維持する場合、変更が必要なことの1つは、テクスチャのクローンを作成するときに、共有イメージをGPUに1回だけ渡す必要があることです。

あれは正しいですか?

@sunag 、おそらく問題は明確ではありません。 共有したコードは、そのマテリアルのすべてのインスタンスで共有されるテクスチャを変更します。 つまり、2つのマテリアルでテクスチャを共有することは不可能ですが、一意のオフセットがあります。たとえば、2つの敵のスプライトが異なるアニメーションフレームを表示します。

うーん、このNodeMaterial確かに解決するので、同じテクスチャを異なるマテリアルと独立したuvオフセット、およびカスタマイズされたフィルタやノードベースのマテリアルが提供できるその他のものなどの利点と共有できます。

https://github.com/mrdoob/three.js/issues/7522

しかし、現時点では、誰かが次のようにuuidをインスタンス化しようとしました。

THREE.Texture.prototype.createInstance = function() {

    var inst = this.clone();

    inst.uuid = this.uuid;
    inst.version = this.version;

    return inst;

}

needsUpdateを使用する場合は、すべてのインスタンスversionも更新します。

例:

var uniqueTextureOffset = map.createInstance();
var material = new THREE.SpriteMaterial( { map: uniqueTextureOffset } );

同じuuidを維持すると、 versionはGPUでtextureを共有します。

https://github.com/mrdoob/three.js/blob/master/src/renderers/WebGLRenderer.js#L2832
https://github.com/mrdoob/three.js/blob/master/src/renderers/webgl/WebGLProperties.js#L11

私にとっては暫定的な解決策ですが。 私は将来のためにNodeMaterialを信じています。

UV変換をマテリアルに移動できますか?

両方の長所はどうですか。 マテリアルにフラグoverrideOffsetRepeatを追加し、マテリアルに新しいuvOffsetとuvRepeatを追加します。 このように、フラグがfalseの場合、下位互換性があり、それがデフォルトです。 そしてそれが本当なら、それは材料のオフセット/リピートを使用します。 ニーズが強く、広範囲に及んでいるように思われるので、私はこれを支持します。 @WestLangley? @mrdoob?

(私は今後すべてにNodeMaterialの使用を本当にサポートしますが、それに切り替えるのは面倒です。)

私はまだこれに対する解決策はTHREE.Imageを作成することだと思います。 https://github.com/mrdoob/three.js/issues/5876#issuecomment -81189892

THREE.Image

@mrdoob 、つまり、割り当てられた各TextureがMaterialと一緒に複製されるということですか?

@mrdoobは書いた:

私はまだこれに対する解決策はTHREE.Imageを作成することだと思います

はい、それは機能しますが、下位互換性は少し低くなりますが(テクスチャを作成する前に全員に画像を作成する必要がある場合)、全体的なデザインはよりクリーンになります。 個別に指定しなかった場合、テクスチャごとに画像を自動的に作成することは可能かもしれません。そうすれば、下位互換性が実現しますか? また、トリッキーなことをしたい場合にのみ、画像を直接操作する必要があります。

このソリューションでは、スプライトのセットに2倍の新しいオブジェクトが必要になると思います。スプライトごとに1つのテクスチャ、1つのマテリアルですか。 スプライトごとに新しいマテリアルが必要になる他のアプローチはどこにありますか?

Unityがマテリアルごとのリピート/オフセットをサポートしていることは知っていますが、3DS Max、Maya、SoftimageなどのハイエンドVFXツールはサポートしていません。ビットマップノードとテクスチャノード(ビットマップノードとUVマッピングの両方を含む)だけがあります。 nod)、これは@mrdoobの設計に似ています。

UE4も@mrdoobが提案しているものと似ており、ビットマップローダーである「テクスチャ」ノードがあり、さまざまなタイプのUVマッピングを行うための一連のUVマッピングノードがあります。

高度なツールは、テクスチャからイメージ/ビットマップを分割し、次の形式で個別のUVマッピングノードも分割します。

 -> Bitmap
 -> UVMapping

現在、メインのStandardMaterialでは多くのUVMappingオプションを許可していません。 ただし、UE4、Maya、Softimage、3DS Maxで使用されるさまざまなタイプのUVMappingは、使用するチャネル、それに適用する変換、ソースとして世界座標を使用するか、球形、立方体、平面投影を行う必要があるかどうかです。それらのプロジェクションに必要なパラメータに基づいています。

UE4には、マテリアル内での繰り返し/オフセットを可能にするスプライトテクスチャがあります。

https://docs.unrealengine.com/latest/INT/Engine/Paper2D/Sprites/index.html

Maya、Softimage、3DS Max、およびUE4は、 @ mrdoobが示唆しているように、ビットマップ/イメージをテクスチャ(およびUV生成)から分離していますが、これらはすべてシェーダーグラフを使用してこれを実現しています。 シェーダーグラフを持たないUnity3Dは、オフセット/リピートをマテリアル自体に組み込むツールです。おそらく、シェーダーグラフノードに適切に分離できないためです。

個別に指定しなかった場合、テクスチャごとに画像を自動的に作成することは可能かもしれません。そうすれば、下位互換性が実現しますか? また、トリッキーなことをしたい場合にのみ、画像を直接操作する必要があります。

まさに😊

おそらく少しおかしな話ですが、できるだけ早くPTEXを組み込むことをお勧めします。
http://ptex.us/PtexFile.html
典型的なプロジェクションなどをNodeTexture(?)にキャスト/変換する方法がある場合、または新しいより強力で包括的なベースレベルテクスチャマッピングシステムであるオプションがありますか? ...それなら、それは前もって考慮すべきことかもしれません。
[さらに同じ点:]
ptexの概念は、実際には2D画像ではなく、UV関係であるため、2Dを3Dに変換する方法の概念/課題なしに、複雑な表面の周りにペイント/スタンプ/投影できます。これは、数学的には、比較するとせいぜいハックです(常に技術的に破壊と戦っています)。
20年以上前は、ptexの方が理にかなっており、優先事項であり、拡張機能や2番目のクラスのパフォーマーと見なされるべきではないことを指摘しましたが、実際にはその逆です。 これは、2D画像がptexの1つの真の常に機能する基本レベルシステムにどのように投影/スタンプされるかを宣言的に言う古い独自の方法である必要があります。 とにかく、より中心的な役割を担うのが最善ではないにしても、それを統合する必要があるという考えを強制するだけです。
高尚な提案をする機会をありがとう。 ptexが仕様に合わせて作られたのはとても嬉しかったです。 10年以上前に自分で考えましたが、子供の頃は新しいスペックなどを定義する力がありませんでした。後から考えると、今でも維持しているオブザーバーの役割ではなく、違いを生むことができたのではないかと思いました。 だからここに長年の間違いを元に戻す試みがあります。

Fluxで潜在的に現在のメソッドをより深く理解している人が、THREEjsでどのように機能するかについてより適切な提案を行うことができれば、誰かが新しいスレッドを開始できるかもしれません。
もう一度聞く機会をありがとう。

@MasterJamesのようなオフトピック...新しいスレッドを作成してください?

「テクスチャ」を使用できるように画像を作成したとしても、実際には複数のuvオフセット/リピートをサポートしていないため、すべてのマテリアルを書き直す必要があります。 明らかにこれは変わる可能性がありますが、冗長なユニフォームが必要になるため、おそらく複雑さが増すことになります(たとえば、法線マップがディフューズからオフセットされるように、複数のオフセット/リピートのセットが必要になる頻度)パフォーマンスがプレミアムであるWebの場合、最も一般的な使用例は、すべてのマップに影響するグローバルオフセット/リピートが1つある場合です。これは、最終的にマテリアルアーキテクチャの一部になるため、マテリアル上にあることは理にかなっています。 カスタムシェーダーマテリアルは、エッジケースを問題なく処理できます。

@QuaziKbうん。 それがNodeMaterial取り組むことです。

Textureが各.clone()に同じOpenGLテクスチャインスタンスを使用しているのではないでしょうか、それとも何かが足りないのでしょうか。 実際にクローンごとに再アップロードしていますか? その場合、これは_非常に_深刻な問題です。

@evrimoztamur 、毎回テクスチャをコピーすると思います。 WebGLInspectorを使用して何が起こっているかを確認できます。

@sunagの回避策を含め、考えられるすべてのアプローチを試しましたが、何も機能しませんでした。 結果が得られなかった私の実験と上記の議論に基づいて、他のライブラリがスプライトアニメーションをどのように処理するかを調べました。 Babylon.jsのSpriteおよびSpriteManagerAPIは、私の特定のニーズに応えるソリューションであることがわかりました。 スプライトシート、オフセットとリピート、およびアニメーションを処理します。 たぶん、これはTHREE.jsが提供することを目的とするよりも高いレベルの抽象化ですが、参照として一見の価値があるかもしれません。

@ rhys-vdw:現在のプロジェクトでは、MeshBasicMaterialのろくでなしバージョンになりました。
https://gist.github.com/karimbeyrouti/790d2e1a8c0137b16bae

マップを設定すると、オフセット/リピートユニフォーム(隠れたマテリアルにある)が自動的に割り当てられます。 それらを個別に簡単に設定できます。これにより、今のところテクスチャのクローンを作成する必要がなくなります。 (r73での作業)

この問題に対処する必要のあるPR、PR#8278を提出しました

@WestLangleyは書いた:

次のマップが同じオフセット/リピート値を持っていると仮定するのは合理的だと思います。

地図
specularMap
normalMap
バンプマップ
alphaMap
aoMap(将来)
光沢マップ(将来)
変位マップ(将来)

常にではない。 私は現在、同じマテリアル(アスファルト)上のマップとバンプマップに異なる繰り返し値を使用して、両方がかなり小さいタイルでタイルされているという事実を隠しています。 そうすれば、大きなテクスチャを生成/持つ必要がありません。 とても便利です。 :-)

編集:まあ、それは少なくとも私がやったと思ったことです。 トリックはおそらく無視されました。 そして、シェーダーなどにノイズを追加することで、同様の結果を得ることができます。 WestLangleyのMatrix3デモはかっこいいです。

これにより、スプライトのUVが異なるインスタンスの問題が解決されると思います。 同じテクスチャを維持しながら、 vertexとpixel shaderを変更することができます。

https://threejs.org/examples/#webgl_sprites_nodes

SpriteNodeMaterialとMeshを共有PlaneBufferGeometryます。 インターフェイスはSpriteは適していませんが、機能します。 たぶんそれはSpriteMeshに進化して、インターフェースをより親しみやすくすることができます

このスレッドは私にとってTL; DRです。 しかし、私はちょうど今、r68でこのコードを発見しました(古いプロジェクト、うん):

        // uv repeat and offset setting priorities
        //  1. color map
        //  2. specular map
        //  3. normal map
        //  4. bump map
        //  5. alpha map

        var uvScaleMap;

        if ( material.map ) {

            uvScaleMap = material.map;

        } else if ( material.specularMap ) {

            uvScaleMap = material.specularMap;

        } else if ( material.normalMap ) {

            uvScaleMap = material.normalMap;

        } else if ( material.bumpMap ) {

            uvScaleMap = material.bumpMap;

        } else if ( material.alphaMap ) {

            uvScaleMap = material.alphaMap;

        }

        if ( uvScaleMap !== undefined ) {

            var offset = uvScaleMap.offset;
            var repeat = uvScaleMap.repeat;

            uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );

        }

だから、ええ...

ここで提案したような根本的な変更をライブラリに提案する場合は、その変更について明確で説得力のある議論を提供する必要があります。

拡散反射光マップと法線マップで異なるリピートを設定しようとしていて、機能しなかったために髪を抜いてみました。 APIはこの設定をテクスチャに配置するので、私はそれができると思いました。 そうです、説得力のある議論のために私の髪を保存するのはどうですか? このチケットはまだ開いており、3jsはまだテクスチャにこの設定を持っており、テクスチャの1つに対してのみ尊重されます=これは事実上、すでにマテリアルごとの設定です。

これを所属する場所に移動しない場合は、少なくともドキュメントでは効果がないと言いますか?

@sunag PRの場合:
https://github.com/mrdoob/three.js/pull/11531

私が遭遇した1つの問題:
https://jsfiddle.net/f0j2v3s8/

SpriteNodeMaterial透明度が失われているようです。この例を機能させるために使用できる、ブレンドの組み合わせはありません。

何か案は?

@karimbeyroutiは書いた:

マップを設定すると、オフセット/リピートユニフォーム(隠れたマテリアルにある)が自動的に割り当てられます。 それらを個別に簡単に設定できます。これにより、今のところテクスチャのクローンを作成する必要がなくなります。 (r73での作業)

uniforms.offsetRepeatがuniforms.uvTransform (r88)に変更されたため、これは廃止されたと思います。

「複数のObject3Dインスタンスでテクスチャアトラスを再利用する」ユースケースに関しては、簡単なウォークアラウンドをお勧めします。

  1. UVデータ(オフセット、リピート)をアトラスjsonオブジェクトに保存します。
  2. Object3DのonBeforeRender\onAfterRender関数ペアをフックします。
  3. before renderコールバックで、atlas jsonオブジェクトからUVデータをロードし、material.mapに設定します。
  4. アフターレンダーコールバックで、リセットし直します。

結果は次のようになります。

  1. 複数のオブジェクトによって共有される1つのテクスチャと1つのマテリアルのみ、クローンは不要であり、info.memory.texturesカウンターは増加しません。
  2. ただし、他のすべてのマップ(normal、ao、displacement ...)は、同じUV変換に準拠する必要があります。
このページは役に立ちましたか?
0 / 5 - 0 評価