# X3D：现代 Web 的声明式 3D 技术

## SVG：可伸缩的矢量图形

SVG





（retained-mode graphics rendering）。

## 画布

canvas

const canvas = document.getElementById(id);
const context = canvas.getContext(contextType);

// call some methods on context to draw onto the canvas

（immediate-mode graphics rendering）。

### 上下文：2D



const canvas = document.getElementById("my-canvas");
const context = canvas.getContext("2d");

function render() {
// Size the drawing surface to match the actual element (no stretch).
canvas.height = canvas.clientHeight;
canvas.width = canvas.clientWidth;

context.beginPath();

// Calculate relative size and position of circle in pixels.
const x = 0.5 * canvas.width;
const y = 0.5 * canvas.height;
const radius = 0.25 * Math.min(canvas.height, canvas.width);

context.arc(x, y, radius, 0, 2 * Math.PI);

context.fillStyle = "red";
context.fill();

context.strokeStyle = "black";
context.stroke();
}

render();



## 上下文：WebGL



const canvas = document.getElementById("my-canvas");
const context = canvas.getContext("webgl");

const redColor = new Float32Array([1.0, 0.0, 0.0, 1.0]);
const blackColor = new Float32Array([0.0, 0.0, 0.0, 1.0]);

// Use an orthogonal projection matrix as we're rendering in 2D.
const projectionMatrix = new Float32Array([
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0,
]);

// Define positions of the vertices of the circle (in clip space).
const segmentCount = 360;
const positions = [0.0, 0.0];
for (let i = 0; i < segmentCount + 1; i++) {
positions.push(radius * Math.sin(2 * Math.PI * i / segmentCount));
positions.push(radius * Math.cos(2 * Math.PI * i / segmentCount));
}

const positionBuffer = context.createBuffer();
context.bindBuffer(context.ARRAY_BUFFER, positionBuffer);
context.bufferData(context.ARRAY_BUFFER, new Float32Array(positions), context.STATIC_DRAW);

attribute vec4 position;
uniform mat4 projection;

void main() {
gl_Position = projection * position;
}
);

uniform lowp vec4 color;

void main() {
gl_FragColor = color;
}
);

const program = context.createProgram();

const positionAttribute = context.getAttribLocation(program, 'position');

const colorUniform = context.getUniformLocation(program, 'color');
const projectionUniform = context.getUniformLocation(program, 'projection');

function render() {
// Size the drawing surface to match the actual element (no stretch).
canvas.height = canvas.clientHeight;
canvas.width = canvas.clientWidth;

context.viewport(0, 0, canvas.width, canvas.height);

context.useProgram(program);

// Scale projection to maintain 1:1 ratio between height and width on canvas.
projectionMatrix[0] = canvas.width > canvas.height ? canvas.height / canvas.width : 1.0;
projectionMatrix[5] = canvas.height > canvas.width ? canvas.width / canvas.height : 1.0;
context.uniformMatrix4fv(projectionUniform, false, projectionMatrix);

const vertexSize = 2;
const vertexCount = positions.length / vertexSize;

context.bindBuffer(context.ARRAY_BUFFER, positionBuffer);
context.vertexAttribPointer(positionAttribute, vertexSize, context.FLOAT, false, 0, 0);
context.enableVertexAttribArray(positionAttribute);

context.uniform4fv(colorUniform, redColor);
context.drawArrays(context.TRIANGLE_FAN, 0, vertexCount);

context.uniform4fv(colorUniform, blackColor);
context.drawArrays(context.LINE_STRIP, 1, vertexCount - 1);
}

render();



## 面向声明式的 3D 图形

• 基于 XML 格式的 3D 模型声明；
• 使用 webgl 上下文将它们绘制到画布上的 JavaScript 代码。

## X3D ——拼图中缺失的这块？

X3D

X_ite

X3DOM 是由弗劳恩霍夫计算机图形研究所 IGD（The Fraunhofer Institute for Computer Graphics Research IGD）开发的，IGD 本身也是 Web3D 联盟的成员。为了使用它，您只需要在 HTML 页面中包含 X3DOM JavaScript 代码和样式表。



x3d > canvas { display: block; }





x3d > canvas { display: block; }



X3DOM 还提供了开箱即用的导航功能，允许您旋转、平移和缩放模型。根据您正在编写的应用程序的类型，还可以使用各种不同的控制方案和导航模式。