Skip to content

Commit

Permalink
Use ispc for basic butterfly effects on MacOS for smaller matrices an…
Browse files Browse the repository at this point in the history
…d if GPU rendering es off
  • Loading branch information
dkulp committed Jan 16, 2025
1 parent 4fe5b56 commit 2710146
Show file tree
Hide file tree
Showing 6 changed files with 440 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ xLights/xLights_l4cpp.log
.objs
wxWidgets*
log4cpp*
ispc*
./ispc*
xLights/xLights.VC.db
lib/linux/libliquidfun.a
*.opensdf
Expand Down
2 changes: 1 addition & 1 deletion macOS
55 changes: 55 additions & 0 deletions xLights/effects/ButterflyEffect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@

#include "../Parallel.h"

#ifdef __WXOSX__
#include "ispc/ButterflyFunctions.ispc.h"
#define HASISPC
#endif

ButterflyEffect::ButterflyEffect(int i) : RenderableEffect(i, "Butterfly", butterfly_16, butterfly_24, butterfly_32, butterfly_48, butterfly_64)
{
//ctor
Expand Down Expand Up @@ -76,6 +81,7 @@ void ButterflyEffect::SetDefaultParameters() {
SetSliderValue(bp->Slider_Butterfly_Speed, 10);
}


void ButterflyEffect::Render(Effect *effect, const SettingsMap &SettingsMap, RenderBuffer &buffer)
{
float oset = buffer.GetEffectTimeIntervalPosition();
Expand All @@ -96,6 +102,55 @@ void ButterflyEffect::Render(Effect *effect, const SettingsMap &SettingsMap, Ren
const int frame=(buffer.BufferHt * curState / 200)%maxframe;
const size_t colorcnt=buffer.GetColorCount();
const double offset = (ButterflyDirection==1 ? -1 : 1) * double(curState)/200.0;

#ifdef HASISPC
if (Style < 6) {
ispc::ButterflyData data;
data.offset = offset;
data.chunks = Chunks;
data.skip = Skip;
data.curState = curState;
data.colorScheme = ColorScheme;
data.width = buffer.BufferWi;
data.height = buffer.BufferHt;
data.numColors = colorcnt;
for (int x = 0; x < colorcnt; x++) {
const xlColor &c = buffer.palette.GetColor(x);
data.colors[x].v[0] = c.red;
data.colors[x].v[1] = c.green;
data.colors[x].v[2] = c.blue;
data.colors[x].v[3] = c.alpha;
}
int max = buffer.BufferHt * buffer.BufferWi;
constexpr int bfBlockSize = 4096;
int blocks = max / bfBlockSize + 1;
parallel_for(0, blocks, [&data, &buffer, max, Style](int y) {
int start = y * bfBlockSize;
int end = start + bfBlockSize;
if (end > max) {
end = max;
}
switch (Style) {
case 1:
ButterflyEffectStyle1(data, start, end, (ispc::uint8_t4 *)buffer.GetPixels());
break;
case 2:
ButterflyEffectStyle2(data, start, end, (ispc::uint8_t4 *)buffer.GetPixels());
break;
case 3:
ButterflyEffectStyle3(data, start, end, (ispc::uint8_t4 *)buffer.GetPixels());
break;
case 4:
ButterflyEffectStyle4(data, start, end, (ispc::uint8_t4 *)buffer.GetPixels());
break;
case 5:
ButterflyEffectStyle5(data, start, end, (ispc::uint8_t4 *)buffer.GetPixels());
break;
}
});
return;
}
#endif
const int xc=buffer.BufferWi/2;
const int yc=buffer.BufferHt/2;
int block = buffer.BufferHt * buffer.BufferWi > 100 ? 1 : -1;
Expand Down
230 changes: 230 additions & 0 deletions xLights/effects/ispc/ButterflyFunctions.ispc
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@

struct ButterflyData
{
uint8<4> colors[8];

float offset;
int chunks;
int skip;
int curState;

uint16 colorScheme;
uint16 width;
uint16 height;
uint16 numColors;

};


const uniform float pi2 = 3.14159*2.0;

inline uint8<4> hsv2rgb(float16 h, float16 s, float16 v) {
float16<3> rgb;
if (0.0f == s) {
rgb.r = v;
rgb.g = v;
rgb.b = v;
} else { // not grey
float16 hue = h * 6.0f16; // sector 0 to 5
int i = (int)floor(hue);
float16 f = hue - (float16)i; // fractional part of h
float16 p = v * (1.0f16 - s);

switch (i) {
case 0:
rgb.r = v;
rgb.g = v * (1.0f16 - s * (1.0f16 - f));
rgb.b = p;
break;
case 1:
rgb.r = v * (1.0f16 - s * f);
rgb.g = v;
rgb.b = p;
break;
case 2:
rgb.r = p;
rgb.g = v;
rgb.b = v * (1.0f16 - s * (1.0f16 - f));
break;
case 3:
rgb.r = p;
rgb.g = v * (1.0f16 - s * f);
rgb.b = v;
break;
case 4:
rgb.r = v * (1.0f16 - s * (1.0f16 - f));
rgb.g = p;
rgb.b = v;
break;
default: // case 5:
rgb.r = v;
rgb.g = p;
rgb.b = v * (1.0f16 - s * f);
break;
}
}
rgb *= 255.0;
uint8<4> ret = {rgb.r, rgb.g, rgb.b, 255};
return ret;
}

inline uint8 channelBlend(float16 c1, float16 c2, float16 ratio) {
return c1 + floor(ratio * (c2 - c1) + 0.5f16);
}

uint8<4> getMultiColorBlend(const uniform ButterflyData &data, float16 n, bool circular) {
if (data.numColors <= 1) {
return data.colors[0];
}

if (n >= 1.0) n = 0.99999f16;
if (n < 0.0) n = 0.0f16;
float16 nc = data.numColors;
float16 realidx = circular ? n * nc : n * (nc - 1.0f16);
int coloridx1 = floor(realidx);
int coloridx2 = (coloridx1 + 1) % data.numColors;
float16 ratio = realidx - coloridx1;
uint8<4> ret;
ret.r = channelBlend(data.colors[coloridx1].r, data.colors[coloridx2].r, ratio);
ret.g = channelBlend(data.colors[coloridx1].g, data.colors[coloridx2].g, ratio);
ret.b = channelBlend(data.colors[coloridx1].b, data.colors[coloridx2].b, ratio);
ret.a = 255;
return ret;
}



export void ButterflyEffectStyle1(const uniform ButterflyData &data,
uniform int startIdx, uniform int endIdx,
uniform uint8<4> result[]) {
uniform float sz = data.height + data.width;
uniform float rsz = rcp(sz) * pi2;

foreach (index = startIdx...endIdx) {
int32 y = index / data.width;
int32 x = index - (y * data.width);

float x2 = x * x;
float y2 = y * y;
float n = abs((x2 - y2) * sin(data.offset + ((x+y)*rsz)));
float d = x2 + y2;
float h = d > 0.001 ? n/d : 0.0;
if (data.chunks <= 1 || (int)(h*data.chunks) % data.skip != 0) {
if (data.colorScheme == 0) {
result[index] = hsv2rgb(h, 1.0, 1.0);
} else {
result[index] = getMultiColorBlend(data, h, false);
}
}
}
}

export void ButterflyEffectStyle2(const uniform ButterflyData &data,
uniform int startIdx, uniform int endIdx,
uniform uint8<4> result[]) {

foreach (index = startIdx...endIdx) {
int32 y = index / data.width;
int32 x = index - (y * data.width);

int maxframe = data.height * 2;
int frame = (data.height * data.curState / 200) % maxframe;

float f = (frame < data.height) ? frame + 1 : maxframe - frame;
float x1= ((float)(x) - (float)(data.width)/2.0)/f;
float y1= ((float)(y) - (float)(data.height)/2.0)/f;
float h = sqrt(x1*x1 + y1*y1);

if (data.chunks <= 1 || (int)(h*data.chunks) % data.skip != 0) {
if (data.colorScheme == 0) {
result[index] = hsv2rgb(h, 1.0, 1.0);
} else {
result[index] = getMultiColorBlend(data, h, false);
}
}
}
}


export void ButterflyEffectStyle3(const uniform ButterflyData &data,
uniform int startIdx, uniform int endIdx,
uniform uint8<4> result[]) {
foreach (index = startIdx...endIdx) {
int32 y = index / data.width;
int32 x = index - (y * data.width);
int maxframe = data.height * 2;
int frame = (data.height * data.curState / 200) % maxframe;

float f = (frame < maxframe/2) ? frame + 1 : maxframe - frame;
f = f * 0.1 + (float)(data.height)/60.0;
float x1 = (x-((float)data.width)/2.0)/f;
float y1 = (y-((float)data.height)/2.0)/f;
float h = sin(x1) * cos(y1);

if (data.chunks <= 1 || (int)(h*data.chunks) % data.skip != 0) {
if (data.colorScheme == 0) {
result[index] = hsv2rgb(h, 1.0, 1.0);
} else {
result[index] = getMultiColorBlend(data, h, false);
}
}
}
}


export void ButterflyEffectStyle4(const uniform ButterflyData &data,
uniform int startIdx, uniform int endIdx,
uniform uint8<4> result[]) {

uniform float sz = data.height + data.width;
uniform float rsz = rcp(sz) * pi2;

foreach (index = startIdx...endIdx) {
int32 y = index / data.width;
int32 x = index - (y * data.width);

float n = ((x*x - y*y) * sin(data.offset + ((x+y)*rsz)));
float d = x*x + y*y;

float h = d>0.001 ? n/d : 0.0;
float intpart = floor(h);
float fractpart = h - intpart;
h = fractpart;
if (h < 0) h = 1.0 + h;

if (data.chunks <= 1 || (int)(h*data.chunks) % data.skip != 0) {
if (data.colorScheme == 0) {
result[index] = hsv2rgb(h, 1.0, 1.0);
} else {
result[index] = getMultiColorBlend(data, h, false);
}
}
}
}


export void ButterflyEffectStyle5(const uniform ButterflyData &data,
uniform int startIdx, uniform int endIdx,
uniform uint8<4> result[]) {

foreach (index = startIdx...endIdx) {
int32 y = index / data.width;
int32 x = index - (y * data.width);

// This section is to fix the colors on pixels at {0,1} and {1,0}
if (x == 0 && y == 1) y++;
if (x == 1 && y == 0) x++;

float n = abs((x*x - y*y) * sin(data.offset + ((x+y)*pi2 / ((float)(data.height*data.width)))));
float d = x*x + y*y;
float h=d>0.001 ? n/d : 0.0;

if (data.chunks <= 1 || (int)(h*data.chunks) % data.skip != 0) {
if (data.colorScheme == 0) {
result[index] = hsv2rgb(h, 1.0, 1.0);
} else {
result[index] = getMultiColorBlend(data, h, false);
}
}
}
}
Loading

0 comments on commit 2710146

Please sign in to comment.