Reputation: 27574
I am working on a scene in threejs that renders an image of a cat.
Specifically, I'd like to render a rectangle, and I'd like for the right half of that rectangle to be red, and for the left half of that rectangle to contain the full image of the cat (the image will be stretched and that's fine).
Here's my scene:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 2;
var renderer = new THREE.WebGLRenderer({antialias: true});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var geometry = new THREE.BufferGeometry();
var imageSize = {width: 3, height: 2};
// add verts
var coords = {x: -1.5, y: -1, z: 0};
var vertices = new Float32Array([
coords.x, coords.y, coords.z,
coords.x+imageSize.width, coords.y, coords.z,
coords.x+imageSize.width, coords.y+imageSize.height, coords.z,
coords.x, coords.y+imageSize.height, coords.z,
])
var uvs = new Float32Array([
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
])
geometry.setIndex([0,1,2, 2,3,0])
geometry.setAttribute('position', new THREE.BufferAttribute( vertices, 3 ));
geometry.setAttribute('uv', new THREE.BufferAttribute( uvs, 2) )
var loader = new THREE.TextureLoader();
var url = 'https://s3.amazonaws.com/duhaime/blog/tsne-webgl/assets/cat.jpg';
var material = new THREE.RawShaderMaterial({
uniforms: {
texture: {
type: 't',
value: loader.load(url)
},
},
vertexShader: document.getElementById('vertex-shader').textContent,
fragmentShader: document.getElementById('fragment-shader').textContent
});
var mesh = new THREE.Mesh(geometry, material);
mesh.position.set(0,0,0)
scene.add(mesh);
function render() {
requestAnimationFrame(render);
renderer.render(scene, camera);
console.clear();
};
render();
<script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js'></script>
<script type='x-shader/x-vertex' id='vertex-shader'>
precision mediump float;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform vec3 cameraPosition;
attribute vec3 position;
attribute vec3 translation;
attribute vec2 uv;
varying vec2 vUv;
varying vec3 vPosition;
void main() {
vUv = uv;
vPosition = position;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
</script>
<script type='x-shader/x-fragment' id='fragment-shader'>
precision highp float;
uniform sampler2D texture;
varying vec2 vUv;
varying vec3 vPosition;
void main() {
vec2 uv = vUv;
if (vPosition.x > 0.0) {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
} else {
gl_FragColor = texture2D(texture, uv);
}
}
</script>
As you can see, only half of the cat image is displayed on the left hand side of the rectangle. I'm not sure how to display the full cat image on the left hand side of the rectangle. Does anyone know? Any pointers would be greatly appreciated!
Upvotes: 1
Views: 118
Reputation: 210878
[...] I'd like for the right half of that rectangle to be red, and for the left half of that rectangle to contain the full image [...]
The texture coordinates are in the range [0.0, 1.0]. The center of the texture is at (0.5, 0.5). Therefore, in the right half of the texture, the x component of the texture coordinate is > 0.5. On the left, you need to scale the x component of the texture coordinates by 2.0:
gl_FragColor = vUv.x > 0.5
? vec4(1.0, 0.0, 0.0, 1.0)
: texture2D(texture, vec2(vUv.x*2.0, vUv.y));
Upvotes: 1