且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在 Three.js 中使用和混合具有自定义值的多个纹理?

更新时间:2022-12-19 19:59:48

正如评论所说,您可以使用自定义着色器来完成此操作.您只需要考虑如何在着色器中自己组合不同的层.举个例子,你可以像这样在你的js中设置你的着色器:

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
});

然后在别处设置制服

uniforms.u_highlightAmt.value -= 0.05;

这是在 u_highlight1Bool 或 u_highlight2Bool 设置为 1 或 0 时设置不同纹理的示例.希望这为您提供了一个使用逻辑影响着色器代码的示例.

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;
}
`;

我从这里的代码中得到这个:https://glitch.com/edit/#!/hostileterrain94?path=script%2FthreeSixtyEnv.js%3A202%3A0 它没有很好的文档记录,但如果你想看看它是如何存在于更广泛的项目中的,请随意看一眼.我确实声称这非常有效,但我知道它可以完成工作.

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.