Turn on the light + strange meshes

ciao all,

today i played around with some meshes definitions from Paul Bourke website … actually it was kind of easy to reproduce some of the examples with a shader. -> see patch

but i don’t know how to do a correct light calculation. so can someone of the “vertex shader experts” please tell me how to do this … help me to turn on the lights :)

thanks
benedikt

VertexMesh01.v4p (4.8 kB)

ääh and the shader

benedikt

VertexMesh_PhongDirectional.fx (5.9 kB)

thats a non trivial task in a shader. in most cases you have to calculate the derivative. thats different for every formula and quite tricky in 3-dimensions. from the derivative of the formula you get the normals.

the problem is, that you can’t access the neighbours in a vertex shader, with them it would be easy. if you find a way to do that, let me know…

i know it is oldschool but if you’d not use the shader to deform the mesh but work on the vertexbuffer directly you could use the Normals (EX9.Geometry) node to generate correct normals for an arbitrary mesh.

thanks tonfilm + joreg.

shit. so i think it’s the “oldschool” way for me -> Normals (EX9.Geometry) and calculate everything “outside” the shader.

… hehe, the neighbours thing can be solved with a brute force method. just calculate the formula 3 times: the position, one in x (u in your shader) direction and one in y (v in your shader) direction, with an offset that is the distance between the grid points. see patch…

vertex_shader_lighning.zip (5.5 kB)

wicked tonfilm!

but unfortunately i must tell you that oldschool beats newschool with 4:1. -> see patch.

no i think there is a small bug in your shader, because with the shader way you get just a quarter of the mesh …

VertexMeshShader_vs_Oldschool.zip (5.3 kB)

on my card the shader is way faster, 60fps with 100x100 mesh. you have to delete the other part to test it, because the vertextbuffer part consumes power all the time.

the shader has offset and scale inputs, you can move the mesh around and select the part you want to see, nothing is missing. i just changed it, because if you have u and v from 0…pi the mesh is doubled, which looks somehow wrong…

with gridScaleXY = 1 everything looks fine.

that’s a nice approach tonfilm!

so i think there a 4 possibilities to solve the problem:

1) calculate the formula for the normals in a mathprogram like mathematica and type this into your shader. (hard)

so if you have any function describing a 2d-surface which is dependant of 2 varaibles u and v, like

F:(u,v) -> (Px, Py, Pz)

which gives back cartesian coordinates Px,Py,Pz for every (u,v) pair, then you can use a math program to calc the normals like this:

At each point on the surface you need 2 tangent vectors along the surface, which you can cross to get the normal at this point.

The trick is: the tangent vectors are just the derivates of the function F in direction u and v.
so first you vary u (and get the derivative with fixed v and changing u)

t = dF / du

and then you fix u and vary v to get the binormal
b = dF / dv

these are called partial derivates for the function F:(u,v).

both t and b are again functions in this form:
t:(u,v) -> (tx, ty, tz)
b:(u,v) -> (bx, by, bz)

when you cross the t and b vector for your current (u,v) then you get the normal…

2) tonfilms more general approach, which is only slightly less accurate and only slightly slower, but much easier to program and it should also need less shader instruction slots.
it could get a little more accurate when substracting the points half-way to the neighbours from each other like

t = F(u+du/2, v) - F(u-du/2, v)
b = F(u, v+dv/2) - F(u, v-dv/2)

and if your graphics card still has power left, it is worth to think about doing these instructions (and the cross) in the pixelshader for even smoother results.

3) mess around with ddx and ddy functions in the pixelshader. these functions are astonishing. they can somehow calculate derivatives of any variables with respect to screenpixels. i.e. what happens with a particular function or variable when calculating the pixelshader for the neighbor screenpixels.

4) do it outside of the shader which is very slow when doing this every frame. however if when you want to calculate the geometry only once it should be faster to render it when normals are already stored in the mesh.

for now. chcheers

2)

approach_tonfilm_but_PS.zip (4.5 kB)

it could get a little more accurate when substracting the points half-way to the neighbours from each other like

t = F(u+du/2, v) - F(u-du/2, v)
b = F(u, v+dv/2) - F(u, v-dv/2)

right, in fact the offset can be choosen as a small constant value. the grid resolution doesn’t really matter. but a problem is edges (as always…), if one offset point is ‘around the corner’ the normal will be wrong. for complicated meshes on could think of calculating 4 neighbours and interpolate them…

and if your graphics card still has power left, it is worth to think about doing these instructions (and the cross) in the pixelshader for even smoother results.

yea, wow, that would be an incredible smooth shading, even without a very high resolution of the mesh, because the mathematical representation of the mesh is available…

@tonfilm
i was a bit in a hurry so i didn’t see that the whole mesh was there … and of course the performance with shadercode is a lot faster. -> u win perfect :)
plus i took me a while until i realised how “universal” your approach is. really cool … now more or less every dynamically generated mesh (inside shader) can be easily shaded. excellent!

@gregsn
emm … i will try to understand that … but that will take a little while.

thanks boys!
benedikt

Hi there!

While playing and coding the surface shader i’ve noticed that this calculation of normals doesn’t really fit some meshes…for exemple the lemniscape exemple shown in this thread…when the surface twist you have points hilighted in the opposite way(inside/outside and vice versa)…anyway to restore the rigth light pos? Would be nice:)

Cheers!

Tear.zip (2.8 kB)

Hi Desaxismundi

I know this thread is long-dead, but if you haven’t found a solution to this already, you could try flipping the normals based on the z-value:

normal = (normal.z < 0) ? -normal : normal;

Might work…

a|x

Hi, MrBenefit

I’m a vvvv user in China. Thank you for all you have done for the community. I found your page pixelshader_for_newbies is very helpful for starters of shader writer, and i would try to translate it to Chinese version. But there is no edit button in the upper bar of your page. Would you please to fix it?

http://vvvv.org/tiki-index.php?page=howto+translate+the+vvvviki
so you should edit
http://vvvv.org/tiki-editpage.php?page=cn.pixelshader_for_newbies
and then MrBenefit can link to that :)