Используя Nurbs Surface (Verb) в webGL, индексы всегда неверны, если только я не использую углы вместо контрольных точек

Я пытаюсь заставить Verb's Nurbs Surface работать с ванильным webGL (хотя немного обманываю с webgl-utils). PIXI.js также дает те же результаты, углы работают, но не контрольные точки.

Я мог бы сделать это, используя углы verb.geom.NurbsSurface.byCorners, однако, когда я пытаюсь использовать контрольные точки с помощью verb.geom.NurbsSurface.byKnotsControlPointsWeights, поверхность искажается, скорее всего, индексы неверны!

Есть пример использования глагола с THREE.js, но даже когда я пробую те же функции, что и в примере, результаты те же.

Я закомментировал функцию, основанную на углах, вы видите, что она работает. Я вошел в консоль srf и из объекта _data я мог видеть, что Verb генерирует эти контрольные точки под капотом, но те же самые точки не будут работать, если я попробую их с byKnotsControlPointsWeights

Помимо рабочего решения, я также хотел бы понять, почему код не работает, и какая часть в THREE.js отличается от моего ванильного кода, который заставляет его работать с THREE, но не здесь.

const flatten = _.flatten;
// const corners = [
//   [100, 100], // top left
//   [450, 50], // top right
//   [650, 650], // bottom right
//   [0, 750] // bottom left
// ];
// var srf = verb.geom.NurbsSurface.byCorners(...corners);

const degreeU = 3;
const degreeV = 3;
const knotsU = [0, 0, 0, 0, 1, 1, 1, 1];
const knotsV = [0, 0, 0, 0, 1, 1, 1, 1];
const controlPoints = [
  [
    [0, 0, 1],
    [0, 249, 1],
    [0, 500, 1],
    [0, 750, 1]
  ],
  [
    [249, 0, 1],
    [249, 249, 1],
    [249, 500, 1],
    [249, 750, 1]
  ],
  [
    [500, 0, 1],
    [500, 249, 1],
    [500, 500, 1],
    [500, 750, 1]
  ],
  [
    [750, 0, 1],
    [750, 249, 1],
    [750, 500, 1],
    [750, 750, 1]
  ]
];

var srf = verb.geom.NurbsSurface.byKnotsControlPointsWeights(
  degreeU,
  degreeV,
  knotsU,
  knotsV,
  controlPoints
);

// tesselate the nurface and get the triangles
var tess = srf.tessellate();
console.info(tess);

const vertexSource = `
  attribute vec2 a_position;
  attribute vec2 a_texCoord;

  uniform vec2 u_resolution;

  varying vec2 v_texCoord;

  void main() {
    vec2 zeroToOne = a_position / u_resolution;
    vec2 zeroToTwo = zeroToOne * 2.0;
    vec2 clipSpace = zeroToTwo - 1.0;

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

const fragmentSource = `
  precision mediump float;

  // our texture
  uniform sampler2D u_image;

  // the texCoords passed in from the vertex shader.
  varying vec2 v_texCoord;

  void main() {
    gl_FragColor = texture2D(u_image, v_texCoord);
  }
