動的テクスチャを使用するカスタムシェーダの例については、最新のPointCloud Markup demoをご覧ください。High-Performance 3D markups with PointCloud in the Forge Viewer
あなたはラベルが含まれているテクスチャを生成するために、同様のアプローチを使用することができます...
createShader (options) {
// Vertex Shader code
const vertexShader = options.vertexShader || `
attribute float pointSize;
attribute vec4 color;
varying vec4 vColor;
void main() {
vec4 vPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * vPosition;
gl_PointSize = pointSize;
vColor = color;
}
`
// Fragment Shader code
const fragmentShader = options.fragmentShader || `
uniform sampler2D texture;
varying vec4 vColor;
void main() {
vec4 tex = texture2D(texture, gl_PointCoord);
if (tex.a < 0.2) discard;
if (vColor.a == 0.0) {
gl_FragColor = vec4(tex.r, tex.g, tex.b, tex.a);
} else {
gl_FragColor = vColor;
}
}
`
const tex = options.texture || defaultTex
// Shader material parameters
const shaderParams = options.shaderParams || {
side: THREE.DoubleSide,
depthWrite: false,
depthTest: false,
fragmentShader,
vertexShader,
opacity: 0.5,
attributes: {
pointSize: {
type: 'f',
value: []
},
color: {
type: 'v4',
value: []
}
},
uniforms: {
texture: {
value: THREE.ImageUtils.loadTexture(tex),
type: 't'
}
}
}
// creates shader material
const material =
new THREE.ShaderMaterial(
shaderParams)
const generateTexture = (size, radius) => {
const pixels = []
for (let u = 0; u < size; ++u) {
for (let v = 0; v < size ; ++v) {
const dist = Math.sqrt(
(u/size - 0.5) * (u/size - 0.5) +
(v/size - 0.5) * (v/size - 0.5))
if (dist < 0.1) {
pixels.push(0xff, 0x00, 0x00, 0xff)
} else if (dist < (radius - 0.05)) {
pixels.push(0xff, 0x00, 0x00, 0x00)
} else if (dist < radius) {
pixels.push(0xff, 0x00, 0x00, 0xff)
} else {
pixels.push(0x00, 0x00, 0x00, 0x00)
}
}
}
const dataTexture = new THREE.DataTexture (
Uint8Array.from (pixels),
size, size,
THREE.RGBAFormat,
THREE.UnsignedByteType,
THREE.UVMapping
)
dataTexture.minFilter = THREE.LinearMipMapLinearFilter
dataTexture.magFilter = THREE.LinearFilter // THREE.NearestFilter
dataTexture.needsUpdate = true
return dataTexture
}
const stopwatch = new Stopwatch()
let radius = 0.0
return {
setTexture: (tex) => {
const {texture} = shaderParams.uniforms
texture.value = THREE.ImageUtils.loadTexture(tex)
texture.needsUpdate = true
},
update:() => {
const dt = stopwatch.getElapsedMs() * 0.001
radius += dt * 0.25
radius = radius > 0.5 ? 0.0 : radius
const {texture} = shaderParams.uniforms
texture.value = generateTexture(96, radius)
texture.needsUpdate = true
},
material
}
}
おかげでたくさんの更新のための
。 これで、フレームごとにどのシンボル(ピクセル)を表示するかを決定できます。 これですべてのアニメーションを行うことができますが、さらに重要なのは、想像できる任意のシンボル/テキストを描画できるため、番号の付いた円が可能になりました。 欠点は、ピクセルごとにプログラムする必要があるということだけです。つまり、次のように言うことはできません:fontsize 20pxで白を中心とするテキスト「50」を描画します。代わりに、あなたは言う必要があります:ピクセル1,1透明、ピクセル1,2白、等それはテキストレンダリングを可能にするには時間がかかるかもしれません。 今は元に戻すことはできませんが、それは重要なことです。 – Mykita
電源には責任があります...シェーダは非常に強力ですが、レベルが低いので、これをあなたの側で処理する必要があります。他の回避策は言及したように2D DOMオーバーレイを使用することです。ここではsvgグラフィックスとともにテキストを簡単に表示できますが、多数のマークアップを表示する予定の場合は、シェイダーで得られるものの近くにはパフォーマンスがありません。 –