Troika: テキストの概要

作成日 2020ĺš´08月20日  Âˇ  39コメント  Âˇ  ソース: protectwise/troika

テキストを読みやすくするために、白いテキストの周りに黒いテキストのアウトラインを配置する方法を見つけようとしています。 よくわかりませんが、troika-three-textを処理するためにシェーダーを使用する必要があるようです。 この効果を達成する方法について、いくつかのガイダンスを提供できますか?

ありがとう!

最も参考になるコメント

Mapbox、@ anzorbに関する情報をありがとう。 私は間違いなくそれらの実装をより詳細にチェックしますが、そのブログ投稿(彼らはアウトラインを「ハロー」と呼んでいます)から、彼らは前に述べたようにSDFアルファしきい値アプローチを使用しているようです。 ただし、SDFの生成とアトラスのパッキング戦略は私のものとは異なり、グリフごとの距離フィールドサイズが不均一であるという同じ問題はありません。 ただし、おそらく同じ最大アウトライン幅の制限があります。

私は実際に、標準の派生物を使用して_screenspace_アウトラインでいくらかの進歩を遂げました。 アウトラインを意味する画面スペースは、テキストのサイズ/スケールまたは斜め度に関係なく、たとえば1画面ピクセル幅になります。 目標が背景とのコントラストを追加することだけである場合、テキストサイズに合わせて拡大縮小するアウトラインと同じくらい良い(またはそれよりも好ましい)ように思われます。 それについて意見はありますか?

全てのコメント39件

色を付けることができれば、必要なことはdebugSDFフラグによって達成されると思います。
image
sdfを表示すると、基本的に、色を付けたり、サイズを調整したり、少し鮮明にすることができれば、おそらく機能するアウトラインが得られます。

これを行うのはそれほど難しいことではありません。 少し前にtextOutlineを機能として使い始めましたが、終了しませんでした。

理論的には、グリフエッジは、エッジに対応する符号付き距離フィールドの値を変更するだけで拡張できます。 これは、現在のシェーダーコードでは0.5ですが、ユニフォームとして渡すことで構成可能にすることができます。

理想的には、シェーダーは1回の描画呼び出しで通常のグリフとその周囲のアウトラインの両方の描画を処理できるため、アウトラインの幅(これがどの単位になるかわからない)との色の2つの新しいユニフォームが必要になります。アウトライン領域。

少し前にtextOutlineを機能として使い始めましたが、終了しませんでした。

ネイティブでサポートされていればとても嬉しいです:)
ただし、シェーダーは初めてなので、どれだけ役立つかわかりません。 私はこの問題を注意深く見守っています。

私はこれに少し戻って、なぜ私が最初にそれを終えなかったのかすぐに気づきました。 SDFは輪郭を描くために使用できますが、いくつかの注意点があります。

  • アウトラインの潜在的な最大幅は、距離フィールド自体の範囲によって制限されます(64x64 SDFテクスチャで約8テクセル)。
  • SDFテクスチャは各グリフの境界に合わせてスケーリングされるため、これはすべてのグリフで一貫した視覚的サイズに対応していません。

したがって、「W」のような大きなグリフはかなり太い輪郭を得ることができますが、ピリオドのような小さなグリフは非常に細い輪郭しか得ることができません。 また、各グリフは、アウトラインを視覚的に一貫させるために、異なるSDFカットオフポイントを使用する必要があります。

これはまだ乗り越えられないと思いますが、最初に思ったほど単純ではありません。

@lojjic 、このライブラリが大好きです🥇、しかしテキストのアウトラインは私たちのプロジェクトの要件です...

私はこれに少し戻って、なぜ私が最初にそれを終えなかったのかすぐに気づきました。 SDFは輪郭を描くために使用できますが、いくつかの注意点があります。

  • アウトラインの潜在的な最大幅は、距離フィールド自体の範囲によって制限されます(64x64 SDFテクスチャで約8テクセル)。
  • SDFテクスチャは各グリフの境界に合わせてスケーリングされるため、これはすべてのグリフで一貫した視覚的サイズに対応していません。

