美文网首页
2022-11-02 webgl绘制圆形点

2022-11-02 webgl绘制圆形点

作者: MrSwilder | 来源:发表于2022-11-02 09:56 被阅读0次

一、原理

1.绘制圆形点,计算到圆心的距离


image.png

2.绘制球背面剔除

  //开启背面剔除
  gl.enable(gl.CULL_FACE)

3.开启多边形偏移解决球遮挡点问题


image.png

二、效果

image.png

三、代码

 //顶点着色器
    var VSHADER_SOURCE = /*glsl*/`
        attribute vec2 a_Uv;
        attribute vec4 a_Position;
        uniform mat4 u_MvpMatrix; 
        varying vec2 v_Uv;

        void main(){ 
            vec4 clip_Position=u_MvpMatrix*a_Position;
            gl_Position=clip_Position;
            v_Uv=a_Uv;

        }`;

    //片元着色器
    var FSHADER_SOURCE = /*glsl*/`
        #ifdef GL_ES
        precision mediump float;
        #endif
        uniform sampler2D u_Texture;
        
        varying vec2 v_Uv;

        void main(){
          
            vec4 baseColor=texture2D(u_Texture,vec2(fract(1.00-v_Uv.x),v_Uv.y));
          
            gl_FragColor=baseColor;
       
        }`;


    var point_VShader =/*glsl*/`
        attribute vec3 a_Position;
        uniform mat4 u_ViewMatrix;
        uniform mat4 u_ProjectMatrix;
        void main(){
            gl_Position=u_ProjectMatrix*u_ViewMatrix*vec4(a_Position,1.0);
            gl_PointSize=10.0;
        }
    `


    var point_FShader =/*glsl*/`
     #ifdef GL_ES
        precision mediump float;
        #endif
        void main(){
            float dist=distance(gl_PointCoord,vec2(0.5));
            if(dist>0.5){
                discard;
            }
            gl_FragColor=vec4(1.0,0.0,0.0,1.0);
        }
    `

    //声明js需要的相关变量
    var canvas = document.getElementById("canvas");
    var gl = getWebGLContext(canvas);
    //设置视角矩阵的相关信息(视点,视线,上方向)
    var viewMatrix = new Matrix4();



    //设置透视投影矩阵
    var projMatrix = new Matrix4();
    projMatrix.setPerspective(30, canvas.width / canvas.height, 0.1, 10);

    const rotateViewMatrix = new Matrix4()


    let value = 4

    var currentAngle = [0, 0]

    var program, pointProgram
    async function main() {
        if (!gl) {
            console.log("你的浏览器不支持WebGL");
            return;
        }

        program = createProgram(gl, VSHADER_SOURCE, FSHADER_SOURCE)

        if (!program) {
            console.error('创建着色器程序失败')
            return
        }

        gl.program = program
        gl.useProgram(program)

        getVariableLocation()

        //绘制球形
        const sphereGeometry = new SphereGeometry(gl, 1, 180, 90)
        const sphere = sphereGeometry.create()
        //绘制纹理
        const texture = Texture2D.initTexture(gl, './image/earth.jpg', 0)

        pointProgram = createProgram(gl, point_VShader, point_FShader)
        if (!pointProgram) {
            console.error('创建点着色器失败!')
            return
        }
        gl.program = pointProgram
        gl.useProgram(pointProgram)

        getVariableLocation()

        const arr = []

        cities.forEach(city => {
            const p = Cartertion3FromDegrees(1, city.value[0] * 1, city.value[1] * 1, 0)
            arr.push(p.x, p.y, p.z)
        })

        // const p1=Cartertion3FromDegrees(1,116,40,0)
        // const p2=Cartertion3FromDegrees(1,-100,40,0)
        const data = new Float32Array(arr)

        //

        // console.log(p,p1,p2)
        const point_positionBuffer = initArrayBuffer(gl, data, 3, gl.FLOAT, gl.position)



        //

        var tick = function () {
            //设置底色
            gl.clearColor(0.0, 0.0, 0.0, 1.0);
            viewMatrix.setLookAt(0, 0, value, 0, 0, 0, 0, 1, 0);
            rotateViewMatrix.setRotate(currentAngle[1], 1, 0, 0)
            rotateViewMatrix.rotate(currentAngle[0], 0, 1, 0)
            viewMatrix.multiply(rotateViewMatrix)

            draw(gl, sphere, point_positionBuffer)
            requestAnimationFrame(tick)
        }
        tick()


        registerMouseEvent()
    }

    /**
     * 
     * 注册鼠标事件
     * */
    function registerMouseEvent() {
        //是否按下
        let isDown = false
        let last_X = 0, last_Y = 0
        canvas.onmousedown = function (e) {
            //获取当前鼠标位置
            const x = e.clientX, y = e.clientY
            //获取canvas边界范围
            const bound = e.target.getBoundingClientRect()

            if (bound.left < x && bound.right > x && bound.top < y && bound.bottom > y) {

                last_X = x
                last_Y = y
                isDown = true
            }

        }

        canvas.onmousemove = function (e) {
            // console.log('鼠标移动',e)
            const x = e.clientX, y = e.clientY
            if (isDown) {

                const offset_X = x - last_X
                const offset_Y = y - last_Y
                currentAngle[0] += offset_X / 10
                currentAngle[1] += offset_Y / 10



            }
            last_X = x
            last_Y = y
        }


        canvas.onmouseup = function (e) {
            isDown = false

        }


        canvas.onwheel = function (e) {

            if (e.wheelDeltaY === 120) {
                value += 0.1
            } else {
                value -= 0.1
            }

        }
    }

    function draw(gl, sphere, point_positionBuffer) {

        gl.useProgram(program)
        gl.program = program
        //设置模型矩阵的相关信息
        var modelMatrix = new Matrix4();

        var mvpMatrix = new Matrix4()
        mvpMatrix.set(projMatrix)

        mvpMatrix.multiply(viewMatrix.multiply(modelMatrix));


        //将试图矩阵传给u_ViewMatrix变量
        gl.uniformMatrix4fv(gl.program.mvpMatrix, false, mvpMatrix.elements);

        //开启隐藏面清除
        gl.enable(gl.DEPTH_TEST);
        //开启背面剔除
        gl.enable(gl.CULL_FACE)
        //开启多边形偏移
        gl.enable(gl.POLYGON_OFFSET_FILL)
        //计算偏移量
        /*
        void WINAPI glPolygonOffset(
            GLfloat factor,
            GLfloat units
        );
        */
        gl.polygonOffset(5.0, 1.0)

        //清空颜色和深度缓冲区
        gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);


        const arrayBuffers = sphere.arrayBuffers
        arrayBuffers.forEach(arrayBuffer => {
            if (arrayBuffer) {
                writeAttributeVariable(gl, arrayBuffer.attribute, arrayBuffer)
            }
        });

        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, sphere.indexBuffer);

        const length = sphere.length

        //绘制图形
        gl.drawElements(gl.TRIANGLES, length, gl.UNSIGNED_SHORT, 0);

        gl.useProgram(pointProgram)
        gl.program = pointProgram
        //将试图矩阵传给u_ViewMatrix变量
        gl.uniformMatrix4fv(gl.program.viewMatrix, false, viewMatrix.elements);
        gl.uniformMatrix4fv(gl.program.projectMatrix, false, projMatrix.elements);

        writeAttributeVariable(gl, point_positionBuffer.attribute, point_positionBuffer)
        gl.drawArrays(gl.POINTS, 0, 360)

    }



    function toRadian(degree) {
        return degree * Math.PI / 180
    }

    //经纬度转世界坐标
    function Cartertion3FromDegrees(r, lon, lat, height) {
        const theta = toRadian(90 - lat)
        const phi = toRadian(180 - lon)
        const x = r * Math.sin(theta) * Math.cos(phi)
        const y = r * Math.cos(theta)
        const z = r * Math.sin(theta) * Math.sin(phi)
        return { x, y, z }
    }

