WebGL绘制三角形以一次筛选一个点

问题描述 投票:0回答:1

我对WebGL真的很陌生,一直在尝试创建一个程序,用鼠标单击将绘制画布上颜色滑块中指定的颜色的点,并在绘制三个点后将它们连接成一个三角形。我创建了一个名为“ points”的数组,以在单击时传递鼠标位置的数据,然后将其展平为“ vertexData”,以发送到缓冲区和着色器。但是,我目前无法解决任何问题。任何帮助将不胜感激。预先感谢。

“使用严格”;

// Constructor
//
// @param canvasID - string containing name of canvas to render.
//          Buttons and sliders should be prefixed with this string.
//
function Lab2(canvasID /* name of canvas to render */) {
  this.canvasID = canvasID;
  this.canvas = document.getElementById(canvasID);
  if (!this.canvas) {
    alert("Canvas ID '" + canvasID + "' not found.");
    return;
  }
  this.gl = WebGLUtils.setupWebGL(this.canvas);
  if (!this.gl) {
    alert("WebGL isn't available in this browser");
    return;
  }

  this.init();
}

// Define prototype values common to all Lab2 objects
Lab2.prototype.gl = null;

Lab2.prototype.toString = function () {
  return JSON.stringify(this);
};

Lab2.prototype.init = function () {
  var canvas = this.canvas;
  var gl = this.gl;
  var t = this;  // make available to event handlers

  // WebGL setup
  gl.viewport(0, 0, canvas.width, canvas.height);

  // Compile and link shaders
  this.shaderProgram = initShaders(gl, "vShader.glsl", "fShader.glsl");
  if (this.shaderProgram === null)
    return;
  gl.useProgram(this.shaderProgram);

  // Define names for colors
  var white = vec3(1.0, 1.0, 1.0);
  var red = vec3(1.0, 0.0, 0.0);
  var green = vec3(0.0, 1.0, 0.0);
  var blue = vec3(0.0, 0.0, 1.0);
  var yellow = vec3(1.0, 1.0, 1.0);

  // Array of alternating initial vertex coordinates and colors for each vertex
  var points = [];

  this.vertexData = flatten(points);

  // Count of points in vertexData
  this.pointCount = points.size();

  var floatSize = 4;  // size of gl.FLOAT in bytes
  // Load vertex data into WebGL buffer
  this.vertexCoordBuffer = gl.createBuffer();  // get unique buffer ID
  gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexCoordBuffer);  // make this the active buffer
  gl.bufferData(gl.ARRAY_BUFFER, this.vertexData, gl.STATIC_DRAW);  // write data to buffer

  // Define data layout in buffer for position.  Postions are 3 floats,
  // interleaved with 3 floats for colors, starting at beginning of buffer.
  this.vPosition = gl.getAttribLocation(this.shaderProgram, "vPosition");
  gl.vertexAttribPointer(this.vPosition, 3, gl.FLOAT, false, 6 * floatSize, 0);
  gl.enableVertexAttribArray(this.vPosition);

  // Define data layout in buffer for colors.  Colors are 3 floats,
  // interleaved with 3 floats for positions, starting after first position in buffer.
  this.vColor = gl.getAttribLocation(this.shaderProgram, "vColor");
  gl.vertexAttribPointer(this.vColor, 3, gl.FLOAT, false, 6 * floatSize, 3 * floatSize);
  gl.enableVertexAttribArray(this.vColor);

  // Define callback for change of slider value
  var sliderCallback = function (e) {
    // Update text display for slider
    var color = e.target.value;
    e.target.valueDisplay.textContent = color;

    // Re-render canvas
    requestAnimationFrame(render);
  };

  // Set up HTML user interface
  this.colors = ["r", "g", "b"];
  var rgbSliders = [];         // array of slider HTML elements
  var rgbSliderValues = [];    // array of slider value HTML elements

  // Set up an object with sliders for the three colors. The sliders are
  // accessed using "indices" of "r", "g", and "b".
  for (var i in this.colors) {
    var color = this.colors[i];
    var sliderID = this.canvasID + "-" + color + "-slider";
    rgbSliders[color] = document.getElementById(sliderID);
    if (rgbSliders[color] === null) {
      alert("Slider ID not found: " + sliderID);
      return;
    }
    var valueID = this.canvasID + "-" + color + "-value";
    rgbSliderValues[color] = document.getElementById(valueID);
    if (rgbSliders[color] === null) {
      alert("Slider value ID not found: " + sliderID);
      return;
    }
    rgbSliders[color].valueDisplay = rgbSliderValues[color];  // attach to slider

    // Set callback on slider input
    rgbSliders[color].addEventListener("input", sliderCallback);
  }
  this.rgbSliders = rgbSliders;

  var resetButton = document.getElementById(this.canvasID + "-reset-button");
  if (resetButton === null) {
    alert("Reset button ID not found: " + this.canvasID + "-reset-button");
    return;
  }

  // Set up callback to render a frame
  var render = function () {
    t.Render();
  };

  // Set up the callback for the reset button
  resetButton.addEventListener("click", function () {
    // Reset all the sliders to the middle value
    for (var i in rgbSliders) {
      rgbSliders[i].value = rgbSliders[i].max / 2.0;
      rgbSliders[i].valueDisplay.textContent =
              rgbSliders[i].valueAsNumber / rgbSliders[i].max;
    }
    requestAnimationFrame(render);
  });

  // Set up mouse tracking
  var mouseX = document.getElementById(this.canvasID + "-mousex");
  var mouseY = document.getElementById(this.canvasID + "-mousey");
  var mouseButton = document.getElementById(this.canvasID + "-mousebutton");
  this.mouseDown = [ false, false, false ];  // track mouse button state
  mouseButton.textContent = this.mouseDown;
  if (mouseX === null || mouseY === null || mouseButton === null) {
    alert("Mouse output HTML IDs not found");
    return;
  }

  // Add mouse event handlers
  canvas.addEventListener("mousedown", function (e) {
    t.mouseDown[e.button] = true;
    mouseButton.textContent = t.mouseDown;
    getMouseClickPosition();
  });
  canvas.addEventListener("mouseup", function (e) {
    t.mouseDown[e.button] = false;
    mouseButton.textContent = t.mouseDown;
  });
  canvas.addEventListener("mousemove", function (e) {
    mouseX.textContent = e.pageX - e.target.offsetLeft;
    mouseY.textContent = e.pageY - e.target.offsetTop;
  });

  // Kick things off with an initial rendering
  requestAnimationFrame(render);
};

