sharing is fun – Math Surface Shader

Sep 14, 2007 at 1:39am

sharing is fun – Math Surface Shader

Hi folks,
Here’s a shader and patch I made following the “Calculate Normals In
Shader” blog entry on http://tonfilm.blogspot.com/ . It should be
quite easy to plug in other equations from
http://local.wasp.uwa.edu.au/%7Epbourke/surfaces_curves/ .

This one implements the Tranguloid Trefoil equation:

http://www.mat.ucsb.edu/~whsmith/ShaderSurface.zip

wes

#33668
Sep 14, 2007 at 2:22am

Nice one :)

I just picked up the Orange Book today, its been super helpful
already. Ive been able to properly antialias some of the procedural
texture generators ive made.

Might be interesting to put in two formulas and add mix() to morph
between vertex targets. Hmmm :)

On Sep 13, 2007, at 9:39 PM, Wesley Smith wrote:

> Hi folks,
> Here’s a shader and patch I made following the “Calculate Normals In
> Shader” blog entry on http://tonfilm.blogspot.com/ . It should be
> quite easy to plug in other equations from
> http://local.wasp.uwa.edu.au/%7Epbourke/surfaces_curves/ .
>
> This one implements the Tranguloid Trefoil equation:
> http://www.mat.ucsb.edu/~whsmith/ShaderSurface.zip
>
>
> wes

v a d e //

http://www.vade.info
abstrakt.vade.info

#112448
Sep 14, 2007 at 2:30am

That’s kind of what electric sheep is doing with iterated function
systems. That system works by having 14 equations each with its own
weight where they all add up to 1. It morphs between functions by
changing relative weights. The only trouble with doing that in a
vertex shader is how many equations th shader can take before it
becomes slow. I bet it could handle 3 on a good card, maybe more if
they’re not very complicated.

wes

On 9/13/07, vade wrote:
> Nice one :)
>
> I just picked up the Orange Book today, its been super helpful already. Ive
> been able to properly antialias some of the procedural texture generators
> ive made.
>
> Might be interesting to put in two formulas and add mix() to morph between
> vertex targets. Hmmm :)
>
>
> On Sep 13, 2007, at 9:39 PM, Wesley Smith wrote:
>
> Hi folks,
> Here’s a shader and patch I made following the “Calculate Normals In
> Shader” blog entry on http://tonfilm.blogspot.com/ . It should be
> quite easy to plug in other equations from
> http://local.wasp.uwa.edu.au/%7Epbourke/surfaces_curves/ .
>
> This one implements the Tranguloid Trefoil equation:
> http://www.mat.ucsb.edu/~whsmith/ShaderSurface.zip
>
>
> wes
>
> v a d e //
>
> http://www.vade.info
> abstrakt.vade.info
>
>
>
>
>
>

#112449
Sep 14, 2007 at 2:42am

I was actually thinking of staggering it, so each shader has 2
forumals in it, weighted between 0 and 1,

so you have shader “A” which has 1,2, shader b has 2 and 3, shader
c forumals 3 and 4

when you go from 1 to 2, you can then switch to shader b, go form 2
to 3, then to shader c which has 3 to 4 ?

I dunno, does having the shader uploaded but not bound waste GPU
cycles? I dont think so right?

Might be a solution :)

Either way, very cool.

#112450
Sep 14, 2007 at 2:53am

erm, formulas. Has someone been spending too many hours on forum-
las ? *sigh* :)

#112451
Sep 14, 2007 at 2:59am

That’s cool, Wes. I’m gonna definitely play around with this. And
thanks for sharing that blog. Some cool stuff there.

AB

#112452
Sep 14, 2007 at 3:00am

I was thinking something similar as well but with 3 instead of 2 but 2
might be just as good with careful mixing. Doing it this way
shouldn’t be a problem at all GPU cycle-wise.

wes

#112453
Sep 14, 2007 at 3:46am

this looks cool, but i’m shocked and saddened about how slow it is on
my 1.67g4 albook. is that a surprise? it feels like 5fps.

On Sep 13, 2007, at 9:39 PM, Wesley Smith wrote:

> Hi folks,
> Here’s a shader and patch I made following the “Calculate Normals In
> Shader” blog entry on http://tonfilm.blogspot.com/ . It should be
> quite easy to plug in other equations from
> http://local.wasp.uwa.edu.au/%7Epbourke/surfaces_curves/ .
>
> This one implements the Tranguloid Trefoil equation:
> http://www.mat.ucsb.edu/~whsmith/ShaderSurface.zip
>
>
> wes
>