したがって、「W」のような大きなグリフはかなり太い輪郭を得ることができますが、ピリオドのような小さなグリフは非常に細い輪郭しか得ることができません。 また、各グリフは、アウトラインを視覚的に一貫させるために、異なるSDFカットオフポイントを使用する必要があります。

これはまだ乗り越えられないと思いますが、最初に思ったほど単純ではありません。

興味があります。シェーダーを使用して、アウトラインやシャドウ効果を実現するために、ある種の後処理を実行できますか? 前もって感謝します!
これが私が達成しようとしている効果です:
Screen Shot 2020-08-31 at 4 32 03 PM

編集:これはmapbox glからのもので、SDFも使用していると思いますhttps://blog.mapbox.com/drawing-text-with-signed-distance-fields-in-mapbox-gl-b0933af6f817彼らのコードを分析して、彼らが何をしたかを確認します。 https://github.com/mapbox/mapbox-gl-js

Mapbox、@ anzorbに関する情報をありがとう。 私は間違いなくそれらの実装をより詳細にチェックしますが、そのブログ投稿(彼らはアウトラインを「ハロー」と呼んでいます)から、彼らは前に述べたようにSDFアルファしきい値アプローチを使用しているようです。 ただし、SDFの生成とアトラスのパッキング戦略は私のものとは異なり、グリフごとの距離フィールドサイズが不均一であるという同じ問題はありません。 ただし、おそらく同じ最大アウトライン幅の制限があります。

私は実際に、標準の派生物を使用して_screenspace_アウトラインでいくらかの進歩を遂げました。 アウトラインを意味する画面スペースは、テキストのサイズ/スケールまたは斜め度に関係なく、たとえば1画面ピクセル幅になります。 目標が背景とのコントラストを追加することだけである場合、テキストサイズに合わせて拡大縮小するアウトラインと同じくらい良い(またはそれよりも好ましい)ように思われます。 それについて意見はありますか?

標準化された幅は、スケーリング幅よりもはるかに優先されます。 このように、cssのように動作します。
cssを介して適用されるtext-shadowは、 font-sizeとは独立して構成されます。
提案されたソリューション@lojjicが同じように実行される場合、それは🎉🎉🎉になります

迅速な対応をありがとう@lojjic!

目標はコントラストを追加することであり、あなたの提案は素晴らしく見えます。 アウトラインが静的になるということですか? つまり、それを制御する方法はありません( @stephencorwinが説明したように、text-shadow-ishアプローチを使用します)。

正直なところ、1ピクセルが超高密度ディスプレイに表示されている限り、問題とは見なされません(現在、フォントサイズにデバイスのピクセル比を掛けて、密度に関係なく「同じ」比率を実現しているため) 、あなたの提案は、DPIの高いデバイスでは輪郭が目に見えて薄くなることを意味すると思いますね。

前もって感謝します!

あなたの提案は、DPIの高いデバイスではアウトラインが目に見えて薄くなることを意味していると思いますね。

はい、それはスクリーンスペースアプローチの1つの欠点です。 これは多くのシナリオでは問題ないかもしれませんが、設計者としてデバイス間で異なる外観を持つのは面倒です。

もう1つの大きな欠点は、(私が思うに)ハローの厚さを増やすと、より多くのテクスチャ読み取りが必要になるため、パフォーマンスに影響が出るということです。 しかし、私はこれを研究し続ける必要があります。

私もこの機能が必要です。 私は何年も前に開発したAndroidアプリにこのような機能を実装し、自分自身と友人のためだけに使用しました。 私はReactでこのアプリを再実装し始め、あなたのプロジェクトを見つけるようになりました。
他の人と同じように、私はこの図書館に感謝したいと思います。 びっくりしました。