相关文章

  • 2022-11-02 webgl绘制圆形点

    一、原理 1.绘制圆形点,计算到圆心的距离 2.绘制球背面剔除 3.开启多边形偏移解决球遮挡点问题 二、效果 三、代码

  • TWaver3D直线、曲线、曲面的绘制

    1. WebGL原生线 WebGL支持绘制点、线、三角;绘制线的方法比较简单,给定顶点,设置绘制方式即可; 假设给...

  • WebGL 绘制Line的bug(一)

    熟悉WebGL的同学都知道,WebGL绘制模式有点、线、面三种;通过点的绘制可以实现粒子系统等,通过线可以绘制一些...

  • webgl 点击绘制点

    index.html cuon-utils.js

  • webgl 绘制多个点

    在是使用 js 定点位的时候,需要建立一份顶点数据给着色器.让着色器根据这份顶点数据绘图 建立顶点数据,两个浮点数...

  • [Android高级动画] 如何让点扩散再聚合?

    如何让多个点扩散再聚合? like this: 一、如何绘制多个点为一个圆形 点击 如何让绘制多个点并按圆形旋转?...

  • webgl基础图形

    WebGL的工作是绘制图形图像,了解WebGL的图形是至关重要的。 一、点 在WebGL中点是一个正方形,用一个三...

  • webgl入门(一)

    webgl是基于 canvas 进行绘制,通过 getWebGLContext()来获取 webgl 的绘图上下文...

  • 用线段绘制球体(three.js webgl_lines_spe

    用线段绘制球体(three.js webgl_lines_spere例子) Three.js中的webgl_lin...

  • Threejs in autonomous driving -(

    绘制各种几何体是webgl的强项,相反各种异性几何体就非常麻烦。比如圆角矩形来说在webgl中绘制就相对比较麻烦。...

网友评论

      本文标题:2022-11-02 webgl绘制圆形点

      本文链接:https://www.haomeiwen.com/subject/xmqjtdtx.html