others - WebGL 多个独立对象

这个问题已经在这里有答案:我不确定如何更改解决方案以允许web gl中的多个形状,是不是每个形状需要多个缓冲区数组和顶点缓冲区?下面是完整的代码:


var VSHADER_SOURCE = `


 attribute vec4 a_Position;


 attribute vec4 a_Color;


 attribute vec4 a_Normal; 


 uniform mat4 u_ModelMatrix;


 uniform mat4 u_NormalMatrix;


 uniform mat4 u_ViewMatrix;


 uniform mat4 u_ProjMatrix;


 uniform vec3 u_LightColor; 


 uniform vec3 u_LightDirection; // Light direction (in the world coordinate, normalized)


 varying vec4 v_Color;


 uniform bool u_isLighting;


 void main() {


 gl_Position = u_ProjMatrix * u_ViewMatrix * u_ModelMatrix * a_Position;


 if(u_isLighting) 


 {


 vec3 normal = normalize((u_NormalMatrix * a_Normal).xyz);


 float nDotL = max(dot(normal, u_LightDirection), 0.0);


 // Calculate the color due to diffuse reflection


 vec3 diffuse = u_LightColor * a_Color.rgb * nDotL;


 v_Color = vec4(diffuse, a_Color.a); }


 else


 {


 v_Color = a_Color;


 } 


 }


`;



// Fragment shader program


var FSHADER_SOURCE = `


 precision mediump float;


 varying vec4 v_Color;


 void main() {


 gl_FragColor = v_Color;


 }


`;



var modelMatrix = new Matrix4(); // The model matrix


var viewMatrix = new Matrix4(); // The view matrix


var projMatrix = new Matrix4(); // The projection matrix


var g_normalMatrix = new Matrix4(); // Coordinate transformation matrix for normals



var ANGLE_STEP = 3.0; // The increments of rotation angle (degrees)


var g_xAngle = 0.0; // The rotation x angle (degrees)


var g_yAngle = 0.0; // The rotation y angle (degrees)



function main() {


 // Retrieve <canvas> element


 var canvas = document.getElementById('webgl');



 // Get the rendering context for WebGL


 var gl = getWebGLContext(canvas);


 if (!gl) {


 console.log('Failed to get the rendering context for WebGL');


 return;


 }



 // Initialize shaders


 if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {


 console.log('Failed to intialize shaders.');


 return;


 }



 // Set clear color and enable hidden surface removal


 gl.clearColor(0.0, 0.0, 0.0, 1.0);


 gl.enable(gl.DEPTH_TEST);



 // Clear color and depth buffer


 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);



 // Get the storage locations of uniform attributes


 var u_ModelMatrix = gl.getUniformLocation(gl.program, 'u_ModelMatrix');


 var u_ViewMatrix = gl.getUniformLocation(gl.program, 'u_ViewMatrix');


 var u_NormalMatrix = gl.getUniformLocation(gl.program, 'u_NormalMatrix');


 var u_ProjMatrix = gl.getUniformLocation(gl.program, 'u_ProjMatrix');


 var u_LightColor = gl.getUniformLocation(gl.program, 'u_LightColor');


 var u_LightDirection = gl.getUniformLocation(gl.program, 'u_LightDirection');



 // Trigger using lighting or not


 var u_isLighting = gl.getUniformLocation(gl.program, 'u_isLighting'); 



 if (!u_ModelMatrix || !u_ViewMatrix || !u_NormalMatrix ||


 !u_ProjMatrix || !u_LightColor || !u_LightDirection ||


 !u_isLighting ) { 


 console.log('Failed to Get the storage locations of u_ModelMatrix, u_ViewMatrix, and/or u_ProjMatrix');


 return;


 }



 // Set the light color (white)


 gl.uniform3f(u_LightColor, 1.0, 1.0, 1.0);


 // Set the light direction (in the world coordinate)


 var lightDirection = new Vector3([0.5, 3.0, 4.0]);


 lightDirection.normalize(); // Normalize


 gl.uniform3fv(u_LightDirection, lightDirection.elements);



 // Calculate the view matrix and the projection matrix


 viewMatrix.setLookAt(0, 0, 15, 0, 0, -100, 0, 1, 0);


 projMatrix.setPerspective(30, canvas.width/canvas.height, 1, 100);


 // Pass the model, view, and projection matrix to the uniform variable respectively


 gl.uniformMatrix4fv(u_ViewMatrix, false, viewMatrix.elements);


 gl.uniformMatrix4fv(u_ProjMatrix, false, projMatrix.elements);



 document.onkeydown = function(ev){


 keydown(ev, gl, u_ModelMatrix, u_NormalMatrix, u_isLighting);


 };



 var then = 0;



 // Draw the scene repeatedly


 function render(now) {


 now *= 0.001; // convert to seconds


 const deltaTime = now - then;


 then = now;


 g_yAngle = (g_yAngle + 1) % 360;


 drawchair(gl, u_ModelMatrix, u_NormalMatrix, u_isLighting, deltaTime)



 requestAnimationFrame(render);


 }


 requestAnimationFrame(render);


 //draw(gl, u_ModelMatrix, u_NormalMatrix, u_isLighting);


}