より多くのテクスチャーの読み取りについてのあなたのコメントについて、私はあなたがそれほど心配するべきではないと思います。 必要な追加のテクセルは、隣接するフラグメントが必要とするテクセルになるため、とにかくGPUのキャッシュに入れられ、コストはほとんどかかりません。

入力@FunMilesをありがとう。 (コロラド代表!😄)

私はあなたがおそらく1、多分2つの断片の厚さの輪郭に正しいと思います。 私の懸念は、厚みが増すにつれて、テクスチャ読み取りの数(4 = 56読み取りの厚み?)と、それらの読み取りがより高価になる可能性の両方が爆発的に増加することです。 しかし、私はいくつかのことを読んで推測しているだけで、GPUの専門家ではありません。 私はおそらくそれを試してみる必要があります。

@lojjic (ここの北😄)フラグメントシェーダーのコードを見つけようとしました。 シェーダーを完全に作成するのではなく、変更するように見える(そしてどこかで読んだと思う)ので、物事を理解するのに苦労していることを認めます。
ただし、フルシェーダーがどのようなもので、実際にどのようにプラグインするのかはわかりませんが、コアルーチンの一部を取得できると思います...

ここで、 texture2D(uTroikaSDFTexture, vTroikaSDFTextureUV).r;を使用してピクセルのスカラー距離を読み取ります。 あなたが以前に書いたことを私が理解しているなら、1つの問題はグリフの周りのスペースに関係しています。 もっと詳しく説明してもらえますか?
「W」と「」の例に戻ると、テクスチャ内のvTroikaSDFTextureUVスパンは、グリフの周囲にぴったりとフィットしていますか、それともスペースが追加されていますか? フラグメントシェーダーは、現在のグリフのUVの境界を知っていますか? もしそうなら、外側に落ちるフラグメントについては、現在のUVを境界に投影し、データを内側に読み取ることができます。

最大で5つのテクセル読み取りまたは派生物を使用して何が必要かを理解することは可能だと思います(それらが利用可能かどうかを確認します)。

「W」と「」の例に戻ると、テクスチャ内のvTroikaSDFTextureUVスパンは、グリフの周囲にぴったりとフィットしていますか、それともスペースが追加されていますか?

各グリフの実際のパス境界の周囲には、距離フィールドの外側の部分を収容するのに十分な、わずかな余分なスペースがあります。 これはSDFの8テクセルですが、各SDFはさまざまなサイズのグリフクワッドにスケーリングされた均一な64x64であるため、その表示マージンはグリフごとに異なります。

フラグメントシェーダーは、現在のグリフのUVの境界を知っていますか? もしそうなら、外側に落ちるフラグメントについては、現在のUVを境界に投影し、データを内側に読み取ることができます。

その情報が利用可能であるはずです。 ただし、「現在のUVを境界に投影し、内部のデータを読み取りに行く」についてはフォローしていません。

テクセルの読み取りを減らして輪郭を太くする方法を知っていれば幸いです。 私はそれを次のように概念化しています:グリフパス内にないフラグメントの場合、放射状検索を実行して、r =内にフラグメントがあるかどうかを確認します。グリフパスに含まれます。 それはそれについて考える間違った方法かもしれません。

1つの問題は、グリフを並べて配置するとどうなるかです。 それはさておき、かなり太い輪郭で描かれた単一のキャラクターの場合を考えてみましょうt 。 キャラクターは、輪郭を収容するのに十分な大きさの長方形で描かれています。
フラグメントシェーダーには、 vTroikaSDFTextureUVとvTroikaGlyphUVの2つの主要な情報があります。

