我试图将2个图像作为纹理加载,在片段着色器中对其进行插值,然后将颜色应用于平面。不幸的是,我什至无法显示单个纹理。
我正在创建飞机并按以下方式加载图像:
const planeGeometry = new THREE.PlaneBufferGeometry(imageSize * screenRatio, imageSize);
loader.load(
"textures/IMG_6831.jpeg",
(image) => {
texture1 = new THREE.MeshBasicMaterial({ map: image });
//texture1 = new THREE.Texture({ image: image });
}
)
当我像往常一样直接使用MeshBasicMaterial作为Mesh的材质时,它可以在平面上正确显示图像。尝试在自定义着色器中执行相同操作时,我只会得到黑色:
const uniforms = {
texture1: { type: "sampler2D", value: texture1 },
texture2: { type: "sampler2D", value: texture2 }
};
const planeMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
fragmentShader: fragmentShader(),
vertexShader: vertexShader()
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
scene.add(plane);
着色器:
const vertexShader = () => {
return `
varying vec2 vUv;
void main() {
vUv = uv;
vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * modelViewPosition;
}
`;
}
const fragmentShader = () => {
return `
uniform sampler2D texture1;
uniform sampler2D texture2;
varying vec2 vUv;
void main() {
vec4 color1 = texture2D(texture1, vUv);
vec4 color2 = texture2D(texture2, vUv);
//vec4 fColor = mix(color1, color2, vUv.y);
//fColor.a = 1.0;
gl_FragColor = color1;
}
`;
}
要解决此问题,我尝试过:
texture1
和texture2
在传递给着色器之前已定义THREE.Texture
代替THREE.MeshBasicMaterial
texture1: { type: "t", value: texture1 },
中更改统一类型我认为问题可能出在将纹理均匀地传递给着色器方面。我可能在某个地方使用了错误的类型。.我将不胜感激!
答案 0 :(得分:0)
假设loader
是TextureLoader
,那么它会给您一个纹理,从而使您
loader.load(
"textures/IMG_6831.jpeg",
(texture) => {
texture1 = texture;
}
)
否则,虽然不是bug,但type
不再用于Three.js制服。
const planeGeometry = new THREE.PlaneBufferGeometry(1, 1);
const loader = new THREE.TextureLoader();
let texture1;
loader.load(
"https://i.imgur.com/KjUybBD.png",
(texture) => {
texture1 = texture;
start();
}
);
const vertexShader = () => {
return `
varying vec2 vUv;
void main() {
vUv = uv;
vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * modelViewPosition;
}
`;
}
const fragmentShader = () => {
return `
uniform sampler2D texture1;
uniform sampler2D texture2;
varying vec2 vUv;
void main() {
vec4 color1 = texture2D(texture1, vUv);
vec4 color2 = texture2D(texture2, vUv);
//vec4 fColor = mix(color1, color2, vUv.y);
//fColor.a = 1.0;
gl_FragColor = color1;
}
`;
}
function start() {
const renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.Camera();
const uniforms = {
texture1: { value: texture1 },
texture2: { value: texture1 },
};
const planeMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
fragmentShader: fragmentShader(),
vertexShader: vertexShader()
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
scene.add(plane);
renderer.render(scene, camera);
}
<script src="https://cdn.jsdelivr.net/npm/three@0.111.0/build/three.min.js"></script>
TextureLoader
还返回纹理,因此,如果您在requestAnimationFrame循环中连续渲染,则可以这样编写
const planeGeometry = new THREE.PlaneBufferGeometry(1, 1);
const loader = new THREE.TextureLoader();
const texture1 = loader.load("https://i.imgur.com/KjUybBD.png");
const texture2 = loader.load("https://i.imgur.com/UKBsvV0.jpg");
const vertexShader = () => {
return `
varying vec2 vUv;
void main() {
vUv = uv;
vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);
gl_Position = projectionMatrix * modelViewPosition;
}
`;
}
const fragmentShader = () => {
return `
uniform sampler2D texture1;
uniform sampler2D texture2;
varying vec2 vUv;
void main() {
vec4 color1 = texture2D(texture1, vUv);
vec4 color2 = texture2D(texture2, vUv);
gl_FragColor = mix(color1, color2, vUv.y);
}
`;
}
const renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);
const scene = new THREE.Scene();
const camera = new THREE.Camera();
const uniforms = {
texture1: { value: texture1 },
texture2: { value: texture2 },
};
const planeMaterial = new THREE.ShaderMaterial({
uniforms: uniforms,
fragmentShader: fragmentShader(),
vertexShader: vertexShader()
});
const plane = new THREE.Mesh(planeGeometry, planeMaterial);
scene.add(plane);
function render() {
renderer.render(scene, camera);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
<script src="https://cdn.jsdelivr.net/npm/three@0.111.0/build/three.min.js"></script>
纹理将为空白,但是在图像加载后,Three.js会更新它们。
您可能会对更多up to date tutorials
感兴趣