#112454
Sep 14, 2007 at 3:54am

Try reducing the dimensions of the input matrix. I set it quite high.
BTW, what graphics card do you have? Radeon 9700? If so all of the
trigonometric stuff might kill it and if the shape takes up large
portion of the screen, the per-pixel lighting won’t help either.

wes

On 9/13/07, joshua goldberg wrote:
> this looks cool, but i’m shocked and saddened about how slow it is on
> my 1.67g4 albook. is that a surprise? it feels like 5fps.
>
>
> On Sep 13, 2007, at 9:39 PM, Wesley Smith wrote:
>
> > Hi folks,
> > Here’s a shader and patch I made following the “Calculate Normals In
> > Shader” blog entry on http://tonfilm.blogspot.com/ . It should be
> > quite easy to plug in other equations from
> > http://local.wasp.uwa.edu.au/%7Epbourke/surfaces_curves/ .
> >
> > This one implements the Tranguloid Trefoil equation:
> > http://www.mat.ucsb.edu/~whsmith/ShaderSurface.zip
> >
> >
> > wes
> >
>
>

#112455
Sep 14, 2007 at 3:56am

lower the vert count. its currently at 100 ?
On Sep 13, 2007, at 11:46 PM, joshua goldberg wrote:

> this looks cool, but i’m shocked and saddened about how slow it is
> on my 1.67g4 albook. is that a surprise? it feels like 5fps.

v a d e //

http://www.vade.info
abstrakt.vade.info

#112456
Sep 14, 2007 at 10:37am

hi wes!

that

#112457
Sep 14, 2007 at 3:02pm

Hi Didi,
Here’s your patch as a shader. Not quite as smooth as nurbs but still nice.

wes

#P window setfont “Sans Serif” 9.;
#P flonum 720 227 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P window linecount 1;
#P message 720 247 59 196617 param6 $1;
#P flonum 658 227 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 658 247 59 196617 param5 $1;
#P flonum 596 227 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 596 247 59 196617 param4 $1;
#P flonum 534 227 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 534 247 59 196617 param3 $1;
#P flonum 472 227 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 472 247 59 196617 param2 $1;
#P flonum 410 227 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 410 247 59 196617 param1 $1;
#P flonum 348 228 35 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 348 248 59 196617 param0 $1;
#P newex 416 304 76 196617 prepend param;
#P flonum 329 284 70 9 0 0 0 3 0 0 0 221 221 221 222 222 222 0 0 0;
#P message 329 303 78 196617 param delta $1;
#P message 223 303 82 196617 file vd.math.jxs;
#P newex 223 333 240 196617 jit.gl.shader test @file vd.math.jxs @name surface;
#P button 107 196 15 0;
#P newex 107 268 157 196617 jit.gl.mesh test @shader surface;
#P newex 107 218 142 196617 jit.matrix 3 float32 100 100;
#P newex 107 240 196 196617 jit.expr @expr “norm[0]” “norm[1]” “0″;
#P message 158 81 34 196617 reset;
#P newex 158 101 186 196617 jit.gl.handle test @inherit_transform 1;
#P newex 23 101 48 196617 r render;
#P toggle 138 72 15 0;
#N vpatcher 53 128 279 297;
#P inlet 106 30 15 0;
#P window setfont “Sans Serif” 9.;
#P window linecount 0;
#P newex 43 95 47 196617 gate 1 1;
#P newex 42 116 41 196617 s draw;
#P window linecount 1;
#P newex 17 52 58 196617 t b b erase;
#P inlet 17 32 15 0;
#P outlet 17 83 15 0;
#P connect 1 0 2 0;
#P fasten 2 2 0 0 70 75 22 75;
#P connect 2 0 0 0;
#P connect 4 0 3 0;
#P fasten 5 0 4 0 111 88 48 88;
#P fasten 2 1 4 1 46 83 85 83;
#P lcolor 15;
#P pop;
#P newobj 76 101 42 196617 p Draw;
#P toggle 214 40 15 0;
#P message 214 60 68 196617 fullscreen $1;
#N vpatcher 30 89 166 253;
#P window setfont “Sans Serif” 9.;
#P newex 50 71 35 196617 sel 27;
#P newex 50 50 40 196617 key;
#P outlet 50 93 15 0;
#P connect 1 0 2 0;
#P connect 2 0 0 0;
#P pop;
#P newobj 231 40 33 196617 p Esc;
#P newex 214 78 151 196617 jit.window test @depthbuffer 1;
#P toggle 76 53 15 0;
#P newex 76 72 57 196617 qmetro 30;
#P newex 76 128 187 196617 jit.gl.render test @erase_color 0 0 0 1;
#P connect 33 0 20 0;
#P connect 31 0 20 0;
#P connect 29 0 20 0;
#P connect 27 0 20 0;
#P connect 25 0 20 0;
#P connect 23 0 20 0;
#P connect 21 0 20 0;
#P connect 34 0 33 0;
#P connect 32 0 31 0;
#P connect 30 0 29 0;
#P connect 28 0 27 0;
#P connect 26 0 25 0;
#P connect 24 0 23 0;
#P connect 22 0 21 0;
#P fasten 20 0 16 0 421 325 228 325;
#P connect 13 0 12 0;
#P connect 12 0 14 0;
#P connect 19 0 18 0;
#P connect 17 0 16 0;
#P fasten 18 0 16 0 334 321 228 321;
#P connect 5 0 3 0;
#P connect 6 0 5 0;
#P connect 4 0 6 0;
#P connect 11 0 10 0;
#P fasten 8 0 7 1 143 94 113 94;
#P connect 15 0 13 0;
#P fasten 10 0 0 0 163 123 81 123;
#P connect 7 0 0 0;
#P fasten 9 0 0 0 28 123 81 123;
#P connect 1 0 7 0;
#P connect 2 0 1 0;
#P window clipboard copycount 35;