私の理解では、 vTroikaGlyphUVは、グリフ内で0から1の間にクランプされた値を持っています。 投影について話したときに意味したのは、 vTroikaGlyphUVがそれらの境界の外側にある場合、グリフ境界に「投影された」点の距離を取得できるということでした。 つまり、uv =(1.05、0.7)の場合、投影点は(1.0、0.7)になります。 (1.0、0.7 +イプシロン)および(1.0、0.7-イプシロン)の値を使用することにより、距離への勾配を取得し、それを使用して、(1.05、0.7)での近似距離を計算できます。
このために自分の仕事をしたとき、テクスチャにグラデーションを付けてSDFを実行している人の記事を読んだことも覚えています。 このアプローチでは、3つのテクセルを読み取る必要がありませんが、テクスチャが3コンポーネントのテクスチャになり、テクスチャの構築が複雑になります。

これはあなたの質問に答えますか?

これで、複数のキャラクターが並んでいる場合、それぞれが隣接するキャラクターを認識している必要があり、これが少し複雑になります。 現在のキャラクターだけでなく、隣人にもGlyphUVとTextureUVを携帯する必要があります。 これには、各文字を2つの長方形にカットする必要がある場合があります。これにより、隣接する文字は、最初の長方形では前に、2番目の長方形では後になることができます。 複数行の処理方法がわかりません。アプリケーションでその場合に対処する必要はありませんでした。 私のアプリケーションは地図で、各ラベルは1行でした。

PS:「各グリフの実際のパス境界の周りの余分なスペース」を誤解した可能性があります。 たとえば、Xの場合、それは長方形に囲まれていて、有効な値を持たない三角形が4つあると言っていますか?

@FunMiles私はあなたがどこに行くのかわかるかもしれません。 熟考するのに少し時間がかかりますが、現時点で焦点を当てる必要のある他の締め切り作業があります。

PS:ちょっとした楽しい数学のメモ:
誰かが2つまたは3つの整列したポイントから勾配を取得する方法を疑問に思った場合に備えて、距離の勾配には固定のノルムがあることを覚えておく必要があります(選択したスケールによって異なります)。 そして、グラデーションは間違いなくグリフボックスの外側を指しています。 したがって、たとえば、例の3つのポイント(1.0、0.7)、(1.0、0.7 +イプシロン)、および(1.0、0.7-イプシロン)がすべて同じ距離にある場合、勾配は(scale、0)になります。

確かにパフォーマンスは良くありませんが、オフセットを使用することは可能です。 私はreact-three-fiberを使用しています。これは、dreiパッケージでtroika-textを活用しますが、ライブラリがストロークをネイティブにサポートするまで、他の人が一時的な解決策を探している場合に備えて共有すると考えました。

import React from 'react';
import {Text} from 'drei';

const StrokedText: React.FC<
  {
    strokeWidth?: number;
    strokeColor?: string;
    strokeResolution?: number;
    bold?: boolean;
  } & any
> = ({
  strokeWidth = 1,
  strokeColor: color = '#000000',
  strokeResolution = 100,
  position,
  bold,
  ...props
}) => {
  const font = bold ? FONTS.BOLD : undefined;
  const sharedProps = {
    ...props,
    font,
    color,
    sdfGlyphSize: 12,
    debugSDF: true,
  };

  let zOffset = 0;
  const offset = () => (zOffset += 0.001);

  return (
    <group name="Stroked Text" position={position}>
      {Array(strokeWidth)
        .fill({})
        .map((_, i) => {
          const s= i / strokeResolution;
          return (
            <React.Fragment key={i}>
              {/* <Text {...sharedProps} position={[-s, 0, offset()]} />*/}
              {/* <Text {...sharedProps} position={[s, 0, offset()]} />*/}
              <Text {...sharedProps} position={[0, -s, offset()]} />
              <Text {...sharedProps} position={[0, s, offset()]} />
              <Text {...sharedProps} position={[-s, -s, offset()]} />
              <Text {...sharedProps} position={[s, s, offset()]} />
              {/* <Text {...sharedProps} position={[-s, s, offset()]} /> */}
              {/* <Text {...sharedProps} position={[s, -s, offset()]} /> */}
            </React.Fragment>
          );
        })}
      <Text name="Text" {...props} position={[0, 0, strokeWidth ? offset() : 0]} />
    </group>
  );
};

