A-Frame A-Text Mask - PullRequest
       30

A-Frame A-Text Mask

0 голосов
/ 17 сентября 2018

Я не могу найти ответ по поводу маскировки изображения с помощью текстового примитива или других возможностей с a-frame или threejs позади. Текст растрового изображения должен быть маской для базового изображения. Кто-то сказал мне, что это может быть решено с помощью шейдеров https://aframe.io/docs/0.8.0/primitives/a-text.html#attributes_shader и посоветовал мне прочитать книгу шейдеров https://thebookofshaders.com с 155 страницами предвидения! Я не уверен, что это правильный совет в любом случае!?

Здесь вы можете увидеть проиллюстрированную позицию задания в виде графика:

https://photos.app.goo.gl/MLZjcucfpuqmtinH7

Codepen: http://codepen.w3x.de

1 Ответ

0 голосов
/ 21 сентября 2018

Скопируйте и вставьте код текстового шейдера A-Frame (удалите module.exports) и зарегистрируйте текстовый шейдер. Вот текущий шейдер MSDF:

AFRAME.registerShader('yourtextshader', {
      schema: {
        alphaTest: {type: 'number', is: 'uniform', default: 0.5},
        color: {type: 'color', is: 'uniform', default: 'white'},
        map: {type: 'map', is: 'uniform'},
        negate: {type: 'boolean', is: 'uniform', default: true},
        opacity: {type: 'number', is: 'uniform', default: 1.0}
      },

      raw: true,

      vertexShader: [
        'attribute vec2 uv;',
        'attribute vec3 position;',
        'uniform mat4 projectionMatrix;',
        'uniform mat4 modelViewMatrix;',
        'varying vec2 vUV;',
        'void main(void) {',
        '  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);',
        '  vUV = uv;',
        '}'
      ].join('\n'),

      fragmentShader: [
        '#ifdef GL_OES_standard_derivatives',
        '#extension GL_OES_standard_derivatives: enable',
        '#endif',

        'precision highp float;',
        'uniform bool negate;',
        'uniform float alphaTest;',
        'uniform float opacity;',
        'uniform sampler2D map;',
        'uniform vec3 color;',
        'varying vec2 vUV;',

        'float median(float r, float g, float b) {',
        '  return max(min(r, g), min(max(r, g), b));',
        '}',

        // FIXME: Experimentally determined constants.
        '#define BIG_ENOUGH 0.001',
        '#define MODIFIED_ALPHATEST (0.02 * isBigEnough / BIG_ENOUGH)',

        'void main() {',
        '  vec3 sample = texture2D(map, vUV).rgb;',
        '  if (negate) { sample = 1.0 - sample; }',

        '  float sigDist = median(sample.r, sample.g, sample.b) - 0.5;',
        '  float alpha = clamp(sigDist / fwidth(sigDist) + 0.5, 0.0, 1.0);',
        '  float dscale = 0.353505;',
        '  vec2 duv = dscale * (dFdx(vUV) + dFdy(vUV));',
        '  float isBigEnough = max(abs(duv.x), abs(duv.y));',

        '  // Do modified alpha test.',
        '  if (alpha < alphaTest * MODIFIED_ALPHATEST) { discard; return; }',
        '  gl_FragColor = vec4(color.xyz, alpha * opacity);',
        '}'
      ].join('\n')
    });

Фрагментный шейдер - это то, что вычисляет цвет текста. Вы получите vUV, которая является УФ-картой для этого фрагмента, указывающей, где взять образец текстуры.

Что вам нужно сделать, чтобы изменить этот шейдер. Еще не успел сделать полный пример, но ...:

  1. Принять другой параметр вашей текстуры, добавить в схему.
  2. Передайте эту текстуру в шейдер (<a-entity text="shader: yourTextShader; yourTexture: #texture).
  3. Добавить униформу для этой текстуры в фрагментный шейдер uniform sampler2D yourTexture).
  4. Измените фрагментный шейдер, чтобы использовать цвет текстуры вместо цвета gl_FragColor = vec4(texture2D(yourTexture, vUv), alpha * opacity)
...