`;

function main() {
  var image = new Image();
  image.crossOrigin = "anonymous";
  image.onload = function () {
    render(image);
  };
  image.src = "https://pixijs.io/examples/examples/assets/bg_scene_rotate.jpg";
}

function render(image) {
  // Get A WebGL context
  /** @type {HTMLCanvasElement} */
  var canvas = document.getElementById("c");
  var gl = canvas.getContext("webgl");

  // setup GLSL program
  var program = webglUtils.createProgramFromSources(gl, [
    vertexSource,
    fragmentSource
  ]);

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

  // 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);

  // Set a rectangle the same size as the image.
  gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array(flatten(tess.points)),
    gl.STATIC_DRAW
  );

  // provide texture coordinates for the rectangle.
  var texcoordBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
  gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array(flatten(tess.uvs)),
    gl.STATIC_DRAW
  );

  // Create a texture.
  var texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);

  // Set the parameters so we can render any size image.
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

  // Upload the image into the texture.
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

  // lookup uniforms
  var resolutionLocation = gl.getUniformLocation(program, "u_resolution");

  // resize canvas to display size
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  // 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);

  // index buffer
  const indexBuffer = gl.createBuffer();
  // make this buffer the current 'ELEMENT_ARRAY_BUFFER'
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
  // Fill the current element array buffer with data

  const indices = new Uint16Array(flatten(tess.faces));
  gl.bufferData(
    gl.ELEMENT_ARRAY_BUFFER,
    new Uint16Array(indices),
    gl.STATIC_DRAW
  );

  // Turn on the position attribute
  gl.enableVertexAttribArray(positionLocation);

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

  // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER)
  var size = 2; // 2 components per iteration
  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(
    positionLocation,
    size,
    type,
    normalize,
    stride,
    offset
  );

  // Turn on the texcoord attribute
  gl.enableVertexAttribArray(texcoordLocation);

  // bind the texcoord buffer.
  gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);

  gl.vertexAttribPointer(
    texcoordLocation,
    size,
    type,
    normalize,
    stride,
    offset
  );

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

  // Draw the rectangle.
  gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
}

main();
body { margin: 0; }
<script src = "https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
<script src = "https://unpkg.com/[email protected]/build/js/verb.js"></script>
<script src = "https://unpkg.com/[email protected]/lodash.js"></script>
<canvas id = "c"></canvas>
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
188
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не знаю, как это должно выглядеть, но код передал 2 для размера позиций при вызове gl.vertexAttribPointer, но данные имеют 3 (x, y, z). Установка этого значения на 3, безусловно, дает другое изображение. Все еще нужно убедиться, что UVs установлен на размер 2

const flatten = _.flatten;
// const corners = [
//   [100, 100], // top left
//   [450, 50], // top right
//   [650, 650], // bottom right
//   [0, 750] // bottom left
// ];
// var srf = verb.geom.NurbsSurface.byCorners(...corners);

const degreeU = 3;
const degreeV = 3;
const knotsU = [0, 0, 0, 0, 1, 1, 1, 1];
const knotsV = [0, 0, 0, 0, 1, 1, 1, 1];
const controlPoints = [
  [
    [0, 0, 1],
    [0, 249, 1],
    [0, 500, 1],
    [0, 750, 1]
  ],
  [
    [249, 0, 1],
    [249, 249, 1],
    [249, 500, 1],
    [249, 750, 1]
  ],
  [
    [500, 0, 1],
    [500, 249, 1],
    [500, 500, 1],
    [500, 750, 1]
  ],
  [
    [750, 0, 1],
    [750, 249, 1],
    [750, 500, 1],
    [750, 750, 1]
  ]
];

var srf = verb.geom.NurbsSurface.byKnotsControlPointsWeights(
  degreeU,
  degreeV,
  knotsU,
  knotsV,
  controlPoints
);

// tesselate the nurface and get the triangles
var tess = srf.tessellate();
console.info(tess);

const vertexSource = `
  attribute vec2 a_position;
  attribute vec2 a_texCoord;

  uniform vec2 u_resolution;

  varying vec2 v_texCoord;

  void main() {
    vec2 zeroToOne = a_position / u_resolution;
    vec2 zeroToTwo = zeroToOne * 2.0;
    vec2 clipSpace = zeroToTwo - 1.0;

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

const fragmentSource = `
  precision mediump float;

  // our texture
  uniform sampler2D u_image;

  // the texCoords passed in from the vertex shader.
  varying vec2 v_texCoord;

  void main() {
    gl_FragColor = texture2D(u_image, v_texCoord);
  }
`;

function main() {
  var image = new Image();
  image.crossOrigin = "anonymous";
  image.onload = function () {
    render(image);
  };
  image.src = "https://pixijs.io/examples/examples/assets/bg_scene_rotate.jpg";
}

function render(image) {
  // Get A WebGL context
  /** @type {HTMLCanvasElement} */
  var canvas = document.getElementById("c");
  var gl = canvas.getContext("webgl");

  // setup GLSL program
  var program = webglUtils.createProgramFromSources(gl, [
    vertexSource,
    fragmentSource
  ]);

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

  // 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);

  // Set a rectangle the same size as the image.
  gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array(flatten(tess.points)),
    gl.STATIC_DRAW
  );

  // provide texture coordinates for the rectangle.
  var texcoordBuffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);
  gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array(flatten(tess.uvs)),
    gl.STATIC_DRAW
  );

  // Create a texture.
  var texture = gl.createTexture();
  gl.bindTexture(gl.TEXTURE_2D, texture);

  // Set the parameters so we can render any size image.
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

  // Upload the image into the texture.
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);

  // lookup uniforms
  var resolutionLocation = gl.getUniformLocation(program, "u_resolution");

  // resize canvas to display size
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;

  // 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);

  // index buffer
  const indexBuffer = gl.createBuffer();
  // make this buffer the current 'ELEMENT_ARRAY_BUFFER'
  gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
  // Fill the current element array buffer with data

  const indices = new Uint16Array(flatten(tess.faces));
  gl.bufferData(
    gl.ELEMENT_ARRAY_BUFFER,
    new Uint16Array(indices),
    gl.STATIC_DRAW
  );

  // Turn on the position attribute
  gl.enableVertexAttribArray(positionLocation);

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

  // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER)
  var size = 3; // 2 components per iteration
  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(
    positionLocation,
    size,
    type,
    normalize,
    stride,
    offset
  );

  // Turn on the texcoord attribute
  gl.enableVertexAttribArray(texcoordLocation);

  // bind the texcoord buffer.
  gl.bindBuffer(gl.ARRAY_BUFFER, texcoordBuffer);

  gl.vertexAttribPointer(
    texcoordLocation,
    2, //size,
    type,
    normalize,
    stride,
    offset
  );

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

  // Draw the rectangle.
  gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
}

main();
body { margin: 0; }
<script src = "https://webglfundamentals.org/webgl/resources/webgl-utils.js"></script>
<script src = "https://unpkg.com/[email protected]/build/js/verb.js"></script>
<script src = "https://unpkg.com/[email protected]/lodash.js"></script>
<canvas id = "c"></canvas>

УХ ТЫ! это была оплошность, ошибка новичка! Большое спасибо!

Hooman Askari 18.12.2020 22:06

Другие вопросы по теме