//keyboard functionality


function keydown(ev, gl, u_ModelMatrix, u_NormalMatrix, u_isLighting) {


 switch (ev.keyCode) {


 case 40: // Up arrow key -> the positive rotation of arm1 around the y-axis


 g_xAngle = (g_xAngle + ANGLE_STEP) % 360;


 break;


 case 38: // Down arrow key -> the negative rotation of arm1 around the y-axis


 g_xAngle = (g_xAngle - ANGLE_STEP) % 360;


 break;


 case 39: // Right arrow key -> the positive rotation of arm1 around the y-axis


 g_yAngle = (g_yAngle + ANGLE_STEP) % 360;


 break;


 case 37: // Left arrow key -> the negative rotation of arm1 around the y-axis


 g_yAngle = (g_yAngle - ANGLE_STEP) % 360;


 break;


 default: return; // Skip drawing at no effective action


 }



}



// square vertices


function initVertexBuffersCube(gl) {


 // Create a cube


 // v6----- v5


 // /| /|


 // v1------v0|


 // | | | |


 // | |v7---|-|v4


 // |/ |/


 // v2------v3


 var vertices = new Float32Array([ // Coordinates


 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5,-0.5, 0.5, 0.5,-0.5, 0.5, // v0-v1-v2-v3 front


 0.5, 0.5, 0.5, 0.5,-0.5, 0.5, 0.5,-0.5,-0.5, 0.5, 0.5,-0.5, // v0-v3-v4-v5 right


 0.5, 0.5, 0.5, 0.5, 0.5,-0.5, -0.5, 0.5,-0.5, -0.5, 0.5, 0.5, // v0-v5-v6-v1 up


 -0.5, 0.5, 0.5, -0.5, 0.5,-0.5, -0.5,-0.5,-0.5, -0.5,-0.5, 0.5, // v1-v6-v7-v2 left


 -0.5,-0.5,-0.5, 0.5,-0.5,-0.5, 0.5,-0.5, 0.5, -0.5,-0.5, 0.5, // v7-v4-v3-v2 down


 0.5,-0.5,-0.5, -0.5,-0.5,-0.5, -0.5, 0.5,-0.5, 0.5, 0.5,-0.5 // v4-v7-v6-v5 back


 ]);



 //shading based on vertices


 var colors = new Float32Array([ // Colors


 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0-v1-v2-v3 front


 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0-v3-v4-v5 right


 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0-v5-v6-v1 up


 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v1-v6-v7-v2 left


 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v7-v4-v3-v2 down


 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0  // v4-v7-v6-v5 back


 ]);



 var normals = new Float32Array([ // Normal


 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, // v0-v1-v2-v3 front


 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v0-v3-v4-v5 right


 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, // v0-v5-v6-v1 up


 -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // v1-v6-v7-v2 left


 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, // v7-v4-v3-v2 down


 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0 // v4-v7-v6-v5 back


 ]);



 // Indices of the vertices, from which things are built from triangle


 // 1_________2


 // | /|


 // | / |


 // | / |


 // | / |


 // |/________|


 // 0 3


 // A clockwise arrangement, as it were starting bottom left


 var indices = new Uint8Array([


 0, 1, 2, 0, 2, 3, // front


 4, 5, 6, 4, 6, 7, // right


 8, 9,10, 8,10,11, // up


 12,13,14, 12,14,15, // left


 16,17,18, 16,18,19, // down


 20,21,22, 20,22,23 // back


 ]);



 // Write the vertex property to buffers (coordinates, colors and normals)


 if (!initArrayBuffer(gl, 'a_Position', vertices, 3, gl.FLOAT)) return -1;


 if (!initArrayBuffer(gl, 'a_Color', colors, 3, gl.FLOAT)) return -1;


 if (!initArrayBuffer(gl, 'a_Normal', normals, 3, gl.FLOAT)) return -1;



 // Write the indices to the buffer object


 var indexBuffer = gl.createBuffer();


 if (!indexBuffer) {


 console.log('Failed to create the buffer object');


 return false;


 }



 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);


 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);



 return indices.length;


}



function initArrayBuffer (gl, attribute, data, num, type) {


 // Create a buffer object


 var buffer = gl.createBuffer();


 if (!buffer) {


 console.log('Failed to create the buffer object');


 return false;


 }


 // Write date into the buffer object


 gl.bindBuffer(gl.ARRAY_BUFFER, buffer);


 gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);


 // Assign the buffer object to the attribute variable


 var a_attribute = gl.getAttribLocation(gl.program, attribute);


 if (a_attribute < 0) {


 console.log('Failed to get the storage location of ' + attribute);


 return false;


 }


 gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0);


 // Enable the assignment of the buffer object to the attribute variable


 gl.enableVertexAttribArray(a_attribute);



 gl.bindBuffer(gl.ARRAY_BUFFER, null);



 return true;


}



