ソースを参照

added depth offset buffer to text geometry

Alexander Rose 6 年 前
コミット
f15f2074cc

+ 8 - 3
src/mol-geo/geometry/text/text-builder.ts

@@ -16,7 +16,7 @@ const quadIndices = new Uint16Array([
 ])
 
 export interface TextBuilder {
-    add(str: string, x: number, y: number, z: number, group: number): void
+    add(str: string, x: number, y: number, z: number, depth: number, group: number): void
     getText(): Text
 }
 
@@ -26,6 +26,7 @@ export namespace TextBuilder {
         chunkSize *= 2
         const centers = ChunkedArray.create(Float32Array, 3, chunkSize, text ? text.centerBuffer.ref.value : initialCount);
         const mappings = ChunkedArray.create(Float32Array, 2, chunkSize, text ? text.mappingBuffer.ref.value : initialCount);
+        const depths = ChunkedArray.create(Float32Array, 1, chunkSize, text ? text.depthBuffer.ref.value : initialCount);
         const indices = ChunkedArray.create(Uint32Array, 3, chunkSize, text ? text.indexBuffer.ref.value : initialCount);
         const groups = ChunkedArray.create(Float32Array, 1, chunkSize, text ? text.groupBuffer.ref.value : initialCount);
         const tcoords = ChunkedArray.create(Float32Array, 2, chunkSize, text ? text.tcoordBuffer.ref.value : initialCount);
@@ -38,7 +39,7 @@ export namespace TextBuilder {
         const outline = fontAtlas.buffer / fontAtlas.lineHeight
 
         return {
-            add: (str: string, x: number, y: number, z: number, group: number) => {
+            add: (str: string, x: number, y: number, z: number, depth: number, group: number) => {
                 let xadvance = 0
                 const nChar = str.length
 
@@ -76,6 +77,7 @@ export namespace TextBuilder {
                     for (let i = 0; i < 4; ++i) {
                         ChunkedArray.add2(tcoords, 10, 10)
                         ChunkedArray.add3(centers, x, y, z);
+                        ChunkedArray.add(depths, depth);
                         ChunkedArray.add(groups, group);
                     }
                     ChunkedArray.add3(indices, offset + quadIndices[0], offset + quadIndices[1], offset + quadIndices[2])
@@ -107,6 +109,7 @@ export namespace TextBuilder {
                     const offset = centers.elementCount
                     for (let i = 0; i < 4; ++i) {
                         ChunkedArray.add3(centers, x, y, z);
+                        ChunkedArray.add(depths, depth);
                         ChunkedArray.add(groups, group);
                     }
                     ChunkedArray.add3(indices, offset + quadIndices[0], offset + quadIndices[1], offset + quadIndices[2])
@@ -114,18 +117,20 @@ export namespace TextBuilder {
                 }
             },
             getText: () => {
+                const ft = fontAtlas.texture
                 const cb = ChunkedArray.compact(centers, true) as Float32Array
                 const mb = ChunkedArray.compact(mappings, true) as Float32Array
+                const db = ChunkedArray.compact(depths, true) as Float32Array
                 const ib = ChunkedArray.compact(indices, true) as Uint32Array
                 const gb = ChunkedArray.compact(groups, true) as Float32Array
                 const tb = ChunkedArray.compact(tcoords, true) as Float32Array
-                const ft = fontAtlas.texture
                 return {
                     kind: 'text',
                     charCount: indices.elementCount / 2,
                     fontTexture: text ? ValueCell.update(text.fontTexture, ft) : ValueCell.create(ft),
                     centerBuffer: text ? ValueCell.update(text.centerBuffer, cb) : ValueCell.create(cb),
                     mappingBuffer: text ? ValueCell.update(text.mappingBuffer, mb) : ValueCell.create(mb),
+                    depthBuffer: text ? ValueCell.update(text.depthBuffer, db) : ValueCell.create(db),
                     indexBuffer: text ? ValueCell.update(text.indexBuffer, ib) : ValueCell.create(ib),
                     groupBuffer: text ? ValueCell.update(text.groupBuffer, gb) : ValueCell.create(gb),
                     tcoordBuffer: text ? ValueCell.update(text.tcoordBuffer, tb) : ValueCell.create(tb),

+ 18 - 7
src/mol-geo/geometry/text/text.ts

@@ -44,6 +44,8 @@ export interface Text {
     readonly centerBuffer: ValueCell<Float32Array>,
     /** Mapping buffer as array of xy values wrapped in a value cell */
     readonly mappingBuffer: ValueCell<Float32Array>,
+    /** Depth buffer as array of z values wrapped in a value cell */
+    readonly depthBuffer: ValueCell<Float32Array>,
     /** Index buffer as array of center index triplets wrapped in a value cell */
     readonly indexBuffer: ValueCell<Uint32Array>,
     /** Group buffer as array of group ids for each vertex wrapped in a value cell */
@@ -54,18 +56,20 @@ export interface Text {
 
 export namespace Text {
     export function createEmpty(text?: Text): Text {
+        const ft = text ? text.fontTexture.ref.value : createTextureImage(0, 1)
         const cb = text ? text.centerBuffer.ref.value : new Float32Array(0)
         const mb = text ? text.mappingBuffer.ref.value : new Float32Array(0)
+        const db = text ? text.depthBuffer.ref.value : new Float32Array(0)
         const ib = text ? text.indexBuffer.ref.value : new Uint32Array(0)
         const gb = text ? text.groupBuffer.ref.value : new Float32Array(0)
         const tb = text ? text.tcoordBuffer.ref.value : new Float32Array(0)
-        const ft = text ? text.fontTexture.ref.value : createTextureImage(0, 1)
         return {
             kind: 'text',
             charCount: 0,
             fontTexture: text ? ValueCell.update(text.fontTexture, ft) : ValueCell.create(ft),
             centerBuffer: text ? ValueCell.update(text.centerBuffer, cb) : ValueCell.create(cb),
             mappingBuffer: text ? ValueCell.update(text.mappingBuffer, mb) : ValueCell.create(mb),
+            depthBuffer: text ? ValueCell.update(text.depthBuffer, db) : ValueCell.create(db),
             indexBuffer: text ? ValueCell.update(text.indexBuffer, ib) : ValueCell.create(ib),
             groupBuffer: text ? ValueCell.update(text.groupBuffer, gb) : ValueCell.create(gb),
             tcoordBuffer: text ? ValueCell.update(text.tcoordBuffer, tb) : ValueCell.create(tb)
@@ -118,7 +122,7 @@ export namespace Text {
 
         const counts = { drawCount: text.charCount * 2 * 3, groupCount, instanceCount }
 
-        const padding = getPadding(text.mappingBuffer.ref.value, text.charCount, getMaxSize(size))
+        const padding = getPadding(text.mappingBuffer.ref.value, text.depthBuffer.ref.value, text.charCount, getMaxSize(size))
         const { boundingSphere, invariantBoundingSphere } = calculateBoundingSphere(
             text.centerBuffer.ref.value, text.charCount * 4,
             transform.aTransform.ref.value, instanceCount, padding
@@ -127,6 +131,7 @@ export namespace Text {
         return {
             aPosition: text.centerBuffer,
             aMapping: text.mappingBuffer,
+            aDepth: text.depthBuffer,
             aGroup: text.groupBuffer,
             elements: text.indexBuffer,
             boundingSphere: ValueCell.create(boundingSphere),
@@ -179,7 +184,7 @@ export namespace Text {
     }
 
     function updateBoundingSphere(values: TextValues, text: Text) {
-        const padding = getPadding(values.aMapping.ref.value, text.charCount, getMaxSize(values))
+        const padding = getPadding(values.aMapping.ref.value, values.aDepth.ref.value, text.charCount, getMaxSize(values))
         const { boundingSphere, invariantBoundingSphere } = calculateBoundingSphere(
             values.aPosition.ref.value, text.charCount * 4,
             values.aTransform.ref.value, values.instanceCount.ref.value, padding
@@ -205,13 +210,19 @@ export namespace Text {
     }
 }
 
-function getPadding(mapping: Float32Array, charCount: number, maxSize: number) {
+function getPadding(mappings: Float32Array, depths: Float32Array, charCount: number, maxSize: number) {
     let maxOffset = 0
+    let maxDepth = 0
     for (let i = 0, il = charCount * 4; i < il; ++i) {
-        const ox = Math.abs(mapping[i])
+        const i2 = 2 * i
+        const ox = Math.abs(mappings[i2])
         if (ox > maxOffset) maxOffset = ox
-        const oy = Math.abs(mapping[i + 1])
+        const oy = Math.abs(mappings[i2 + 1])
         if (oy > maxOffset) maxOffset = oy
+        const d = Math.abs(depths[i])
+        if (d > maxDepth) maxDepth = d
     }
-    return maxSize + maxSize * maxOffset
+    // console.log(maxDepth + maxSize, maxDepth, maxSize, maxSize + maxSize * maxOffset, depths)
+    return Math.max(maxDepth, maxSize + maxSize * maxOffset)
+    // return maxSize + maxSize * maxOffset + maxDepth
 }

+ 1 - 0
src/mol-gl/renderable/text.ts

@@ -16,6 +16,7 @@ export const TextSchema = {
     ...SizeSchema,
     aPosition: AttributeSpec('float32', 3, 0),
     aMapping: AttributeSpec('float32', 2, 0),
+    aDepth: AttributeSpec('float32', 1, 0),
     elements: ElementsSpec('uint32'),
 
     aTexCoord: AttributeSpec('float32', 2, 0),

+ 2 - 1
src/mol-gl/shader/text.vert

@@ -15,6 +15,7 @@ uniform mat4 uModelView;
 
 attribute vec3 aPosition;
 attribute vec2 aMapping;
+attribute float aDepth;
 attribute vec2 aTexCoord;
 attribute mat4 aTransform;
 attribute float aInstance;
@@ -43,7 +44,7 @@ void main(void){
 
     float offsetX = uOffsetX * scale;
     float offsetY = uOffsetY * scale;
-    float offsetZ = uOffsetZ * scale;
+    float offsetZ = (uOffsetZ + aDepth * 0.95) * scale;
     if (vTexCoord.x == 10.0) {
         offsetZ -= 0.01;
     }

+ 5 - 5
src/tests/browser/render-text.ts

@@ -37,11 +37,11 @@ function textRepr() {
     }
 
     const textBuilder = TextBuilder.create(props, 1, 1)
-    textBuilder.add('Hello world', 0, 0, 0, 0)
-    textBuilder.add('Добрый день', 0, 1, 0, 0)
-    textBuilder.add('美好的一天', 0, 2, 0, 0)
-    textBuilder.add('¿Cómo estás?', 0, -1, 0, 0)
-    textBuilder.add('αβγ Å', 0, -2, 0, 0)
+    textBuilder.add('Hello world', 0, 0, 0, 0, 0)
+    textBuilder.add('Добрый день', 0, 1, 0, 0, 0)
+    textBuilder.add('美好的一天', 0, 2, 0, 0, 0)
+    textBuilder.add('¿Cómo estás?', 0, -1, 0, 0, 0)
+    textBuilder.add('αβγ Å', 0, -2, 0, 0, 0)
     const text = textBuilder.getText()
 
     const values = Text.Utils.createValuesSimple(text, props, Color(0xFFDD00), 1)