The following method will render circular glow behind an item (there are a few other possibilities which I'll mention below)
I got the idea to do this from a pk server a while ago (iirc it was spawnpk) which had glow behind certain items(altho im p sure it was just a 'glow sprite' drawn before the item, the method i wrote actually generates the glow programmatically, the color, intensity, radius etc are adjustable)
Code:
Code:
public static void renderGlow(int drawX, int drawY, int glowColor, int r) {
// center
drawX += r / 2;
drawY += r / 2;
int startX = drawX - r;
int endX = drawX + r;
int startY = drawY - r;
int endY = drawY + r;
// clipping
if (startX < clipLeft) {
startX = clipLeft;
}
if (endX > clipRight) {
endX = clipRight;
}
if (startY < clipTop) {
startY = clipTop;
}
if (endY > clipBottom) {
endY = clipBottom;
}
float edge0 = -(r / 2f);
for (int x = startX; x < endX; x++) {
for (int y = startY; y < endY; y++) {
int index = x + y * width;
float d = MathUtils.dist(x, y, drawX, drawY);
float dist = MathUtils.smoothstep(edge0, r, d);
int oldColor = raster[index];
int newColor = blend(oldColor, glowColor, 1f - dist);
raster[index] = newColor;
}
}
}
dist defines the euclidean distance
smoothstep:
Code:
public static float smoothstep(float edge0, float edge1, float x) {
// Scale, bias and saturate x to 0..1 range
x = constrain((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
// Evaluate polynomial
return x * x * (3 - 2 * x);
}
blend just implements linear interpolation between 2 colors
Another way to generate glow without using smoothstep would be to use norm(d, 0, r) for dist, altho smoothstep is definitely more flexible
You can also render glow on top of the item, which would give you a bloomy effect(looks nice in some cases)
Another way would be to render the item to a seperate buffer, then apply glow to that buffer, render the glow and then render the item on top of it.
Glow can also be applied to text (you wouldn't apply circular glow tho) instead you would use bloom, which works like this:
1) Draw text
2) Blur text
3) Draw text on top of it
Perfect gaussian blur (for example) would be very expensive to do on the cpu however you can approximate blur(average error rate per pixel is only 0.04%) in O
(linear time)
Feel free to read more about it
here
Note: if you want this to use the average color of the sprite(excluding transparent pixels) u should either put this in the sprite class and cache the calculated color or take a sprite as param (should also cache the result)
Average color can be calculated in the following way:
Code:
private int averageColor() {
long redSum = 0;
long greenSum = 0;
long blueSum = 0;
int count = 0;
for (int x = 0; x < myWidth; x++) {
for (int y = 0; y < myHeight; y++) {
int color = myPixels[x + y * myWidth];
if (color == 0) {
continue; // 0 is considered transparent
}
redSum += (color >> 16) & 0xFF;
greenSum += (color >> 8) & 0xFF;
blueSum += color & 0xFF;
count++;
}
}
long r = redSum / count;
long g = greenSum / count;
long b = blueSum / count;
return (int) (r << 16 | g << 8 | b);
}
This is also what i did for the examples below
Pic & Gifs:
Rendering the glow after the item was rendered with varying intensity for the original(non transparent) pixels of the sprite
for a radius of 32 (Which is what i used for items in interfaces) it took about 0.025 ms to generate the glow, this can be optimized further but shouldn't really be necessary if you cache the result and only re-generate if needed.
Note: if ur gonna use a different radius than 32 but always want the glow to be centered around the item and not the glow itself then to center just add 16 instead of r / 2