411 REFERENCE · Wikibooks
Fractals/Iterations in the complex plane/slope
Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.
It is an algorithm for converting 2D image to 3D
Description
"three points are iterated for each pixel and then are used to create a three-dimensional surface. A vector perpendicular to that surface is used as the z variable and is passed to the coloring routine. When a Slope formula is used with the Lighting coloring, the result resembles a fractal surface being illuminated from above and to the side." Kerry Mitchellkerrymitchellart : uf1-5
names
lifted domain coloring
Hill-Shading the Mandelbrot SetExploring the Mandelbrot Set by Eamonn O'Brien-Strain
almondbread
Hill-Shading the Mandelbrot Set 29 stycznia 2021 - article
How to calculate shaded relief for the entire world with GDAL, fast by Anna Thieme
How Hillshade works from ArcGIS Pro 3.1
Differences
shaded relief or hill shade: Creates a shaded relief from a surface raster by considering the illumination source angle and shadows
Slope = Identifies the slope (gradient or steepness) from each cell of a raster.
slope of the line
right|thumb|Slope:
In mathematics, the slope or gradient of a line is a number that describes both the direction and the steepness of the line.http://web.cortland.edu/matresearch/OxfordDictionaryMathematics.pdf Oxford Concise Dictionary of Mathematics, Gradient C. Clapham J. Nicholson Addison-Wesley 2009 348 1 September 2013 dead https://web.archive.org/web/20131029203826/http://web.cortland.edu/matresearch/OxfordDictionaryMathematics.pdf 29 October 2013 Slope is often denoted by the letter m; there is no clear answer to the question why the letter m is used for slope,
y = mx + b
Slope of the line through 2 points: (x1,y1) and (x2,y2) is:
the slope m of a line is related to its angle of inclination θ by the tangent function:
Apply to
Mandelbrothiddendimension Slope_Tutorial_2
Julia
Newton hiddendimension Slope_Tutorial_3
Kleinian group fractalshiddendimension tutorials: Slope_Tutorial_9
strange attractors hiddendimension slope tutorial 7
code
Ultrafractal formulas by Damien Jones in dmj.ufm and standard.ufm
c
hue = fmod(1 + carg(de) / (2 * pi), 1); // slope of complex number de
matlab
Matlab code by nickspiker
%for each pixel do the stuff below
c=somethingreal+somethingimaginary;
z=0;
d=1;
while (real(z)^2+imaginary(z)^2)<realbignumber
z=z^2+c;
d=2*z*d+1;%derivative step and I think the plus one comes from the derivative of c, not totally sure on that one
endwhile
slope=sign(z/d)%values are strange because of where we abruptly end the step but the sign is clean
%then this is what I do for the shading bit
%you can look at the real and imaginary parts of slope before you do the steps below to better understand what's going on
sunangle=45;
brightness=slope*e^(i*sunangle*pi/180);%this rotates the sign by the angle above
brightness=real(brightness)/2+.5;
%Mandelbrot rendering algorithms utilizing interior and exterior slope finding steps copyright 2020 Nick Spiker nick@nickspiker.com
maxn=2^32;
steps=2^5;%anti aliasing steps
mns=2^8;%max newton steps
dpi=90;
bleed=0;%change to 6 when final render, 3 per side
width=42;
height=48;
zoom=3;
center=-.75;
rotation=90;
alias=2^-6;
tiles=3;
starttile=1;
preview=false;
if preview
dpi=30;
tiles=1;
bleed=0;
end
rez=[(width+bleed).*dpi,(height+bleed).*dpi];
zoom=zoom./height.*(height+bleed);
localrez=ceil(rez./tiles);%finds closest multiple equal to or greater than rez
localrezb=localrez+2;
pixelsize=zoom./rez(2);
tlx=-zoom./rez(2).*rez(1)./2;
tly=zoom./2;
localzoom=localrezb(2).*pixelsize;
tic;
for tiley=floor((starttile-1)./tiles)+1:tiles
for tilex=mod(starttile-1,tiles)+1:tiles
tn=toc;
starttile=1;
localcenter=tlx+pixelsize.*localrez(1).*(tilex-.5)+(tly-pixelsize.*localrez(2).*(tiley-.5)).*i;
localcenter=center+localcenter.*exp(1i*rotation*pi/180);
xlim = [(pixelsize-localzoom./localrezb(2).*localrezb(1))./2,(localzoom./localrezb(2).*localrezb(1)-pixelsize)./2];
ylim = [(localzoom-pixelsize)./2,(pixelsize-localzoom)./2];
x=linspace(xlim(1),xlim(2),localrezb(1));
y=linspace(ylim(1),ylim(2),localrezb(2));
[xGrid,yGrid]=meshgrid(x,y);
cleanc=xGrid+1i*yGrid;
cleanc=cleanc*exp(1i*rotation*pi/180)+localcenter;
stackalpha=zeros(localrezb(2),localrezb(1),3);
stackimage=zeros(localrezb(2),localrezb(1),3);
stackalias=true(localrezb(2),localrezb(1));
aliasstep=alias;
for step=1 :steps
tm=toc;
aliasstep=aliasstep+alias;
totalpixels=sum(sum(stackalias));
if totalpixels==0
break
end
c=(cleanc(stackalias)+rand(totalpixels,1).*(cleanc(1,1)-cleanc(1,2))+rand(totalpixels,1).*(cleanc(1,1)-cleanc(2,1)));
ac=abs(c);
acs=ac.*ac;
acs=acs.*acs;
acs=acs.*acs;
cr=real(c);
ci=imag(c);
inside=false(totalpixels,1);
a=zeros(totalpixels,1);
frame=cat(3,a,a,a);
dr=a;
di=a;
er=a;
ei=a;
slope=a;
maxcount=1;
parfor p=1:totalpixels%parfor
insidep=false;
%orbitcount=1;
crp=cr(p);
cip=ci(p);
zr=crp;
zi=cip;
ap=maxn;
drp=0;
dip=0;
dsp=0;
erp=0;
eip=0;
esp=0;
srp=1;
sip=0;
osr=1;
osi=0;
%orbit=0;
zsmallest=realmax;
for n=1:maxn
srpt=2.*(srp.*zr-sip.*zi);
sip=2.*(srp.*zi+sip.*zr);
srp=srpt+1;
zrs=zr.*zr;
zis=zi.*zi;
zs=zrs+zis;
ns=n.*n;
if zs>4
llzs=log(log(zs));
taper=(llzs-0.326634259978281)./6.238324625039508;
taper=1-taper.*taper;
taper=taper.*taper;
taper=taper.*taper.*taper.*ns;
zsq=taper./sqrt(zs);
esp=esp+taper;
erp=erp+zr.*zsq;
eip=eip+zi.*zsq;
zsi=ns./zs;
dsp=dsp+zsi;
drp=drp+zr.*zsi;
dip=dip+zi.*zsi;
if zs>1.340780792994260e+154
ap=n-(llzs-5.174750624576761).*1.442695040888963;
break
end
durt=2.*(zr.*osr-zi.*osi)+1;
osi=2.*(osr.*zi+osi.*zr);
osr=durt;
zi=2.*zr.*zi+cip;
zr=zrs-zis+crp;
else
taper=ns;
zsq=taper./sqrt(zs);
esp=esp+taper;
erp=erp+zr.*zsq;
eip=eip+zi.*zsq;
zsi=ns./zs;
dsp=dsp+zsi;
drp=drp+zr.*zsi;
dip=dip+zi.*zsi;
if zsmallest>zs
adcs=zs./zsmallest;
zsmallest=zs;
if adcs<.25
period=n;
wr=zr;
wi=zi;
for l=1:mns
ur=wr;
ui=wi;
dur=1;
dui=0;
for m=1:period
%du=2*du*u
durt=2.*(dur.*ur-dui.*ui);
dui=2.*(dur.*ui+dui.*ur);
dur=durt;
%u=u*u+c
uis=ui.*ui;
ui=2.*ur.*ui+cip;
ur=ur.*ur-uis+crp;
end
%nw=w-(u-w)/(du-1)
nwr=ur-wr;
nwi=ui-wi;
duro=dur-1;
durt=duro.*duro+dui.*dui;
nwrt=(nwr.*duro+nwi.*dui)./durt;
nwi=(nwi.*duro-nwr.*dui)./durt;
nwr=nwrt;
ns=nwr.*nwr+nwi.*nwi;
wr=wr-nwr;
wi=wi-nwi;
if ns<2^-32
if dur.*dur+dui.*dui<1
drp=dur;
dip=dui;
erp=wr;
eip=wi;
insidep=true;
ap=m;
break
end
end
end
if insidep
break
end
end
end
durt=2.*(zr.*osr-zi.*osi)+1;
osi=2.*(osr.*zi+osi.*zr);
osr=durt;
zi=2.*zr.*zi+cip;
zr=zrs-zis+crp;
end
if insidep
break
end
end
maxcount=max(maxcount,n);
if insidep
inside(p)=true;
dr(p)=drp;
di(p)=dip;
er(p)=erp;
ei(p)=eip;
cca=crp+cip.*i;
ccc=cca;
for l=1:mns
zzz=ccc;
ddd=1;
for z=2:period
ddd=2.*ddd.*zzz+1;
zzz=zzz.*zzz+ccc;
end
ddd=ccc-zzz./ddd+2^-256.*i;
if ddd==ccc
ccc=ddd;
break
end
ccc=ddd;
end
slope(p)=ccc-cca;
else
dsp=1./dsp;
esp=1./esp;
dr(p)=drp.*dsp;
di(p)=dip.*dsp;
er(p)=erp.*esp;
ei(p)=eip.*esp;
slope(p)=sign((osr+osi.*i)./(zr+zi.*i));
end
a(p)=ap;
end
tm=toc-tm;
hrs=floor(tm/(60*60));
mnt=floor((tm-hrs*60*60)/60);
snd=tm-hrs*60*60-mnt*60;
['Tile ',num2str(tilex+tiley.*tiles-tiles),' of ',num2str(tiles.^2),', ',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tiley),'x',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tilex),', Step ',num2str(step),', ',num2str(hrs),' hours, ',num2str(mnt),' minutes, ',num2str(snd),' seconds per step, Max N=2^',num2str(log2(maxcount)),' alias%',num2str(totalpixels./(localrezb(1).*localrezb(2)).*100)]
ia=a(inside);%interior period count
oa=a(not(inside));%exterior iteration count
d=dr+di.*i;
ic=d(inside);%interior coordinate,
ea=d(not(inside));%exterior average
e=er+ei.*i;
iw=e(inside);%interior W
ef=e(not(inside));%Exterior flames
is=slope(inside);
inside3=cat(3,inside,inside,inside);
stackalias3=cat(3,stackalias,stackalias,stackalias);
%start color
interiorrotationoffset=1.5;
exteriorrotationoffset=pi./4;
squarerotation=-.05;
squarebrightness=.7;
fresnelbrightness=.125;
reflectionrotation=.1;
reflectionoffset=1/4;
reflectioncurve=1/16;
reflectionwavies=1/8;
reflectionbrightness=0.125;
shaderotation=-pi./5;
slopescale=.5;
aic=abs(ic);
isreflect=sign(is).*aic;
shading=real(isreflect.*exp(shaderotation.*i))./3+.75;
iss=isreflect.*exp(i.*squarerotation);
cc=exp(i.*(angle(iw)+1./aic+interiorrotationoffset)).*aic;
waves=real(exp(i.*(angle(is)+1./aic)).*aic);
o=real(cc.*exp(i*120*pi/180));
p=real(cc);
q=real(cc.*exp(i*270*pi/180));
cc=cat(3,o,p,q);
cc=cc./2+.5;
aic=aic.*aic;
iss=iss.*aic;
aic=aic.*aic;
aics=aic.*aic;
aic=aics+fresnelbrightness;
aics=aics.*aics;
shading=1-(1-aics).*shading;
cc=1-cc.*(1-shading);
issr=real(iss);
issi=imag(iss);
cc=1-cc.*(1-(and(and(issr>.3,issr<.7),and(issi>0.1,issi<.4)).*squarebrightness+(real(isreflect.*exp(reflectionrotation.*i))>(reflectionoffset-aics.*reflectioncurve+waves.*reflectionwavies)).*reflectionbrightness).*aic);
frame(inside3)=cc;
outsideslope=slope(not(inside));
outsideslope=0.5-real(outsideslope.*exp(exteriorrotationoffset.*i))./2;
oc=erf(12./oa);
%cc=abs(ef).*exp(i.*(angle(ef)+oa.*16.*oa));
cc=ef;
o=real(cc.*exp(i*120*pi/180));
p=real(cc);
q=real(cc.*exp(i*270*pi/180));
cc=cat(3,o,p,q);
cc=cc./2+.5;
oc3=5./oa;
oc3=1-oc3;
oc3=1-cat(3,oc3,oc3,oc3).*(1-cc)./2;
cc=oc3.*oc.*(outsideslope.*slopescale+(1-slopescale));
frame(not(inside3))=cc;
if preview
stackimage(stackalias3)=reshape(frame,size(frame,1).*size(frame,2).*size(frame,3),1);
imshow(stackimage)
return
%else
%frame=frame./2+.25;%declip for post
end
%end color
stackimage(stackalias3)=stackimage(stackalias3)+reshape(frame,size(frame,1).*size(frame,2).*size(frame,3),1);
stackalpha=stackalpha+stackalias3;
frame=stackimage./stackalpha;
if step~=steps
if step==1
stackdiff=false(localrezb(2),localrezb(1));
else
previousframe=abs(frame-previousframe);
stackdiff=previousframe(:,:,1)+previousframe(:,:,2)+previousframe(:,:,3)+stackdiff./stackalpha(:,:,2);
end
r=frame(:,:,1);
g=frame(:,:,2);
b=frame(:,:,3);
r=ordfilt2(r,1,ones(3,3),'symmetric');
g=ordfilt2(g,1,ones(3,3),'symmetric');
b=ordfilt2(b,1,ones(3,3),'symmetric');
mn=cat(3,r,g,b);
r=frame(:,:,1);
g=frame(:,:,2);
b=frame(:,:,3);
r=ordfilt2(r,9,ones(3,3),'symmetric');
g=ordfilt2(g,9,ones(3,3),'symmetric');
b=ordfilt2(b,9,ones(3,3),'symmetric');
mx=cat(3,r,g,b);
mx=mx-mn;
mx=mx(:,:,1).*2+mx(:,:,2).*3+mx(:,:,3);
stackalias=or(mx>aliasstep,stackdiff>alias);
end
previousframe=frame;
end
imwrite(uint16(frame(2:localrez(2)+1,2:localrez(1)+1,:).*2^16),['Z ',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tiley),'x',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tilex),'.tif'])
tm=toc-tn;
hrs=floor(tm/(60*60));
mnt=floor((tm-hrs*60*60)/60);
snd=tm-hrs*60*60-mnt*60;
['Tile ',num2str(tilex+tiley.*tiles-tiles),' of ',num2str(tiles.^2),', ',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tiley),'x',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tilex),', ',num2str(hrs),' hours, ',num2str(mnt),' minutes, ',num2str(snd),' seconds per tile.']
end
end
clear('a','a3','afull','aliasstep','ang','b','c','ca','cavg','cavgi','cavgr','cavgs','ci','cleanc','count','cr','cscale','fcs','frame','g','gby','gbys','gc','gm','go','grg','grgs','gs','hrs','inside','inside3','insidef','lcolor','lmag','localcenter','localrezb','loop','loopi','loopr','loops','maxn','mn','mnt','mx','n','o','outside','p','pixelsize','previousframe','r','snd','stackalias','stackalpha','stackdiff','stackimage','step','tic1','tilex','tiley','tlx','tly','tm','totalpixels','waitstepcheck','x','xGrid','xlim','y','yGrid','ylim','zi','zr');
try
finalimage=zeros(localrez(2).*tiles,localrez(1).*tiles,3,'uint16');
for tiley=1:tiles
for tilex=1:tiles
['Z ',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tiley),'x',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tilex)]
finalimage((tiley-1).*localrez(2)+1:(tiley).*localrez(2),(tilex-1).*localrez(1)+1:(tilex).*localrez(1),:)=imread(['Z ',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tiley),'x',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tilex),'.tif']);
end
end
imwrite(finalimage,'out.tif');
catch
finalimage=zeros(localrez(2),localrez(1).*tiles,3,'uint16');
for tiley=1:tiles
for tilex=1:tiles
['Z ',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tiley),'x',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tilex)]
finalimage(:,(tilex-1).*localrez(1)+1:(tilex).*localrez(1),:)=imread(['Z ',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tiley),'x',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tilex),'.tif']);
end
imwrite(finalimage,['F ',sprintf(['%0',num2str(floor(log10(tiles))+1),'.0f'],tiley),'.tif']);
end
end
C++
C++ code by LionHeartfractalforums.org : algorithm-for-rendering-slope-in-a-fractal
/*
FWDDIFF.CPP a module for determining the slope using forward differencing calculations of fractals.
Written in Microsoft Visual 'C++' by Paul de Leeuw.
https://github.com/hrkalona/Fractal-Zoomer/blob/master/src/fractalzoomer/core/ThreadDraw.java#L3640
https://github.com/hrkalona/Fractal-Zoomer/blob/master/src/fractalzoomer/main/app_settings/BumpMapSettings.java
*/
#include "slope.h"
/**************************************************************************
Calculate functions
**************************************************************************/
void CSlope::DoSlopeFwdDiffFn(Complex *z, Complex *q)
{
Complex sqr, temp;
Complex t = { 1.0, 0.0 };
double real_imag;
int k;
int degree = (int)param[5];
int degree1, degree2;
// PaletteStart = (int)param[4];
switch (subtype)
{
case 0: // Mandelbrot
sqr.x = z->x * z->x;
sqr.y = z->y * z->y;
real_imag = z->x * z->y;
z->x = q->x + sqr.x - sqr.y;
z->y = q->y + real_imag + real_imag;
break;
// other cases removed
}
}
/**************************************************************************
Get the gradients in the x and y directions
**************************************************************************/
double CSlope::getGradientX(double *wpixels, int index, int width)
{
int x = index % width;
double it = *(wpixels + index);
if (x == 0) {
return (*(wpixels + index + 1) - it) * 2;
}
else if (x == width - 1) {
return (it - *(wpixels + index - 1)) * 2;
}
else {
double diffL = it - *(wpixels + index - 1);
double diffR = it - *(wpixels + index + 1);
return diffL * diffR >= 0 ? 0 : diffL - diffR;
}
}
double CSlope::getGradientY(double *wpixels, int index, int width, int height)
{
int y = index / width;
double it = *(wpixels + index);
if (y == 0) {
return (it - *(wpixels + index + width)) * 2;
}
else if (y == height - 1) {
return (*(wpixels + index - width) - it) * 2;
}
else {
double diffU = it - *(wpixels + index - width);
double diffD = it - *(wpixels + index + width);
return diffD * diffU >= 0 ? 0 : diffD - diffU;
}
}
/**************************************************************************
Brightness Scaling
**************************************************************************/
int CSlope::changeBrightnessOfColorScaling(int rgb, double delta)
{
int new_color = 0;
double bump_transfer_factor = param[0]; // future add to dialogue box
// double mul = getBumpCoef(delta);
double mul = (1.5 / (fabs(delta * bump_transfer_factor) + 1.5));
if (delta > 0) {
rgb ^= 0xFFFFFF;
int r = rgb & 0xFF0000;
int g = rgb & 0x00FF00;
int b = rgb & 0x0000FF;
int ret = (int)(r * mul + 0.5) & 0xFF0000 | (int)(g * mul + 0.5) & 0x00FF00 | (int)(b * mul + 0.5);
new_color = 0xff000000 | (ret ^ 0xFFFFFF);
}
else {
int r = rgb & 0xFF0000;
int g = rgb & 0x00FF00;
int b = rgb & 0x0000FF;
new_color = 0xff000000 | (int)(r * mul + 0.5) & 0xFF0000 | (int)(g * mul + 0.5) & 0x00FF00 | (int)(b * mul + 0.5);
}
return new_color;
}
/**************************************************************************
Slope Fractal
**************************************************************************/
int CSlope::RunSlopeFwdDiff(HWND hwndIn, void(*plot)(WORD, WORD, DWORD), int user_data(HWND hwnd), char* StatusBarInfo, bool *ThreadComplete, int subtypeIn, int NumThreadsIn, int threadIn, Complex j, double mandel_width, double hor, double vert, double xgap, double ygap,
double rqlim, long threshold, double paramIn[], CTrueCol *TrueCol, CDib *Dib, double *SlopeDataPtr, BYTE juliaflag)
{
Complex z = 0.0; // initial value for iteration Z0
Complex c, q;
BigComplex cBig, zBig, qBig;
BigDouble BigTemp, BigTemp1;
double log_zn, nu;
int lastChecked = -1;
int x, y, i;
DWORD index;
double iterations;
thread = threadIn;
NumThreads = NumThreadsIn;
subtype = subtypeIn;
hwnd = hwndIn;
for (i = 0; i < NUMSLOPEDERIVPARAM; i++)
param[i] = paramIn[i];
if (NumThreads == 0)
StripWidth = xdots;
else
StripWidth = xdots / NumThreads;
StripStart = StripWidth * thread;
*ThreadComplete = false;
for (y = 0; y < ydots; y++)
{
if (BigNumFlag)
cBig.y = BigVert + BigWidth - Big_ygap * y;
else
c.y = vert + mandel_width - y * ygap;
double progress = (double)y / ydots;
if (int(progress * 100) != lastChecked)
{
lastChecked = int(progress * 10);
sprintf(StatusBarInfo, "Progess (%d%%), %d Threads", int(progress * 100), NumThreads);
}
for (x = StripStart; x < StripStart + StripWidth; x++)
{
if (user_data(hwnd) < 0) // trap user input
return -1;
c.x = hor + x * xgap;
{
if (juliaflag)
{
q = j;
z = c;
}
else
{
q = c;
z = 0.0;
}
}
iterations = 0.0;
for (;;)
{
iterations++;
if (iterations >= threshold)
break;
DoSlopeFwdDiffFn(&z, &q);
if ((z.x * z.x + z.y * z.y) >= rqlim)
break;
}
if (iterations < threshold)
{
if (BigNumFlag)
{
// sqrt of inner term removed using log simplification rules.
BigTemp = zBig.x * zBig.x + zBig.y * zBig.y;
BigTemp1 = BigTemp.BigLog();
log_zn = mpfr_get_d(BigTemp1.x, MPFR_RNDN) / 2;
nu = log(log_zn / log(2.0)) / log(2.0);
}
else
{
// sqrt of inner term removed using log simplification rules.
log_zn = log(z.x * z.x + z.y * z.y) / 2;
nu = log(log_zn / log(2.0)) / log(2.0);
}
iterations = iterations + 1 - nu;
}
index = ((DWORD)y * (DWORD)width) + (DWORD)x;
if (x >= 0 && x < xdots - 1 && y >= 0 && y < ydots - 1)
*(SlopeDataPtr + index) = iterations;
plot(x, y, (long)iterations);
}
}
*ThreadComplete = true;
return 0;
}
/**************************************************************************
Slope Fractal
**************************************************************************/
int CSlope::RenderSlope(long threshold, double paramIn[], CTrueCol *TrueCol, CDib *Dib, double *SlopeDataPtr)
{
double dotp, gradAbs, gradCorr, cosAngle, sizeCorr, smoothGrad, lightAngleRadians, lightx, lighty;
for (int i = 0; i < NUMPARAM; i++)
param[i] = paramIn[i];
double bumpMappingDepth = param[3]; // future add to dialogue box
double bumpMappingStrength = param[4]; // future add to dialogue box
double lightDirectionDegrees = param[2]; // future add to dialogue box
int PaletteStart = (int)param[1];
double iterations;
int lastChecked = -1;
DWORD index;
int x, y;
double gradx, grady;
unsigned char r, g, b;
RGBTRIPLE colour;
int modified;
lastChecked = -1;
sizeCorr = 0.0;
lightx = 0.0;
lighty = 0.0;
gradCorr = pow(2, (bumpMappingStrength - DEFAULT_BUMP_MAPPING_STRENGTH) * 0.05);
sizeCorr = ydots / pow(2, (MAX_BUMP_MAPPING_DEPTH - bumpMappingDepth) * 0.16);
lightAngleRadians = lightDirectionDegrees * PI / 180.0;
lightx = cos(lightAngleRadians) * gradCorr;
lighty = sin(lightAngleRadians) * gradCorr;
for (y = 0; y < ydots; y++)
{
for (x = 0; x < xdots; x++)
{
index = ((DWORD)y * (DWORD)width) + (DWORD)x;
if (SlopeDataPtr)
iterations = *(SlopeDataPtr + index);
else
return 0; // oops, we don't actually have forward differencing
if (iterations >= threshold)
{ // interior of Mandelbrot set = inside_color
colour.rgbtRed = (BYTE)TrueCol->InsideRed; // M_waves
colour.rgbtGreen = (BYTE)TrueCol->InsideGreen;
colour.rgbtBlue = (BYTE)TrueCol->InsideBlue;
}
else
{
// modified = rgbs[index];
if (iterations < PaletteStart)
modified = 0x00FFFFFF;
else
modified = 0xFF000000 | ((DWORD)*(TrueCol->PalettePtr + (BYTE)(((long)iterations) % 256) * 3 + 0) << 16) | ((DWORD)*(TrueCol->PalettePtr + (BYTE)(((long)iterations) % 256) * 3 + 1) << 8) | *(TrueCol->PalettePtr + (BYTE)(((long)iterations) % 256) * 3 + 2);
gradx = getGradientX(SlopeDataPtr, index, xdots);
grady = getGradientY(SlopeDataPtr, index, xdots, ydots);
dotp = gradx * lightx + grady * lighty;
// int original_color = modified; // not sure what this is for
if (dotp != 0)
{
gradAbs = sqrt(gradx * gradx + grady * grady);
cosAngle = dotp / gradAbs;
smoothGrad = -2.3562 / (gradAbs * sizeCorr + 1.5) + 1.57;
//smoothGrad = Math.atan(gradAbs * sizeCorr);
modified = changeBrightnessOfColorScaling(modified, cosAngle * smoothGrad);
}
r = (modified >> 16) & 0xFF;
g = (modified >> 8) & 0xFF;
b = modified & 0xFF;
colour.rgbtRed = r;
colour.rgbtGreen = g;
colour.rgbtBlue = b;
}
outRGBpoint(Dib, x, y, colour);
}
}
return 0;
}
GLSL
slope lighting in an OpenGLSL code shader by Softologyfractalforums.org : algorithm-for-rendering-slope-in-a-fractal
#version 400
//the following uniform values are set by Visions of Chaos prior to shader execution
uniform vec2 resolution;
uniform vec3 palette[256];
uniform double xmin;
uniform double xmax;
uniform double ymin;
uniform double ymax;
uniform double bailout;
uniform int maxiters;
uniform int samplepixels;
double sqrsamplepixels=double(samplepixels*samplepixels);
double bailout_squared=double(bailout*bailout);
double magnitude,r1,r2,g1,g2,b1,b2,r,g,b,tweenval;
float realiters;
vec4 finalcol,col;
int superx,supery;
double stepx=(xmax-xmin)/resolution.x/double(samplepixels);
double stepy=(ymax-ymin)/resolution.y/double(samplepixels);
int index,colval,colval2;
dvec2 z,c,dc,der,u,v,ctwo;
double h2,angle,pi,t;
//------------------------------------------------------------
// complex number operations
dvec2 cadd( dvec2 a, dvec2 b ) { return dvec2( a.x+b.x, a.y+b.y ); }
dvec2 csub( dvec2 a, dvec2 b ) { return dvec2( a.x-b.x, a.y-b.y ); }
dvec2 cmul( dvec2 a, dvec2 b ) { return dvec2( a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x ); }
dvec2 cdiv( dvec2 a, dvec2 b ) { double d = dot(b,b); return dvec2( dot(a,b), a.y*b.x - a.x*b.y ) / d; }
dvec2 csqr( dvec2 a ) { return dvec2(a.x*a.x-a.y*a.y, 2.0*a.x*a.y ); }
dvec2 csqrt( dvec2 z ) { double m = length(z); return sqrt( 0.5*dvec2(m+z.x, m-z.x) ) * dvec2( 1.0, sign(z.y) ); }
dvec2 conj( dvec2 z ) { return dvec2(z.x,-z.y); }
dvec2 cabs( dvec2 c) { return dvec2(sqrt(c.x * c.x + c.y * c.y)); }
//------------------------------------------------------------
void main(void)
{
finalcol=vec4(0,0,0,0);
pi=3.14159265359;
h2=1.5; // height factor of the incoming light
angle=45; // incoming direction of light
v=dvec2(exp(float(1.0*angle*2*pi/360)),0.0); // unit 2D vector in this direction
ctwo=dvec2(2.0,0.0);
for (supery=0;supery<samplepixels;supery++)
{
for (superx=0;superx<samplepixels;superx++)
{
c.x = xmin+gl_FragCoord.x/resolution.x*(xmax-xmin)+(stepx*double(superx));
c.y = ymin+gl_FragCoord.y/resolution.y*(ymax-ymin)+(stepy*double(supery));
int i;
z = dvec2(0.0,0.0);
dc = dvec2(1.0,0.0);
der = dc;
for(i=0; i<maxiters; i++)
{
//START OF FRACTAL FORMULA
z=cadd(csqr(z),c);
//END OF FRACTAL FORMULA
magnitude=(z.x * z.x + z.y * z.y);
if(magnitude>bailout_squared) break;
// der = der*2*z + dc
der = cadd(cmul(der,cmul(ctwo,z)),dc);
}
if (i==maxiters) {
col=vec4(0.0,0.0,0.0,1.0);
} else {
//CPM smooth colors
//note that double precision does not support log so it needs to be cast as float
realiters=float(i+1-((log(log(sqrt(float(magnitude))))/log(2.0))));
colval=int(mod(realiters,255));
colval2=int(mod(colval+1,255));
tweenval=realiters-int(realiters);
r1=palette[colval].r;
g1=palette[colval].g;
b1=palette[colval].b;
r2=palette[colval2].r;
g2=palette[colval2].g;
b2=palette[colval2].b;
r=r1+((r2-r1)*tweenval);
g=g1+((g2-g1)*tweenval);
b=b1+((b2-b1)*tweenval);
u = cdiv(z,der);
u = cdiv(u,cabs(u)); // normal vector: (u.re,u.im,1)
t = u.x*v.x + u.y*v.y + h2; // dot product with the incoming light
t = t/(1+h2); // rescale so that t does not get bigger than 1
if (t<0) { t=0; }
//p.color = linear_interpolation(black,white,t)
t=1.0-t;
r=r*t;
g=g*t;
b=b*t;
col=vec4(r,g,b,1.0);
}
finalcol+=col;
}
}
gl_FragColor = vec4(finalcol/double(sqrsamplepixels));
}
programs
ultrafractalultrafractal standard formulas : slope
directional DE, which can be used for slope colouring
Compare with
bumpmaping
Derivative
References