three.js - GLSL/THREE.js 将形状变成立方体的数学问题
问题描述
我正在编写代码以在顶点着色器中将球体变成立方体,但它似乎变成了这种奇怪的形状,我的逻辑是这样的:
注释掉的代码是迭代版本。
vec3 p = position;
if(true)
{
if(p.y<s&&p.y>-s){
p.x = -(p.x-s);//p.x-=(p.x-s)*t*0.1;
}
if(p.x<s&&p.x>-s){
p.y = -(p.y-s);//p.y-=(p.y-s)*t*0.1;
}
}
gl_Position = projectionMatrix * modelViewMatrix * vec4( p, 1.0 );
但这会变成这样:
进入这个:
任何帮助表示赞赏。
解决方案
THREE.BoxBufferGeometry()
用作基础,然后添加另一个带有坐标的缓冲区属性以形成球体,然后在着色器中插入(混合)盒子和球体的坐标:
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(1, 3, 5);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
scene.add(new THREE.GridHelper(10, 10));
var side = 2;
var rad = Math.sqrt(3) * 0.5 * side; // radius of the sphere is a half of cube's diagonal
var geom = new THREE.BoxBufferGeometry(side, side, side, 10, 10, 10);
var pos = geom.attributes.position;
var spherePos = []; // array of coordinates for the sphere formation
var vec3 = new THREE.Vector3(); // vector for re-use
for (let i = 0; i < pos.count; i++) {
vec3.fromBufferAttribute(pos, i).setLength(rad); // create coordinate for the sphere formation
spherePos.push(vec3.x, vec3.y, vec3.z);
}
geom.addAttribute("spherePos", new THREE.BufferAttribute(new Float32Array(spherePos), 3));
var mat = new THREE.ShaderMaterial({
uniforms: {
mixShapes: {
value: 0
}
},
vertexShader: `
uniform float mixShapes;
attribute vec3 spherePos;
void main() {
vec3 pos = mix(position, spherePos, mixShapes); // interpolation between shapes
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
fragmentShader: `
void main() {
gl_FragColor = vec4(1.0, 0.0, 1.0,1.0);
}
`,
wireframe: true
});
var shape = new THREE.Mesh(geom, mat);
scene.add(shape);
var gui = new dat.GUI();
gui.add(mat.uniforms.mixShapes, "value", 0.0, 1.0).name("mixShapes");
renderer.setAnimationLoop(() => {
renderer.render(scene, camera)
});
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.6/dat.gui.min.js"></script>
如果你想从一个球体中得到一个立方体,你可以将顶点夹在你需要的边界框的最小和最大向量上(但这种方法的准确性取决于球体的顶点数量):
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(1, 3, 5);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
scene.add(new THREE.GridHelper(10, 10));
var side = 2;
var rad = Math.sqrt(3) * 0.5 * side; // radius of the sphere is a half of cube's diagonal
var geom = new THREE.SphereBufferGeometry(rad, 36, 36);
var mat = new THREE.ShaderMaterial({
uniforms: {
mixShapes: {
value: 0
}
},
vertexShader: `
uniform float mixShapes;
attribute vec3 spherePos;
void main() {
vec3 pos = clamp(position, vec3(${-side * 0.5}), vec3(${side * 0.5})); // clamp to min and max vectors
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
fragmentShader: `
void main() {
gl_FragColor = vec4(1.0, 0.0, 1.0,1.0);
}
`,
wireframe: true
});
var shape = new THREE.Mesh(geom, mat);
scene.add(shape);
renderer.setAnimationLoop(() => {
renderer.render(scene, camera)
});
body {
overflow: hidden;
margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
推荐阅读
- python - 用浓度箱 Python 绘制风玫瑰图
- ansible - 将字典传递给子模块角色时未定义的变量
- typescript - 错误:获取https://deno.land/std@0.59.0/path/mod.ts的编译源代码失败。原因:系统找不到指定的路径。(操作系统错误 3)
- excel - 将用户窗体按钮标签链接到 VLookup 代码
- python-3.x - 如何从 Flask 中的 jinja 模板创建 PDF 文件?[标记为 pythonanywhere 的问题]
- firebase - 如何更新 firebase 数组中的地图数据?(扑)
- java - 当我已经导入了它们所在的包时,为什么还需要导入枚举类才能使用它们?[爪哇]
- r - 你可以在不声明的情况下命名一个变量吗?
- javascript - 重新渲染平面列表没有自动上传项目
- php - php cURL PATCH 请求返回数据但不更新字段