【问题标题】:Setting texture to geometry in Three.js在 Three.js 中将纹理设置为几何图形
【发布时间】:2019-05-16 02:03:50
【问题描述】:

我有这个几何:Picture

我想添加山与雪纹理等相同的效果:
Texture splatting with Three.js

我从 Three.js 向着色器提供什么信息的小背景:

//importing grass and snow textures:
var grassTexture = new THREE.ImageUtils.loadTexture( 'images/grass-512.jpg' );
grassTexture.wrapS = grassTexture.wrapT = THREE.RepeatWrapping;
var snowTexture = new THREE.ImageUtils.loadTexture( 'images/snow-512.jpg' );
snowTExture.wrapS = snowTExture.wrapT = THREE.RepeatWrapping;

this.customUniforms = {
 grassTexture:  { value: grassTexture },
 snowTexture:   { value: snowTexture },

};
var customMaterial = new THREE.ShaderMaterial({
 uniforms: customUniforms,
 side: THREE.DoubleSide,
 vertexShader:   document.getElementById( 'vertexShader'   ).textContent,
 fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
});
//creating mesh, geometry is the model in picture.
mesh = new THREE.Mesh(geometry, customMaterial);

顶点和片段着色器:

//vertexShader:
varying vec2 vUV;

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

我用这个得到全红色模型:

//fragmentShader:
void main(){
 gl_FragColor = vec4(1, 0.0, 0.0, 1.0) ;
}

我想要使用 snowTexture 较高且使用 GrassTexture 较低的纹理。

uniform sampler2D grassTexture;  
uniform sampler2D snowTexture;
varying vec2 vUV;
//Something like this?:
vec4 grass = texture2D( grassTexture, vUV);
vec4 snow = texture2D( snowTexture, vUV);
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0) + grass + snow;

【问题讨论】:

  • bumpTexture的内容是什么?它是否包含法线向量和/或位移高度?如果它是平面几何,那么你可以做到。 newPosition = position + normalize(bumpnormal) * bumpheight);。如果几何由一个镶嵌平面组成,并且模型空间中平面的法向量为 (0, 0, 1),这将起作用。更准确地说,如果地图中的法线向量在模型空间中。
  • 基本上我希望顶点着色器遍历所有已经创建的顶点,而不是将它们移动到任何地方,现在当我应用它时,它会创建一组全新的顶点。 BumpTexture 包含我使用加载器函数加载的 three.js 中的纹理
  • 很难理解您在 OP 中的含义以及“遍历所有顶点”的含义,我建议您编辑您的帖子并尝试使其更清晰。您提供的链接使用纹理作为置换贴图来控制顶点的高度。如果这不是您想要的,那么也许这不是一个好的起点。
  • 好吧,我改了,也许现在你能理解得更好了。

标签: three.js glsl


【解决方案1】:

这真的不难理解,让我带你了解一下逻辑。

在您的情况下,您不想使用置换贴图。因此,您需要在您的 vertexShader 上设置一个 varying height 以将您的顶点上坐标 [0,1] 映射到您的 fragmentShader。

//vertexShader:
varying vec2 vUV;
varying float height;

void main() {

  vUV = uv;

  float maxPosition = 30.0; // this is an example value.
  height = max( 0.0, min(1.0, position.y/maxPosition ) ); // assuming +y is up

  gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );

}

现在您可以从您的 fragmentShader 访问 height 并使用该信息来选择您希望转换发生的位置。

uniform sampler2D grassTexture;  
uniform sampler2D snowTexture;

varying vec2 vUV;
varying float height;

void main(){

  vec4 grass = (1.0 - smoothstep( 0.48, 0.52, height)) * texture2D( grassTexture, vUV);
  vec4 snow =  (smoothstep(0.48, 0.52, height) - 0.0) * texture2D( snowTexture, vUV);

  gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0) + grass + snow;

}

提供的链接使用函数smoothstep 在纹理之间进行渐变。我们可以使用以下模式( a - b ) * textureColor 创建过渡。

在这种情况下,a 控制纹理何时开始影响片段颜色。 b 控制纹理何时停止贡献。

换句话说,你的草纹理已经开始在每个高度做出贡献,所以我们将a 映射到 1.0。它在 0.5 左右停止贡献,所以我们给 b 在接近 0.5 时平滑淡出。

另一方面,你的雪纹理只会开始贡献大约 0.5。所以,当a 接近 0.5 时,我们给它一个平滑的淡入。它永远不会停止贡献,因此我们将 b 设置为 0.0。

希望这可以为您解决问题。

【讨论】:

  • 很高兴我能提供帮助。
  • 我有一个后续问题,我怎样才能让沙子从 0 开始到 10% 的高度,草占到 40% 等等到顶部,而不是价值,因为每个当我让我的山更高时,纹理就像一个是 99%,另一个是 1%。我让我的 z 高度总是从 0 开始。在链接示例中,他提高了比例,看起来纹理的百分比保持不变..
  • 您说得对,我们正在手动映射 %。因为你不想要置换贴图。每次更改几何的最大高度时,都需要更新。您可以从 .js 代码中传递一个 maxHeight 制服来通知这些更改,而不必在 GLSL 内部进行更改
  • 要映射一个新的纹理,你使用我上面指定的相同模式。 sand = ( 1.0 - smoothstep( 0.38, 0.42, height) ) * texture2D。然后你需要更新你的草纹理,只从 40% 开始。我建议您尝试我提供的模式,我将无法无限期地继续提供帮助。
  • 最后一个问题,我得到了沙子部分,但是当我把它带上我的制服时,我是否需要```height= position.z/ value。
猜你喜欢
  • 2019-08-23
  • 2017-03-28
  • 2021-08-14
  • 2018-10-30
  • 2016-10-27
  • 2018-12-03
  • 1970-01-01
  • 2017-06-10
  • 2012-08-27
相关资源
最近更新 更多