Ошибка WebGL GL_INVALID_OPERATION вне диапазона - PullRequest
1 голос
/ 04 мая 2019

Все. Я новичок в webgl, но я проверил ресурсы об этой ошибке. Я пытаюсь нарисовать один квадрат прямо рядом с моим кругом. Я нарисовал круг после того, как я добавил 4 индекса для квадрата иорганизовать drawArrays на основе этого. Но я получаю эту ошибку:

ОШИБКА GL: GL_INVALID_OPERATION: glDrawArrays: попытка доступа к вершинам вне диапазона в атрибуте 0

Также проверил мои границы и индексы, но здесь нет проблем с кодом:

var vPosition,angle=10,j=1,xr=0.2,yr=0.2,rad;
var transformationMatrix, transformationMatrixLoc;

window.onload = function init()
{

canvas = document.getElementById( "gl-canvas" );
gl = WebGLUtils.setupWebGL( canvas );

if ( !gl ) { alert( "WebGL isn't available" ); }
gl.viewport( 0, 0, canvas.width, canvas.height );

gl.clearColor( 1.0, 1.0, 1.0, 1.0 );
//  Load shaders and initialize attribute buffers

var program = initShaders( gl, "vertex-shader", "fragment-shader" );
gl.useProgram( program );

vertices = [
   vec2(0,0)
];

for(var i =0 ; i<=360 ; i+=10)
{
   vertices.push(vec2(xr*Math.cos(i*(Math.PI/180)),yr*Math.sin(i* 
   (Math.PI/180))));
}

 vertices.push(vec2(0.20,0));
 vertices.push(vec2(0.25,-0.05));
 vertices.push(vec2(0.3,0));
 vertices.push(vec2(0.25,0.05));

vBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer );
gl.bufferData( gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW );

// Associate out shader variables with our data buffer
vPosition = gl.getAttribLocation( program, "vPosition" );
gl.vertexAttribPointer( vPosition, 2, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vPosition );

transformationMatrixLoc = 
 gl.getUniformLocation(program,"transformationMatrix" );
render();
 }


render(){
gl.clear( gl.COLOR_BUFFER_BIT );
var MStack = [] ;

var transformationMatrix = mat4();
MStack.push(transformationMatrix);
gl.uniformMatrix4fv( transformationMatrixLoc, false, 
flatten(transformationMatrix) );
gl.uniform4fv(colorLoc, vec4(red, green, blue, 1.0));

gl.drawArrays( gl.TRIANGLE_FAN, 0, vertices.length-4 );

transformationMatrix = MStack.pop();
MStack.push(transformationMatrix);
gl.uniformMatrix4fv( transformationMatrixLoc, false, 
flatten(transformationMatrix) );

gl.drawArrays(gl.TRIANGLE_FAN,vertices.length-4,vertices.length);
gl.uniform4fv(colorLoc, vec4(red, green, blue, 1.0));

window.requestAnimFrame(render);
}

Надеюсь, вы, ребята, помогите мне. Действительно, спасибо.

Ответы [ 2 ]

1 голос
/ 04 мая 2019

Массив данных, который передается в .bufferData(), должен быть ArrayBuffer.

Используйте Float32Array для создания массива 32-битных чисел с плавающей запятой. Это соответствует типу gl.FLOAT в спецификации массива данных общего атрибута вершины:

gl.bufferData( gl.ARRAY_BUFFER, new Float32Array(flatten(vertices)), gl.STATIC_DRAW );

Обратите внимание, что размер хранилища данных объектов буфера определяется размером буфера массива.


Последний параметр для .drawArrays() - это число отображаемых вершин, а не индекс последнего атрибута:

gl.drawArrays(gl.TRIANGLE_FAN, vertices.length-4, 4); 
0 голосов
/ 04 мая 2019

Вот рабочий фрагмент.В следующий раз, пожалуйста, опубликуйте фрагмент, который воспроизводит вашу проблему

Вещи, которые мне нужно исправить в коде, который вы разместили

  1. Код не включает шейдеры

    Я догадался, что некоторые шейдеры, похоже, соответствуют коду

    <script id="vertex-shader" type="x-shader/x-vertex">
    attribute  vec4 vPosition;
    uniform mat4 transformationMatrix;
    void main() 
    {
        gl_Position = transformationMatrix*vPosition;
    } 
    </script>
    
    <script id="fragment-shader" type="x-shader/x-fragment">
    precision highp float;
    uniform vec4 color;
    void
    main()
    {
        gl_FragColor = color;
    }
    </script>
    
  2. Код не определил холст

    Я добавил один с идентификатором, который соответствует коду

    <canvas id="gl-canvas" width="200" height="200"></canvas>
    
  3. Код не ссылается на используемые вами скрипты.Такие вещи, как vec2 и flatten, используемые в JavaScript, не являются частью WebGL.Они являются частью какой-то библиотеки.Без них мы не можем знать, что делает ваш код

    Я догадался, что это были: https://github.com/esangel/WebGL, и поэтому я включил их, добавив

    <script src="https://esangel.github.io/WebGL/Common/webgl-utils.js"></script>
    <script src="https://esangel.github.io/WebGL/Common/initShaders.js"></script>
    <script src="https://esangel.github.io/WebGL/Common/MV.js"></script>
    
  4. Код не определил или не нашел colorLoc для color унифицированного местоположения.

  5. Код не определил red, green и blue.

