Я хочу нарисовать трехмерный шар или сферу на холсте HTML 5.0. Я хочу понять алгоритм рисования трехмерной сферы. Кто может поделиться этим со мной?
Как нарисовать 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++;
}
}
}
}
вы можете попробовать с библиотекой three.js, которая абстрагирует много кода от основного программирования webgl. Включите библиотеку three.js в свой html из three.js lib.
вы можете использовать средство визуализации холста для браузера сафари, webgl работает для хрома
найдите JS FIDDLE FOR SPHERE
var camera, сцена, материал, сетка, геометрия, рендерер
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();
Обновление: этот код устарел и ограничен. Сейчас есть библиотеки для создания 3D-сфер: http://techslides.com/d3-globe-with-canvas-webgl-and-three-js/
Более десяти лет назад я написал Java-апплет для рендеринга текстурированной сферы, фактически выполняя математические вычисления, чтобы выяснить, где находится поверхность сферы в сцене (без использования треугольников).
Я переписал его на JavaScript для холста и получил демонстрационная визуализация земли в виде сферы:
(источник: haslers.info)
Я получаю около 22 кадров в секунду на моей машине. Это примерно так же быстро, как версия Java, на которой она была основана на рендерах, если не немного быстрее!
Прошло много времени с тех пор, как я написал код Java - и он был довольно тупым - поэтому я точно не помню, как он работает, я просто портировал его на JavaScript. Однако это из медленной версии кода, и я не уверен, была ли более быстрая версия связана с оптимизацией методов Java, которые я использовал для управления пикселями, или с ускорением в математике, которую он выполняет, чтобы решить, какой пиксель отображать из текстура. Я также переписывался в то время с кем-то, у кого был похожий апплет, который был намного быстрее моего, но опять же я не знаю, возможно ли какое-либо улучшение скорости, которое у них было, в JavaScript, поскольку он мог полагаться на библиотеки Java. (Я никогда не видел их кода, поэтому не знаю, как они это сделали.)
Таким образом, может улучшить скорость. Но это хорошо работает в качестве доказательства концепции.
Через какое-то время я попытаюсь преобразовать свою более быструю версию, чтобы посмотреть, смогу ли я добиться каких-либо улучшений скорости в версии JavaScript.
Что ж, изображение сферы всегда будет иметь круглую форму на вашем экране, поэтому единственное, что имеет значение, — это затенение. Это будет определяться тем, где вы разместите источник света.
Что касается алгоритмов, трассировка лучей — самый простой, но и самый медленный. до сих пор, поэтому вы, вероятно, не захотите использовать его для выполнения чего-либо очень сложного в <CANVAS>
(особенно с учетом отсутствия графического ускорения, доступного в этой среде), но это может быть достаточно быстро, если вы просто хотите сделать одну сферу.