{
let shaderv = gl.createShader(gl.VERTEX_SHADER);
let shaderf = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(shaderv, vertex_shader);
gl.compileShader(shaderv);
if (!gl.getShaderParameter(shaderv, gl.COMPILE_STATUS)) {
throw gl.getShaderInfoLog(shaderv);
}
gl.shaderSource(shaderf, fragment_shader);
gl.compileShader(shaderf);
if (!gl.getShaderParameter(shaderf, gl.COMPILE_STATUS)) {
throw gl.getShaderInfoLog(shaderf);
}
let shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, shaderv);
gl.attachShader(shaderProgram, shaderf);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
throw "Could not initialise shaders";
}
gl.useProgram(shaderProgram);
// There are mainly two types of variables in shaders: Attributes and Uniforms
// Attributes are arrays of data. We use them to store things like vertex positions or colors
// Uniforms are the same among all shader runs. We use them for global data like camera position or transformation matrices
// Here we only use attributes to store the positions of our triangle vertices
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
// We then enable this variable
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
// Before storing data to the variable, we need to wrap it in a WebGL buffer
// Here we create a buffer
let triangleVertexBuffer;
triangleVertexBuffer = gl.createBuffer();
// Next we set the buffer active by calling bindBuffer
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexBuffer);
// Finally, we create a list of coordinates (x,y,z,x,y,z,...) ...
let vertices = [
-0.5, -0.5, 0.0, // Note that coordinates in WebGL are always in the range [-1.0, 1.0]
0.5, -0.5, 0.0, // Later on we will use transformation matrices to scale our coordinates to that range
0.0, 0.5, 0.0 // Right now we just provide the data in the right format directly
];
// ... and send them to the shader using bufferData
// Note that the array needs to be a Float32Array, so we convert it here
// STATIC_DRAW is there to optimize performance. There are different values we can set here if the data changes a lot
// Since we don't change the triangle vertices, STATIC_DRAW is sufficient
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
// Here we define some data count variables
// itemSize is the number of floats that make up a vertex
// Our vertices are in 3D, so we need 3 floats to represent them
// numItems is the number of vertices that we have in total
// We need three vertices to represent a triangle, so that number is three
triangleVertexBuffer.itemSize = 3; //three floats (x,y,z) per vertex
triangleVertexBuffer.numItems = 3; //three vertices (one triangle, three vertices)
// This is the part where we draw our geometry
// First clear the screen (Note that we clear both color and depth)
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// Next we activate the vertex buffer that we created previously
// Technically it is still active since we didn't bind any other buffer in between but that might change as our programs become more complex
gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexBuffer);
// Here we tell WebGL about the structure of our data array and where to map this data in the shader
// The first parameter is the reference to the shader that we got earlier
// Next we pass in the itemSize (remember, that's the number of floats in a vertex)
// We need that so that WegGL knows how many single entries in our buffer represent one atomic element (i.e. vertex)
// Lastly, we need to specify that our data comes as floats (gl.FLOAT) and pass in some additional configuration that will be discussed further later in the class. For now this can always be false,0,0
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
// Define the viewport to render to (whole screen)
gl.viewport(0, 0, width, height);
// This command 'starts' the shader and renders our image
// We specify the type of geometry that we want to draw. This influences how many vertices make up one object on the screen
// Triangles are the most common primitives in computer graphics, but WebGL also supports things like LINES, POINTS, and more.
// Later versions of OpenGL also support QUADS (i.e. 4 point rectangles)
// The other two parameters define the start and end index of the items in the vertex array that we want to draw
// Since we just want to draw everything in the buffer we set these values to 0 as the start index and numItems as the end
gl.drawArrays(gl.TRIANGLES, 0, triangleVertexBuffer.numItems);
return "OK"
}