threejs: как визуализировать текстуру с помощью пользовательских шейдеров, ВКЛЮЧАЯ смещения UV текстур

Я хочу визуализировать текстуру на плоскости с помощью пользовательских шейдеров. Эта текстура имеет свойство «смещение», которое работает правильно, когда я использую стандартный материал threejs. Однако я не могу понять, как получить доступ к этим смещениям в моем пользовательском шейдере фрагментов. Он просто отображает всю текстуру по всей плоскости:

шейдеры:

<script id="vertex_shader" type="x-shader/x-vertex">
    varying vec2 vUv;

    void main() {
        vUv = uv;
        gl_Position = projectionMatrix *
            modelViewMatrix *
            vec4(position,1.0);
    }

    </script>

    <script id="fragment_shader" type="x-shader/x-fragment">

    uniform sampler2D texture1;
    varying vec2 vUv;

    void main()
    {
        gl_FragColor = texture2D(texture1, vUv); 
    }

    </script>

если бы я мог как-то сказать что-нибудь вроде:

gl_FragColor = texture2D(texture1, vUv + texture1.offset); 

? Может, это сработает. Но очевидно, что это вызывает ошибку.

ОБНОВЛЕНИЕ: поэтому я отправил смещение текстуры как униформу, и это сработало. Не знаю, почему я не подумал об этом.


person korrbit    schedule 05.09.2018    source источник
comment
да. В заголовке своего вопроса я написал threejs.   -  person korrbit    schedule 05.09.2018


Ответы (1)


Если я правильно понимаю ваш вопрос, то ответ должен заключаться в том, чтобы добавить и использовать униформу uniform mat3 uvTransform; для вашего фрагментного шейдера.

THREE будет искать и заполнять эту форму преобразованием текстуры (которое включает texture1.offset) при рендеринге текстуры на вашу геометрию.

У вас должна быть возможность получить доступ и извлечь данные, предоставленные texture1.offset, чтобы компенсировать выборку текстуры следующим образом:

<script id="vertex_shader" type="x-shader/x-vertex">
varying vec2 vUv;

void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}

</script>

<script id="fragment_shader" type="x-shader/x-fragment">

    // [UPDATE] The uv offset uniform we defined below
    uniform vec2 uvOffset;
    // [UPDATE] The texture uniform we defined below
    uniform sampler2D texture;

    varying vec2 vUv;

    void main()
    {
        // [UPDATE] Apply offset to texture lookup
        gl_FragColor = texture2D(texture, vUv + uvOffset); 
    }

</script>

Затем вы должны добавить к вышеприведенным вершинным и фрагментным шейдерам следующее THREE.ShaderMaterial:

<script>
  var material = new THREE.ShaderMaterial({
  uniforms: THREE.UniformsUtils.merge([
    {
      //Declare texture uniform in shader
      texture: { type: 't', value: null }, 
      //Declare texture offset in shader
      uvOffset : { type : 'v', value : new THREE.Vector2(0,0) } 
    }
  ]),
  vertexShader: 
  document.getElementById('vertexshader').textContent,
  fragmentShader: 
  document.getElementById('fragmentshader').textContent
});

// Shader uniforms can be updated like so
material.uniforms.map.value = yourTexture;
material.uniforms.uvOffset.value = yourTextureOffsetVector2;
</script>
person Dacre Denny    schedule 05.09.2018
comment
Выглядит отлично! это не работает для меня, это не имеет никакого эффекта. Я не могу найти документацию по uvTransform, которая автоматически передается шейдерам. Есть ли стандартный способ нанесения матрицы на текстуру? - person korrbit; 05.09.2018
comment
Как вы загружаете шейдер? через THREE.Shader или THREE.RawShader? - person Dacre Denny; 05.09.2018
comment
var material = new THREE.ShaderMaterial. Если есть лучший, более стандартный способ получить простой настраиваемый шейдер с UV-отображением, я бы хотел найти где-нибудь пример. - person korrbit; 05.09.2018
comment
Возможно, вам придется применить фактическое смещение к униформе, например, myMaterial.uniforms.uvOffset.value = myTexture.transformMatrix или как там это называется. Это будет mat3, поэтому вам нужно умножить его, для одного смещения вы, вероятно, могли бы сделать uniform vec2 uOffset myMateria.uniforms.uOffset.value = myTexture.offset - person pailhead; 05.09.2018
comment
@korrbit только что обновили ответ - надеюсь, это поможет! - person Dacre Denny; 05.09.2018