给定一个凸多边形作为一组边(在这种情况下,在从[[—1,1],[—1,1]的平面上,如下所示:

edges = [
   [[-0.8, 0],[-0.3,0.6]],
   [[-0.3,0.6],[0,0.8]],
   [[0,0.8],[0.7,0.6]],
   [[0.7,0.6],[0.6,-0.9]],
   [[0.6,-0.9],[-0.8,0]]
]

我怎样才能根据每一个斑点离最近的边缘有多远来给内部区域涂上 colored颜色 ?我想达到一个效果,如以下搅拌器文档:https://docs.blender.org/manual/en/latest/render/shader_nodes/textures/voronoi.html(在"距离边缘"下)

enter image description here

我真的不知道如何实现这种不规则的梯度.我最有希望的 idea 是将内部区域切成几块,然后用线性梯度填充,但到目前为止我还没有运气.

我也试着从blender查找相应的源代码,但这也没有真正帮助我:https://projects.blender.org/blender/blender/src/branch/main/source/blender/gpu/shaders/material/gpu_shader_material_tex_voronoi.glsl

我的两个多边形渲染,在2d环境和webgl环境下看起来像这样.

edges = [
   [[-0.8, 0],[-0.3,0.6]],
   [[-0.3,0.6],[0,0.8]],
   [[0,0.8],[0.7,0.6]],
   [[0.7,0.6],[0.6,-0.9]],
   [[0.6,-0.9],[-0.8,0]]
]


const canvas = document.querySelector("canvas");

var ctx = canvas.getContext('2d');
ctx.strokeStyle = '#fff';
ctx.fillStyle = "rgba(0,0,0,0.5)";
ctx.fillRect(0, 0, canvas.width, canvas.height);

ctx.beginPath();
edges.forEach(edge => {
   let x = (canvas.width * 0.5) + ( edge[0][0] * 0.5 * canvas.width);
   let y = (canvas.height * 0.5) - ( edge[0][1] * 0.5 * canvas.height);
   console.log("Move to " + x + ", " + y)
   ctx.moveTo(x, y);
   x = (canvas.width * 0.5) + ( edge[1][0] * 0.5 * canvas.width);
   y = (canvas.height * 0.5) - ( edge[1][1] * 0.5 * canvas.height);
   console.log("Line to " + x + ", " + y)

   ctx.lineTo(x,y);
});
ctx.closePath();
ctx.stroke();
<canvas width="640" height="360"></canvas>

edges = [
   [[-0.8, 0],[-0.3,0.6]],
   [[-0.3,0.6],[0,0.8]],
   [[0,0.8],[0.7,0.6]],
   [[0.7,0.6],[0.6,-0.9]],
   [[0.6,-0.9],[-0.8,0]]
]

vertices = [];

edges.forEach(edge => {
   vertices.push(edge[0][0], edge[0][1], 0.);
   vertices.push(edge[1][0], edge[1][1], 0.);
   
});


//
// start here
//
  const canvas = document.querySelector("canvas");
  // Initialize the GL context
  const gl = canvas.getContext("webgl");

  // Only continue if WebGL is available and working
  if (gl === null) {
    alert(
      "Unable to initialize WebGL. Your browser or machine may not support it.",
    );
  }

  // Set clear color to black, fully opaque
  gl.clearColor(0.0, 0.0, 0.0, 1.0);
  // Clear the color buffer with specified clear color
  gl.clear(gl.COLOR_BUFFER_BIT);

// Create an empty buffer object
var vertex_buffer = gl.createBuffer();

// Bind appropriate array buffer to it
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);

// Pass the vertex data to the buffer
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

// Unbind the buffer
gl.bindBuffer(gl.ARRAY_BUFFER, null);

/*=================== Shaders ====================*/

// Vertex shader source code
var vertCode =
   'attribute vec3 coordinates;' +
   'void main(void) {' +
      ' gl_Position = vec4(coordinates, 1.0);' +
   '}';

// Create a vertex shader object
var vertShader = gl.createShader(gl.VERTEX_SHADER);

// Attach vertex shader source code
gl.shaderSource(vertShader, vertCode);

// Compile the vertex shader
gl.compileShader(vertShader);

// Fragment shader source code
var fragCode =
   'void main(void) {' +
      'gl_FragColor = vec4(0.0, 0.0, 0.0, 0.1);' +
   '}';

// Create fragment shader object
var fragShader = gl.createShader(gl.FRAGMENT_SHADER);

// Attach fragment shader source code
gl.shaderSource(fragShader, fragCode);

// Compile the fragmentt shader
gl.compileShader(fragShader);

// Create a shader program object to store
// the combined shader program
var shaderProgram = gl.createProgram();

// Attach a vertex shader
gl.attachShader(shaderProgram, vertShader);

// Attach a fragment shader
gl.attachShader(shaderProgram, fragShader);

// Link both the programs
gl.linkProgram(shaderProgram);

// Use the combined shader program object
gl.useProgram(shaderProgram);

/*======= Associating shaders to buffer objects ======*/

// Bind vertex buffer object
gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer);

// Get the attribute location
var coord = gl.getAttribLocation(shaderProgram, "coordinates");

// Point an attribute to the currently bound VBO
gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0);

// Enable the attribute
gl.enableVertexAttribArray(coord);

/*============ Drawing the triangle =============*/

// Clear the canvas
gl.clearColor(0.5, 0.5, 0.5, 1);