export default StrokedText;

その後、他の場所では、通常<Text /> <StrokedText />で呼び出すことができます。

<StrokedText
  color="#ffffff"
  fontSize={fontSize}
  clipRect={[-0.5, -0.15, 0.5, 0.15]}
  textAlign="center"
  position={[0, 0, 0.01]}
>
  {text}
</StrokedText>

image

@FunMiles私はついにあなたの提案を解析する時間がありました。 グリフのSDF長方形全体に、有用な(> 0.0)距離値が含まれていると仮定すると、これは理にかなっていると思います。 現在はそうではありません。 「x」についてのフォローアップでそれを認識していたと思います。ここでは、SDFがクワッドの境界内でゼロに十分に低下するため、外挿するための有用な距離勾配がない重要な領域があります。

image

おそらく、SDFジェネレーターを変更して、クワッド全体でゼロ以外の勾配を確保することを検討できます...? 大声で考えると、距離の精度に影響があり、アトラステクスチャ内のキャラクター間にアーティファクトが発生する可能性があります...🤔

おそらく、SDFジェネレーターを変更して、クワッド全体でゼロ以外のグラデーションを確保することを検討できます。

私はそれを試しましたが、そうです、距離フィールドをクワッド境界を超えて外挿することができますが、恐れていたように、グリフ自体の品質が大幅に低下します。 これは、8ビットのグラデーションだけで予想されます。 それをより長い距離に広げると、各テクセルの精度が低下します。 :(

おそらく、2番目のテクスチャチャネルにエンコードされたアウトライン(より拡散しているが精度の低いフィールド)に対して個別のSDFを生成することができます。 テクスチャサイズは2倍になりますが、大幅に遅くなることはありません。 🤔

2番目のテクスチャチャネルにエンコードされます。

@lojjicこれは非常に合理的に聞こえ、基本的に現在の私の回避策を模倣しています。 さらに、オプトインできるため、ユーザーがアウトラインを要求しなくてもパフォーマンスが低下することはありません。

@lojjic @stephencorwinによって提案されたオプトインアプローチは、誰も支払う準備ができている以上に支払うことがないようにします。

技術的な側面に戻ります。 応答でX画像を取りましょう。 すべてのグリフで64x64ピクセルであることを正しく理解していますか? 8ビットの場合、距離空間全体をエンコードする必要がある場合は、2_小数_ビットの精度があることを意味します。 この精度では不十分だとおっしゃっていると思います。

非常に少ないコストで精度を上げるために使用するトリックがあるかもしれません。 8ビットの64x64のグリッドを実行する代わりに、2x2ブロックのデータを32ビットデータに圧縮します。 2つのピクセル間の符号付き距離の明確な特徴の1つは、常に[-1,1]左右、上下、[-sqrt(2)、sqrt(2)]の対角線内にあることです。 したがって、2x2ブロックの中心のSDに12ビットを使用するとします。ピクセルの中心と2x2の中心の差をエンコードするために、ピクセルの中心ごとに5ビットが必要になります。 これらの5ビットは、最大でsqrt(2)/ 2の距離を表します。 事実上、5.5ビットの精度があります。
中心点の12ビットは、最大64の距離で少なくとも6ビットの精度をエンコードします。技術的には、ボックスのコーナーに1つのポイントしかない場合、12ビットは最大sqrt(2)* 64までエンコードできる必要があります。ボックスはすべてのグリフを中心に配置されていると考えられるため、実際には不可能だと思います。 実際、グリフエッジから離れると、デルタがエンコードする必要のある情報が少なくなります(グリフエッジから遠く離れている場合、勾配フィールドは近傍でほぼ均一になります)。したがって、情報理論の観点からは、エンコーディングを改善することが可能
より多くの実際の情報を取得するために....しかし、私はそのような追加の最適化から始めません。

このアプローチの興味深い結果の1つは、テクスチャリングハードウェアに補間を行わせないことです。 しかし、逆に言えば、無料でグラデーションを取得できます。

ヘルプが必要な場合は、これらすべてのエンコード/デコードを実装できます。

PS:README.mdの1つで、より洗練されたSDFについての議論を見た記憶があります。 私はそれを夢見ましたか? 😛誰かが私にそれを指摘して、他のシステムがここで役立つかどうかを確認できますか?

@FunMiles非常に巧妙な圧縮のアイデア。 他のオプションが失敗した場合は、それを覚えておきます。 ハードウェアによる線形補間を失うことは、私が行う必要のないトレードオフです。 😉

十分なビットがないという私の問題は、「ゼロ」距離として0.5を使用することで悪化することがわかりました。そのため、グリフの「外側」の距離をエンコードするために使用できるアルファ値は半分だけです。 これをシフトして、外側の距離に多くの値を使用し、内側の距離に少ない値を使用して、周辺の精度を上げることができます。

再。 「より洗練されたSDF」とは、複数のカラーチャンネルが使用される「MSDF」を意味する場合がありますか?

@FunMiles非常に巧妙な圧縮のアイデア。 他のオプションが失敗した場合は、それを覚えておきます。 ハードウェアによる線形補間を失うことは、私が行う必要のないトレードオフです。 😉

その補間を失うことを心配する必要はないと思います。 コストは非常に低いですが、ハードウェアのサポートがない場合に常に勾配(および少しの曲率)を持つことの利点は、私の見解ではより重要です。 実際には、サンプルポイントを丸めて、丸められたサンプルポイントへの新しいオフセット値を取得します。 アンチエイリアシングのためにフラグメントの部分的なカバーを計算することは、利用可能なグラデーションで通常行うのと同じように進行します。
十分なビットがないという私の問題は、「ゼロ」距離として0.5を使用することで悪化することがわかりました。そのため、グリフの「外側」の距離をエンコードするために使用できるアルファ値は半分だけです。 これをシフトして、外側の距離に多くの値を使用し、内側の距離に少ない値を使用して、周辺の精度を上げることができます。

これにより、せいぜい1ビットの精度が得られます。 くしゃみをする必要はありませんが、それでもそれほど重要ではありません。

再。 「より洗練されたSDF」とは、複数のカラーチャンネルが使用される「MSDF」を意味する場合がありますか?
それが私が意味したことです。 私はそれについてのGitHubプロジェクトをC ++で見つけました。 それを使うものはありましたか、それとも2週間前に調べたさまざまなものをマッシュアップして混乱しましたか?

ちなみに、MSDFは役に立たないと思います。
JavaScriptでSDFを構築する方法を説明する小さな.mdファイルを入手できるかどうか尋ねてもいいですか? これで、圧縮のアイデアを実装するためのコードを作成できると思います。

SDFはここで構築されます: https ://github.com/protectwise/troika/blob/master/packages/troika-three-text/src/worker/SDFGenerator.js#L134-ほとんど説明することはあまりありませんテクセルをフォント単位にマッピングし、測定された距離をテクセル値に書き込みます。 各2x2ブロックの中心点について、そこにいくつかの距離測定値を追加する必要があります。

私の脳をこれに完全に包み込もうとしています... GLSLで双一次補間を複製することは、4つの最も近い値が得られれば、十分に単純/安価に見えます。 圧縮スキームでエンコードされたときにこれらの値を取得するには、次のことが必要になると思います。

  • テクセルの真ん中にある場合:2つまたは3つのテクスチャサンプル
  • 2x2ブロックの4つのテクセルの間にある場合:4つのテクスチャサンプル
  • 2つの隣接するブロック間の場合:〜9テクスチャサンプル〜7または8テクスチャサンプル
  • 4つの隣接するブロック間の場合:〜11テクスチャサンプル〜13テクスチャサンプル

私はそれを正しくしゃべっていますか?

ちょっと待ってください、私はまだシングルチャンネルのテクスチャを考えていました。 4つのrgbaチャネルを使用すると、各データブロックは1回の読み取りのみになります。 したがって、最大4つのテクスチャサンプル。

私はSDFGenerator.jsを読み始めました。 もっと見ていきます。

すべての側面がグリフエッジに囲まれている可能性があるコーナーケースのアルファブレンディングを特に改善したい場合を除いて、フラグメントごとに1つのテクセルを読み取る以上の必要はないと思います。 フラグメントの中心がある2x2ブロックの最も近い中心が必要です。
ただし、予期していなかった問題がある可能性があることを認識しています... WebGL 1.0は、ここで使用できるものに非常に制限があります。符号なし整数型uintはなく、32ビット整数でもありません。 🤯そしてビット単位の演算はありません...したがって、私が提案している圧縮は、16ビット整数を使用して記述するのが少し難しいです。

これらはすべてWebGL2.0で利用できますが、ここでWebGL 1.0をターゲットにしたいと思いますか?

これらはすべてWebGL2.0で利用できますが、ここでWebGL 1.0をターゲットにしたいと思いますか?

テキストのアウトラインをwebgl2に制限し、ユーザーがそのブラウザーと互換性があるかどうかを検出するのが合理的かもしれないと思います。 ただし、webgl2の最適なバージョンとwebgl1のフォールバックの両方を実行している可能性があることは理解できます。 Imoは、webgl 2から始めて、すぐに両方をサポートしようとする前に、コミュニティに浸透させることができます。

精度の問題を回避するための別のアプローチがあると思うので、 @ FunMilesは今のところ圧縮に関する問題について心配する必要はありません。

ねえ@lojjic 、これをチェックインするだけです。 何か進歩や私たちが助けることができることはありますか?

補足:SafariはついにWebGL2をサポートするようになりました。そのため、この機能ではWebGL1をサポートしない可能性があります。

WebGL2の実装は十分な状態にあるため、より広範なテストのためにデフォルトで有効にする必要があります。
https://trac.webkit.org/changeset/267027/webkit

私はiPhone6を持っていますが、WebGL2.0はありません😒

興味深いことに、WebGL 1.0は、私が思っていたよりもさらに悪い要件を指定しています。 整数は実際には存在しません:

4.1.3整数
整数は主にプログラミング支援としてサポートされています。 ハードウェアレベルでは、実数が役立ちます
ループと配列インデックスの効率的な実装、およびテクスチャユニットの参照。 しかし、ありません
言語の整数がハードウェアの整数型にマップされるという要件。 それは期待されていません
基盤となるハードウェアは、さまざまな整数演算を完全にサポートしています。 OpenGLESシェーディング
言語実装は、整数を浮動小数点数に変換して操作する場合があります。 したがって、ポータブルはありません
ラッピング動作。

しかし、私は希望を失っていません。 少し考え直さなければならない...
その間、 @ lojjic 、あなたが考えた別のアプローチを教えていただけませんか?

@FunMilesもちろんです。 非線形スケールを使用して距離値をエンコードすることにより、グリフの形状に十分な精度を維持しながら、距離フィールドをテクスチャのエッジまで拡張できます。 したがって、グリフのパスに非常に近い距離(1〜2テクセル以内)には多くの値がありますが、遠い距離には少ない値があります。 シェーダーは、元の直線距離に戻す方法を知っている必要があります。 グリフの適切な形状は見栄えがよく、押し出された輪郭の精度の低さは、とにかく丸められているため、ほとんど目立ちません。

これは、2層の線形スケールと指数スケールの両方を使用して証明しました。 どちらにも長所と短所があります。

現在、隣接するエッジ値を使用してクワッドの外側のグラデーションを概算するという(非常にスマートな)アプローチを実装している最中です。 角の外側の領域についてはどうしたらよいかわかりませんが、これまでのところ理にかなっています。 深く掘り下げてみると明らかになるかもしれませんが、簡単な答えがあればありがたいです:)

