Есть много проблем с кодом выше
Для начала вы создаете пустой массив с именем 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
Далее вы добавляете 2d значения в points
в getMouseClickPosition
, но в соответствии с вашим кодом, в котором вы создаете буферы 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();
не имеет смысла и, скорее всего, взломает sh, поскольку для javascript массивов нет функции size
. Длина массива равна array.length
, как в points.length
, и далее, если вы помещаете 2 значения vec3 на точку, одно для позиции, одно для цвета, то pointCount будет points.length / 2
I также не вижу где, где this.points
назначается, даже если на него есть ссылка.
И это только некоторые из проблем.
Если вы хотите нарисовать как точки, так и треугольники, вам потребуется 2 вызова на gl.drawArrays
. Один для точек и один для треугольников.
this.mouseX
и this.mouseY
не определены.
getSliderColor вместо этого возвращает массив vec3 vec3
не вызывает рендер после добавления точки
прочее ...
А ты не показывал свои шейдеры. кажется маловероятно, что код будет работать как есть, когда вы передаете пиксельные координаты, но шейдеры работают с координатами пространства клипа. В вашем коде нет настроек для этого преобразования. Возможно, это жестко закодировано в ваших шейдерах, но это ненормально. Чаще встречается передача разрешения холста в той или иной форме, матрицы проекции или преобразование в пространство клипа в JavaScript (реже), но в вашем коде ничего подобного не появляется.
Я бы посоветовал вам узнать, как использовать отладчик , поскольку он будет показывать ошибки для некоторых проблем с кодом.
Я бы также предложил эти статьи для получения дополнительной помощи 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');
#outer { display: flex; }
<div id="outer"><canvas id='c'></canvas><div>
<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>
</div>
</div>
<script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>