// Enable the depth test
gl.enable(gl.DEPTH_TEST);

// Clear the color and depth buffer
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

// Set the view port
gl.viewport(0,0,canvas.width,canvas.height);

// Draw the triangle
gl.drawArrays(gl.LINES, 0, 10);
<canvas width="640" height="360"></canvas>

推荐答案

使用WebGl,如果您将三个顶点发送到片段着色器,则很容易绘制一个单色三角形.

现在你可能不知道的是,你也可以 for each 顶点指定不同的 colored颜色 .因此,如果我们给顶点A和B一个黑色,而顶点C一个白色,WebGl将在 colored颜色 之间插入并显示一个梯度.

与WebGl一样,我们首先需要对多边形进行三角化.这是通过计算加权质心并最终将多边形的每一边连接到该中心点来完成的.

就是这样—我们有5个三角形可以独立着色!

这里有一个例子:

const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl");



function polygonCentroid(vertices) {
  let a = 0;
  let x = 0;
  let y = 0;

  for (let i = 0; i < vertices.length; i++) {
    let s = i === vertices.length - 1 ? 0 : i + 1,
      v0 = vertices[i],
      v1 = vertices[s],
      f = v0[0] * v1[1] - v1[0] * v0[1];
    a += f;
    x += (v0[0] + v1[0]) * f;
    y += (v0[1] + v1[1]) * f;
  }

  let d = a * 3;
  return [x / d, y / d];
}

let edges = [
  [-0.8, 0],
  [-0.3, 0.6],
  [0, 0.8],
  [0.7, 0.6],
  [0.6, -0.9]
];

let center = polygonCentroid(edges);
let colorMesh = [];
for (let a = 0; a < edges.length; a++) {
  colorMesh.push(edges[a][0]);
  colorMesh.push(edges[a][1]);
  colorMesh.push(0);
  colorMesh.push(0);
  colorMesh.push(0);
  if (a != edges.length - 1) {
    colorMesh.push(edges[a + 1][0]);
    colorMesh.push(edges[a + 1][1]);
  } else {
    colorMesh.push(edges[0][0]);
    colorMesh.push(edges[0][1]);
  }
  colorMesh.push(0);
  colorMesh.push(0);
  colorMesh.push(0);
  colorMesh.push(center[0]);
  colorMesh.push(center[1]);
  colorMesh.push(1);
  colorMesh.push(1);
  colorMesh.push(1);
}

let vertexSource = `
attribute vec2 position;
attribute vec3 color;
varying vec3 _color;

void main() {
  gl_Position = vec4(position.x, position.y , 0, 1.0);
  _color = color;
}`;

let fragmentSource = `
precision mediump float;
varying vec3 _color;

void main() {
  gl_FragColor = vec4(_color, 1.0);
}`;


function createShader(source, type) {
  let shader = gl.createShader(type);
  gl.shaderSource(shader, source);
  gl.compileShader(shader);

  return shader;
}

function createProgram(vertexSource, fragmentSource) {
  let program = gl.createProgram();
  let vertexShader = createShader(vertexSource, gl.VERTEX_SHADER);
  let fragmentShader = createShader(fragmentSource, gl.FRAGMENT_SHADER);
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  gl.linkProgram(program);
  return program;
}

let triangleBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, triangleBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colorMesh), gl.STATIC_DRAW);

program = createProgram(vertexSource, fragmentSource);
let attrPosition = gl.getAttribLocation(program, "position");
let attrColor = gl.getAttribLocation(program, "color");

gl.enableVertexAttribArray(attrPosition);
gl.enableVertexAttribArray(attrColor);

gl.useProgram(program);

gl.viewport(0, 0, canvas.width, canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT);

gl.bindBuffer(gl.ARRAY_BUFFER, triangleBuffer);
gl.vertexAttribPointer(attrPosition, 2, gl.FLOAT, false, 4 * (2 + 3), 0);
gl.vertexAttribPointer(attrColor, 3, gl.FLOAT, false, 4 * (2 + 3), 4 * 2);
gl.drawArrays(gl.TRIANGLES, 0, 15);
<canvas width="640" height="360"></canvas>

Javascript相关问答推荐

fetch在本地设置相同来源的cookie,但部署时相同的代码不会设置cookie

调用removeEvents不起作用

Phaser 3 console. log()特定游戏角色的瓷砖属性

Chrome是否忽略WebAuthentication userVerification设置?""

当作为表达式调用时,如何解析方法decorator 的签名?

更改JSON中使用AJAX返回的图像的路径

使用GraphQL查询Uniswap的ETH价格

如何在ASP.NET JavaScript中使用Google Charts API仅对绘制为负方向的条形图移动堆叠条形图标签位置

如何在每次单击按钮时重新加载HighChart/设置HighChart动画?

try 使用javascript隐藏下拉 Select

Use Location位置成员在HashRouter内为空

为什么客户端没有收到来自服务器的响应消息?

OpenAI转录API错误请求

SPAN不会在点击时关闭模式,尽管它们可以发送日志(log)等

为什么云存储中的文件不能公开使用?

如何使用基于promise (非事件emits 器)的方法来传输数据?

在D3条形图中对具有相同X值的多条记录进行分组

bootstrap S JS赢得了REACT中的函数/加载

将字体样式应用于material -UI条形图图例

如何在css中裁剪成一定Angular 的圆的一部分,而不需要复杂的多边形