JavaScript 中的 3D 渲染

问题描述 投票:0回答:1

我正在尝试用 JavaScript 制作一个 3D 物理引擎,只是为了好玩。

唯一的问题是 3D 渲染,因为我不知道它是如何完成的,所以任何人都可以解释 3D 渲染的想法。

这是一个 3D 透视立方体旋转的示例。



<style>

    *{

        margin: 0;

    }

    canvas {

        background: black;

    }

</style>

<canvas></canvas>

<script>

    var canvas = document.querySelector("canvas")

    
var fov = [120 * Math.PI / 180, 90 * Math.PI / 180]



canvas.width = innerWidth

var dist = (canvas.width / 2) / Math.tan(fov[0] / 2)

canvas.height = (Math.tan(fov[1] / 2) * dist) * 2



if (canvas.height > innerHeight) {

    canvas.height = innerHeight

    var dist = (canvas.height / 2) / Math.tan(fov[1] / 2)

    canvas.width = (Math.tan(fov[0] / 2) * dist) * 2

}



var c = canvas.getContext("2d")



c.fillStyle = "red"

c.strokeStyle = "white"



var solids = []



function rotateX(vector, angle) {

    angle = angle * Math.PI / 180

    var l = Math.hypot(vector.y, vector.z)

    var cAngle = Math.atan2(vector.z, vector.y)

    cAngle += angle

    vector.y = Math.cos(cAngle) * l

    vector.z = Math.sin(cAngle) * l

}

function rotateY(vector, angle) {

    angle = angle * Math.PI / 180

    var l = Math.hypot(vector.x, vector.z)

    var cAngle = Math.atan2(vector.z, vector.x)

    cAngle += angle

    vector.x = Math.cos(cAngle) * l

    vector.z = Math.sin(cAngle) * l

}

function rotateZ(vector, angle) {

    angle = angle * Math.PI / 180

    var l = Math.hypot(vector.x, vector.y)

    var cAngle = Math.atan2(vector.y, vector.x)

    cAngle += angle

    vector.x = Math.cos(cAngle) * l

    vector.y = Math.sin(cAngle) * l

}



class Vertex {

    constructor(x, y, z) {

        this.x = x,

        this.y = y,

        this.z = z 

    }

}



class Cube {

    constructor(pos, size) {

        this.size = size

        this.pos = pos

        this.angleX = 0

        this.angleY = 0

        this.angleZ = 30

        this.vertices = []

        this.vertices.push(new Vertex(0, 0, 0))

        this.vertices.push(new Vertex(size, 0, 0))

        this.vertices.push(new Vertex(0, size, 0))

        this.vertices.push(new Vertex(0, 0, size))

        this.vertices.push(new Vertex(size, size, 0))

        this.vertices.push(new Vertex(size, 0, size))

        this.vertices.push(new Vertex(0, size, size))

        this.vertices.push(new Vertex(size, size, size))

    }

    draw() {

        this.vertices.forEach(v => {

            rotateX(v, 1)

            rotateY(v, 1)

            rotateZ(v, 1)

            var d = v.z + this.pos.z

            var width = (Math.tan(fov[0] / 2) * d) * 2

            var height = (Math.tan(fov[1] / 2) * d) * 2

            

            var x = (width / 2 - v.x - this.pos.x) * canvas.width / width

            var y = (height / 2 - v.y - this.pos.y) * canvas.height / height

            

            

            

            this.vertices.forEach(v2 => {

                var d2 = v2.z + this.pos.z

                var width2 = (Math.tan(fov[0] / 2) * d2) * 2

                var height2 = (Math.tan(fov[1] / 2) * d2) * 2

                

                var x2 = (width2 / 2 - v2.x - this.pos.x) * canvas.width / width2

                var y2 = (height2 / 2 - v2.y - this.pos.y) * canvas.height / height2

                this.vertices.forEach(v3 => {

                    if (v != v2 && v2 != v3) {

                        var d3 = v3.z + this.pos.z

                        var width3 = (Math.tan(fov[0] / 2) * d3) * 2

                        var height3 = (Math.tan(fov[1] / 2) * d3) * 2

                        

                        var x3 = (width3 / 2 - v3.x - this.pos.x) * canvas.width / width3

                        var y3 = (height3 / 2 - v3.y - this.pos.y) * canvas.height / height3

                        c.beginPath()

                        c.moveTo(x, y)

                        c.lineTo(x2, y2)

                        c.lineTo(x3, y3)

                        c.lineTo(x, y)

                        c.fillStyle = "red"

                        c.fill()

                        

                    }

                })

            })

        })

        this.vertices.forEach(v => {

            var d = v.z + this.pos.z

            var width = (Math.tan(fov[0] / 2) * d) * 2

            var height = (Math.tan(fov[1] / 2) * d) * 2

            

            var x = (width / 2 - v.x - this.pos.x) * canvas.width / width

            var y = (height / 2 - v.y - this.pos.y) * canvas.height / height

            

            

            

            this.vertices.forEach(v2 => {

                var d2 = v2.z + this.pos.z

                var width2 = (Math.tan(fov[0] / 2) * d2) * 2

                var height2 = (Math.tan(fov[1] / 2) * d2) * 2

                

                var x2 = (width2 / 2 - v2.x - this.pos.x) * canvas.width / width2

                var y2 = (height2 / 2 - v2.y - this.pos.y) * canvas.height / height2

                

                if (Math.round(Math.hypot(v.x - v2.x, v.y - v2.y, v.z - v2.z)) == this.size) {

                    var d2 = v2.z + this.pos.z

                    var width2 = (Math.tan(fov[0] / 2) * d2) * 2

                    var height2 = (Math.tan(fov[1] / 2) * d2) * 2

                    

                    var x2 = (width2 / 2 - v2.x - this.pos.x) * canvas.width / width2

                    var y2 = (height2 / 2 - v2.y - this.pos.y) * canvas.height / height2

                    

                    c.beginPath()

                    c.moveTo(x, y)

                    c.lineTo(x2, y2)

                    c.stroke()

                }

            })

            

            c.beginPath()

            c.arc(x, y, 3, 0, Math.PI * 2, false)

            c.fillStyle = "blue"

            //c.fill()

            //c.stroke()

        })

    }

}



solids.push(new Cube({x: 0, y: 0, z: 300}, 50))



function animate() {

    requestAnimationFrame(animate)

    c.clearRect(0, 0, canvas.width, canvas.height)

    solids.forEach(solid => {

        solid.draw()

    })

}

animate()

我搜索了很多关于解释这一点的文章,但我没有找到任何有用的东西

javascript 3d rendering
1个回答
0
投票

WebGL 是实现 3D 的方式,所以而不是通常的...

var Cx = C.getContext('2d');

现在变成了...

var Gl = C.getContext('webgl');

if(Gl){

 // WebGL is supported so proceed...

}

WebGL 是一个庞大而复杂的世界,您可以在这里开始研究......

https://devdoc.net/web/developer.mozilla.org/en-US/docs/Web/WebGL/Getting_started_with_WebGL.html

© www.soinside.com 2019 - 2024. All rights reserved.