現在、隣接するエッジ値を使用してクワッドの外側のグラデーションを概算するという(非常にスマートな)アプローチを実装している最中です。 角の外側の領域についてはどうしたらよいかわかりませんが、これまでのところ理にかなっています。 深く掘り下げてみると明らかになるかもしれませんが、簡単な答えがあればありがたいです:)

_角の外_が何を意味するのかわかりません。 最も近い投影がコーナー自体である、各コーナーに根ざしたクォータープレーンを意味しますか? そこでは、垂直エッジと水平エッジの両方のエッジでルールを使用し、それぞれまでの距離に基づいて加重平均を行うことができると思います。

PS:WebGL整数ナンセンスを読んだ後、今日、精度を大幅に下げるというアイデアが思い浮かびました...😛圧縮技術をWebGL 1.0に実装して、11ビットの精度を安価に取得できることを期待しています。より多くのテストでより多くのビット。 つまり、 rgbaを使用すると、 aは平均の8ビットを保持でき、 rgbごとに署名され、符号はそれぞれ1ビットの精度を表します。平均、そして最後に0から127の範囲にある余りは、必要な4つの値のうちの3つに対して7ビットを表すために、値64が減算されます。 実際の値は、center(0から2 ^ 11-1の範囲)+ dist_iになります。 合計は平均でなければならないため、4番目の値はそれらの合計を引いたものを実行することによって回復されます。 11ビットしか得られませんが、おそらくそれで十分です。 より多くのビットを取得するには、値またはr 、 g 、およびbが-64より小さいか、正または負、64より大きいかをテストする必要があります。中央に14ビット、違いに6ビットのみを与えます。 おそらく良い妥協点ですか? WebGL 1.0が正確さを保証するという非常に緩い保証が、この考え方に干渉しないことをテストする必要があります。