Если предположить, что все они существовали в вашем фактическом коде, тогда я предполагаю, что проблема заключалась в этой строке

gl.drawArrays(gl.TRIANGLE_FAN,vertices.length-4,vertices.length);

Вероятно, это должно было быть

gl.drawArrays(gl.TRIANGLE_FAN, 0, vertices.length);

Аргументами drawArrays являются

gl.drawArrays(primitiveType, offset, count);

, где primitiveType - тип примитива для рисования.offset - это количество вершин, которые нужно пропустить в настроенных вами атрибутах, а count - это количество обрабатываемых вершин.

var vPosition, angle = 10,
  j = 1,
  xr = 0.2,
  yr = 0.2,
  colorLoc,
  rad;
var transformationMatrix, transformationMatrixLoc;

function init() {
  canvas = document.getElementById("gl-canvas");
  gl = WebGLUtils.setupWebGL(canvas);

  if (!gl) {
    alert("WebGL isn't available");
  }
  gl.viewport(0, 0, canvas.width, canvas.height);

  gl.clearColor(1.0, 1.0, 1.0, 1.0);
  //  Load shaders and initialize attribute buffers

  var program = initShaders(gl, "vertex-shader", "fragment-shader");
  gl.useProgram(program);

  vertices = [
    vec2(0, 0)
  ];

  for (var i = 0; i <= 360; i += 10) {
    vertices.push(vec2(xr * Math.cos(i * (Math.PI / 180)), yr * Math.sin(i *
      (Math.PI / 180))));
  }

  vertices.push(vec2(0.20, 0));
  vertices.push(vec2(0.25, -0.05));
  vertices.push(vec2(0.3, 0));
  vertices.push(vec2(0.25, 0.05));

  vBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW);

  // Associate out shader variables with our data buffer
  vPosition = gl.getAttribLocation(program, "vPosition");
  gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0);
  gl.enableVertexAttribArray(vPosition);

  transformationMatrixLoc =
    gl.getUniformLocation(program, "transformationMatrix");
  colorLoc = gl.getUniformLocation(program, "color");
  render();
}

function render() {
  gl.clear(gl.COLOR_BUFFER_BIT);
  var MStack = [];
  const red = 1;
  const green = 0.5;
  const blue = 0.25;

  var transformationMatrix = mat4();
  MStack.push(transformationMatrix);
  gl.uniformMatrix4fv(transformationMatrixLoc, false,
    flatten(transformationMatrix));
  gl.uniform4fv(colorLoc, vec4(red, green, blue, 1.0));

  gl.drawArrays(gl.TRIANGLE_FAN, 0, vertices.length - 4);

  transformationMatrix = MStack.pop();
  MStack.push(transformationMatrix);
  gl.uniformMatrix4fv(transformationMatrixLoc, false,
    flatten(transformationMatrix));

  gl.drawArrays(gl.TRIANGLE_FAN, 0, vertices.length);
  gl.uniform4fv(colorLoc, vec4(red, green, blue, 1.0));

  window.requestAnimFrame(render);
}

init();
canvas { border: 1px solid black; }
<script src="https://esangel.github.io/WebGL/Common/webgl-utils.js"></script>
<script src="https://esangel.github.io/WebGL/Common/initShaders.js"></script>
<script src="https://esangel.github.io/WebGL/Common/MV.js"></script>
<canvas id="gl-canvas" width="200" height="200"></canvas>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute  vec4 vPosition;
uniform mat4 transformationMatrix;
void main() 
{
    gl_Position = transformationMatrix*vPosition;
} 
</script>

<script id="fragment-shader" type="x-shader/x-fragment">
precision highp float;
uniform vec4 color;
void
main()
{
    gl_FragColor = color;
}
</script>

Еще одна вещь, которую сделал код, это использование устаревшего способа начала использования

window.onload = function init() { ...

Более современный способпросто поместите ваши скрипты внизу страницы вместо вершины и вызовите init напрямую.В противном случае используйте window.addEventListener('load', function init() { ..., так как это позволит нескольким сценариям инициализировать вещи на странице.

Вы можете найти эти статьи полезными.

...