我想在 HTML 5.0 画布中绘制一个 3D 球或球体。我想了解有关如何绘制 3D 球体的算法。谁能和我分享这个?
4 回答
您将需要对球体进行建模,并使其具有不同的颜色,以便在旋转时您可以看到它不仅是球体,而且正在被渲染。
否则,空间中没有参考点的球体看起来像一个圆,如果它都是一种纯色的话。
首先,您将要尝试用矩形绘制一个圆,因为这是您拥有的主要图元。
一旦您了解了如何做到这一点,或者使用 Path 方法创建一个新的基本体(例如三角形)并创建一个圆,那么您就可以将其移动到 3D 了。
3D 只是一个技巧,因为您将获取可能由方程式生成的模型,然后将其展平,因为您确定将看到哪些部分,然后显示它。
但是,您需要根据三角形与光源的距离以及该部分与光源的角度来更改三角形的颜色。
这是您可以开始进行优化的地方,因为如果您逐个像素地进行此操作,那么您就是在进行光线追踪。如果您有较大的块和一个点光源,并且对象正在旋转但没有四处移动,那么您可以重新计算每个三角形的颜色如何变化,那么只需改变颜色来模拟旋转即可。
该算法将取决于您想要进行哪些简化,因此当您获得经验时回来询问,显示您到目前为止所做的事情。
这是一个例子,下面我复制了3D球体部分,但请看整篇文章。
function Sphere3D(radius) {
this.point = new Array();
this.color = "rgb(100,0,255)"
this.radius = (typeof(radius) == "undefined") ? 20.0 : radius;
this.radius = (typeof(radius) != "number") ? 20.0 : radius;
this.numberOfVertexes = 0;
// Loop from 0 to 360 degrees with a pitch of 10 degrees ...
for(alpha = 0; alpha <= 6.28; alpha += 0.17) {
p = this.point[this.numberOfVertexes] = new Point3D();
p.x = Math.cos(alpha) * this.radius;
p.y = 0;
p.z = Math.sin(alpha) * this.radius;
this.numberOfVertexes++;
}
// Loop from 0 to 90 degrees with a pitch of 10 degrees ...
// (direction = 1)
// Loop from 0 to 90 degrees with a pitch of 10 degrees ...
// (direction = -1)
for(var direction = 1; direction >= -1; direction -= 2) {
for(var beta = 0.17; beta < 1.445; beta += 0.17) {
var radius = Math.cos(beta) * this.radius;
var fixedY = Math.sin(beta) * this.radius * direction;
for(var alpha = 0; alpha < 6.28; alpha += 0.17) {
p = this.point[this.numberOfVertexes] = new Point3D();
p.x = Math.cos(alpha) * radius;
p.y = fixedY;
p.z = Math.sin(alpha) * radius;
this.numberOfVertexes++;
}
}
}
}
更新:此代码相当陈旧且有限。现在有用于制作 3D 球体的库:http: //techslides.com/d3-globe-with-canvas-webgl-and-three-js/
十多年前,我编写了一个 Java 小程序,通过实际计算来计算球体表面在场景中的位置(不使用三角形)来渲染带纹理的球体。
我已经用 JavaScript 为画布重写了它,并且我有一个将地球渲染为球体的演示:
(来源:haslers.info)
我的机器上大约 22 fps。这与它基于渲染的 Java 版本一样快,如果不是快一点的话!
现在距离我编写 Java 代码已经有很长时间了——而且它非常迟钝——所以我真的不记得它是如何工作的,我只是将它移植到 JavaScript。然而,这是来自代码的慢版本,我不确定更快的版本是由于我用来操作像素的 Java 方法中的优化,还是由于它计算出从哪个像素渲染的数学加速质地。当时我也与一个拥有类似小程序的人通信,该小程序比我的要快得多,但我不知道他们在 JavaScript 中是否可以实现任何速度改进,因为它可能依赖于 Java 库。(我从未见过他们的代码,所以我不知道他们是如何做到的。)
所以有可能提高速度。但这可以很好地作为概念证明。
一段时间后,我将尝试转换我的更快版本,看看是否可以在 JavaScript 版本中获得任何速度改进。
您可以尝试使用 three.js 库,它从核心 webgl 编程中抽象出大量代码。在您的 html 中从three.js lib中包含 three.js 库。
您可以将画布渲染器用于 safari 浏览器,webgl 可用于 chrome
var 相机, 场景, 材质, 网格, 几何, 渲染器
function drawSphere() {
init();
animate();
}
function init() {
// camera
scene = new THREE.Scene()
camera = new THREE.PerspectiveCamera(50, window.innerWidth / innerHeight, 1, 1000);
camera.position.z = 300;
scene.add(camera);
// sphere object
var radius = 50,
segments = 10,
rings = 10;
geometry = new THREE.SphereGeometry(radius, segments, rings);
material = new THREE.MeshNormalMaterial({
color: 0x002288
});
mesh = new THREE.Mesh(geometry, material);
//scene
;
scene.add(mesh);
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
}
function animate() {
requestAnimationFrame(animate);
render();
}
function render() {
mesh.rotation.x += .01;
mesh.rotation.y += .02;
renderer.render(scene, camera);
}
// fn callin
drawSphere();
好吧,球体图像在屏幕上总是呈圆形,所以唯一重要的是阴影。这将取决于您放置光源的位置。
至于算法,光线追踪是最简单的,但也是迄今为止最慢的——所以你可能不想用它来做任何非常复杂的事情<CANVAS>
(特别是考虑到在那个环境中缺乏可用的图形加速),但它如果您只想做一个球体,可能就足够快了。