# Bonus Mirror Shaders

I finally got around to trying out thte mirror shaders from a few

weeks back. Did anyone else using 10.4.4 with a radeon mob 9700 have

trouble with the rf.kaleido.jxs shader? I get only a black screen

from it. The other ones work just fine.

thanks,

wes

I’ve been going through the shader bit by bit and I can get the

reflections to work, but I had to comment out the last section dealing

with folding with large offsets. I can’t seem to get that part to

work properly. Here’s the modded version:

kaleidoscope

//setup for 2 texture

varying vec2 texcoord0;

varying vec2 texcoord1;

uniform vec2 size;

uniform vec2 scale;

uniform vec2 offset;

uniform vec2 origin;

uniform float div;

uniform sampler2DRect tex0;

uniform sampler2DRect tex1;

const float pi=3.1415926;

void main()

{

// where is the point?

vec2 sizea = abs(size);

vec2 point = abs(mod(texcoord0*scale+origin,sizea));

// cartesian to polar conversion

vec2 dt = point-0.5*sizea;

float radius = sqrt(dot(dt,dt)); //hypot

float theta = atan(dt.y,dt.x)+pi;

float phi = 2.*pi/div;

// fold theta in the range 0-phi

float foldtheta;

//reflect over radius at phi

foldtheta = mod(theta,phi*2.);

if (foldtheta>=phi)

foldtheta = phi – (foldtheta – phi);

// polar to cartesian conversion

vec2 no = vec2(-cos(foldtheta)*radius, -sin(foldtheta)*radius);

no = no+0.5*sizea;

// fold x and y in the range 0-size

float offx,offy,foldx,foldy;

offx = abs(no.x+offset.x);

foldx = mod(offx,sizea.x*2.);

//if (foldx>=sizea.x)

// foldx = sizea.x – (foldx-sizea.x);

offy = abs(no.y+offset.y);

foldy = mod(offy,sizea.y*2.);

//if (foldy>=sizea.y)

// foldy = sizea.y – (foldy-sizea.y);

vec2 not = vec2(offx,offy);

vec4 a = texture2DRect(tex0,not);

// output texture

gl_FragColor = a;

}

]]>

Here’s the current state of the kaleido shader that I’ve got working

on my system. It seems that if I uncomment any more code, nothing

works. I find this quite strange as the code doesn’t do anything

malicious or unusual. Could it be I’m running out of memory to hold

the shader in? OS 10.4.4 pb 1.67 radeon mob 9700.

wes

kaleidoscope

//setup for 2 texture

varying vec2 texcoord0;

varying vec2 texcoord1;

uniform vec2 size;

uniform vec2 scale;

uniform vec2 offset;

uniform vec2 origin;

uniform float div;

uniform sampler2DRect tex0;

uniform sampler2DRect tex1;

const float pi=3.1415926;

void main()

{

// where is the point?

vec2 sizea = abs(size);

vec2 point = abs(mod(texcoord0*scale+origin,sizea));

// cartesian to polar conversion

vec2 dt = point-0.5*sizea;

float radius = sqrt(dot(dt,dt)); //hypot

float theta = atan(dt.y,dt.x)+pi;

float phi = 2.*pi/div;

// fold theta in the range 0-phi

float foldtheta;

//reflect over radius at phi

foldtheta = mod(theta,phi*2.);

if (foldtheta>=phi)

foldtheta = phi – (foldtheta – phi);

// polar to cartesian conversion

vec2 no = vec2(-cos(foldtheta)*radius, -sin(foldtheta)*radius);

no = no+0.5*sizea;

// fold x and y in the range 0-size

float offx,offy;

float foldx,foldy;

offx = abs(no.x+offset.x);

offx = mod(offx, sizea.x);

//if (offx>=sizea.x)

// offx = sizea.x – (offx-sizea.x);

offy = abs(no.y+offset.y);

//offy = mod(offy, sizea.y);< --uncommented make nothing appear

//if (foldy>=sizea.y)

// foldy = sizea.y – (foldy-sizea.y);

vec2 not = vec2(offx,offy);

vec4 a = texture2DRect(tex0,not);

// output texture

gl_FragColor = a;

}

]]>

Hi Wes,

This is most likely due to a limitation of the GLSL compiler’s

ability to handle multiple if statements. I think that this was

covered in a thread on one of the lists a while back. Note that any

if statement can be changed from a logical clause to an arithmetic

operation that always calculates all branches (which is required for

older gen cards which don’t support HW branching). This can sometimes

be faster than branching anyway, even on cards which support it,

since there is no pipeline flush. Depends on the complexity of the

branches of course.

So the statement:

if (foldtheta>=phi)

foldtheta = phi – (foldtheta – phi);

Can be rewritten as:

foldtheta = mix (foldtheta, phi – (foldtheta – phi), float

(foldtheta>=phi));

This converts the boolean to a floating point number zero or one,

used as the mixing coefficient in the arithmetic mix operator. If

zero, the first term is returned. If one, the second term is

returned. Make sense? This might seem wasteful, but as mentioned

before, it is supported on more hardware and often not even as

wasteful as a pipeline flush. It is also worth noting that oftentimes

with pixel processing shaders, the operation is more memory bound

than compute bound, as I would imagine this particular shader to be.

So replacing all the if statements below with the corresponding

arithmetic operation should make this shader work on your card. This

is what we did with most of the compositing shaders like

co.hardlight.jxs. A useful exercise would be to compare this version

with the version in the OpenGL Orange Book.

Let us know if you encounter further problems.

-Joshua