Vic*_*ree 1 javascript processing graphics canvas p5.js
我刚刚开始使用 P5.js,我想创建下图所示的效果。我不知道如何开始。对于实现此效果的任何帮助,我将不胜感激。
这个问题的完整答案将非常广泛。这可能不是一个完整的答案,但这是许多可能的解决方案之一的第一步。
创建一个函数,将 [0, 1] 范围内的值映射为HSL Color:
p.HUEtoRGB = function(H) {
let R = Math.abs(H * 6.0 - 3.0) - 1.0;
let G = 2.0 - Math.abs(H * 6.0 - 2.0);
let B = 2.0 - Math.abs(H * 6.0 - 4.0);
return [Math.max(0, Math.min(255, R*255)),
Math.max(0, Math.min(255, G*255)),
Math.max(0, Math.min(255, B*255))];
}
Run Code Online (Sandbox Code Playgroud)
并创建一个生成平滑边缘的函数:
p.SmoothStep = function(edge0, edge1, x) {
t = Math.max(0.0, Math.min(1.0, (x - edge0) / (edge1 - edge0)));
return t * t * (3.0 - 2.0 * t);
}
Run Code Online (Sandbox Code Playgroud)
使用该函数创建一个图像,该图像从左到右 ( createImage()) 具有彩虹色,并且其边界的 alpha 通道递减:
img = p.createImage(100, 10);
img.loadPixels();
for (let i = 0; i < img.width; i++) {
for (let j = 0; j < img.height; j++) {
let pi = 4*(j*img.width + i);
// color dependent on u (column)
let col = p.HUEtoRGB(1.0-i/img.width);
// alpha dependent on the distance to the border
let fx = p.SmoothStep(0, img.width/5, Math.min(i, img.width-i))
let fy = p.SmoothStep(0, img.height/20, Math.min(j, img.height-j))
let alpha = Math.max(0, Math.min(255, fx*fy*200))
img.pixels[pi] = col[0];
img.pixels[pi + 1] = col[1];
img.pixels[pi + 2] = col[2];
img.pixels[pi + 3] = alpha;
}
}
img.updatePixels();
Run Code Online (Sandbox Code Playgroud)
使用WEBGL画布 ( createCanvas()):
p.createCanvas(p.windowWidth, p.windowHeight, p.WEBGL);
Run Code Online (Sandbox Code Playgroud)
创建弯曲带形状 ( beginShape()):
p.beginShape(p.TRIANGLE_STRIP)
p.texture(img)
let no = 20;
for (let i = 0; i <= no; ++ i ) {
let ps = p.createVector(p.height/3-50, 0);
let pc = p.createVector(p.height/3-50-10000, 0);
let dir = p.createVector(-0.5, -1).normalize();
let pd = p5.Vector.add(ps, p5.Vector.mult(dir, 10000*i/no));
let p2 = p5.Vector.add(pc, p5.Vector.sub(pd, pc).normalize().mult(10000));
p.vertex(-p.width/2, p2.x, p2.y, 0, i/no);
p.vertex( p.width/2, p2.x, p2.y, 100, i/no);
}
p.endShape();
Run Code Online (Sandbox Code Playgroud)
使用透视投影查看形状 ( perspective()):
p.perspective(p.PI / 3.0, p.width / p.height, 0.1, 15000);
Run Code Online (Sandbox Code Playgroud)
参见示例:
var sketch = function( p ) {
let img;
p.HUEtoRGB = function(H) {
let R = Math.abs(H * 6.0 - 3.0) - 1.0;
let G = 2.0 - Math.abs(H * 6.0 - 2.0);
let B = 2.0 - Math.abs(H * 6.0 - 4.0);
return [Math.max(0, Math.min(255, R*255)),
Math.max(0, Math.min(255, G*255)),
Math.max(0, Math.min(255, B*255))];
}
p.SmoothStep = function(edge0, edge1, x) {
t = Math.max(0.0, Math.min(1.0, (x - edge0) / (edge1 - edge0)));
return t * t * (3.0 - 2.0 * t);
}
p.setup = function() {
let sketchCanvas = p.createCanvas(p.windowWidth, p.windowHeight, p.WEBGL);
sketchCanvas.parent('p5js_canvas');
p.updateCamera();
img = p.createImage(100, 100);
img.loadPixels();
for (let i = 0; i < img.width; i++) {
for (let j = 0; j < img.height; j++) {
let pi = 4*(j*img.width + i);
// color dependent on u (column)
let col = p.HUEtoRGB(1.0-i/img.width);
// alpha dependent on the distance to the border
let fx = p.SmoothStep(0, img.width/5, Math.min(i, img.width-i))
let fy = p.SmoothStep(0, img.height/20, Math.min(j, img.height-j))
let alpha = Math.max(0, Math.min(255, fx*fy*200))
img.pixels[pi] = col[0];
img.pixels[pi + 1] = col[1];
img.pixels[pi + 2] = col[2];
img.pixels[pi + 3] = alpha;
}
}
img.updatePixels();
}
p.windowResized = function() {
p.resizeCanvas(p.windowWidth, p.windowHeight);
p.updateCamera();
}
p.updateCamera = function() {
p.perspective(p.PI / 3.0, p.width / p.height, 0.1, 15000);
}
p.draw = function() {
p.background(255, 255, 255, 0);
p.push();
p.translate(0, 0, -5);
p.texture(img)
p.beginShape(p.TRIANGLE_STRIP)
let no = 20;
for (let i = 0; i <= no; ++ i ) {
let ps = p.createVector(p.height/2.2-50, 0);
let pc = p.createVector(p.height/2.2-50-10000, 0);
let dir = p.createVector(-0.5, -1).normalize();
let pd = p5.Vector.add(ps, p5.Vector.mult(dir, 10000*i/no));
let p2 = p5.Vector.add(pc, p5.Vector.sub(pd, pc).normalize().mult(10000));
p.vertex(-p.width/2, p2.x, p2.y, 0, 100*i/no);
p.vertex( p.width/2, p2.x, p2.y, 100, 100*i/no);
}
p.endShape();
p.pop();
}
};
var rainbow_3d = new p5(sketch);Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
<div id="p5js_canvas"></div>Run Code Online (Sandbox Code Playgroud)