Jump to content

View more

Image of the Day

Adding some finishing touches...
Follow us for more
#screenshotsaturday #indiedev... by #MakeGoodGames https://t.co/Otbwywbm3a
IOTD | Top Screenshots

The latest, straight to your Inbox.

Subscribe to GameDev.net Direct to receive the latest updates and exclusive content.


Sign up now

GLSL Droste

4: Adsense

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.


  • You cannot reply to this topic
10 replies to this topic

#1 ArKano22   Members   

650
Like
0Likes
Like

Posted 09 December 2010 - 10:02 PM

I´m trying to achieve a Droste effect in GLSL, like this:

http://www.josleys.com/article_show.php?id=82
(scroll down past the explanation to see some beautiful examples)

However the math explained there isn´t valid as-is as they assume you can write to arbitrary positions in the image. I´ve been trying to use alternative transforms and i´ve managed to create a pseudo-droste using an archimedean spiral instead of a logarithmic one (convert cartesian to polar, adjust radius, convert back to cartesian).

Not to my surprise, it doesn´t look good. Can anyone point me to more Droste effect material? Are there GLSL droste effects out there that i can take a look at?

#2 Pragma   Members   

395
Like
0Likes
Like

Posted 10 December 2010 - 03:49 AM

If you know the forward transformation, then there are two ways to proceed:

1. Get out a pen and paper, and calculate the inverse transformation. This doesn't look like it will be too difficult, since it's just made up of rotation, scaling, log and exp which are all easily invertible. Then you can do the whole effect in a pixel shader.

2. If you don't want to do the inverse transformation you can put your image on a grid and just transform by the forward transformation in the vertex shader. Of course you won't be able to zoom in infinitely, but you can just stop when you get down to the size of one pixel.

Hope that is helpful. Looks like a cool effect, now I'm tempted to try it ...

#3 ArKano22   Members   

650
Like
0Likes
Like

Posted 10 December 2010 - 03:18 PM

Quote:
Original post by Pragma
If you know the forward transformation, then there are two ways to proceed:

1. Get out a pen and paper, and calculate the inverse transformation. This doesn't look like it will be too difficult, since it's just made up of rotation, scaling, log and exp which are all easily invertible. Then you can do the whole effect in a pixel shader.

Hope that is helpful. Looks like a cool effect, now I'm tempted to try it ...


Well, i did the inverse transform (first exp(z), then transform, then log(z)). From this article (pag4 diagram):
http://www.ams.org/notices/200304/fea-escher.pdf

If i only do complex exp then log, the image stays the same, which means that transforming forth and back works. However to do the rotation transform i think i should multiply "z" with 1+1i (45º). If i do it alone, it works, but multiplying after the complexExp() only translates the image, and when untransforming with complexLog() i find my original image, but offsetted.



vec2 complexExp(in vec2 z){
return vec2(exp(z.x)*cos(z.y),exp(z.x)*sin(z.y));
}
vec2 complexLog(in vec2 z){
return vec2(log(length(z)), atan(z.y, z.x));
}
vec2 complexMult(in vec2 a,in vec2 b){
return vec2(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x);
}

vec4 droste(in vec2 co){
vec2 z = (co-0.5)*2.0;
z = complexExp(z);
z = complexMult(z,vec2(1.0,1.0));
z = complexLog(z);
z = z*0.5+0.5;
vec4 final = texture2D(Texture0,fract(z));
return final;
}




Is there something obvious that i´m missing here? I think the transforms are correct and it should work, but...

#4 knighty   Members   

313
Like
0Likes
Like

Posted 11 December 2010 - 02:10 AM

Hi,
Here is the link to an Excellent pixel bender implementation of this effect. pixel bender language is not GLSL but it's very close. Hope you'll find it useful.

#5 Pragma   Members   

395
Like
0Likes
Like

Posted 11 December 2010 - 03:09 AM

Try putting the log before the multiplication, and the exp after. Remember when you invert a set of functions, you need to reverse the order. For example, if y = f(g(x)) the inverse is x = g^-1(f^-1(y))

