webGL 在一个页面上,同时显示DDA算法和Bresenham算法画直线

博客围绕直线的光栅化绘制展开,介绍了DDA和Bresenham两种算法思想。DDA算法根据直线斜率分情况让x或y每次递增1;Bresenham算法则涉及初始和后继决策参数值的计算。此外还给出了效果图和相关源码。

直线的光栅化绘制

算法思想

DDA

设直线两端点为:起点A(x0,y0);终点为B(x1,y1)。
则直线的斜率和方程为:
在这里插入图片描述

下面分为两种情况考虑:当斜率小于等于1的时候,x每次增加1,y最多增加1。
在这里插入图片描述

而当斜率大于1的时候,让y每次递增1,x每次递增最多1

Bresenham

  • 求出初始决策参数值
    p0=2△y-△x

  • 计算后继决策参数值
    2△y
    2△y-2△x

效果图

在这里插入图片描述

源码

HelloLineDDA.html

<!DOCTYPE HTML>
<html lang="en">

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>DDA & Bresenham</title>
</head>

<body onload="startup()">
    <canvas id="webgl" width="640" height="480">
        </canvas>
</body>
<script src="HellolineDDA.js">
</script>

</html>

HelloLineDDA.js

var gl;

function createGLContext(canvas) {
    var names = ["webgl", "experimental-webgl"];
    var context = null;
    for (var i = 0; i < names.length; i++) {
        try {
            context = canvas.getContext(names[i]); //获取webgl context绘图上下文
        } catch (e) {}
        if (context) {
            break;
        }
    }
    if (context) {
        context.viewportWidth = canvas.width;
        context.viewportHeight = canvas.height;
    } else {
        alert("Failed to create WebGL context!");
    }
    return context;
}

function loadShader(type, shaderSource) {
    var shader = gl.createShader(type);
    gl.shaderSource(shader, shaderSource);
    gl.compileShader(shader);

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        alert("Error compiling shader" + gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        return null;
    }
    return shader;
}

function setupShaders() {
    //顶点着色器程序
    var vertexShaderSource =
        'attribute vec4 a_Position;\n' +
        'void main() {\n' +
        '  gl_Position = a_Position;\n' +
        '  gl_PointSize = 5.0;\n' +
        '}\n';

    //片元着色器程序
    var fragmentShaderSource =
        'void main(){ \n' +
        '    gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); \n' + //gl_FragColor指定像素的颜色
        '} \n';

    var vertexShader = loadShader(gl.VERTEX_SHADER, vertexShaderSource);
    var fragmentShader = loadShader(gl.FRAGMENT_SHADER, fragmentShaderSource);

    var shaderProgram = gl.createProgram();
    gl.attachShader(shaderProgram, vertexShader);
    gl.attachShader(shaderProgram, fragmentShader);
    gl.linkProgram(shaderProgram);

    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
        alert("Failed to setup shaders");
    }

    gl.useProgram(shaderProgram);
    gl.program = shaderProgram;

    var a_PosLocation = gl.getAttribLocation(gl.program, 'a_Position');
    gl.vertexAttribPointer(a_PosLocation, 2, gl.FLOAT, false, 0, 0);
}

function DDA_Bresenham(x0, y0, xEnd, yEnd, x1, y1, x1End, y1End) {
    //DDA
    var arr = new Array();
    var dx = xEnd - x0,
        dy = yEnd - y0,
        steps, k;
    var xIncrement, yIncrement, x = x0,
        y = y0;
    if (Math.abs(dx) > Math.abs(dy)) {
        steps = Math.abs(dx);
    } else {
        steps = Math.abs(dy);
    }
    xIncrement = dx / steps;
    yIncrement = dy / steps;
    arr[0] = x;
    arr[1] = y;
    for (var i = 0; i < steps; i++) {
        x += xIncrement;
        y += yIncrement;
        k = 2 * i + 2;
        arr[k] = x / 100;
        arr[k + 1] = y / 100;
    }

    //Bresenham
    var dx1 = Math.abs(x1End - x1),
        dy1 = Math.abs(y1End - y1);
    var p = 2 * dy1 - dx1;
    var twoDy = 2 * dy1,
        twoDyMinusDx = 2 * (dy1 - dx1);
    if (x1 > x1End) {
        x = x1End;
        y = y1End;
        x1End = x1;
    } else {
        x = x1;
        y = y1;
    }
    k += 2;
    arr[k++] = x;
    arr[k++] = y;
    while (x < x1End) {
        x++;
        if (p < 0) {
            p += twoDy;
        } else {
            y++;
            p += twoDyMinusDx;
        }
        arr[k++] = x / 100;
        arr[k++] = y / 100;
    }
    console.log(arr);
    return arr;
}

function initVertexBuffers(gl) {
    var arr = DDA_Bresenham(-25.0, -100.0, 100.0, 100.0, -50.0, -50.0, 50.0, 50.0);
    var vertices = new Float32Array(arr);
    var n = arr.length / 2; // The number of vertices

    // Create a buffer object
    var vertexBuffer = gl.createBuffer();
    if (!vertexBuffer) {
        console.log('Failed to create the buffer object');
        return -1;
    }

    // Bind the buffer object to target
    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
    // Write date into the buffer object
    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

    var a_PosLocation = gl.getAttribLocation(gl.program, 'a_Position');
    if (a_PosLocation < 0) {
        console.log('Failed to get the storage location of a_Position');
        return -1;
    }
    // Assign the buffer object to a_Position variable
    gl.vertexAttribPointer(a_PosLocation, 2, gl.FLOAT, false, 0, 0);

    // Enable the assignment to a_Position variable
    gl.enableVertexAttribArray(a_PosLocation);

    return n;
}

function startup() {
    var canvas = document.getElementById('webgl'); //获取<canvas>元素
    gl = createGLContext(canvas);
    setupShaders();
    var n = initVertexBuffers(gl);
    if (n < 0) {
        console.log('Failed to set the positions of the vertices');
        return;
    }
    gl.clearColor(0.0, 0.0, 0.0, 1.0); //指定清空<canvas>的颜色    
    gl.clear(gl.COLOR_BUFFER_BIT); //清空<canvas>
    gl.drawArrays(gl.POINTS, 0, n); //从第0个元素开始,在指定位置(gl_Position)画1个点
}
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值