我尝试使用三角形和2个缓冲区(gl.ARRAY_BUFFER和gl.ELEMENT_ARRAY_BUFFER)绘制球体,但是出了点问题。我只看到空显示...我使用了一些代码http://learningwebgl.com/blog/?p=1253和这个{{ 3}}。
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
' gl_PointSize = 10.0;\n' +
'}\n';
var FSHADER_SOURCE =
'void main() {\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
'}\n';
function resize(canvas)
{
var displayWidth = canvas.clientWidth;
var displayHeight = canvas.clientHeight;
if (canvas.width != displayWidth || canvas.height != displayHeight)
{
canvas.width = displayWidth;
canvas.height = displayHeight;
}
}
function initArrayBuffers(gl)
{
var SPHERE_DIV = 6;
var i, ai, si, ci;
var j, aj, sj, cj;
var p1, p2;
var vertices = [],indices = [];
for (j = 0; j <= SPHERE_DIV; j++)
{
aj = j * Math.PI / SPHERE_DIV;
sj = Math.sin(aj);
cj = Math.cos(aj);
for (i = 0; i <= SPHERE_DIV; i++)
{
ai = i * 2 * Math.PI / SPHERE_DIV;
si = Math.sin(ai);
ci = Math.cos(ai);
vertices.push(si * sj); // X
vertices.push(cj); // Y
vertices.push(ci * sj); // Z
}
for (j = 0; j < SPHERE_DIV; j++)
{
for (i = 0; i < SPHERE_DIV; i++)
{
p1 = j * (SPHERE_DIV+1) + i;
p2 = p1 + (SPHERE_DIV+1);
indices.push(p1);
indices.push(p2);
indices.push(p1 + 1);
indices.push(p1 + 1);
indices.push(p2);
indices.push(p2 + 1);
}
}
var vertexBuffer = gl.createBuffer();
if (!vertexBuffer)
{
console.log('Failed to create the buffer object');
return -1;
}
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
}
return indices.length;
}
function main()
{
var canvas = document.getElementById('webgl');
var gl = getWebGLContext(canvas);
resize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
var n=initArrayBuffers(gl);
if (!gl)
{
console.log('Failed to retrieve the <canvas> element');
return;
}
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE))
{
console.log('Failed to intialize shaders.');
return;
}
gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT );
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0)
{
console.log('Failed to get the storage location of a_Position');
return -1;
}
gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_SHORT, 0);
}
答案 0 :(得分:2)
您必须定义通用顶点属性数据(gl.vertexAttribPointer
)的数组,并且必须在绘制网格时启用顶点属性(gl.enableVertexAttribArray
):
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
gl.vertexAttribPointer( a_Position, 3, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( a_Position );
gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_SHORT, 0);
并且函数initArrayBuffers
function initArrayBuffers(gl)
{
var SPHERE_DIV = 6;
var i, ai, si, ci;
var j, aj, sj, cj;
var p1, p2;
var vertices = [],indices = [];
for (j = 0; j <= SPHERE_DIV; j++)
{
aj = j * Math.PI / SPHERE_DIV;
sj = Math.sin(aj);
cj = Math.cos(aj);
for (i = 0; i <= SPHERE_DIV; i++)
{
ai = i * 2 * Math.PI / SPHERE_DIV;
si = Math.sin(ai);
ci = Math.cos(ai);
vertices.push(si * sj); // X
vertices.push(cj); // Y
vertices.push(ci * sj); // Z
}
} // <------------------------------------------------------------- ADD
for (j = 0; j < SPHERE_DIV; j++)
{
for (i = 0; i < SPHERE_DIV; i++)
{
p1 = j * (SPHERE_DIV+1) + i;
p2 = p1 + (SPHERE_DIV+1);
indices.push(p1);
indices.push(p2);
indices.push(p1 + 1);
indices.push(p1 + 1);
indices.push(p2);
indices.push(p2 + 1);
}
}
var vertexBuffer = gl.createBuffer();
if (!vertexBuffer)
{
console.log('Failed to create the buffer object');
return -1;
}
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
// } <------------------------------------------------------ REMOVE
return indices.length;
}
请参阅代码段:
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n' +
'void main() {\n' +
' gl_Position = a_Position;\n' +
' gl_PointSize = 10.0;\n' +
'}\n';
var FSHADER_SOURCE =
'void main() {\n' +
' gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n' +
'}\n';
var ShaderProgram = {};
ShaderProgram.Create = function( shaderList ) {
var shaderObjs = [];
for ( var i_sh = 0; i_sh < shaderList.length; ++ i_sh ) {
var shderObj = this.CompileShader( shaderList[i_sh].source, shaderList[i_sh].stage );
if ( shderObj == 0 )
return 0;
shaderObjs.push( shderObj );
}
var progObj = this.LinkProgram( shaderObjs )
if ( progObj != 0 ) {
progObj.attribIndex = {};
var noOfAttributes = gl.getProgramParameter( progObj, gl.ACTIVE_ATTRIBUTES );
for ( var i_n = 0; i_n < noOfAttributes; ++ i_n ) {
var name = gl.getActiveAttrib( progObj, i_n ).name;
progObj.attribIndex[name] = gl.getAttribLocation( progObj, name );
}
progObj.unifomLocation = {};
var noOfUniforms = gl.getProgramParameter( progObj, gl.ACTIVE_UNIFORMS );
for ( var i_n = 0; i_n < noOfUniforms; ++ i_n ) {
var name = gl.getActiveUniform( progObj, i_n ).name;
progObj.unifomLocation[name] = gl.getUniformLocation( progObj, name );
}
}
return progObj;
}
ShaderProgram.AttributeIndex = function( progObj, name ) { return progObj.attribIndex[name]; }
ShaderProgram.UniformLocation = function( progObj, name ) { return progObj.unifomLocation[name]; }
ShaderProgram.Use = function( progObj ) { gl.useProgram( progObj ); }
ShaderProgram.SetUniformI1 = function( progObj, name, val ) { if(progObj.unifomLocation[name]) gl.uniform1i( progObj.unifomLocation[name], val ); }
ShaderProgram.SetUniformF1 = function( progObj, name, val ) { if(progObj.unifomLocation[name]) gl.uniform1f( progObj.unifomLocation[name], val ); }
ShaderProgram.SetUniformF2 = function( progObj, name, arr ) { if(progObj.unifomLocation[name]) gl.uniform2fv( progObj.unifomLocation[name], arr ); }
ShaderProgram.SetUniformF3 = function( progObj, name, arr ) { if(progObj.unifomLocation[name]) gl.uniform3fv( progObj.unifomLocation[name], arr ); }
ShaderProgram.SetUniformF4 = function( progObj, name, arr ) { if(progObj.unifomLocation[name]) gl.uniform4fv( progObj.unifomLocation[name], arr ); }
ShaderProgram.SetUniformM33 = function( progObj, name, mat ) { if(progObj.unifomLocation[name]) gl.uniformMatrix3fv( progObj.unifomLocation[name], false, mat ); }
ShaderProgram.SetUniformM44 = function( progObj, name, mat ) { if(progObj.unifomLocation[name]) gl.uniformMatrix4fv( progObj.unifomLocation[name], false, mat ); }
ShaderProgram.CompileShader = function( source, shaderStage ) {
var shaderScript = document.getElementById(source);
if (shaderScript) {
source = "";
var node = shaderScript.firstChild;
while (node) {
if (node.nodeType == 3) source += node.textContent;
node = node.nextSibling;
}
}
var shaderObj = gl.createShader( shaderStage );
gl.shaderSource( shaderObj, source );
gl.compileShader( shaderObj );
var status = gl.getShaderParameter( shaderObj, gl.COMPILE_STATUS );
if ( !status ) alert(gl.getShaderInfoLog(shaderObj));
return status ? shaderObj : 0;
}
ShaderProgram.LinkProgram = function( shaderObjs ) {
var prog = gl.createProgram();
for ( var i_sh = 0; i_sh < shaderObjs.length; ++ i_sh )
gl.attachShader( prog, shaderObjs[i_sh] );
gl.linkProgram( prog );
status = gl.getProgramParameter( prog, gl.LINK_STATUS );
if ( !status ) alert("Could not initialise shaders");
gl.useProgram( null );
return status ? prog : 0;
}
function initShaders(gl, vert_code, frag_code)
{
var progDraw = ShaderProgram.Create(
[ { source : VSHADER_SOURCE, stage : gl.VERTEX_SHADER },
{ source : FSHADER_SOURCE, stage : gl.FRAGMENT_SHADER }
] );
progDraw.inPos = gl.getAttribLocation( progDraw, "a_Position" );
if ( progDraw == 0 )
return false;
ShaderProgram.Use( progDraw );
gl.program = progDraw;
return true;
}
function initArrayBuffers(gl)
{
var SPHERE_DIV = 6;
var i, ai, si, ci;
var j, aj, sj, cj;
var p1, p2;
var vertices = [],indices = [];
for (j = 0; j <= SPHERE_DIV; j++)
{
aj = j * Math.PI / SPHERE_DIV;
sj = Math.sin(aj);
cj = Math.cos(aj);
for (i = 0; i <= SPHERE_DIV; i++)
{
ai = i * 2 * Math.PI / SPHERE_DIV;
si = Math.sin(ai);
ci = Math.cos(ai);
vertices.push(si * sj); // X
vertices.push(cj); // Y
vertices.push(ci * sj); // Z
}
}
for (j = 0; j < SPHERE_DIV; j++)
{
for (i = 0; i < SPHERE_DIV; i++)
{
p1 = j * (SPHERE_DIV+1) + i;
p2 = p1 + (SPHERE_DIV+1);
indices.push(p1);
indices.push(p2);
indices.push(p1 + 1);
indices.push(p1 + 1);
indices.push(p2);
indices.push(p2 + 1);
}
}
var vertexBuffer = gl.createBuffer();
if (!vertexBuffer)
{
console.log('Failed to create the buffer object');
return -1;
}
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
return indices.length;
}
var n = 0;
function drawScene(){
var canvas = document.getElementById( "glow-canvas" );
gl.viewport( 0, 0, canvas.width, canvas.height );
gl.enable( gl.DEPTH_TEST );
gl.clearColor(0.0, 0.0, 0.0, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT );
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
if (a_Position < 0)
{
console.log('Failed to get the storage location of a_Position');
return -1;
}
gl.vertexAttribPointer( a_Position, 3, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( a_Position );
gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_SHORT, 0);
}
var gl;
function sceneStart() {
var canvas = document.getElementById( "glow-canvas");
var vp = [canvas.width, canvas.height];
gl = canvas.getContext( "experimental-webgl" );
if ( !gl )
return;
n = initArrayBuffers(gl);
if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE))
{
console.log('Failed to intialize shaders.');
return;
}
setInterval(drawScene, 50);
}
<body onload="sceneStart();">
<canvas id="glow-canvas" style="border: none;" width="512" height="512"></canvas>
</body>
答案 1 :(得分:0)
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
position: absolute;
margin-left: auto;
margin-right: auto;
left: 0;
right: 0;
border: solid 1px white;
border-radius: 10px;
}
</style>
<canvas id="canvas"></canvas>
<script type="application/javascript">
var imageWidth = 180;
var imageHeight = 160;
var canvas = null;
var gl = null;
var indexBuffer = null; // element array buffer
var vertexBuffer = null; // array buffer
var program = null;
var uAngle = null;
var circleAngle = 0.0;
var circleRadius = 0.75;
var circleVertexCount = 5; // No of verticies going around the circle's edge
// ES6 has handy dandy `` syntax for strings, they allow for multiple lines.
var vsCode = `
precision lowp float;
attribute vec2 aPosition;
attribute vec3 aColour;
varying vec3 vColour;
uniform float uAngle;
void main() {
float s = sin(uAngle);
float c = cos(uAngle);
mat2 rot = mat2(
c,-s,
s,c
);
vColour = aColour;
gl_Position = vec4(rot * aPosition,0.0,1.0);
}
`;
var fsCode = `
precision lowp float;
varying vec3 vColour;
void main() {
gl_FragColor = vec4(vColour,1.0);
}
`;
function loop() {
circleAngle += 0.05;
if (circleAngle > 2.0 * Math.PI) { circleAngle = 0.0; }
gl.uniform1f(uAngle,circleAngle);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElements(gl.TRIANGLES,circleVertexCount * 3,gl.UNSIGNED_SHORT,0);
requestAnimationFrame(loop);
}
window.onload = function() {
canvas = document.getElementById("canvas");
canvas.width = imageWidth;
canvas.height = imageHeight;
gl = canvas.getContext("webgl") || console.error("Couldn't get WebGL context");
gl.clearColor(0.5,0.5,0.5,1.0);
// generate verticies
// There will be one vertex in the center of the circle,
// with the rest covering the outer edge.
// vec2 + vec3 per vertex = 5 floats per vertex
var circleVerticies = new Float32Array(circleVertexCount * 5 + 5);
// add an extra point for the center
// position
circleVerticies[0] = 0.0;
circleVerticies[1] = 0.0;
// colour
circleVerticies[2] = 0.5;
circleVerticies[3] = 0.5;
circleVerticies[4] = 0.5;
for (
var i = 5, angle = 0.0;
i < circleVerticies.length;
i += 5, angle += (2.0 * Math.PI) / circleVertexCount
) {
// position
circleVerticies[i ] = Math.sin(angle) * circleRadius;
circleVerticies[i+1] = Math.cos(angle) * circleRadius;
// colour
circleVerticies[i+2] = Math.random();
circleVerticies[i+3] = Math.random();
circleVerticies[i+4] = Math.random();
}
// generate indexes
var circleIndicies = new Uint16Array(circleVertexCount * 3);
for (var i = 0, j = 1; i < circleIndicies.length - 3; i += 3, ++j) {
circleIndicies[i ] = 0;
circleIndicies[i+1] = j;
circleIndicies[i+2] = j + 1;
}
// Last triangle to connect the edge to the start
/*
|\
> | \
--- |
\ /
\ /
*/
circleIndicies[circleIndicies.length - 3] = 0;
circleIndicies[circleIndicies.length - 2] = j;
circleIndicies[circleIndicies.length - 1] = 1;
// upload buffers to gpu
vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER,circleVerticies,gl.STATIC_DRAW);
indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER,indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER,circleIndicies,gl.STATIC_DRAW);
// create program
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(vertexShader,vsCode);
gl.shaderSource(fragmentShader,fsCode);
gl.compileShader(vertexShader);
gl.compileShader(fragmentShader);
console.log(gl.getShaderInfoLog(vertexShader));
console.log(gl.getShaderInfoLog(fragmentShader));
program = gl.createProgram();
gl.attachShader(program,vertexShader);
gl.attachShader(program,fragmentShader);
gl.linkProgram(program);
gl.deleteShader(vertexShader);
gl.deleteShader(fragmentShader);
uAngle = gl.getUniformLocation(program,"uAngle");
// set state for rendering
gl.useProgram(program);
gl.vertexAttribPointer(
0, // attrib location
2, // attrib size
gl.FLOAT, // value type
gl.FALSE, // normalize?
5 * Float32Array.BYTES_PER_ELEMENT, // total vertex size in bytes (5 * 4)
0 * Float32Array.BYTES_PER_ELEMENT // offset from the start of the vertex in bytes
);
gl.vertexAttribPointer(
1, // attrib location
3, // attrib size
gl.FLOAT, // value type
gl.FALSE, // normalize?
5 * Float32Array.BYTES_PER_ELEMENT, // total vertex size in bytes (5 * 4)
2 * Float32Array.BYTES_PER_ELEMENT // offset from the start of the vertex in bytes
);
// Enable these attributes on the bound buffer for use
gl.enableVertexAttribArray(0);
gl.enableVertexAttribArray(1);
requestAnimationFrame(loop);
}
window.onunload = function() {
gl.deleteBuffer(indexBuffer);
gl.deleteBuffer(vertexBuffer);
gl = null;
}
</script>
</head>
</html>