我想通过制服将鼠标位置传递到着色器,以便在移动鼠标时交互式地改变颜色。
请参阅“★”的评论,我想这是我的问题的关键代码。
我对着色器很新,我只是出于锻炼目的而创造这个。我想知道的是如何将鼠标位置从js(我使用three.js)传递到着色器以及如何在着色器中使用它。 (我认为需要对其进行规范化才能使用r,g和b中的值?)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/104/three.min.js"></script>
<title>Document</title>
</head>
<body>
<div id="container"></div>
<script id="vertexShader" type="x-shader/x-vertex">
void main(){
gl_Position = vec4(position, 1.0);
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
uniform vec2 u_resolution;
uniform float u_time;
uniform vec2 u_mouse;
//★set the mouse positions to the colors
void main(){
vec2 st = gl_FragCoord.xy / u_resolution.xy;
vec2 um = u_mouse.xy;
gl_FragColor = vec4(um.x, um.y, 0.0, 0.1);
}
</script>
<script>
var container;
var camera, scene, renderer;
var uniforms;
init();
animate();
function init() {
container = document.getElementById('container');
camera = new THREE.Camera();
camera.position.z = 1;
scene = new THREE.Scene();
var geometry = new THREE.PlaneBufferGeometry(2, 2);
uniforms = {
u_time: { type: "f", value: 1.0 },
u_resolution: { type: "v2", value: new THREE.Vector2() },
u_mouse: { type: "v2", value: new THREE.Vector2() }
};
var material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent
});
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
container.appendChild(renderer.domElement);
onWindowResize();
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize(e) {
renderer.setSize(window.innerWidth, window.innerHeight);
uniforms.u_resolution.value.x = renderer.domElement.width;
uniforms.u_resolution.value.y = renderer.domElement.height;
}
function animate() {
requestAnimationFrame(animate);
render();
}
//★set the mouse positions to shader
function render() {
uniforms.u_time.value += 0.05;
document.onmousemove = function (e) {
uniforms.u_mouse.x = e.pageX;
uniforms.u_mouse.y = (e.pageY;
}
renderer.render(scene, camera);
}
</script>
</body>
</html>
首先,请了解如何使用snippet进一步提问。有一个很好的例子here
其次,问题的答案在你的问题中。你能看出它们之间的区别吗?
uniforms.u_resolution.value.x = renderer.domElement.width;
uniforms.u_resolution.value.y = renderer.domElement.height;
还有这个?
uniforms.u_mouse.x = e.pageX;
uniforms.u_mouse.y = e.pageY;
Three.js制服的形式为uniforms.<name>.value.property
。你没有把'价值'放在一边。
但是其他问题,three.js中的颜色从0变为1,所以只使用e.pageX
和e.pageY
不会给你任何颜色,除了页面左上角的黑色和白色的其他地方,因为值将是1或更大到处
你可以试试
uniforms.u_mouse.x = e.pageX / window.innerWidth;
uniforms.u_mouse.y = e.pageY / window.innerHeight;
为了给你一个更合适的价值。我说也许是因为你不清楚你想要改变颜色的上下文。在窗口上,在页面上,在画布上,在其他元素上,所有这些都可以是不同的。
另外一件事,你通常不想在渲染循环中分配一个事件。您可以在初始时分配一次。
这是代码片段中的代码
var container;
var camera, scene, renderer;
var uniforms;
init();
animate();
function init() {
container = document.getElementById('container');
camera = new THREE.Camera();
camera.position.z = 1;
scene = new THREE.Scene();
var geometry = new THREE.PlaneBufferGeometry(2, 2);
uniforms = {
u_time: {
type: "f",
value: 1.0
},
u_resolution: {
type: "v2",
value: new THREE.Vector2()
},
u_mouse: {
type: "v2",
value: new THREE.Vector2()
}
};
var material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent
});
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio(window.devicePixelRatio);
container.appendChild(renderer.domElement);
onWindowResize();
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize(e) {
renderer.setSize(window.innerWidth, window.innerHeight);
uniforms.u_resolution.value.x = renderer.domElement.width;
uniforms.u_resolution.value.y = renderer.domElement.height;
}
function animate() {
requestAnimationFrame(animate);
render();
}
document.onmousemove = function(e) {
uniforms.u_mouse.value.x = e.pageX / window.innerWidth;
uniforms.u_mouse.value.y = e.pageY / window.innerHeight;
}
//★set the mouse positions to shader
function render() {
uniforms.u_time.value += 0.05;
renderer.render(scene, camera);
}
body { margin: 0; }
canvas { display: block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/104/three.min.js"></script>
<div id="container"></div>
<script id="vertexShader" type="x-shader/x-vertex">
void main(){
gl_Position = vec4(position, 1.0);
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
uniform vec2 u_resolution;
uniform float u_time;
uniform vec2 u_mouse;
//set the mouse positions to the colors
void main(){
vec2 st = gl_FragCoord.xy / u_resolution.xy;
vec2 um = u_mouse.xy;
gl_FragColor = vec4(um.x, um.y, 0.0, 0.1);
}
</script>