ええ、それは私が意味したことです、UとVの両方が0-1の外側にあるエリア。 ありがとう、私はそれを試してみます。

@lojjic余談ですが、以前の投稿では、メモリのためにSDFテクセルごとに2つのテクスチャ値があることを懸念しているようです。 私自身はメモリを減らすことを好みますが、64x64グリッド上の256個のグリフは1 / 4MBのテクスチャメモリしか消費していません。 一部の言語ではさらに多くのグリフが必要になる場合があることは知っていますが、それでもBBCは、新聞を読むのに必要なのは2000/3000文字だけだと言っています。 したがって、4000文字は、テクセルSDFごとに1バイトで4MBになります。 心配する価値がありますか?

@FunMilesフェアポイント、そして私は実際にはそのtbhについてあまり心配していませんでした。

いくつかの未解決の作業が残っていますが、b19cd3aff4b0876253d76b3fc66b7e2a1f16a7e5でこの問題が修正されています。 react-three-fiberを使用している場合、これはdreiv2.2.0でリリースされています。
https://github.com/pmndrs/drei/pull/156

閉店していることは承知しておりますが、お仕事ありがとうございました。 私はそれを私のアプリで動作させることができました。 プロパティがアウトラインサイズの数値だけを受け入れないことを少し理解しました。 しかし、結果はまさに私が必要としていたものです。
Screen Shot 2020-11-09 at 7 44 52 PM

@FunMilesよさそうだ! outlineWidthに数値を使用できるはずです。何らかの理由でそれが機能しない場合は、お知らせください。

そして、途中であなたの入力に感謝します。 あなたが言及した種類の手法を使用して、クワッド境界の外側の距離をスムーズに外挿することはまだできませんでした。そのため、太いアウトラインには現在、特にコーナーにゴツゴツしたビットがありますが、ほとんどの場合(最大〜フォントサイズの10%)。 私はそれをまだ洗練しようと試みることに間違いなくオープンです。

このページは役に立ちましたか?
0 / 5 - 0 評価