How to use and blend multiple textures with custom values in Three.js?

后端 未结 1 883
别跟我提以往
别跟我提以往 2021-01-02 18:52

In Three.js, is it possible to create a material (shader?) containing a number of textures, each one with its own specifics, blend them together and assign to geometry? I\'d

相关标签:
1条回答
  • 2021-01-02 19:54

    Like the comments say, you can do this with a custom shader. You will just have to think about how to combine the different layers yourself in the shader. So just to give you an example, you can set up your shader in your js like this:

    blurTexture360 = new THREE.TextureLoader().load(imgURLBlur);
    unblurTexture360 = new THREE.TextureLoader().load(imgURLUnblur);
    highlight1Texture360 = new THREE.TextureLoader().load(imgURLHighlight1);
    highlight2Texture360 = new THREE.TextureLoader().load(imgURLHighlight2);
    
    blurTexture360.magFilter = THREE.LinearFilter;
    blurTexture360.minFilter = THREE.LinearFilter;
    
    const shader = THREE.ShaderLib.equirect;
    uniforms = {
      u_resolution: { type: "v2", value: resolution },
      u_blur: { type: "t", value: blurTexture360 },
      u_unblur: { type: "t", value: unblurTexture360 },
      u_highlight1: { type: "t", value: highlight1Texture360 },
      u_highlight2: { type: "t", value: highlight2Texture360 },
      u_mix: { type: "f", value: 0.0 },
      u_highlightAmt: { type: "f", value: 0.0 },
      u_highlight1Bool: { type: "f", value: 1.0 },
      u_highlight2Bool: { type: "f", value: 1.0 }
    };
    let material360 = new THREE.ShaderMaterial({
      uniforms: uniforms,
      vertexShader: shader.vertexShader,
      fragmentShader: fragmentShader(),
      depthWrite: false,
      side: THREE.BackSide
    });
    

    then to set the uniforms elsewhere

    uniforms.u_highlightAmt.value -= 0.05;
    

    this this is an example of setting different textures to come in when u_highlight1Bool or u_highlight2Bool is set to 1 or 0. Hopefully this gives you an example of using logic to affect your shader code.

    function fragmentShader() {
        return `        
    uniform sampler2D u_blur;
    uniform sampler2D u_unblur;
    uniform sampler2D u_highlight1;
    uniform sampler2D u_highlight2;
    
    uniform vec2 u_resolution;
    uniform float u_mix;
    uniform float u_highlight1Bool;
    uniform float u_highlight2Bool;
    uniform float u_highlightAmt;
    
    varying vec3 vWorldDirection;
    #define RECIPROCAL_PI2 0.15915494309189535
    #define RECIPROCAL_PI 0.3183098861837907
    
    vec2 equirectUv( in vec3 dir ) {
        // dir is assumed to be unit length
        float u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;
        float v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;
        return vec2( u, v );
    }
    
    void main() {
        vec3 direction = normalize( vWorldDirection );
        vec2 sampleUV = equirectUv( direction );
      vec4 blur =  texture2D(u_blur, sampleUV);
      vec4 unblur =  texture2D(u_unblur,  sampleUV);
      vec4 highlight1 = texture2D(u_highlight1, sampleUV);
      vec4 highlight2 = texture2D(u_highlight2, sampleUV);
    
        blur = mapTexelToLinear( blur );
      unblur = mapTexelToLinear( unblur );
      highlight1 = mapTexelToLinear(highlight1);
      highlight2 = mapTexelToLinear(highlight2);
      vec4 highlight = (highlight1*u_highlight1Bool) + (highlight2 * u_highlight2Bool);
    
      vec4 ret = mix(blur, unblur, u_mix);
      float thresh = ceil(highlight.r - 0.09) * u_highlightAmt;
      ret = mix(ret,highlight,thresh);
    
      gl_FragColor = ret;
    }
    `;
    

    I got this from my code here: https://glitch.com/edit/#!/hostileterrain94?path=script%2FthreeSixtyEnv.js%3A202%3A0 its not super well documented but if you wanted to see how this exists in a broader project feel free to take a peek. I dot claim this is really efficient but I know it can get the job done.

    0 讨论(0)
提交回复
热议问题