直线的光栅化绘制
算法思想
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个点
}