/**
 * GetSliderColors - get the current RGB color represented by the sliders
 *   as a vec3.
 *   
 * @returns {vec3} current slider color
 */
Lab2.prototype.getSliderColor = function () {
  // Build an array of color values based on the current slider colors
  var colorValues = [];
  for (var i in this.colors) {
    var color = this.colors[i];
    var colorValue = this.rgbSliders[color].valueAsNumber;
    colorValues[i] = colorValue;
  }

  return vec3(colorValues);
};

Lab2.prototype.getMouseClickPosition = function (){
    var point = vec2(this.mouseX, this.mouseY);
    this.points.push(point);
};

/**
 * Render - draw the frame
 *
 */
Lab2.prototype.Render = function () {
  var gl = this.gl;
  gl.clearColor(0.0, 0.0, 0.25, 1.0);
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.drawArrays(gl.POINTS, 0, this.pointCount);
};
javascript graphics 2d webgl
1个回答
0
投票
上面的代码有很多问题

首先,创建一个名为points的空数组,然后将其展平,它是空的,因此展平的版本为空,然后创建一个WebGL缓冲区,其结果为空。将点推入javascript数组不会更新WebGL中的缓冲区,因此至少每次添加点时都需要更新WebGL中的缓冲区。

Lab2.prototype.getMouseClickPosition = function (){ var point = vec2(this.mouseX, this.mouseY); this.points.push(point); this.vertexData = flatten(this.points); // Count of points in vertexData this.pointCount = this.points.size(); var floatSize = 4; // size of gl.FLOAT in bytes // Load vertex data into WebGL buffer gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexCoordBuffer); // make this the active buffer gl.bufferData(gl.ARRAY_BUFFER, this.vertexData, gl.STATIC_DRAW); // write data to buffer

此外,您还向points中的getMouseClickPosition添加了2d值,但是根据您在其中创建WebGL缓冲区的代码进行了设置,因此它期望每个点具有3个值,而不是2个,然后期望3个颜色值。换句话说,您要将[x, y, x, y, x, y]放在points中,但根据您的设置代码,它必须为[x, y, z, r, g, b, x, y, z, r, g, b, x, y, z, r, g, b]

Lab2.prototype.getMouseClickPosition = function (){ var point = vec3(this.mouseX, this.mouseY, 0); // no idea what Z value you want this.points.push(point); this.points.push(vec3(red, green, blue)); // you need to figure out red, green, and blue ...

您进一步呼叫points是一个javascript数组,因此此代码

this.pointCount = points.size();

没有意义,并且可能会崩溃,因为JavaScript数组没有size函数。数组的长度为array.length,与points.length一样,此外,如果每个点放置2个vec3值,一个为位置,一个为颜色,那么pointCount为points.length / 2

即使引用,也看不到this.points的分配位置。

而这只是其中一些问题。

  • 如果要同时绘制点和三角形,则需要2次调用gl.drawArrays。一个用于点,另一个用于三角形。
  • this.mouseXthis.mouseY未定义。
  • getSliderColor返回vec3而不是vec3的数组

而且您没有显示着色器。

似乎代码不太可能像在传递像素坐标时那样按原样工作,但着色器可以与剪贴空间坐标一起工作。您的代码中没有用于处理该转换的设置。可能在着色器中对其进行了硬编码,但这是不正常的。更常见的是,以一种或另一种形式通过画布分辨率传递投影矩阵,或者在JavaScript中转换为剪贴空间(较不常见),但在您的代码中却没有任何一种出现。

我建议您学习如何use a debugger,因为它会显示某些代码问题的错误。

我也建议these articles以获取更多WebGL帮助。

// Constructor // // @param canvasID - string containing name of canvas to render. // Buttons and sliders should be prefixed with this string. // function Lab2(canvasID /* name of canvas to render */) { this.canvasID = canvasID; this.canvas = document.getElementById(canvasID); if (!this.canvas) { alert("Canvas ID '" + canvasID + "' not found."); return; } this.gl = WebGLUtils.setupWebGL(this.canvas); if (!this.gl) { alert("WebGL isn't available in this browser"); return; } this.init(); } // Define prototype values common to all Lab2 objects Lab2.prototype.gl = null; Lab2.prototype.toString = function () { return JSON.stringify(this); }; Lab2.prototype.init = function () { var canvas = this.canvas; var gl = this.gl; var t = this; // make available to event handlers // WebGL setup gl.viewport(0, 0, canvas.width, canvas.height); // Compile and link shaders this.shaderProgram = initShaders(gl, "vShader.glsl", "fShader.glsl"); if (this.shaderProgram === null) return; gl.useProgram(this.shaderProgram); this.resolutionLoc = gl.getUniformLocation(this.shaderProgram, 'resolution'); // Define names for colors var white = vec3(1.0, 1.0, 1.0); var red = vec3(1.0, 0.0, 0.0); var green = vec3(0.0, 1.0, 0.0); var blue = vec3(0.0, 0.0, 1.0); var yellow = vec3(1.0, 1.0, 1.0); // Array of alternating initial vertex coordinates and colors for each vertex var points = []; this.points = points; this.vertexData = flatten(points); // Count of points in vertexData this.pointCount = 0; var floatSize = 4; // size of gl.FLOAT in bytes // Load vertex data into WebGL buffer this.vertexCoordBuffer = gl.createBuffer(); // get unique buffer ID gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexCoordBuffer); // make this the active buffer gl.bufferData(gl.ARRAY_BUFFER, this.vertexData, gl.STATIC_DRAW); // write data to buffer // Define data layout in buffer for position. Postions are 3 floats, // interleaved with 3 floats for colors, starting at beginning of buffer. this.vPosition = gl.getAttribLocation(this.shaderProgram, "vPosition"); gl.vertexAttribPointer(this.vPosition, 3, gl.FLOAT, false, 6 * floatSize, 0); gl.enableVertexAttribArray(this.vPosition); // Define data layout in buffer for colors. Colors are 3 floats, // interleaved with 3 floats for positions, starting after first position in buffer. this.vColor = gl.getAttribLocation(this.shaderProgram, "vColor"); gl.vertexAttribPointer(this.vColor, 3, gl.FLOAT, false, 6 * floatSize, 3 * floatSize); gl.enableVertexAttribArray(this.vColor); // Define callback for change of slider value var sliderCallback = function (e) { // Update text display for slider var color = e.target.value; e.target.valueDisplay.textContent = color; // Re-render canvas requestAnimationFrame(render); }; // Set up HTML user interface this.colors = ["r", "g", "b"]; var rgbSliders = []; // array of slider HTML elements var rgbSliderValues = []; // array of slider value HTML elements // Set up an object with sliders for the three colors. The sliders are // accessed using "indices" of "r", "g", and "b". for (var i in this.colors) { var color = this.colors[i]; var sliderID = this.canvasID + "-" + color + "-slider"; rgbSliders[color] = document.getElementById(sliderID); if (rgbSliders[color] === null) { alert("Slider ID not found: " + sliderID); return; } var valueID = this.canvasID + "-" + color + "-value"; rgbSliderValues[color] = document.getElementById(valueID); if (rgbSliders[color] === null) { alert("Slider value ID not found: " + sliderID); return; } rgbSliders[color].valueDisplay = rgbSliderValues[color]; // attach to slider // Set callback on slider input rgbSliders[color].addEventListener("input", sliderCallback); } this.rgbSliders = rgbSliders; var resetButton = document.getElementById(this.canvasID + "-reset-button"); if (resetButton === null) { alert("Reset button ID not found: " + this.canvasID + "-reset-button"); return; } // Set up callback to render a frame var render = function () { t.Render(); }; // Set up the callback for the reset button resetButton.addEventListener("click", function () { // Reset all the sliders to the middle value for (var i in rgbSliders) { rgbSliders[i].value = rgbSliders[i].max / 2.0; rgbSliders[i].valueDisplay.textContent = rgbSliders[i].valueAsNumber / rgbSliders[i].max; } requestAnimationFrame(render); }); // Set up mouse tracking var mouseX = document.getElementById(this.canvasID + "-mousex"); var mouseY = document.getElementById(this.canvasID + "-mousey"); var mouseButton = document.getElementById(this.canvasID + "-mousebutton"); this.mouseDown = [ false, false, false ]; // track mouse button state mouseButton.textContent = this.mouseDown; if (mouseX === null || mouseY === null || mouseButton === null) { alert("Mouse output HTML IDs not found"); return; } // Add mouse event handlers canvas.addEventListener("mousedown", function (e) { t.mouseDown[e.button] = true; mouseButton.textContent = t.mouseDown; t.mouseX = e.pageX - e.target.offsetLeft; t.mouseY = e.pageY - e.target.offsetTop; t.getMouseClickPosition(); requestAnimationFrame(render); }); canvas.addEventListener("mouseup", function (e) { t.mouseDown[e.button] = false; mouseButton.textContent = t.mouseDown; }); canvas.addEventListener("mousemove", function (e) { mouseX.textContent = e.pageX - e.target.offsetLeft; mouseY.textContent = e.pageY - e.target.offsetTop; }); // Kick things off with an initial rendering requestAnimationFrame(render); }; /** * GetSliderColors - get the current RGB color represented by the sliders * as a vec3. * * @returns {vec3} current slider color */ Lab2.prototype.getSliderColor = function () { // Build an array of color values based on the current slider colors var colorValues = []; for (var i in this.colors) { var color = this.colors[i]; var colorValue = this.rgbSliders[color].valueAsNumber; colorValues[i] = colorValue; } return vec3(...colorValues); }; Lab2.prototype.getMouseClickPosition = function (){ var point = vec3(this.mouseX, this.mouseY, 0); this.points.push(point, this.getSliderColor()); this.vertexData = flatten(this.points); // Count of points in vertexData this.pointCount = this.points.length / 2; var floatSize = 4; // size of gl.FLOAT in bytes var gl = this.gl; // Load vertex data into WebGL buffer gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexCoordBuffer); // make this the active buffer gl.bufferData(gl.ARRAY_BUFFER, this.vertexData, gl.STATIC_DRAW); // write data to buffer }; /** * Render - draw the frame * */ Lab2.prototype.Render = function () { var gl = this.gl; gl.clearColor(0.0, 0.0, 0.25, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); if (!this.pointCount) return; gl.useProgram(this.shaderProgram); gl.uniform2f(this.resolutionLoc, gl.canvas.width, gl.canvas.height); gl.drawArrays(gl.POINTS, 0, this.pointCount); gl.drawArrays(gl.TRIANGLES, 0, this.pointCount); }; const WebGLUtils = { setupWebGL(elem) { return elem.getContext('webgl'); }, }; function initShaders(gl, vsHref, fsHref) { // ignore vsHref and fsHref and guess what the shaders are return twgl.createProgram(gl, [` attribute vec4 vPosition; attribute vec3 vColor; uniform vec2 resolution; varying vec3 v_color; void main() { gl_PointSize = 10.0; gl_Position = vec4(vPosition.xy / resolution * vec2(2, -2) + vec2(-1, 1), 0, 1); v_color = vColor; } `, ` precision mediump float; varying vec3 v_color; void main() { gl_FragColor = vec4(v_color, 1); } `]); } const vec3 = (x, y, z) => [x, y, z]; const flatten = a => new Float32Array(a.flat()); const lab = new Lab2('c');
<canvas id='c'></canvas><br>
<input type="range" value="1" min="0" max="1" step="0.01" id="c-r-slider"><span id="c-r-value"></span><br>
<input type="range" min="0" max="1" step="0.01"  id="c-g-slider"><span id="c-g-value"></span><br>
<input type="range" min="0" max="1" step="0.01"  id="c-b-slider"><span id="c-b-value"></span><br>
<button type="button" id="c-reset-button">reset</button>
<div id="c-mousex"></div>
<div id="c-mousey"></div>
<div id="c-mousebutton"></div>
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
© www.soinside.com 2019 - 2024. All rights reserved.