Html 如何绘制 3D 球体?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1584854/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 01:04:46  来源:igfitidea点击:

How to draw a 3D sphere?

htmlhtml5-canvas

提问by user165273

I want to draw a 3D ball or sphere in HTML 5.0 canvas. I want to understand the Algorithm about how to draw a 3D sphere. Who can share this with me?

我想在 HTML 5.0 画布中绘制一个 3D 球或球体。我想了解有关如何绘制 3D 球体的算法。谁能与我分享这个?

回答by James Black

You will need to model a sphere, and have it be varying colors so that as it rotates you can see that it is not only a sphere, but being rendered.

您需要对一个球体建模,并为其设置不同的颜色,以便在它旋转时您可以看到它不仅是一个球体,而且正在被渲染。

Otherwise, a sphere in space, with not point of reference around it looks like a circle, if it is all one solid color.

否则,空间中没有参考点的球体看起来像一个圆,如果它都是一种纯色。

To start with you will want to try drawing a circle with rectangles, as that is the main primitive you have.

首先,您需要尝试用矩形绘制一个圆,因为这是您拥有的主要基元。

Once you understand how to do that, or create a new primitive, such as a triangle, using the Path method, and create a circle, then you are ready to move it to 3D.

一旦您了解了如何做到这一点,或者使用 Path 方法创建一个新的图元(例如三角形)并创建一个圆,那么您就可以将其移动到 3D 了。

3D is just a trick, as you will take your model, probably generated by an equation, and then flatten it, as you determine which parts will be seen, and then display it.

3D 只是一个技巧,因为您将使用可能由方程生成的模型,然后将其展平,以确定将看到哪些部分,然后显示它。

But, you will want to change the color of the triangles based on how far they are from a source of light, as well as based on the angle of that part to the light source.

但是,您需要根据三角形与光源的距离以及该部分与光源的角度来更改三角形的颜色。

This is where you can start to do optimizations, as, if you do this pixel by pixel then you are raytracing. If you have larger blocks, and a point source of light, and the object is rotating but not moving around then you can recalculate how the color changes for each triangle, then it is just a matter of changing colors to simulate rotating.

这是您可以开始进行优化的地方,因为,如果您逐个像素地执行此操作,那么您就是在进行光线跟踪。如果您有更大的块和一个点光源,并且对象正在旋转但不四处移动,那么您可以重新计算每个三角形的颜色如何变化,那么这只是改变颜色来模拟旋转的问题。

The algorithm will depend on what simplifications you want to make, so as you gain experience come back and ask, showing what you have done so far.

该算法将取决于您想要进行哪些简化,因此当您获得经验时,请回来询问,展示您到目前为止所做的工作。

Here is an example of doing it, and below I copied the 3D sphere part, but please look at the entire article.

下面是做的一个例子,下面我复制了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++;
     }
   }
 }
}

回答by Sam Hasler

Update:This code is quite old and limited. There are libraries for doing 3D spheres now: http://techslides.com/d3-globe-with-canvas-webgl-and-three-js/

更新:这段代码很旧而且有限。现在有用于制作 3D 球体的库:http: //techslides.com/d3-globe-with-canvas-webgl-and-three-js/



Over ten years ago I wrote a Java applet to render a textured sphere by actually doing the math to work out where the surface of the sphere was in the scene (not using triangles).

十多年前,我编写了一个 Java 小程序,通过实际进行数学运算来计算球体表面在场景中的位置(不使用三角形)来渲染带纹理的球体。

I've rewritten it in JavaScript for canvas and I've got a demo rendering the earth as a sphere:

我已经用 JavaScript 为画布重写了它,并且我有一个将地球渲染为球体演示

alt text
(source: haslers.info)

替代文字
(来源:haslers.info

I get around 22 fps on my machine. Which is about as fast as the Java version it was based on renders at, if not a little faster!

我在我的机器上获得了大约 22 fps。这与它基于渲染的 Java 版本一样快,甚至快一点!

Now it's a long time since I wrote the Java code - and it was quite obtuse - so I don't really remember exactly how it works, I've just ported it JavaScript. However this is from a slow version of the code and I'm not sure if the faster version was due to optimisations in the Java methods I used to manipulate pixels or from speedups in the math it does to work out which pixel to render from the texture. I was also corresponding at the time with someone who had a similar applet that was much faster than mine but again I don't know if any of the speed improvements they had would be possible in JavaScript as it may have relied on Java libraries. (I never saw their code so I don't know how they did it.)

现在距离我编写 Java 代码已经很长时间了——而且它非常迟钝——所以我真的不记得它是如何工作的,我只是将它移植到 JavaScript。然而,这是来自代码的慢版本,我不确定更快的版本是由于我用来操作像素的 Java 方法中的优化还是由于数学中的加速来计算出从哪个像素渲染质地。当时我还与一个拥有类似小程序的人通信,该小程序比我的快得多,但我不知道他们在 JavaScript 中是否可以实现任何速度改进,因为它可能依赖于 Java 库。(我从未见过他们的代码,所以我不知道他们是如何做到的。)

So it maybe possible to improve on the speed. But this works well as a proof of concept.

所以有可能提高速度。但这可以很好地作为概念证明。

I'll have a go at converting my faster version some time to see if I can get any speed improvements into the JavaScript version.

有时间我会尝试转换我的更快版本,看看我是否可以在 JavaScript 版本中获得任何速度改进。

回答by Bhupendra

u can try with three.js library , which abstracts a lot of code from core webgl programming. Include three.js library in your html from three.js lib.

你可以尝试使用three.js库,它从核心webgl编程中抽象出很多代码。在您的 html 中从three.js lib 中包含three.js 库。

u can use canvas renderer for safari browser , webgl works for chrome

你可以为 safari 浏览器使用画布渲染器,webgl 适用于 chrome

please find the JS FIDDLE FOR SPHERE

请找到JS FIDDLE FOR SPHERE

var camera, scene, material, mesh, geometry, renderer

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();

回答by David

Well, an image of a sphere will always have a circular shape on your screen, so the only thing that matters is the shading. This will be determined by where you place your light source.

好吧,球体的图像在您的屏幕上总是呈圆形,因此唯一重要的是阴影。这将取决于您放置光源的位置。

As for algorithms, ray tracingis the simplest, but also the slowest by far — so you probably wouldn't want to use it to do anything very complicated in a <CANVAS>(especially given the lack of graphics acceleration available in that environment), but it might be fast enough if you just wanted to do a single sphere.

至于算法,光线追踪是最简单的,但也是最慢的——所以你可能不想用它来做任何非常复杂的事情<CANVAS>(特别是考虑到该环境中缺乏可用的图形加速),但它如果你只想做一个球体,可能已经足够快了。