////////////////////////////////////////////////////////////////Shader

Shader Phong per-pixel lighting in GLSL















< ![CDATA[

varying vec3 N;
varying vec3 P;

#define PI 3.141519
#define TWOPI 6.28

uniform float delta;
uniform float param0;
uniform float param1;
uniform float param2;
uniform float param3;
uniform float param4;
uniform float param5;
uniform float param6;

vec3 surface(vec2 point)
{

vec3 s_point;

/*
s_point.x = 2.*sin(3.*point.x) / (2. + cos(point.y));
s_point.y = 2.*(sin(point.x) + 2.*sin(2.*point.x)) / (2. +
cos(point.y + 2.*PI / 3.));
s_point.z = (cos(point.x) – 2.*cos(2.*point.x))*(2. +
cos(point.y))*(2. + cos(point.y + 2.*PI / 3.)) / 4.;
*/

s_point.x = param1*(1.-((param0*param5*point.x*TWOPI)/TWOPI))*cos(param0*param4*param5*point.x*TWOPI)*(1.+cos(param0*param6*point.y*PI))+param3*cos(param0*param4*param5*point.x*TWOPI);
s_point.y = param1*(1.-((param0*param5*point.x*TWOPI)/TWOPI))*sin(param0*param4*param5*point.x*TWOPI)*(1.+cos(param0*param6*point.y*PI))+param3*sin(param0*param4*param5*point.x*TWOPI);
s_point.z = param2*((param0*param5*point.x*TWOPI)/TWOPI)+param1*(1.-((param0*param5*point.x*TWOPI)/TWOPI))*sin(param0*param6*point.y*PI);

return s_point;
}

void main (void)
{
vec4 V = vec4( surface(gl_Vertex.xy), 1.);

//get the vertices into eye space
P = (gl_ModelViewMatrix*V).xyz;

vec3 neighbour1 = surface(vec2(gl_Vertex.x + delta, gl_Vertex.y));
vec3 neighbour2 = surface(vec2(gl_Vertex.x, gl_Vertex.y + delta));

vec3 tangent = normalize(neighbour1 – V.xyz);
vec3 bitangent = normalize(neighbour2 – V.xyz);

//get the normals into eye space
N = normalize( cross(tangent, bitangent) );
N = mat3( gl_ModelViewMatrixInverseTranspose[0].xyz,
gl_ModelViewMatrixInverseTranspose[1].xyz,
gl_ModelViewMatrixInverseTranspose[2].xyz)*N;

gl_Position = gl_ModelViewProjectionMatrix*V;
}
]]>

< ![CDATA[

uniform vec4 Ia;
uniform vec4 Ii;
uniform vec3 eyePosition;
uniform vec4 Ke;
uniform vec4 Ka;
uniform vec4 Kd;
uniform vec4 Ks;
uniform float Ns;

varying vec3 N;
varying vec3 P;

void main (void)
{
vec3 Nn = normalize(N);

//ambient contribution
vec4 ambient = Ia*Ka;

vec3 lightPosition = vec3(gl_LightSource[0].position);

//diffuse contribution
vec3 L = normalize(lightPosition – P);
vec4 diffuse = Kd*Ii*max(dot(Nn, L), 0.);

//calculate specular contribution
vec3 V = normalize(eyePosition – P);
vec3 H = normalize(L + V); //average of lighting and view vector)
not true reflection vector
vec4 specular = Ks*Ii * pow(max(dot(Nn,H), 0.), Ns);

gl_FragColor = Ke + ambient + diffuse + specular;
}
]]>

