如何在 Three.js 中使用和混合多个纹理与自定义值? [英] How to use and blend multiple textures with custom values in Three.js?

查看:28
本文介绍了如何在 Three.js 中使用和混合多个纹理与自定义值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Three.js 中,是否可以创建包含多个纹理的材质(着色器?),每个纹理都有自己的细节,将它们混合在一起并分配给几何体?我想使用多种精加工技术来模拟纸张表面,例如箔压花或点 UV 上光.

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 like to simulate paper surface with multiple finishing techniques applied like foil embossing or spot UV varnishing.

我想要实现的是一种具有以下特性的材料:

What I'd like to achieve is a material that would have the following characteristics:

  1. '基础'层:
    • 纸张颜色(例如白色、灰白色、米色等)
    • 镜面反射
    • 反射率
    • 凹凸(光滑或有纹理的纸)
  • 图像纹理(印刷在纸上的艺术品,与基色"混合)
  • 用于控制图层透明度的黑白图像纹理
  • 颜色(重叠基础"层)
  • 镜面反射
  • 反射率
  • 凹凸纹理(升高或降低基础"凹凸)
  • 用于控制图层透明度的黑白图像纹理
  • 镜面反射
  • 反射率
  • 凹凸(略微升高基础"凹凸)

所有单独层的原因是我想单独控制它们(在运行时替换不同的纹理并更改值).除了图像"层,我不确定我应该为其他层使用什么混合值来实现逼真的模拟.

The reason for all the separate layers is I'd like to control them individually (replace different textures and change values at runtime). Apart from the 'Image' layer, I'm not sure what blend values I should use for the other layers to achieve realistic looking simulation.

要说明应用于纸张的整理技术,请看以下照片(由 PrintHouse Corporation 提供):

To illustrate the finishing techniques applied to paper, take a look at the following photographs (courtesy of PrintHouse Corporation):

盲压纹 (图案) &金箔压花(logo、标题)

银箔压纹(徽标)和点 UV 清漆(照片)

点 UV 清漆(线条)

有可能吗?我找不到任何使用如此复杂材料的 Three.js 示例.如果您能给我指出一个或解释如何以编程方式解决这个问题,我将不胜感激.

Is it at all possible? I couldn't find any Three.js example that would use such complex materials. If you could point me to one or explain how to approach this programmatically, I'd be grateful.

推荐答案

就像评论所说的,您可以使用自定义着色器来做到这一点.您只需要考虑如何在着色器中自己组合不同的层.举个例子,你可以像这样在你的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.

这篇关于如何在 Three.js 中使用和混合多个纹理与自定义值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