è¡åã¯ã空éå
ã®ãªãã¸ã§ã¯ãã®å¤æã表ãããã«ä½¿ç¨ã§ããç»åãæ§ç¯ããããã¦ã§ãä¸ã§ãã¼ã¿ãè¦è¦åãããããã¨ãã«ãå¤ãã®ä¸»è¦ãªç¨®é¡ã®è¨ç®ãå®è¡ããããã«ä½¿ç¨ããã¾ãã ãã®è¨äºã§ã¯ãè¡åã使ããæ¹æ³ã¨ãCSS 座æ¨å¤æ ããã³ matrix3d
transform åã§ãããã使ç¨ããæ¹æ³ã«ã¤ãã¦èª¬æãã¾ãã
ãã®è¨äºã§ã¯ CSS ã使ç¨ãã¦èª¬æãç°¡ç¥åãã¾ãããè¡å㯠WebGLãWebXRï¼VR ããã³ ARï¼APIãGLSL ã·ã§ã¼ãã¼ãªã©ã®ãã¾ãã¾ãªãã¯ããã¸ã¼ã§ä½¿ç¨ãããã³ã¢ã³ã³ã»ããã§ãã ãã®è¨äºã¯ãMDN ã³ã³ãã³ããããã¨ãã¦ãå
¥æã§ãã¾ãã å®éã®ä¾ã§ã¯ãMDN
ã¨ããååã®ã°ãã¼ãã«ãªãã¸ã§ã¯ãã§ä½¿ç¨ã§ããã¦ã¼ãã£ãªãã£é¢æ°ã®ã³ã¬ã¯ã·ã§ã³ã使ç¨ãã¦ãã¾ãã
è¡åã«ã¯å¤ãã®ç¨®é¡ãããã¾ãããç§ãã¡ãèå³ãæã£ã¦ããã®ã¯ 3D 夿è¡åã§ãã ãããã®è¡åã¯ã 4Ã4 ã®ã°ãªããã«é ç½®ããã 16 åã®å¤ã®ã»ããã§æ§æããã¦ãã¾ãã JavaScript ã§ã¯ãè¡åãé åã¨ãã¦è¡¨ãã®ã¯ç°¡åã§ãã
ã¾ããåä½è¡å (identity matrix) ã«ã¤ãã¦æ¤è¨ãã¾ãã ããã¯ç¹å¥ãªå¤æè¡åã§ãããã¹ã«ã©ã¼ä¹ç®ã§ã® 1 ã¨åãããã«æ©è½ãã¾ãã n * 1 = n ã¨åæ§ã«ãä»»æã®è¡åã«åä½è¡åãä¹ç®ããã¨ãå ã®è¡åã¨å¤ãä¸è´ããçµæã®è¡åãå¾ããã¾ãã
åä½è¡å㯠JavaScript ã§ã¯æ¬¡ã®ããã«ãªãã¾ãã
let identityMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
åä½è¡åã®ä¹ç®ã¨ã¯ã©ã®ãããªãã®ã§ããããï¼ æãç°¡åãªä¾ã¯ãåä¸ã®ç¹ã«åä½è¡åãä¹ç®ãããã¨ã§ãã 3D ã®ç¹ã«å¿
è¦ãªã®ã¯ 3 ã¤ã®å¤ (x
ãy
ãz
) ã ãã§ããã夿è¡å㯠4Ã4 ã®å¤ã®è¡åãªã®ã§ãç¹ã«ã¯ 4 çªç®ã®æ¬¡å
ã追å ããå¿
è¦ãããã¾ãã æ
£ä¾ã«ããããã®æ¬¡å
ã¯è¦ç¹è·é¢ (perspective) ã¨å¼ã°ããæå w
ã§è¡¨ããã¾ãã ä¸è¬çã«ã¯ã w
ã 1 ã«è¨å®ããã¨ãè¨ç®ããã¾ãããã¾ãã
w æåãç¹ã«è¿½å ããå¾ãè¡åã¨ç¹ãã©ã®ããã«ãããã«ä¸¦ãã§ãããã«æ³¨ç®ãã¦ãã ããã
[1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1]
[4, 3, 2, 1] // Point at [x, y, z, w]
w
æåã«ã¯ããã®è¨äºã®ç¯å²å¤ã®ããã¤ãã®è¿½å ã®ç¨éãããã¾ãã WebGL ã®ã¢ãã«ããã¥ã¼ãæå½±ã«é¢ããè¨äºã調ã¹ã¦ãã©ã®ããã«å½¹ç«ã¤ããè¦ãã¦ã¿ã¦ãã ããã
ãã®ãµã³ãã«ã³ã¼ãã§ã¯ãè¡åã¨ç¹ãä¹ç®ãã颿° multiplyMatrixAndPoint()
ãå®ç¾©ãã¦ãã¾ãã
// ç¹ â¢ è¡å
function multiplyMatrixAndPoint(matrix, point) {
// è¡åã®åé¨åã«ãå cãè¡ r ã®çªå·ã§åç´ãªå¤æ°åãä»ãã¾ã
let c0r0 = matrix[0],
c1r0 = matrix[1],
c2r0 = matrix[2],
c3r0 = matrix[3];
let c0r1 = matrix[4],
c1r1 = matrix[5],
c2r1 = matrix[6],
c3r1 = matrix[7];
let c0r2 = matrix[8],
c1r2 = matrix[9],
c2r2 = matrix[10],
c3r2 = matrix[11];
let c0r3 = matrix[12],
c1r3 = matrix[13],
c2r3 = matrix[14],
c3r3 = matrix[15];
// 次ã«ãç¹ã«ããåç´ãªååãè¨å®ãã¾ã
let x = point[0];
let y = point[1];
let z = point[2];
let w = point[3];
// 1çªç®ã®åã®åé¨åã«å¯¾ãã¦ç¹ãä¹ç®ããæ¬¡ã«åè¨ãã¾ã
let resultX = x * c0r0 + y * c0r1 + z * c0r2 + w * c0r3;
// 2çªç®ã®åã®åé¨åã«å¯¾ãã¦ç¹ãä¹ç®ããæ¬¡ã«åè¨ãã¾ã
let resultY = x * c1r0 + y * c1r1 + z * c1r2 + w * c1r3;
// 3çªç®ã®åã®åé¨åã«å¯¾ãã¦ç¹ãä¹ç®ããæ¬¡ã«åè¨ãã¾ã
let resultZ = x * c2r0 + y * c2r1 + z * c2r2 + w * c2r3;
// 4çªç®ã®åã®åé¨åã«å¯¾ãã¦ç¹ãä¹ç®ããæ¬¡ã«åè¨ãã¾ã
let resultW = x * c3r0 + y * c3r1 + z * c3r2 + w * c3r3;
return [resultX, resultY, resultZ, resultW];
}
ä¸è¨ã®é¢æ°ã使ç¨ãã¦ãç¹ã«è¡åãæãããã¨ãã§ãã¾ãã åä½è¡åã使ç¨ããã¨ãå ã®è¡åã¨åãè¡åãè¿ããã¾ãã ããã¯ãåä½è¡åãæããè¡åã¯å¸¸ã«ããèªä½ã¨çããããã§ãã
// identityResult ã [4,3,2,1] ã«è¨å®ãã¾ã
let identityResult = multiplyMatrixAndPoint(identityMatrix, [4, 3, 2, 1]);
åãç¹ãè¿ããã¨ã¯ãã¾ãå½¹ã«ç«ã¡ã¾ããããç¹ã«å¯¾ãã¦ä¾¿å©ãªæä½ãå®è¡ã§ããä»ã®ç¨®é¡ã®è¡åãããã¾ãã æ¬¡ã®ã»ã¯ã·ã§ã³ã§ã¯ããããã®è¡åã®ããã¤ãã示ãã¾ãã
2 ã¤ã®è¡åã®ä¹ç®è¡åã¨ç¹ãä¹ç®ãããã¨ã«å ãã¦ã2 ã¤ã®è¡åãä¹ç®ãããã¨ãã§ãã¾ãã ä¸è¨ã®é¢æ°ã¯ããã®ããã»ã¹ãæ¯æ´ããããã«åå©ç¨ã§ãã¾ãã
// è¡åB ⢠è¡åA
function multiplyMatrices(matrixA, matrixB) {
// 2çªç®ã®è¡åãè¡ã«ã¹ã©ã¤ã¹ãã¾ã
let row0 = [matrixB[0], matrixB[1], matrixB[2], matrixB[3]];
let row1 = [matrixB[4], matrixB[5], matrixB[6], matrixB[7]];
let row2 = [matrixB[8], matrixB[9], matrixB[10], matrixB[11]];
let row3 = [matrixB[12], matrixB[13], matrixB[14], matrixB[15]];
// åè¡ã«è¡åAãæãã¾ã
let result0 = multiplyMatrixAndPoint(matrixA, row0);
let result1 = multiplyMatrixAndPoint(matrixA, row1);
let result2 = multiplyMatrixAndPoint(matrixA, row2);
let result3 = multiplyMatrixAndPoint(matrixA, row3);
// çµæã®è¡ãåä¸ã®è¡åã«æ»ãã¾ã
return [
result0[0],
result0[1],
result0[2],
result0[3],
result1[0],
result1[1],
result1[2],
result1[3],
result2[0],
result2[1],
result2[2],
result2[3],
result3[0],
result3[1],
result3[2],
result3[3],
];
}
ãã®é¢æ°ã®åä½ãè¦ã¦ã¿ã¾ãããã
let someMatrix = [4, 0, 0, 0, 0, 3, 0, 0, 0, 0, 5, 0, 4, 8, 4, 1];
let identityMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
// someMatrix ã¨åçã®æ°ããé
åãè¿ãã¾ã
let someMatrixResult = multiplyMatrices(identityMatrix, someMatrix);
è¦å: ãããã®è¡å颿°ã¯ã説æãæç¢ºã«ããããã«æ¸ããã¦ãããé度ãã¡ã¢ãªç®¡çã®ããã«ã¯æ¸ããã¦ãã¾ããã ãããã®é¢æ°ã¯å¤ãã®æ°ããé åã使ãã¾ãããããã¯ã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ã®ããã«ããªã¢ã«ã¿ã¤ã æä½ã«ç¹ã«ã³ã¹ãããããå¯è½æ§ãããã¾ãã å®éã®è£½åã³ã¼ãã§ã¯ãæé©åããã颿°ã使ç¨ããã®ãæåã§ãã glMatrix ã¯ãé度ã¨ããã©ã¼ãã³ã¹ã«éç¹ãç½®ããã©ã¤ãã©ãªã¼ã®ä¾ã§ãã glMatrix ã©ã¤ãã©ãªã¼ã®ç¦ç¹ã¯ãæ´æ°ã«ã¼ãã®åã«å²ãå½ã¦ãããã¿ã¼ã²ããé åãæã¤ãã¨ã§ãã
å¹³è¡ç§»åè¡åå¹³è¡ç§»åè¡å (translation matrix) ã¯åä½è¡åã«åºã¥ãã¦ããã3D ã°ã©ãã£ãã¯ã¹ã§ä½¿ç¨ããã3 ã¤ã®æ¹åï¼x
ãy
ãz
ï¼ã® 1 ã¤ã¾ãã¯è¤æ°ã«ç¹ã¾ãã¯ãªãã¸ã§ã¯ããç§»åãã¾ãã å¹³è¡ç§»åãèããæãç°¡åãªæ¹æ³ã¯ãã³ã¼ãã¼ã«ãããæã«åããããªãã®ã§ãã ã³ã¼ãã¼ããã¼ããªãããã«ãã³ã¼ãã¼ã«ããã¯ç´ç«ãããåãæ¹åã«åããå¿
è¦ãããã¾ãã ããã¯ããã¼ãã«ããé¢ãã¦ç©ºä¸ããã¡ãã¡ã¨ç§»åã§ãã¾ãã
ã³ã¼ãã¼ãå£ã®ä¸ã«æ³¨ãã«ã¯ãã«ãããå¾ãããå転ããããããå¿ è¦ããããããå®éã«ã¯å¹³è¡ç§»åè¡åã ãã使ç¨ãã¦ã³ã¼ãã¼ã飲ããã¨ã¯ã§ãã¾ããã ãããè¡ãããã«ä½¿ç¨ããè¡åã®ç¨®é¡ï¼å·§å¦ã«**å転è¡å**ã¨å¼ã°ãã¾ãï¼ãå¾ã§è¦ã¦ããã¾ãã
let x = 50;
let y = 100;
let z = 0;
let translationMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, x, y, z, 1];
3 ã¤ã®è»¸ã«æ²¿ã£ãè·é¢ãå¹³è¡ç§»åè¡åã®å¯¾å¿ããä½ç½®ã«é ç½®ãã3D 空éãç§»åããããã«å¿ è¦ãªç¹ã¾ãã¯è¡åã«æãã¾ãã
è¡åã§ DOM ãæä½ããè¡åã使ãå§ããæ¬å½ã«ç°¡åãªæ¹æ³ã¯ãCSS matrix3d()
transform
ã使ç¨ãããã¨ã§ãã ã¾ããã³ã³ãã³ããå«ãåç´ãª <div>
ãè¨å®ãã¾ãã ã¹ã¿ã¤ã«ã¯ç¤ºãã¾ããããå¹
ã¨é«ããåºå®ããããã¼ã¸ã®ä¸å¤®ã«é
ç½®ããã¾ãã <div>
ã«ã¯ transform ç¨ã®é·ç§»ã»ããããããããä½ãè¡ããã¦ããããç°¡åã«ç¢ºèªã§ããããã«è¡åãã¢ãã¡ã¼ã·ã§ã³åããã¾ãã
<div id="move-me" class="transformable">
<h2>Move me with a matrix</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elitâ¦</p>
</div>
æå¾ã«ãåä¾ã§ 4Ã4 ãããªãã¯ã¹ãçæãã<div>
ã®ã¹ã¿ã¤ã«ãæ´æ°ãã¦ãtransform ãé©ç¨ããmatrix3d
ã«è¨å®ãã¾ãã è¡åã 4 è¡ 4 åã§æ§æããã¦ããå ´åã§ããè¡å㯠16 åã®å¤ã® 1 è¡ã«ã¤ã¶ããã¦ãããã¨ã«æ³¨æãã¦ãã ããã è¡åã¯å¸¸ã« JavaScript ã® 1 次å
ã®ãªã¹ãã«æ ¼ç´ããã¾ãã
// è¡åã®é
åãã matrix3d ã¹ã¿ã¤ã«ããããã£ã使ãã¾ã
function matrixArrayToCssMatrix(array) {
return `matrix3d(${array.join(",")})`;
}
// DOM è¦ç´ ãåå¾ãã¾ã
let moveMe = document.getElementById("move-me");
// 次ã®ãããªçµæãè¿ãã¾ã: "matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 50, 100, 0, 1);"
let matrix3dRule = matrixArrayToCssMatrix(translationMatrix);
// transform ãè¨å®ãã¾ã
moveMe.style.transform = matrix3dRule;
æ¡å¤§ç¸®å°è¡å
æ¡å¤§ç¸®å°è¡å (scale matrix) ã¯ãå¹ ãé«ãã奥è¡ãã® 3 ã¤ã®æ¬¡å ã® 1 ã¤ä»¥ä¸ã§ä½ãã大ããã¾ãã¯å°ãããã¾ãã å ¸åçãªï¼ãã«ã«ãï¼åº§æ¨ã§ã¯ãããã«ãããªãã¸ã§ã¯ãã対å¿ããæ¹åã«ä¼¸ç¸®ãã¾ãã
å¹ ãé«ãã奥è¡ãã®ããããã«é©ç¨ãã夿´ã®éã¯ãå·¦ä¸é ããå³ä¸ã«åãã£ã¦æãã«é ç½®ããã¾ãã
let w = 1.5; // width (x)
let h = 0.7; // height (y)
let d = 1; // depth (z)
let scaleMatrix = [w, 0, 0, 0, 0, h, 0, 0, 0, 0, d, 0, 0, 0, 0, 1];
å転è¡å
å転è¡å (rotation matrix) ã¯ãç¹ã¾ãã¯ãªãã¸ã§ã¯ããå転ãããããã«ä½¿ç¨ãã¾ãã å転è¡åã¯ãæ¡å¤§ç¸®å°è¡åãå¹³è¡ç§»åè¡åãããå°ãè¤éã«è¦ãã¾ãã ããã¯ãä¸è§é¢æ°ã使ç¨ãã¦å転ãå®è¡ãã¾ãã ãã®ç¯ã§ã¯ãæé ãå®å ¨ãªè©³ç´°ã«åè§£ãã¾ãããï¼Wolfram MathWorld ã®ãã®è¨äºã調ã¹ã¦ãã ããï¼ã説æã®ããã«ãã®ä¾ãåãä¸ãã¾ãã
ã¾ããè¡åã使ç¨ããã«åç¹ãä¸å¿ã«ç¹ãå転ãããã³ã¼ããæ¬¡ã«ç¤ºãã¾ãã
// è¡åãªãã§åç¹ãä¸å¿ã«æåã§ç¹ãå転
let point = [10, 2];
// åç¹ããã®è·é¢ãè¨ç®ãã¾ã
let distance = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
// ã©ã¸ã¢ã³ã§ 60 度ã«ç¸å½
let rotationInRadians = Math.PI / 3;
let transformedPoint = [
Math.cos(rotationInRadians) * distance,
Math.sin(rotationInRadians) * distance,
];
ãããã®ã¿ã¤ãã®ã¹ããããè¡åã«ã¨ã³ã³ã¼ãããx
ãy
ãz
ã®å次å
ã«å¯¾ãã¦ãããè¡ããã¨ãã§ãã¾ããä¸è¨ã¯åæè¨åãã® Z 軸å転ãå·¦æåº§æ¨ç³»ã§è¡¨ãããã®ã§ãã
let sin = Math.sin;
let cos = Math.cos;
// 注: ãããã®å¤æã«ã¯è¦ç¹è·é¢ããªãããã
// ãã®æç¹ã§ã®å転㯠div ã縮å°ããããã«ã®ã¿ç¤ºããã¾ã
let a = Math.PI * 0.3; // ã©ã¸ã¢ã³ã§ã®å転é
// Z 軸ãä¸å¿ã«å転
let rotateZMatrix = [
cos(a),
-sin(a),
0,
0,
sin(a),
cos(a),
0,
0,
0,
0,
1,
0,
0,
0,
0,
1,
];
3 ã¤ã®è»¸ã®ãããããä¸å¿ã«å転ããããã®å転è¡åãè¿ã颿°ã®ã»ãããæ¬¡ã«ç¤ºãã¾ãã 大ããªæ³¨æç¹ã® 1 ã¤ã¯ãè¦ç¹è·é¢ãé©ç¨ããã¦ããªããããã¾ã ã¨ã¦ã 3D ã«æããããªãå¯è½æ§ããããã¨ã§ãã å¹³é¢åº¦ (flatness) ã¯ãã«ã¡ã©ãé ãã®ãªãã¸ã§ã¯ãã«ãºã¼ã ã¤ã³ã§éå¸¸ã«æ¥è¿ããã¨ãã¨åãã§ããé è¿æ (sense of perspective) ããªããªãã¾ãã
function rotateAroundXAxis(a) {
return [1, 0, 0, 0, 0, cos(a), -sin(a), 0, 0, sin(a), cos(a), 0, 0, 0, 0, 1];
}
function rotateAroundYAxis(a) {
return [cos(a), 0, sin(a), 0, 0, 1, 0, 0, -sin(a), 0, cos(a), 0, 0, 0, 0, 1];
}
function rotateAroundZAxis(a) {
return [cos(a), -sin(a), 0, 0, sin(a), cos(a), 0, 0, 0, 0, 1, 0, 0, 0, 0, 1];
}
è¡ååæ
è¡åã®æ¬å½ã®åã¯ãè¡ååæ (matrix composition) ã«ç±æ¥ãã¾ãã ç¹å®ã®ã¯ã©ã¹ã®è¡åãæãåãããã¨ã夿ã®å±¥æ´ãä¿æãããå ã«æ»ããã¨ãã§ãã¾ãã ã¤ã¾ããå¹³è¡ç§»åãåè»¢ãæ¡å¤§ç¸®å°ã®è¡åããã¹ã¦çµã¿åãããã¦ããå ´åãè¡åã®é åºãéã«ãã¦åé©ç¨ããã¨ãå ã®ç¹ãè¿ããã¾ãã
è¡åãä¹ç®ããé åºã¯éè¦ã§ãã æ°å¤ãä¹ç®ããå ´åã a * b = c 㨠b * a = c ã¯ã©ã¡ããæ£ããã§ãã ä¾ãã°ã3 * 4 = 12 㨠4 * 3 = 12 ã§ãã æ°å¦ã§ã¯ããããã®æ°å¤ã¯å¯æ (commutative) ã§ããã¨èª¬æããã¾ãã é åºãå ¥ãæ¿ãã£ãå ´åãè¡åã§ã¯åãã§ãããã¨ãä¿è¨¼ãããªããããè¡åã¯é坿 (non-commutative) ã§ãã
ãã 1 ã¤ã®ãã¤ã³ããã³ãã¼ã¯ãWebGL ããã³ CSS ã§ã®è¡åä¹ç®ã¯ãæä½ãç´æçã«çºçããã®ã¨ã¯éã®é åºã§çºçããå¿ è¦ããããã¨ã§ãã ä¾ãã°ãä½ãã 80% 縮å°ãã200 ãã¯ã»ã«ä¸ã«ç§»åãã¦ãããåç¹ãä¸å¿ã« 90 度å転ããã¨ãçä¼¼ã³ã¼ãã§ã¯æ¬¡ã®ããã«ãªãã¾ãã
transformation = rotate * translate * scaleè¤æ°ã®å¤æã®åæ
è¡åã®åæã«ä½¿ç¨ãã颿°ã¯ multiplyArrayOfMatrices()
ã§ãã ããã¯ããã®è¨äºã®åé ã§ç´¹ä»ããã¦ã¼ãã£ãªãã£é¢æ°ã®ã»ããã®ä¸é¨ã§ãã è¡åã®é
åãåããããããæãåããã¦çµæãè¿ãã¾ãã WebGL ã·ã§ã¼ãã¼ã³ã¼ãã§ã¯ãããã¯è¨èªã«çµã¿è¾¼ã¾ãã¦ããã*
æ¼ç®åã使ç¨ã§ãã¾ãã ããã«ããã®ä¾ã§ã¯ãä¸ã§å®ç¾©ããè¡åãè¿ã scale()
颿°ã¨ translate()
颿°ã使ç¨ãã¦ãã¾ãã
let transformMatrix = MDN.multiplyArrayOfMatrices([
rotateAroundZAxis(Math.PI * 0.5), // ã¹ããã 3: 90度å転
translate(0, 200, 0), // ã¹ããã 2: 100ãã¯ã»ã«ä¸ã«ç§»å
scale(0.8, 0.8, 0.8), // ã¹ããã 1: 縮å°
]);
æå¾ã«ãè¡åãã©ã®ããã«æ©è½ããããç¤ºãæ¥½ããæé ã¯ãæé ãéã«ãã¦ãè¡åãå ã®åä½è¡åã«æ»ããã¨ã§ãã
let transformMatrix = MDN.multiplyArrayOfMatrices([
scale(1.25, 1.25, 1.25), // ã¹ããã 6: 縮å°ãå
ã«æ»ã
translate(0, -200, 0), // ã¹ããã 5: ç§»åãå
ã«æ»ã
rotateAroundZAxis(-Math.PI * 0.5), // ã¹ããã 4: å転ãå
ã«æ»ã
rotateAroundZAxis(Math.PI * 0.5), // ã¹ããã 3: 90度å転
translate(0, 200, 0), // ã¹ããã 2: 100ãã¯ã»ã«ä¸ã«ç§»å
scale(0.8, 0.8, 0.8), // ã¹ããã 1: 縮å°
]);
è¡åãéè¦ã§ããçç±
è¡åãéè¦ãªã®ã¯ã空éå ã®ãã¾ãã¾ãªå¤æãè¨è¿°ãããã¨ãã§ããå°ããªæ°ã®éåã§æ§æããã¦ããããã§ããè¡åã¯ããã°ã©ã ã®ä¸ã§ç°¡åã«å ±æã§ãã¾ãããã¾ãã¾ãªåº§æ¨ç©ºéãè¡åã§è¨è¿°ãããã¨ãã§ããããã¤ãã®è¡åã®ä¹ç®ã«ãã£ã¦ããã座æ¨ç©ºéããå¥ã®åº§æ¨ç©ºéã¸ãã¼ã¿éåãç§»åããããã¨ãã§ãã¾ããè¡åã¯ããããçæããããã«ä½¿ç¨ããåå夿ã®ãã¹ã¦ã®é¨åã广çã«è¨æ¶ãã¾ãã
WebGL ã§ä½¿ç¨ããå ´åãã°ã©ãã£ãã¯ã¹ã«ã¼ãã¯ã空éå ã®å¤æ°ã®ç¹ã«è¡åãä¹ç®ããã®ã«ç¹ã«é©ãã¦ãã¾ãã ç¹ã®é ç½®ãç §æã®è¨ç®ãã¢ãã¡ã®ãã£ã©ã¯ã¿ã¼ã®ãã¼ãºãªã©ã®ãã¾ãã¾ãªæä½ã¯ãã¹ã¦ããã®åºæ¬çãªãã¼ã«ã«ä¾åãã¦ãã¾ãã
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4