#112458
Sep 14, 2007 at 3:44pm

I couldn’t let Wes have all the fun, so here is a version that does
Spherical Harmonics. I also threw in my special normal-dependent
pixel-disposal sauce to make it that much more interesting. Try
animating the delta value and changing the fig/thresh params. Also, the
sphere param mixes between a sphere and the distorted shape, and of
course you can extrapolate. For those of you not running the latest and
greatest hardware, I recommend lowering the jit.matrix dims. It does
look really nice at 500×500 though

I’m not usually a big supporter of mathematical surfaces, but I guess
I’m beginning to see the light.

Happy Patching!

Andrew B.

#112459
Sep 14, 2007 at 3:52pm

oops, that patch had a minor issue. This one will work better.

AB

#112460
Sep 14, 2007 at 4:28pm

All it did on my computer was completely kill the framerate for a black screen.

Max 4.6.3 Jitter 1.6.3
1.67 Ghz Powerbook G4
OS 10.4.10

May just be my problem,
Keith

On 9/14/07, Andrew Benson wrote:
> oops, that patch had a minor issue. This one will work better.
>
> AB
>
>
>
>

#112461
Sep 14, 2007 at 4:44pm

Hi Kieth,
Try lowering the dimensions of the shape matrix to something reasonable
(say 50×50) or something and see if that helps. It could just be that
the shader pushes the limits of your graphics card. I’ll have a look at
it later and see if I can streamline the code a little.

AB

#112462
Sep 14, 2007 at 5:07pm

> Try lowering the dimensions of the shape matrix to something reasonable
> (say 50×50) or something and see if that helps.

That helped with the framerate. I was confused by the complete black
jit.window. A little jit.gl.handle and parameter tweaking did the
trick too.

Thanks,
Keith

#112463
Sep 14, 2007 at 5:37pm

Andrew Benson skrev:
> oops, that patch had a minor issue. This one will work better.
Looks fantastic!

I have just one issue with it, and that is that the texture params “fig”
and “thresh” control an effect that seems quite jagged – is there a way
to antialias there? That would make it even more awesome.

Andreas.

#112464
Sep 14, 2007 at 5:52pm

andrew.
can you show the web forum some love?

many thanks to all

#112465
Sep 14, 2007 at 6:04pm

Unfortunately, this effect makes use of the “discard” method, which is
either on or off. Basically, it’s just throwing out pixels if the
output of a formula falls below a threshold. If you don’t care about
depthbuffering, you can use a
smoothstep(thresh,thresh+fwidth(goop)*fade,goop); and apply that to the
glFragColor alpha.

If you do want to keep the depthbuffering and need antialiasing, you
could always render to a double-size texture and do averaging
downsamples, as has been discussed previously.

Best,
Andrew B.

#112466
Sep 14, 2007 at 6:50pm

Oh, sorry. Here you go.

AB

#112467
Sep 17, 2007 at 1:16pm

Here’s a random question about this… not to provoke an argument,
but simply because I’m always curious about the “best” way of doing
anything.

Why do all this in a shader, why not use jit.expr to calculate
geometry for surfaces and then the normals? Is there a benefit to
first calculating a normal-distribution-based coordinate spread for a
plane, and then using that as input into a shader?

I have a friend who does a lot of OpenGL programming, and he swears
by using only vertex arrays (especially cached) and standard opengl
blend modes. But he doesn’t know shaders well, I feel like there
could be something he’s missing.

Cheers
Evan

On Sep 14, 2007, at 2:39 AM, Wesley Smith wrote:

> Hi folks,
> Here’s a shader and patch I made following the “Calculate Normals In
> Shader” blog entry on http://tonfilm.blogspot.com/ . It should be
> quite easy to plug in other equations from
> http://local.wasp.uwa.edu.au/%7Epbourke/surfaces_curves/ .
>
> This one implements the Tranguloid Trefoil equation:
> http://www.mat.ucsb.edu/~whsmith/ShaderSurface.zip
>
>
> wes

#112468
Sep 17, 2007 at 2:51pm

