processing - 如何使 PImage 中的黑色像素透明?
问题描述
以下代码产生上升的烟雾效果。
PImage buffer1;
PImage buffer2;
PImage cooling;
PImage buffer3;
float yInitial = 0.0;
void setup() {
size(600, 200);
buffer1 = createImage(width, 200, RGB);
buffer2 = createImage(width, 200, RGB);
buffer3 = createImage(width, 200, RGB);
cooling = createImage(width, 200, RGB);
}
void newLine(int rows) {
//create row of white pixels
buffer1.loadPixels();
for (int x = 0; x< buffer1.width; x++){
for(int j = 0; j< rows; j++){
//find location to draw pixels
int y = buffer1.height - (j+1);
int index = x + y * buffer1.width;
buffer1.pixels[index] = color(255);
}
}
buffer1.updatePixels();
}
void cool(){
cooling.loadPixels();
//start x at 0
float xoff = 0.0;
float increment = 0.02;
for (int x = 0; x < cooling.width; x++){
xoff += increment;
//start y at 0
float yoff = yInitial;
for (int y = 0; y < cooling.height; y++){
yoff += increment;
//calculate noise and enlarge
float n = noise(xoff, yoff);
if(n<0.4)
n = 0;
float bright = noise(xoff, yoff) *25;
//set pixel to grayscale value
cooling.pixels[x+y*cooling.width]= color(bright);
}
}
cooling.updatePixels();
yInitial += increment;
}
void draw(){
cool();
newLine(10);
background(0);
buffer1.loadPixels();
buffer2.loadPixels();
//look through all x and y coordinates and find the neightboring pixels colour
for (int x = 1; x < buffer1.width-1; x++) {
for (int y = 1; y < buffer1.height-1; y++) {
int index0 = x + y * buffer1.width;
int index1 = (x+1) + y * buffer1.width;
int index2 = (x-1) + y * buffer1.width;
int index3 = x + (y+1) * buffer1.width;
int index4 = x + (y-1) * buffer1.width;
color c1 = buffer1.pixels[index1];
color c2 = buffer1.pixels[index2];
color c3 = buffer1.pixels[index3];
color c4 = buffer1.pixels[index4];
color c5 = cooling.pixels[index0];
float newC = brightness(c1) + brightness(c2)+ brightness(c3) + brightness(c4);
newC = newC - brightness(c5);
newC = newC / 4;
buffer2.pixels[index4] = color(newC);
}
}
buffer2.updatePixels();
//swap
PImage temp = buffer1;
buffer1 = buffer2;
buffer2 = temp;
image(buffer2, 0, 0);
}
我打算使用这段代码在背景中的图像上绘制移动的烟雾(我还没有把它放进去)。为此,我试图使 PImage 中的所有黑色像素都透明。这应该意味着只有烟雾会被绘制在背景图像上。然后,在绘制 PImage 后,我将所有透明像素改回黑色。但是,当我在烟雾中添加它时,它完全停止了绘制。我做错了什么,这是尝试在背景图像上绘制烟雾的正确方法吗?这是我的代码:
PImage buffer1;
PImage buffer2;
PImage cooling;
PImage buffer3;
float yInitial = 0.0;
void setup() {
size(600, 200);
buffer1 = createImage(width, 200, RGB);
buffer2 = createImage(width, 200, RGB);
buffer3 = createImage(width, 200, RGB);
cooling = createImage(width, 200, RGB);
}
void newLine(int rows) {
//create row of white pixels
buffer1.loadPixels();
for (int x = 0; x< buffer1.width; x++){
for(int j = 0; j< rows; j++){
//find location to draw pixels
int y = buffer1.height - (j+1);
int index = x + y * buffer1.width;
buffer1.pixels[index] = color(255);
}
}
buffer1.updatePixels();
}
void cool(){
cooling.loadPixels();
//start x at 0
float xoff = 0.0;
float increment = 0.02;
for (int x = 0; x < cooling.width; x++){
xoff += increment;
//start y at 0
float yoff = yInitial;
for (int y = 0; y < cooling.height; y++){
yoff += increment;
//calculate noise and enlarge
float n = noise(xoff, yoff);
if(n<0.4)
n = 0;
float bright = noise(xoff, yoff) *25;
//set pixel to grayscale value
cooling.pixels[x+y*cooling.width]= color(bright);
}
}
cooling.updatePixels();
yInitial += increment;
}
void draw(){
cool();
newLine(10);
buffer1.loadPixels();
buffer2.loadPixels();
//look through all x and y coordinates and find the neightboring pixels colour
for (int x = 1; x < buffer1.width-1; x++) {
for (int y = 1; y < buffer1.height-1; y++) {
int index0 = x + y * buffer1.width;
int index1 = (x+1) + y * buffer1.width;
int index2 = (x-1) + y * buffer1.width;
int index3 = x + (y+1) * buffer1.width;
int index4 = x + (y-1) * buffer1.width;
color c1 = buffer1.pixels[index1];
color c2 = buffer1.pixels[index2];
color c3 = buffer1.pixels[index3];
color c4 = buffer1.pixels[index4];
color c5 = cooling.pixels[index0];
float newC = brightness(c1) + brightness(c2)+ brightness(c3) + brightness(c4);
newC = newC - brightness(c5);
newC = newC / 4;
buffer2.pixels[index4] = color(newC);
//make the black pixels transparent
if(color(buffer2.pixels[index0])==color(0));
buffer2.pixels[index0] = color(0,0);
if(color(buffer1.pixels[index0])==color(0));
buffer1.pixels[index0] = color(0,0);
}
}
buffer2.updatePixels();
//swap
PImage temp = buffer1;
buffer1 = buffer2;
buffer2 = temp;
image(buffer2, 0, 0);
//set transparent pixels back to black
for (int x = 1; x < buffer1.width-1; x++) {
for (int y = 1; y < buffer1.height-1; y++) {
int index0 = x + y * buffer1.width;
if(color(buffer2.pixels[index0])==color(0,0))
buffer2.pixels[index0] = color(0);
if(color(buffer1.pixels[index0])==color(0,0));
buffer1.pixels[index0] = color(0);
}
}
}
解决方案
这是一个非常酷的烟雾效果。
使用 .com 可以更轻松地合成烟雾效果blendMode()
。您所追求的是类似于blendMode(SCREEN);
或blendMode(ADD);
会使效果图像上的黑色像素透明的东西。
PImage buffer1;
PImage buffer2;
PImage cooling;
PImage buffer3;
float yInitial = 0.0;
void setup() {
size(600, 200);
fill(192,0,0);
// change blend mode to treat black pixels as transparent
blendMode(SCREEN);
buffer1 = createImage(width, 200, RGB);
buffer2 = createImage(width, 200, RGB);
buffer3 = createImage(width, 200, RGB);
cooling = createImage(width, 200, RGB);
}
void newLine(int rows) {
//create row of white pixels
buffer1.loadPixels();
for (int x = 0; x< buffer1.width; x++){
for(int j = 0; j< rows; j++){
//find location to draw pixels
int y = buffer1.height - (j+1);
int index = x + y * buffer1.width;
buffer1.pixels[index] = color(255);
}
}
buffer1.updatePixels();
}
void cool(){
cooling.loadPixels();
//start x at 0
float xoff = 0.0;
float increment = 0.02;
for (int x = 0; x < cooling.width; x++){
xoff += increment;
//start y at 0
float yoff = yInitial;
for (int y = 0; y < cooling.height; y++){
yoff += increment;
//calculate noise and enlarge
float n = noise(xoff, yoff);
if(n<0.4)
n = 0;
float bright = noise(xoff, yoff) *25;
//set pixel to grayscale value
cooling.pixels[x+y*cooling.width]= color(bright);
}
}
cooling.updatePixels();
yInitial += increment;
}
void updateSmokeEffect(){
cool();
newLine(10);
buffer1.loadPixels();
buffer2.loadPixels();
//look through all x and y coordinates and find the neightboring pixels colour
for (int x = 1; x < buffer1.width-1; x++) {
for (int y = 1; y < buffer1.height-1; y++) {
int index0 = x + y * buffer1.width;
int index1 = (x+1) + y * buffer1.width;
int index2 = (x-1) + y * buffer1.width;
int index3 = x + (y+1) * buffer1.width;
int index4 = x + (y-1) * buffer1.width;
color c1 = buffer1.pixels[index1];
color c2 = buffer1.pixels[index2];
color c3 = buffer1.pixels[index3];
color c4 = buffer1.pixels[index4];
color c5 = cooling.pixels[index0];
float newC = brightness(c1) + brightness(c2)+ brightness(c3) + brightness(c4);
newC = newC - brightness(c5);
newC = newC / 4;
buffer2.pixels[index4] = color(newC);
}
}
buffer2.updatePixels();
swapBuffers();
}
void swapBuffers(){
//swap
PImage temp = buffer1;
buffer1 = buffer2;
buffer2 = temp;
}
void draw(){
background(0);
// test drawing something in the background
ellipse(mouseX,mouseY,30,30);
updateSmokeEffect();
// render blended image on top
image(buffer2, 0, 0);
}
您可以使用blendMode(BLEND)
恢复到默认混合模式:
void draw(){
background(0);
blendMode(ADD);
// test drawing something in the background
ellipse(mouseX,mouseY,30,30);
updateSmokeEffect();
// render blended image on top
image(buffer2, 0, 0);
blendMode(BLEND);
// test drawing something in the foreground
ellipse(mouseX + 35,mouseY,30,30);
}
此外,您可以结帐PGraphics
以模仿图层,但对于像这样的像素效果,您可以做很多事情PImage
(它的set()
/ copy()
/ blend()
/ 等方法)
您可能还对着色器感兴趣:片段着色器,特别是用于 GPU 上的“像素”操作
推荐阅读
- r - 使用 shinyjs 时,renderPlot 出错但 renderPrint 不出错
- php - 如何在 Symfony 的 PHPUnit Bridge 中使用 PHPUnit 扩展?
- java - AWS lambda:格式错误的 Lambda 代理响应
- javascript - 将数据写入firebase会删除节点并且没有数据写入
- javascript - 从选项值中获取要出现的输入字段
- c# - Linq Result into Observable 集合引发解析异常
- python - 如何创建具有多个角色的服务帐户?谷歌云部署管理器
- vb.net - 创建一个变量名,其值在字符串变量内
- hangout - 环聊聊天监控
- javascript - 无法使用 O365 Comm-Services 的 javascript 获取 azure OAuth2 令牌