Круг не рендеринг на холст - PullRequest
0 голосов
/ 26 апреля 2020

Я пытаюсь сделать круг, используя WebGL. Мне нужно всего лишь перевести окружность с помощью значения пикселя Dynami c, поэтому я использовал некоторые логики перевода c из учебника, преобразующего пространство пикселей в пространство клипов, и поместил его в вершинный шейдер. Я также использую общую технику TRIANGLE_FAN для создания круга.

В настоящее время я не вижу ничего на холсте; он отображается как белый экран, и нигде нет круга. Я только хочу, чтобы круг имел радиус 1px.

//shaders
const glsl = (x) => x;

const vertex = glsl`
  attribute vec2 a_position;

  uniform vec2 u_resolution;
  uniform vec2 u_translation;

  void main() {

    //add in the translation
    vec2 position = a_position + u_translation;

    // convert the circle points from pixels to 0.0 to 1.0
    vec2 zeroToOne = a_position / u_resolution;

    // convert from 0->1 to 0->2
    vec2 zeroToTwo = zeroToOne * 2.0;

    // convert from 0->2 to -1->+1 (clipspace)
    vec2 clipSpace = zeroToTwo - 1.0;

    gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
  }
`;

const fragment = glsl`
  precision mediump float;

  uniform vec4 u_color;

  void main() {
    gl_FragColor = u_color;
  }
`;

function main() {
  // Get A WebGL context
  var canvas = document.querySelector("#c");
  var gl = canvas.getContext("webgl");
  if (!gl) {
    return;
  }

  const opacity = 0.5; //opacity will be dynamic
  const color = [0, 0, 0, opacity];
  const translation = [50, 50]; //this translation value with be dynamic but using [50,50] for demo purposes

  // Use our boilerplate utils to compile the shaders and link into a program
  var program = webglUtils.createProgramFromScripts(gl, [vertex, fragment]);

  // look up where the vertex data needs to go.
  var positionAttributeLocation = gl.getAttribLocation(program, "a_position");

  // look up uniform locations
  var resolutionUniformLocation = gl.getUniformLocation(program,"u_resolution");
  var translationUniformLocation = gl.getUniformLocation(program, "u_translation");
  var colorUniformLocation = gl.getUniformLocation(program, "u_color");

  // Create a buffer to put three 2d clip space points in
  var positionBuffer = gl.createBuffer();

  // Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer)
  gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

  const positions = [
    0.0, 0.0 //circle center vertex
  ];

  const stops = 100;

  for (i = 0; i < stops; i++){
    positions.push(Math.cos(i * 2 * Math.PI/stops)); // x coord
    positions.push(Math.sin(i * 2 * Math.PI/stops)); // y coord
  }

  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

  //sets canvas width and height to current size of canvas as specified in css
  webglUtils.resizeCanvasToDisplaySize(gl.canvas);

  // Tell WebGL how to convert from clip space to pixels
  gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

  // Clear the canvas
  gl.clearColor(0, 0, 0, 0);
  gl.clear(gl.COLOR_BUFFER_BIT);

  // Tell it to use our program (pair of shaders)
  gl.useProgram(program);

  // Turn on the attribute
  gl.enableVertexAttribArray(positionAttributeLocation);

  // Bind the position buffer.
  gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

  // Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER)
  var size = 2; // 2 components per stop
  var type = gl.FLOAT; // the data is 32bit floats
  var normalize = false; // don't normalize the data
  var stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position
  var offset = 0; // start at the beginning of the buffer
  gl.vertexAttribPointer(
    positionAttributeLocation,
    size,
    type,
    normalize,
    stride,
    offset
  );

  // set the resolution
  gl.uniform2f(resolutionUniformLocation, gl.canvas.width, gl.canvas.height);

  //set the translation
  gl.uniform2fv(translationUniformLocation, translation);

  //set the color
  gl.uniform4fv(colorUniformLocation, color);


  // draw
  var primitiveType = gl.TRIANGLE_FAN;
  var offset = 0;
  const count = stops + 1; //adding one for center of circle
  gl.drawArrays(primitiveType, offset, count);
}

main();
<script src="https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
<canvas id="c"></canvas>

1 Ответ

1 голос
/ 26 апреля 2020

Есть 3 проблемы с кодом выше

  1. Он вызывает createProgramFromScripts вместо createProgramFromSources

  2. Шейдер не используйте u_translation

    Вот первые 2 строки

    //add in the translation
    vec2 position = a_position + u_translation;
    
    // convert the circle points from pixels to 0.0 to 1.0
    vec2 zeroToOne = a_position / u_resolution;
    

    , которые вторая строка использует a_position вместо position

  3. Вентилятор пропускает последний треугольник.

    Вы, вероятно, хотите, чтобы <= stops в вашем распоряжении для l oop

Я настоятельно рекомендую вам следовать учебным пособиям там и освоитесь с использованием матриц. Они начинаются с кода шейдера, как в коде выше, но постепенно заменяются матрицами. Даже для пикселей матрицы разрешают многие вещи, без которых будет сложно.

...