In this post I want to share experience I accidentally got experimenting with WebGL. To get some fun and explore WebGL (never write a line of JS code before) I render a Mobius strip. It's not the hardest task in the world, but definitely more interesting than usual WebGL getting-started samples with two polygons. And after all, Mobius strip is cool, isn't it?
There is not so much to talk about, we have all the usual stuff such as VBO, shaders and so on. The most interesting part is Mobius strip vertices and polygons calculation. I use parametric representation of Mobius strip for tesselation:
There is not so much to talk about, we have all the usual stuff such as VBO, shaders and so on. The most interesting part is Mobius strip vertices and polygons calculation. I use parametric representation of Mobius strip for tesselation:
function calcMobiusPoint(u, v, coef) {
var x = ( 1 + ((v * coef) / 2) * Math.cos(u / 2) ) *
Math.cos( u );
var y = ( 1 + ((v * coef) / 2) * Math.cos(u / 2) ) *
Math.sin( u );
var z = ( (v * coef) / 2) * Math.sin( u / 2 );
return [x, y, z];
}
Unfortunately got no time for long explanations; take a look at method that calculates vertices, indexes and colors of strip (below), throw a glance at jsfiddle or download entire sample from bitbucket if necessary.
Finally, several pictures of rendered Mobius strip:function initBuffers() {
// math data for tesselation
var verticesPerCurve = 120;
var tBegin = 0.0;
var tEnd = Math.PI * 2;
var dt = ( tEnd - tBegin ) / ( verticesPerCurve - 2 );
var stripCoef = 0.5;
// surface bounary colors
var beginColor = [ 0.0, 0.3, 1.0 ];
var endColor = [ 1.0, 0.3, 0.0 ];
// vertices calculation scheme:
// / /
// / /
// #2 o o #(verticesPerCurve + 2)
// / /
// / /
// #1 o o #(verticesPerCurve + 1)
// / /
// / /
// #0 o o #(verticesPerCurve + 0)
// / /
// curve1 curve2
// VERTICES
modelVerticesBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, modelVerticesBuffer );
var vertices = new Array();
for ( var i = 0; i < verticesPerCurve; ++i ) {
var t = tBegin + dt * i;
var p1 = calcMobiusPoint(t, -1.0, stripCoef);
var p2 = calcMobiusPoint(t, 1.0, stripCoef);
// first curve vertex
vertices[ i * 3 ] = p1[ 0 ];
vertices[ i * 3 + 1 ] = p1[ 1 ];
vertices[ i * 3 + 2 ] = p1[ 2 ];
// second curve vertex
var k = ( i + verticesPerCurve );
vertices[ k * 3 ] = p2[ 0 ];
vertices[ k * 3 + 1 ] = p2[ 1 ];
vertices[ k * 3 + 2 ] = p2[ 2 ];
}
gl.bufferData( gl.ARRAY_BUFFER,
new Float32Array(vertices), gl.STATIC_DRAW );
modelVerticesBuffer.itemSize = 3;
modelVerticesBuffer.numItems = verticesPerCurve * 2;
// COLORS
modelVerticesColorBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER,
modelVerticesColorBuffer );
var verticesColors = new Array();
var halfVerticesPerCurve = verticesPerCurve / 2.0;
for ( var i = 0; i < verticesPerCurve; ++i ) {
var curColor = [ 0.0, 0.0, 0.0 ];
for ( var k = 0; k < curColor.length; ++k ) {
if ( i < halfVerticesPerCurve ) {
curColor[ k ] = beginColor[ k ] +
(endColor[k] - beginColor[k]) *
(i / halfVerticesPerCurve);
} else {
curColor[ k ] = endColor[ k ] +
(beginColor[k] - endColor[k]) *
((i - halfVerticesPerCurve) /
halfVerticesPerCurve);
}
}
// first curve vertex color
verticesColors[ i * 3 ] = curColor[ 0 ];
verticesColors[ i * 3 + 1 ] = curColor[ 1 ];
verticesColors[ i * 3 + 2 ] = curColor[ 2 ];
// second curve vertex color
var k = ( i + verticesPerCurve );
verticesColors[ k * 3 ] = curColor[ 0 ];
verticesColors[ k * 3 + 1 ] = curColor[ 1 ];
verticesColors[ k * 3 + 2 ] = curColor[ 2 ];
}
gl.bufferData( gl.ARRAY_BUFFER,
new Float32Array(verticesColors), gl.STATIC_DRAW );
modelVerticesColorBuffer.itemSize = 3;
modelVerticesColorBuffer.numItems =
verticesPerCurve * 2;
// polygons calculation scheme:
// / \ /
// / \ /
// / #poly2 \ /
// #2 o-----------o #(verticesPerCurve + 1)
// / \ #poly1 /
// / \ /
// / \ /
// / \ /
// / #poly0 \ /
// #1 o-----------o #(verticesPerCurve + 0)
// / /
// curve1 curve2
// POLYGONS
modelVerticesIndexBuffer = gl.createBuffer();
gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER,
modelVerticesIndexBuffer );
var verticesIndices = new Array();
for ( var i1 = 0; i1 < (verticesPerCurve - 1); ++i1 ) {
var i1Next = i1 + 1;
var i2 = i1 + verticesPerCurve;
var i2Next = i2 + 1;
var nPoly1 = i1 * 2;
var nPoly2 = nPoly1 + 1;
// first polygon
verticesIndices[ nPoly1 * 3 ] = i2;
verticesIndices[ nPoly1 * 3 + 1 ] = i1;
verticesIndices[ nPoly1 * 3 + 2 ] = i1Next;
// first polygon
verticesIndices[ nPoly2 * 3 ] = i1Next;
verticesIndices[ nPoly2 * 3 + 1 ] = i2Next;
verticesIndices[ nPoly2 * 3 + 2 ] = i2;
}
gl.bufferData( gl.ELEMENT_ARRAY_BUFFER,
new Uint16Array(verticesIndices), gl.STATIC_DRAW );
modelVerticesIndexBuffer.itemSize = 3;
modelVerticesIndexBuffer.numItems =
verticesIndices.length /
modelVerticesIndexBuffer.itemSize;
}
Комментариев нет:
Отправить комментарий