To glow thing, you can do various ways. this time, i will show you how to glow thing by manipulating Pixels and using Texture (PImage).
- Using loadPixels and updatePixels (Slow but best)
by calculating distance between the source and pixel, we can determine how bright the spread at that pixel.
we updating pixels in given boundary. bigger boundary, nice looking glowing, but costs computing power, slows down frame updating.
these simple codes determine how far any given pixel to the center of the source
//bright multiplier
const multiplier = 100;
//calculating the distance using euclidean formula
dx = centerX - x;
dy = centerY - y;
d = sqrt(sq(dx) + sq(dy));
// convert to brightness
col = 1/d * multiplier;
to prevent current pixels color overwritten, we can use lerpColor() function
meaning, if there is an object behind it, it will be overlapped
Method 1:
// updating the pixels from the center source to the circle edges
//
// Pros
// Circle boundary
// Stable Pixels Update
//
// Cons
// Step-like bright radials
// Rough spreads
void glow(PVector gPos, float gSize, float spread, color spreadColor) {
loadPixels();
float distance = gSize;
float rot = 0;
while (rot < TWO_PI) { // spin the starting pixel draw by full rotation (360 degree = Two Pi)
for (int len = 0; len < distance; len++) { //update pixels from center toward the current angle*boundary radius
int x = floor(cos(rot) * len + gPos.x);
int y = floor(sin(rot) * len + gPos.y);
int index = x + y * width;
float dx = gPos.x - x;
float dy = gPos.y - y;
float d = sqrt(sq(dx) + sq(dy));
float col = spread/d;
// drawing at the edges of the window? here is the solution
if (index < height * width && index > 0)
// update pixel
pixels[index] = lerpColor(pixels[index], spreadColor, sq(col));
}
// next starting angle
rot += 0.01;
}
updatePixels();
}
Method 2
// updating the pixels from circle edges to another circle edges
//
// Pros
// Circle boundary
// Smooth Spread
//
// Cons
// Unstable Spread
// Changing distance leads to spread interference
// minor spread error
void glow(PVector gPos, float gSize, float spread, color spreadColor) {
loadPixels();
float k = 0;
float distance = 100// = gSize;
while (k < HALF_PI) { //
int yPlus = floor(sin(TWO_PI-k) * distance + gPos.y); // for top part glows
int yMinus = floor(sin(PI-(k+0.01)) * distance + gPos.y); // for bottom part glows
float aStart = PI+k; // starting angle
float aEnd = TWO_PI - k; // ending angle
int xStart = round(cos(aStart) * distance + gPos.x); // starting point.x
int xEnd = round(cos(aEnd) * distance + gPos.x); // ending point x
for (int i = xStart; i < xEnd; i++) {
float dx = gPos.x - i;
float dy = gPos.y - yPlus;
float d = sqrt(sq(dx) + sq(dy));
float col = 1/d * spread;
//draw the top part
int index = i + yMinus * width;
if (index < height * width && index > 0)
pixels[index] = lerpColor(pixels[index], spreadColor, sq(col));
//draw the bottom part
index = i + yPlus * width;
if (index < height * width && index > 0)
pixels[index] = lerpColor(pixels[index], spreadColor, sq(col));
}
k += 0.01;
}
updatePixels();
}
Method 3
// updating pixels in given Rectangle boundary
//
// Pros
// Stable Spread
// Smooth Spread
//
// Cons
// Rectangle boundary leads to bounded-like spread if boundary not quite big
void glow(PVector gPos, float gSize, float spread, color spreadColor) {
loadPixels();
for (int x = int(gPos.x-gSize); x < int(gPos.x + gSize); x++) {
for (int y = int(gPos.y-gSize); y < int(gPos.y+gSize); y++) {
int index = x + y * width;
float dx = gPos.x - x;
float dy = gPos.y - y;
float d = sqrt(sq(dx) + sq(dy));
float col = 1/d * spread;
if (index < height * width && index > 0)
pixels[index] = lerpColor(pixels[index], spreadColor, sq(col));
}
}
updatePixels();
}
- Using texture (Fast but Fake)
by applying glowing texture, we can get instant result!
fast!
but
it is fake.
PImage img;
void setup(){
img = loadImage("texture.png"); //your glowing texture
size(640, 480, P2D);
}
void draw(){
blendMode(ADD);
glow(50, 100);
}
void glow(float x, float y) {
imageMode(CENTER);
image(img,x,y);
}
edit: adding image
btw, i have that in video:
bit.ly/2FZQRDY
Anyone can help me improve my dirty Code!
Thank you!