Im trying to create a cube with some texture using web GLSL shaders for the first time. But the entire box is the top left pixel of the image and i cant quite figure out how to fix this. Help pls :))
entire code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>My first three.js app</title>
<style>
body { margin: 0; }
</style>
</head>
<body>
<script type="module">
import * as THREE from 'https://unpkg.com/three/build/three.module.js';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.RawShaderMaterial({
vertexShader: `
attribute vec3 position;
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform float uTime;
varying vec2 vUv;
void main() {
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
precision mediump float;
uniform sampler2D uTexture;
uniform float uTime;
varying vec2 vUv;
void main() {
vec4 color = texture2D(uTexture, vUv);
gl_FragColor = vec4(color.xyz, 1);
}
`
});
material.uniforms.uTime = {value: 0};
material.uniforms.uTexture = {value: new THREE.TextureLoader().load("Sandblock.jpg")}
console.log(material.uniforms);
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
camera.position.z = 2;
function animate() {
requestAnimationFrame( animate );
renderer.render( scene, camera );
}
animate();
document.addEventListener('keydown', (event) => {
if (event.code == "KeyD") {
camera.position.x += 1;
}
if (event.code == "KeyA") {
camera.position.x -= 1;
}
if (event.code == "KeyS") {
camera.position.z += 1;
}
if (event.code == "KeyW") {
camera.position.z -= 1;
}
});
</script>
</body>
</html>
have been messing around the GLSL for some time now, and tried changing
uniform sampler2D uTexture; -> uniform sampler3D uTexture;
but nothing is changed so i just left it :)
You need to add the uv attribute to your vertex shader, then pass it as a varying to your fragment shader:
attribute vec uv;
varying vec2 vUv;
void main() {
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(position, 1.0);
// We need to assign a value to the varying
vUv = uv;
}
This way, when you do a texture lookup in the fragment shader with texture2D(uTexture, vUv);
, the values will be available. Otherwise, I think they'll either be 0.0
, or just give you an error.