Некоторые проблемы
Нет такой вещи, как gl.viewportWidth
и gl.viewportHeight
Использование gl.canvas.width
и gl.canvas.height
.
Там есть сайткоторый учит использовать gl.viewportWidth
и gl.viewportHeight
.Это возможно анти-образец.Эти переменные не являются частью WebGL.Это пользовательские переменные, добавляемые примером в контекст WebGL.Существует абсолютно нулевая причина сделать это, поскольку они всегда должны обновляться вручную, а фактическая ширина и высота всегда доступны.
Опечатка в triangleVertices
Вторая запятая ниже должна бытьточка
плохо
const triangleVertices = [
0.0, 0, 5, 0.0, -0.5, -0.5, 0.0,
0.5, -0.5, 0.0
]
хорошо
const triangleVertices = [
0.0, 0.5, 0.0, -0.5, -0.5, 0.0,
0.5, -0.5, 0.0
]
С этим он работает, но вот еще одна опечатка
vertextPositionAttribute
должно быть vertexPositionAttribute
shaderProgram.vertextPositionAttribute = gl.getAttribLocation(shaderProgram, 'vertexPos')
//gl.enableVertexAttribArray(shaderProgram.vertextPositionAttribute)
При этом есть несколько предложений.
- Использование литералов многострочных шаблонов для шейдеров
вместо
const vertexShaderText = [
'attribute vec3 vertexPos;',
'',
'void main() {',
' gl_Position = vec4(vertexPos, 1.0);',
'}'
].join('\n')
сделать это
const vertexShaderText = `
attribute vec3 vertexPos;
void main() {
gl_Position = vec4(vertexPos, 1.0);
}
`;
Намного проще!Используйте кавычки вместо кавычек для многострочных строк
- Сделайте
initShader
возврат шейдера вместо того, чтобы назначить глобальный
В WebGL не часто встречается один шейдерпоэтому гораздо полезнее иметь функцию, которая создает шейдеры
- Не вызывайте
gl.useProgram
в initShader
Опять же, нередко иметь один шейдер,Вызов gl.useProgram
обычно относится к draw
Не добавляйте атрибуты к объектам браузера, особенно к объектам WebGL
bad
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, 'vertexPos');
хорошо (один из многих способов)
const shaderProgramInfo = {}
shaderProgramInfo.program = initShader(...)
shaderProgramInfo.vertexPositionAttribute =
gl.getAttribLocation(shaderProgramInfo.program, 'vertexPos');
Это потому, что в случае сбоя initShader (например, потеря контекста) ваш gl.createProgram
будет иметь значение null, а попытка присвоить свойству значение null приведет к тому, что ваша страницапотерпеть поражение.Та же проблема с буфером
плохо
const buffer = gl.createBuffer();
...
buffer.itemSize = 3
buffer.numberOfItems = 3
хорошо (один из многих способов)
const bufferInfo = {
buffer: gl.createBuffer(),
}
...
bufferInfo.itemSize = 3
bufferInfo.numberOfItems = 3
Позвоните gl.bindBuffer
перед вызовом gl.vertexAttribPointer
Ваш код работает, потому что есть только один буфер.Если имеется 2 буфера, он, скорее всего, перестанет работать, потому что gl.vertexAttribPointer
ссылается на текущий связанный буфер
Рекомендуем прочитать лучшие учебники.
I 'буду рекомендовать https://webglfundamentals.org
const vertexShaderText = `
attribute vec3 vertexPos;
void main() {
gl_Position = vec4(vertexPos, 1.0);
}
`;
const fragmentShaderText = `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`;
let gl, shaderProgramInfo, bufferInfo
function startup() {
const canvas = document.getElementById('myCanvas')
gl = canvas.getContext('webgl')
shaderProgramInfo = {
program: initShader(gl, vertexShaderText, fragmentShaderText),
};
shaderProgramInfo.vertexPositionAttribute = gl.getAttribLocation(shaderProgramInfo.program, 'vertexPos');
bufferInfo = initBuffer()
gl.clearColor(0.0, 0.0, 0.0, 1.0)
draw()
}
function initShader(gl, vertexShaderText, fragmentShaderText) {
// VERTEX SHADER
let vertexShader = gl.createShader(gl.VERTEX_SHADER)
gl.shaderSource(vertexShader, vertexShaderText)
gl.compileShader(vertexShader)
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
alert('vertex', gl.getShaderInfoLog(vertexShader))
return
}
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER)
gl.shaderSource(fragmentShader, fragmentShaderText)
gl.compileShader(fragmentShader)
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
alert('fragment', gl.getShaderInfoLog(fragmentShader))
return
}
const shaderProgram = gl.createProgram()
gl.attachShader(shaderProgram, vertexShader)
gl.attachShader(shaderProgram, fragmentShader)
gl.linkProgram(shaderProgram)
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert('Failed to setup shaders')
}
return shaderProgram;
}
function initBuffer() {
buffer = gl.createBuffer()
gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
const triangleVertices = [
0.0, 0.5, 0.0, -0.5, -0.5, 0.0,
0.5, -0.5, 0.0
]
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW)
return {
buffer,
itemSize: 3,
numberOfItems: 3,
};
}
function draw() {
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT)
gl.useProgram(shaderProgramInfo.program)
gl.bindBuffer(gl.ARRAY_BUFFER, bufferInfo.buffer);
gl.vertexAttribPointer(shaderProgramInfo.vertexPositionAttribute,
bufferInfo.itemSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(shaderProgramInfo.vertexPositionAttribute)
//Draw the triangle
gl.drawArrays(gl.TRIANGLES, 0, bufferInfo.numberOfItems)
}
startup()
<canvas id="myCanvas" width="500" height="500"></canvas>