创建一个三维球体

<!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>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值