首页
IT
登录
6mi
u
盘
搜
搜 索
IT
创建一个三维球体
创建一个三维球体
xiaoxiao
2025-05-02
10
<!doctype html>
<
html
lang
=
"en"
>
<
head
>
<
meta
charset
=
"UTF-8"
>
<
title
>
Document
</
title
>
</
head
>
<
body
>
<
canvas
width
=
"500"
height
=
"500"
id
=
"testCanvas"
>
</
canvas
>
</
body
>
</
html
>
<
script
>
//获取canvas
var
canvas = document.getElementById(
"testCanvas"
);
// 获取上下文
var
ctx = canvas.getContext(
"2d"
);
// 获取宽度
var
w = canvas.attributes.width.value;
// 获取高度
var
h = canvas.attributes.height.value;
// 设置填充颜色
ctx.fillStyle =
"rgb(255,0,0)"
;
//设置矩形的宽高
ctx.fillRect(
0
,
0
, w, h);
var
imgdata = ctx.getImageData(
0
,
0
, w, h);
var
pixels = imgdata.data;
var
i =
0
;
for
(
var
y =
0
; y < h; y++)
for
(
var
x =
0
; x < w; x++) { pixels[i++] = x / w *
255
; pixels[i++] = y / h *
255
; pixels[i++] =
0
; pixels[i++] =
255
; } ctx.putImageData(imgdata,
0
,
0
); Vector3 =
function
(x, y, z)
{
this
.x = x;
this
.y = y;
this
.z = z; }; Vector3.prototype = { copy :
function
()
{
return
new
Vector3(
this
.x,
this
.y,
this
.z); }, length :
function
()
{
return
Math
.sqrt(
this
.x *
this
.x +
this
.y *
this
.y +
this
.z *
this
.z); }, sqrLength :
function
()
{
return
this
.x *
this
.x +
this
.y *
this
.y +
this
.z *
this
.z; }, normalize :
function
()
{
var
inv =
1
/
this
.length();
return
new
Vector3(
this
.x * inv,
this
.y * inv,
this
.z * inv); }, negate :
function
()
{
return
new
Vector3(-
this
.x, -
this
.y, -
this
.z); }, add :
function
(v)
{
return
new
Vector3(
this
.x + v.x,
this
.y + v.y,
this
.z + v.z); }, subtract :
function
(v)
{
return
new
Vector3(
this
.x - v.x,
this
.y - v.y,
this
.z - v.z); }, multiply :
function
(f)
{
return
new
Vector3(
this
.x * f,
this
.y * f,
this
.z * f); }, divide :
function
(f)
{
var
invf =
1
/f;
return
new
Vector3(
this
.x * invf,
this
.y * invf,
this
.z * invf); }, dot :
function
(v)
{
return
this
.x * v.x +
this
.y * v.y +
this
.z * v.z; }, cross :
function
(v)
{
return
new
Vector3(-
this
.z * v.y +
this
.y * v.z,
this
.z * v.x -
this
.x * v.z, -
this
.y * v.x +
this
.x * v.y); } }; Ray3 =
function
(origin, direction)
{
this
.origin = origin;
this
.direction = direction; } Ray3.prototype = { getPoint :
function
(t)
{
return
this
.origin.add(
this
.direction.multiply(t)); } }; Sphere =
function
(center, radius)
{
this
.center = center;
this
.radius = radius; }; Sphere.prototype = { copy :
function
()
{
return
new
Sphere(
this
.center.copy(),
this
.radius.copy()); }, initialize :
function
()
{
this
.sqrRadius =
this
.radius *
this
.radius; }, intersect :
function
(ray)
{
var
v = ray.origin.subtract(
this
.center);
var
a0 = v.sqrLength() -
this
.sqrRadius;
var
DdotV = ray.direction.dot(v);
if
(DdotV <=
0
) {
var
discr = DdotV * DdotV - a0;
if
(discr >=
0
) {
var
result =
new
IntersectResult(); result.geometry =
this
; result.distance = -DdotV -
Math
.sqrt(discr); result.position = ray.getPoint(result.distance); result.normal = result.position.subtract(
this
.center).normalize();
return
result; } }
return
IntersectResult.noHit; } }; IntersectResult =
function
()
{
this
.geometry =
null
;
this
.distance =
0
;
this
.position = Vector3.zero;
this
.normal = Vector3.zero; }; IntersectResult.noHit =
new
IntersectResult(); PerspectiveCamera =
function
(eye, front, up, fov)
{
this
.eye = eye;
this
.front = front;
this
.refUp = up;
this
.fov = fov; }; PerspectiveCamera.prototype = { initialize :
function
()
{
this
.right =
this
.front.cross(
this
.refUp);
this
.up =
this
.right.cross(
this
.front);
this
.fovScale =
Math
.tan(
this
.fov *
0.5
*
Math
.PI /
180
) *
2
; }, generateRay :
function
(x, y)
{
var
r =
this
.right.multiply((x -
0.5
) *
this
.fovScale);
var
u =
this
.up.multiply((y -
0.5
) *
this
.fovScale);
return
new
Ray3(
this
.eye,
this
.front.add(r).add(u).normalize()); } };
// renderDepth.htm
function
renderDepth
(canvas, scene, camera, maxDepth)
{
// 从canvas取得imgdata和pixels,跟之前的代码一样
// ...
scene.initialize(); camera.initialize();
var
i =
0
;
for
(
var
y =
0
; y < h; y++) {
var
sy =
1
- y / h;
for
(
var
x =
0
; x < w; x++) {
var
sx = x / w;
var
ray = camera.generateRay(sx, sy);
var
result = scene.intersect(ray);
if
(result.geometry) {
var
depth =
255
-
Math
.min((result.distance / maxDepth) *
255
,
255
); pixels[i ] = depth; pixels[i +
1
] = depth; pixels[i +
2
] = depth; pixels[i +
3
] =
255
; } i +=
4
; } } ctx.putImageData(imgdata,
0
,
0
); }
function
renderNormal
(canvas, scene, camera)
{
// ...
if
(result.geometry) { pixels[i ] = (result.normal.x +
1
) *
128
; pixels[i +
1
] = (result.normal.y +
1
) *
128
; pixels[i +
2
] = (result.normal.z +
1
) *
128
; pixels[i +
3
] =
255
; }
// ...
} Color =
function
(r, g, b)
{
this
.r = r;
this
.g = g;
this
.b = b }; Color.prototype = { copy :
function
()
{
return
new
Color(
this
.r,
this
.g,
this
.b); }, add :
function
(c)
{
return
new
Color(
this
.r + c.r,
this
.g + c.g,
this
.b + c.b); }, multiply :
function
(s)
{
return
new
Color(
this
.r * s,
this
.g * s,
this
.b * s); }, modulate :
function
(c)
{
return
new
Color(
this
.r * c.r,
this
.g * c.g,
this
.b * c.b); } }; Color.black =
new
Color(
0
,
0
,
0
); Color.white =
new
Color(
1
,
1
,
1
); Color.red =
new
Color(
1
,
0
,
0
); Color.green =
new
Color(
0
,
1
,
0
); Color.blue =
new
Color(
0
,
0
,
1
); CheckerMaterial =
function
(scale, reflectiveness)
{
this
.scale = scale;
this
.reflectiveness = reflectiveness; }; CheckerMaterial.prototype = { sample :
function
(ray, position, normal)
{
return
Math
.abs((
Math
.floor(position.x *
0.1
) +
Math
.floor(position.z *
this
.scale)) %
2
) <
1
? Color.black : Color.white; } };
//初始化
setInterval(
function
()
{
renderDepth( document.getElementById(
'testCanvas'
),
new
Sphere(
new
Vector3(
0
,
10
, -
10
),
10
),
new
PerspectiveCamera(
new
Vector3(
0
,
10
,
10
),
new
Vector3(
0
,
0
, -
1
),
new
Vector3(
0
,
1
,
0
),
90
),
20
); },
1000
);
</
script
>
转载请注明原文地址: https://ju.6miu.com/read-1298688.html
最新回复
(
0
)