我们正在尝试在3D模型中每个对象顶部的特定位置(右上角)显示标记。我们还想在3D标记上渲染文本。这可能吗?如果是的话,我们会在它上面放置一个后期处理着色器,这样当我们四处走动时它就不会隐藏在模型中的其他东西下面。
选项2: 在2D中,无论是Forge还是HTML,这都是顶部有文字的图像,在每一帧中,这些图像+文本的位置必须更新以匹配3D对象的2D位置,这可能有效,但它可能会有效延迟,这就是为什么我们更喜欢使用3D选项 - 如果可能的话。
答案 0 :(得分:2)
查看我最新的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
}
}