On Sep 17, 2007, at 3:16 PM, evan.raskob [lists] wrote:

> Here’s a random question about this… not to provoke an argument,
> but simply because I’m always curious about the “best” way of doing
> anything.

I guess my general practice is to let the system breathe… So stuff
as much as you can on a GPU, until it strats to choke.

> Why do all this in a shader, why not use jit.expr to calculate
> geometry for surfaces and then the normals? Is there a benefit to
> first calculating a normal-distribution-based coordinate spread for
> a plane, and then using that as input into a shader?

It is simple, and since the vertices are sent only once – there’s
almost no performance hit.
Also, as far as I know, shaders are incapable of creating new vertices.

> I have a friend who does a lot of OpenGL programming, and he swears
> by using only vertex arrays (especially cached) and standard opengl
> blend modes. But he doesn’t know shaders well, I feel like there
> could be something he’s missing.

he’s missing a lot! Many of the patches posted lately on the list
would be very hard, if not impossible, to recreate while using only
GPU without the shaders.

just my 0.2RSD

nesa

#112469
Sep 17, 2007 at 3:30pm

> > Why do all this in a shader, why not use jit.expr to calculate
> > geometry for surfaces and then the normals? Is there a benefit to
> > first calculating a normal-distribution-based coordinate spread for
> > a plane, and then using that as input into a shader?
>

Imagine doing this:

x = 2 sin(3 u) / (2 + cos(v))
y = 2 (sin(u) + 2 sin(2 u)) / (2 + cos(v + 2 pi / 3))
z = (cos(u) – 2 cos(2 u)) (2 + cos(v)) (2 + cos(v + 2 pi / 3)) / 4

with jit.expr at 30fps on a 50×50 grid. You’re framerate will crawl
if not die if you do it on the CPU. On the GPU you can warp the
coordinate range and other fun stuff dynamically for smooth
animations. jit.gl.mesh does use VBOs under the hood for sending the
planar data so that is also fast.

> It is simple, and since the vertices are sent only once – there’s
> almost no performance hit.
> Also, as far as I know, shaders are incapable of creating new vertices.
>

Not entirely true. With Geometry shaders, you can generate quite a
large number of vertices on the GPU.

>
> > I have a friend who does a lot of OpenGL programming, and he swears
> > by using only vertex arrays (especially cached) and standard opengl
> > blend modes. But he doesn’t know shaders well, I feel like there
> > could be something he’s missing.

VBOs are definnitely best practice for dispatching data to the GPU but
shaders are required for complex rendering effects. Blend modes are
nice but limited. For example, you can’t do per-pixel lighting with
just VBOs and blend modes.

wes

#112470
Sep 17, 2007 at 5:10pm

> Not entirely true. With Geometry shaders, you can generate quite a
> large number of vertices on the GPU.

ah yes!(that is too new for my hardware:)

also, how would one do that with jitter?

#112471
Sep 17, 2007 at 6:10pm

> also, how would one do that with jitter?

Wait for a version of Jitter that supports it.

wes

#112472
Sep 18, 2007 at 2:37am

Hiya peepz,

I’ve been following this thread for a while and it is really fun.
This is my first attempt at 3D open GL, so I am having quite a time
with it. I sat and watched Dan Vatsky at Share the other week and we
were wondering why it isn’t possible to morph a 3D shape he had
designed in maya in Jitter. And you guys point us in the some near
direction of that now!

Basically I wrote the shader to mix() between two of the shapes
documented on the website mentioned in the beginning of this thread.
Values for the param “sphere” – 0. shows the owl shape and 1. shows
the mobius strip. After some tuning of the incoming points each
formula seems to work and the fade does too. What I am having
difficulty with is the lighting and adding a video texture.

Am I right to assume that the lighting and texturing is done for each
point on the shape (and only one “side”) and not as a shape in
general and that is why the lighting and texturing don’t quite work?

Surprisingly I could figure out the math, but I am fairly new to
this. Any explanation on what is happening with lighting and
texturing and how it might work would help.

Thanks again for all the sharing and the great ideas on the list.

(())_n

#112473
Sep 18, 2007 at 2:51am

Nice. Here’s a question for you:

How do you imagine the video on the form looking? Is is mapped to the
surface directly? Is it reflection mapped? For the former, you will
have to generate texture coordinates in some fashion. The simplest
way it linearly with the input points. For the latter, just take the
fragment shader portion of the refract.reflect shader I posted last
week and it should work.

wes

#112474

You must be logged in to reply to this topic.