Broadsword93
Broadsword93

Reputation: 133

How to implement keyboard input in WebGL?

I'm looking to implement keyboard input that will allow the user to change the colour of a generated shape. Below is the current code I've implemented that generates a red triangle. How would I be able to alter the code, so that if the user presses 'B' on their keyboard, the colour of the triangle will change to blue, or green if 'G' is pressed, etc.

UPDATED IMPLEMENTATION:

// Regular Polygon - Generates Triangle (or 3-Sided Shape)

// Vertex shader program
var VSHADER_SOURCE =
  'attribute vec4 a_Position;\n' +
  'void main() {\n' +
  '  gl_Position = a_Position;\n' +
  '}\n';

// Fragment shader program (assigns a color to fill in the polygon)
var FSHADER_SOURCE =
  'void main() {\n' +
  '  uniform vec3 uColor;' +
  '  gl_FragColor = vec4(uColor, 1.0);\n' +
  '}\n';

//Cyan vec4(0.0, 1.0, 1.0, 1.0)
//Brown vec(0.6, 0.5, 0.4, 1.0)
//Yellow vec4(1.0, 1.0, 0.0, 1.0)

function onKeyUp(event)
{
    if (event.key == 'c')
    {
        gl.uniform3fv(u_Color, [0.0, 1.0, 1.0])
    }
    else if (event.key == 'y')
    {
        gl.uniform3fv(u_Color, [1.0, 1.0, 0.0])
    }
    else if (event.key == 'b')
    {
      gl.uniform3fv(u_Color, [0.6, 0.5, 0.4])
    }

    gl.clear(gl.COLOR_BUFFER_BIT);  

    gl.drawArrays(gl.TRIANGLES, 0, 3);
}

function main() {
  // Retrieves canvas element
  var canvas = document.getElementById('webgl');

  // Acquires 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;
  }

  // Write the positions of each vertex to a vertex shader
  var n = initVertexBuffers(gl);
  if (n < 0) {
    console.log('Failed to set the positions of the vertices');
    return;
  }

  u_Color = gl.getUniformLocation(gl.program, 'uColor')
  if (u_Color === null)
  {
    console.log('Failed to get color uniform location');
    return;
  }
  // Default value: brown color
  gl.uniform3fv(u_Color, [0.6, 0.5, 0.4])

  document.addEventListener('keyup', onKeyUp, false);

  // Specify the color for clearing the canvas (in this case, white)
  gl.clearColor(0, 0, 0, 0);

  // Clears the canvas
  gl.clear(gl.COLOR_BUFFER_BIT);

  // Draws the triangle (or 3-sided shape)
  gl.drawArrays(gl.TRIANGLES, 0, n);




function initVertexBuffers(gl) {
  var vertices = new Float32Array([
    0, 0.5,   -0.5, -0.5,   0.5, -0.5
  ]);
  var n = 3; // The number of vertices of the polygon

  // Create a buffer object
  var vertexBuffer = gl.createBuffer();
  if (!vertexBuffer) {
    console.log('Failed to create the buffer object');
    return -1;
  }

  // Buffer object binded to target
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  // Data is written to buffer object
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);

  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;
  }
  // Position variable is assigned a buffer object
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);

  // Allows position variable to be assigned a buffer object
  gl.enableVertexAttribArray(a_Position);


  return n;
}

Upvotes: 1

Views: 3747

Answers (1)

YGilk1
YGilk1

Reputation: 464

You can easily do this job by passing a color as uniform value to your shader

var FSHADER_SOURCE =
  'precision mediump float;\n' +
  'uniform vec3 uColor;\n' +
  'void main() {\n' +
  '  gl_FragColor = vec4(uColor, 1.0);\n' +
  '}\n';

Write down a keyup event handler and set the uniform value depending on the event.key value

To set a default color, add this into your init method once the program is ready and in use

u_Color = gl.getUniformLocation(gl.program, 'uColor')
if (u_Color === null)
{
    console.log('Failed to get color uniform location');
    return;      
}
// Default value: white color
gl.uniform3fv(u_Color, [1.0, 1.0, 1.0])

To handle the keyboard event, add this to your init method

document.addEventListener('keyup', onKeyUp, false);

And this function into your code (I let you set the variables and scopes)

function onKeyUp(event)
{
    if (event.key == 'g')
    {
        gl.uniform3fv(u_Color, [0.0, 1.0, 0.0])
    }
    else if (event.key == 'b')
    {
        gl.uniform3fv(u_Color, [0.0, 0.0, 1.0])
    }

    gl.clear(gl.COLOR_BUFFER_BIT);  

    gl.drawArrays(gl.TRIANGLES, 0, 3);
}

Upvotes: 4

Related Questions