创建一个三维球体

    xiaoxiao2025-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)