#6 ArKano22   Members   

650
Like
0Likes
Like

Posted 11 December 2010 - 04:02 PM

Thanks guys, i got it working. And most important i understand why it works :). The droste math i was looking at is not really the droste effect itself, but a transform which makes the droste(feedback) effect look like a spiral. I got the transform right thanks to Pragma and then coded a quick n dirty feedback effect to test it on. Once i optimize the code a little bit i´ll post it here just in case someone needs it.

Here´s a pic:


Uploaded with ImageShack.us

#7 ArKano22   Members   

650
Like
0Likes
Like

Posted 12 December 2010 - 01:21 AM

Here´s the code. Pass your UV <0,1> coordinates to the droste() function and it will deliver a color. There are three adjustable parameters: scale factor between self-similar images, number of branches the spiral has (0.0 for discrete droste effect, >0.0 for continuous) and animation speed. Note that you must pass "time" as a float uniform for animation (infinite zoom) to work.

This version has rectangular self-similarity, but making a circular one should not be difficult. Hope someone finds this useful.


const float TWO_PI = 3.141592*2.0;

//ADJUSTABLE PARAMETERS:
const float branches = 1.0;
const float scale = 0.25;
const float speed = 2.0;

//Complex Math:
vec2 complexExp(in vec2 z){
return vec2(exp(z.x)*cos(z.y),exp(z.x)*sin(z.y));
}
vec2 complexLog(in vec2 z){
return vec2(log(length(z)), atan(z.y, z.x));
}
vec2 complexMult(in vec2 a,in vec2 b){
return vec2(a.x*b.x - a.y*b.y, a.x*b.y + a.y*b.x);
}
float complexMag(in vec2 z){
return float(pow(length(z), 2.0));
}
vec2 complexReciprocal(in vec2 z){
return vec2(z.x / complexMag(z), -z.y / complexMag(z));
}
vec2 complexDiv(in vec2 a,in vec2 b){
return complexMult(a, complexReciprocal(b));
}
vec2 complexPower(in vec2 a, in vec2 b){
return complexExp( complexMult(b,complexLog(a)) );
}
//Misc Functions:
float nearestPower(in float a, in float base){
return pow(base, ceil( log(abs(a))/log(base) )-1.0 );
}
float map(float value, float istart, float istop, float ostart, float ostop) {
return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
}

vec4 droste(in vec2 co){

//SHIFT AND SCALE COORDINATES TO <-1,1>
vec2 z = (co-0.5)*2.0;

//ESCHER GRID TRANSFORM:
float factor = pow(1.0/scale,branches);
z = complexPower(z, complexDiv(vec2( log(factor) ,TWO_PI), vec2(0.0,TWO_PI) ) );

//RECTANGULAR DROSTE EFFECT:
z *= 1.0+fract(time*speed)*(scale-1.0);
float npower = max(nearestPower(z.x,scale),nearestPower(z.y,scale));
z.x = map(z.x,-npower,npower,-1.0,1.0);
z.y = map(z.y,-npower,npower,-1.0,1.0);

//UNDO SHIFT AND SCALE:
z = z*0.5+0.5;

return texture2D(Texture0,z);
}






#8 Hodgman   Moderators   

50868
Like
0Likes
Like

Posted 13 December 2010 - 02:21 AM

Thanks for sharing! Would be fun to try and integrate this with the display of a 3d rendered scene ;)

#9 kloffy   Members   

1315
Like
0Likes
Like

Posted 15 December 2010 - 09:45 AM

Coolest thing I've seen in a while. I had seen these kinds of pictures before, but I never knew anything about how they are generated. Great stuff!

#10 circassia   Members   

100
Like
0Likes
Like

Posted 08 November 2011 - 08:44 AM

Thanks for sharing mate!

#11 johnchapman   Members   

601
Like
0Likes
Like

Posted 08 November 2011 - 12:05 PM

I've used a recursive approach to render a droste-like effect for simulating visual feedback within a deferred renderer:



Basically it uses the output from the previous frame which, due to the setup of the rendering pipeline, is available during the rendering of the current frame.




Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.