var g_matrixStack = []; // Array for storing a matrix


function pushMatrix(m) { // Store the specified matrix to the array


 var m2 = new Matrix4(m);


 g_matrixStack.push(m2);


}



function popMatrix() { // Retrieve the matrix from the array


 return g_matrixStack.pop();


}



function drawchair(gl, u_ModelMatrix, u_NormalMatrix, u_isLighting) {



 // Clear color and depth buffer


 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);



 gl.uniform1i(u_isLighting, false); // Will not apply lighting



 // Calculate the view matrix and the projection matrix


 modelMatrix.setTranslate(0, 0, 0); // No Translation


 // Pass the model matrix to the uniform variable


 gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);



 // Draw x and y axes


 gl.drawArrays(gl.LINES, 0, n);



 gl.uniform1i(u_isLighting, true); // Will apply lighting



 // Set the vertex coordinates and color (for the cube)


 var n = initVertexBuffersCube(gl);


 if (n < 0) {


 console.log('Failed to set the vertex information');


 return;


 }



 //x,y,z 


 // Rotate, and then translate


 modelMatrix.setTranslate(0, 0, -5); // Translation (No translation is supported here)


 modelMatrix.rotate(g_yAngle, 0, 1, 0); // Rotate along y axis


 modelMatrix.rotate(g_xAngle, 1, 0, 0); // Rotate along x axis



 // Model the chair seat


 pushMatrix(modelMatrix);


 modelMatrix.scale(2.0, 0.4, 2.0); // Scale


 drawbox(gl, u_ModelMatrix, u_NormalMatrix, n);


 modelMatrix = popMatrix();



 // Model the chair back


 pushMatrix(modelMatrix);


 modelMatrix.translate(0, 1.20, -0.8); // Translation


 modelMatrix.scale(2.0, 2.2, 0.4); // Scale


 drawbox(gl, u_ModelMatrix, u_NormalMatrix, n);


 modelMatrix = popMatrix();



 //As if you were sitting on the chair;


 //Back right leg


 pushMatrix(modelMatrix);


 modelMatrix.scale(0.3, 1.9, 0.3);


 modelMatrix.translate(-2.6,-0.4,-2.6)


 drawbox(gl, u_ModelMatrix, u_NormalMatrix, n);


 modelMatrix = popMatrix();



 //Back left leg


 pushMatrix(modelMatrix);


 modelMatrix.scale(0.3, 1.9, 0.3);


 modelMatrix.translate(2.6,-0.4,-2.6)


 drawbox(gl, u_ModelMatrix, u_NormalMatrix, n);


 modelMatrix = popMatrix();



 //Front right leg


 pushMatrix(modelMatrix);


 modelMatrix.scale(0.3, 1.9, 0.3);


 modelMatrix.translate(-2.6,-0.4,2.6)


 drawbox(gl, u_ModelMatrix, u_NormalMatrix, n);


 modelMatrix = popMatrix();



 //Front left leg


 pushMatrix(modelMatrix);


 modelMatrix.scale(0.3, 1.9, 0.3);


 modelMatrix.translate(2.6,-0.4,2.6)


 drawbox(gl, u_ModelMatrix, u_NormalMatrix, n);


 modelMatrix = popMatrix();



}



function drawbox(gl, u_ModelMatrix, u_NormalMatrix, n) {


 pushMatrix(modelMatrix);



 // Pass the model matrix to the uniform variable


 gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);



 // Calculate the normal transformation matrix and pass it to u_NormalMatrix


 g_normalMatrix.setInverseOf(modelMatrix); //set the normal matrix as the inverse of the current model


 g_normalMatrix.transpose();


 gl.uniformMatrix4fv(u_NormalMatrix, false, g_normalMatrix.elements);



 // Draw the cube


 gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);


 modelMatrix = popMatrix();


}



function drawsphere(gl, u_ModelMatrix, u_NormalMatrix, n) {


 pushMatrix(modelMatrix);



 // Pass the model matrix to the uniform variable


 gl.uniformMatrix4fv(u_ModelMatrix, false, modelMatrix.elements);



 // Calculate the normal transformation matrix and pass it to u_NormalMatrix


 g_normalMatrix.setInverseOf(modelMatrix); //set the normal matrix as the inverse of the current model


 g_normalMatrix.transpose();


 gl.uniformMatrix4fv(u_NormalMatrix, false, g_normalMatrix.elements);



 // Draw the cube


 gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0);


 modelMatrix = popMatrix();


}



时间:

你需要为每个图形原语创建着色器等的副本,

通过将图形原语抽象为类,并使用组合来创建复杂的形状和图形,可以改进代码,一旦切换到OOP,就会受益于拥有多个对象。

...