Three.js:在自定义 ShaderMaterial 中修改我的纹理的 UV
Three.js : Modify the UV of my texture inside a custom ShaderMaterial
我有一个平面几何体,我正在创建一个与其相关的 CustomShader material。它将接收一些纹理作为制服。我希望纹理能够完美地覆盖我的平面(例如 background-size:cover
css 属性)
当我将我的纹理与 MeshBasicMaterial
一起使用时,我设法通过一个实用函数来做到这一点:
cover( texture, aspect ) {
var imageAspect = texture.image.width / texture.image.height;
if ( aspect < imageAspect ) {
texture.matrix.setUvTransform( 0, 0, aspect / imageAspect, 1, 0, 0.5, 0.5 );
} else {
texture.matrix.setUvTransform( 0, 0, 1, imageAspect / aspect, 0, 0.5, 0.5 );
}
}
但不幸的是,由于我使用的是 ShaderMaterial
,我的“封面”功能不再适用。我是否强制在片段着色器中执行此操作?如果是这样,我如何设法重现此行为?
这是我的代码:
const vertexShader = `
precision highp float;
uniform mat3 uUvTransform;
varying vec2 vUv;
void main() {
vUv = ( uUvTransform * vec3( uv, 1 ) ).xy;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`;
const fragmentShader = `
precision highp float;
uniform sampler2D uText1;
varying vec2 vUv;
void main() {
vec2 xy = vUv;
vec4 color = texture2D(uText1,xy);
gl_FragColor = color;
}`;
这是我目前的结果:
非常感谢
Three.js 处理像 .offset, .repeat, .rotation, .center
这样的纹理变换的方式是通过 Matrix3 作为 uniform
传递到顶点着色器中。顶点着色器执行矩阵乘法,然后将修改后的 UV 作为变量传递给片段着色器。
- 你可以看到正在申报制服in the
uv_pars_vertex.glsl.js
file
- 您可以在
uv_vertex.glsl.js
file 中看到正在应用的转换
您可以将这些 GLSL 代码行复制到您的 ShaderMaterial
的顶点着色器中,我认为纹理属性会自动出现在 Matrix3 中。但是,如果由于某种原因它没有,您可以重新创建 Matrix3 by copying it from the source 并手动将其作为统一传递。我不知道你的效用函数是什么样的,所以很难说你是如何实现所需的缩放的。
您可以简单地使用自定义制服,例如:
uniform sampler2D uText1;
uniform vec2 uUvScale;
varying vec2 vUv;
void main() {
vec2 uv = (vUv - 0.5) * uUvScale + 0.5;
gl_FragColor = texture2D(uText1, uv);
}
并且:
var imageAspect = texture.image.width / texture.image.height;
if ( aspect < imageAspect ) {
material.uniforms.uUvScale.value.set(aspect / imageAspect, 1)
} else {
material.uniforms.uUvScale.value.set(1, imageAspect / aspect)
}
我有一个平面几何体,我正在创建一个与其相关的 CustomShader material。它将接收一些纹理作为制服。我希望纹理能够完美地覆盖我的平面(例如 background-size:cover
css 属性)
当我将我的纹理与 MeshBasicMaterial
一起使用时,我设法通过一个实用函数来做到这一点:
cover( texture, aspect ) {
var imageAspect = texture.image.width / texture.image.height;
if ( aspect < imageAspect ) {
texture.matrix.setUvTransform( 0, 0, aspect / imageAspect, 1, 0, 0.5, 0.5 );
} else {
texture.matrix.setUvTransform( 0, 0, 1, imageAspect / aspect, 0, 0.5, 0.5 );
}
}
但不幸的是,由于我使用的是 ShaderMaterial
,我的“封面”功能不再适用。我是否强制在片段着色器中执行此操作?如果是这样,我如何设法重现此行为?
这是我的代码:
const vertexShader = `
precision highp float;
uniform mat3 uUvTransform;
varying vec2 vUv;
void main() {
vUv = ( uUvTransform * vec3( uv, 1 ) ).xy;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`;
const fragmentShader = `
precision highp float;
uniform sampler2D uText1;
varying vec2 vUv;
void main() {
vec2 xy = vUv;
vec4 color = texture2D(uText1,xy);
gl_FragColor = color;
}`;
这是我目前的结果:
非常感谢
Three.js 处理像 .offset, .repeat, .rotation, .center
这样的纹理变换的方式是通过 Matrix3 作为 uniform
传递到顶点着色器中。顶点着色器执行矩阵乘法,然后将修改后的 UV 作为变量传递给片段着色器。
- 你可以看到正在申报制服in the
uv_pars_vertex.glsl.js
file - 您可以在
uv_vertex.glsl.js
file 中看到正在应用的转换
您可以将这些 GLSL 代码行复制到您的 ShaderMaterial
的顶点着色器中,我认为纹理属性会自动出现在 Matrix3 中。但是,如果由于某种原因它没有,您可以重新创建 Matrix3 by copying it from the source 并手动将其作为统一传递。我不知道你的效用函数是什么样的,所以很难说你是如何实现所需的缩放的。
您可以简单地使用自定义制服,例如:
uniform sampler2D uText1;
uniform vec2 uUvScale;
varying vec2 vUv;
void main() {
vec2 uv = (vUv - 0.5) * uUvScale + 0.5;
gl_FragColor = texture2D(uText1, uv);
}
并且:
var imageAspect = texture.image.width / texture.image.height;
if ( aspect < imageAspect ) {
material.uniforms.uUvScale.value.set(aspect / imageAspect, 1)
} else {
material.uniforms.uUvScale.value.set(1, imageAspect / aspect)
}