Author : jdvi


Reply
Reply
 
Thread Tools Display Modes
JRoman's Avatar
Old (#1)
Hi Polycount! Long time lurker here, first time posting. I finally landed my first job in the game industry about 8 months ago(!!!) as a 3D artist, it's been awesome and I really owe this community a big thanks for all the wisdom, laughs and inspiration it has given me over the years. So, thank you Polycounters!

But I've now been tasked with learning the art of shaders, which I've always wanted to do, but I think I may be in need of some guidance from you guys...

So I'm trying to achieve the look of a "Point Cloud" much like the following images:




The Specifics:

I'm trying to achieve this on Shader Model 2.0, and without using the actual geometry verts (the geometry is very low poly, mostly interior walls). Ideally there would be a greater number of points along edges to give the player a fairly accurate representation of the room depth/shape.

On top of all of this, I'm hoping to get this working on iOS. I know this is a really tall order but I'm determined to make this work if it can be done. (Or get as close as possible to the desired effect)

Initially I thought the easiest/cheapest way to go about this was a rim lighting shader that has an alpha channel for the rim to create the illusion of points. (I then planned to distribute points (2D texture) evenly along the rest of the surface on a second pass) However, this did not give me even close to the desired effect, and I'm a bit lost as to what I should try next.

I should mention I'm working in Unity, using the Cg/Shaderlab language. I'm not necessarily looking for actual code or anything (although that is welcome) but more of your guys' opinion on how you would go about achieving such an effect.

Any ideas?
Offline , null, 3 Posts, Join Date Jun 2012,  
   Reply With Quote

JamesWild's Avatar
Old (#2)
Draw a grid of grey dots on a black background with an additive blend.

If you have normal maps, use them to shift the UVs around to generate the impression of bunching in seams/etc.
Offline , polygon, 661 Posts, Join Date Nov 2011,  
   Reply With Quote

Xoliul's Avatar
Old (#3)
Hmm, I think it might work if you use something like modulo on the world coordinates, to divide the thing into a grid. Then your could set the opacity (or color if you use additive blending) for each grid point. The hard thing is probably controlling the size of the point, might have to use some extra math on top, I'm thinking something like get distance values to the closest grid point, so you will get like radial gradients, and then just perform a step on those to control the size...

Hope it makes some sense?
Offline , card carrying polycounter, 2,432 Posts, Join Date Oct 2008, Location London, UK Send a message via MSN to Xoliul  
   Reply With Quote

Ace-Angel's Avatar
Old (#4)
I would use a texture, and have it tiled, have it face the camera, all on the mesh at Pixel Shader level.

Also, pending on engine, you should also be able to get the depth distance, to make things up close brighter, and those further away darker, although at 2.0 level, I'm not sure how much math you can push before falling off.
There's a very good chance that I experienced MORE problems, then all the internet put together in the area of 3D. Talk about being original for once...
Offline , veteran polycounter, 4,501 Posts, Join Date Apr 2011, Location Canada  
   Reply With Quote

Gestalt's Avatar
Old (#5)
3d texture? using masked opacity? UDK comes with shader functions that describe projecting 3d textures if you want to see an implementation. You could project the same repeating dotted texture along each axis and have them add together and clamp to represent where all intersect or something (idk just a thought). edit: you'd probably multiply them

Last edited by Gestalt; 06-15-2012 at 02:26 PM..
"Not all those who wander are lost"
Offline , triangle, 301 Posts, Join Date Nov 2011,  
   Reply With Quote

Xoliul's Avatar
Old (#6)
Some proper math is much easier guys
Here you go, this works:

Quote:
float scale = 0.5;
float3 grid = float3(0,0,0);
float3 pos = In.worldposition.xyz;

grid.x = fmod(pos.x,scale);
grid.y = fmod(pos.y,scale);
grid.z = fmod(pos.z,scale);

float dotsize = 0.2;
float3 input1 = step(length(grid),dotsize);

float4 ret = float4(1,1,1, input1);
That's a pixel shader, make sure to feed in a proper worldposition ( = mul(In.position, WorldMatrix) )

scale determines the spacing of grid points, dotsize is the size of dots. That last one is really dependant on distance, as I expected it becomes a jittery mess easily...

edit: you can use UV-space as well, instead of world space. It doesn't look great on curved meshes, since some pixels can fall between the grid. Disadvantage of UV space is your UV density will cause scaling to be all over the place...

Last edited by Xoliul; 06-15-2012 at 07:04 PM..
Offline , card carrying polycounter, 2,432 Posts, Join Date Oct 2008, Location London, UK Send a message via MSN to Xoliul  
   Reply With Quote

Ace-Angel's Avatar
Old (#7)
Correct me if I'm wrong, but I thought the Length function is not available on the iOS, so they would need to calculate it manually?

IIRC, this is how it would be;

Length = Square Root (X^2 + Y^2 + Z^2)

Correct me if I'm wrong.
There's a very good chance that I experienced MORE problems, then all the internet put together in the area of 3D. Talk about being original for once...
Offline , veteran polycounter, 4,501 Posts, Join Date Apr 2011, Location Canada  
   Reply With Quote

Xoliul's Avatar
Old (#8)
I have no clue, never worked with IOS before. It can't be a true PS2.0 implementation if it doesn't have basic functions like that though...
Offline , card carrying polycounter, 2,432 Posts, Join Date Oct 2008, Location London, UK Send a message via MSN to Xoliul  
   Reply With Quote

Ace-Angel's Avatar
Old (#9)
I know UDK doesn't have have it declared, so you need to declare it manually (at least for the IOS platform) from my past experience.

Either way, thanks for the math, looks awesome.
There's a very good chance that I experienced MORE problems, then all the internet put together in the area of 3D. Talk about being original for once...
Offline , veteran polycounter, 4,501 Posts, Join Date Apr 2011, Location Canada  
   Reply With Quote

Xoliul's Avatar
Old (#10)
I put a little more effort in this, now it works by actually projecting points onto a surface (based on the normal), so it works with eveyrthing.

Quote:
float scale = 0.7;
float3 grid = float3(0,0,0);
float3 pos = In.worldposition.xyz ;

grid.x = fmod(pos.x,scale);
grid.y = fmod(pos.y,scale);
grid.z = fmod(pos.z,scale);


float zgrid = length(grid.xy);
float xgrid = length(grid.yz);
float ygrid = length(grid.xz);

float3 normal = In.worldNormal;
float nyblend = abs(normal.y);
float nzblend = abs(normal.z);

float dotsize = 0.1;
float3 result = step(lerp(lerp(xgrid,ygrid,nyblend),zgrid, nzblend),dotsize);

float4 ret = float4(1, result);
return ret;
Need to pass in the world normal obviously. It's still a bit sloppy where for curved objects the scale and point size isn't uniform, that just comes down to using something more elegant than just the vector length.

Edit: here's the FX: https://dl.dropbox.com/u/12093849/dump/pointcloud.fx

Last edited by Xoliul; 06-16-2012 at 07:47 AM..
Offline , card carrying polycounter, 2,432 Posts, Join Date Oct 2008, Location London, UK Send a message via MSN to Xoliul  
   Reply With Quote

JRoman's Avatar
Old (#11)
Wow you guys are awesome! First and foremost, thank you all for the helpful replies and suggestions.

Xoliul, I'm incredibly grateful for your help with achieving this result, and even going as far as improving it and sharing your work. Besides what I've learned in the past 2 weeks from tutorials and experimentation I'm brand new to this so I really appreciate your help.

That being said, I have loaded the .fx file into Max and started playing around with it. It's very very close to effect I'm looking for! At this time I'm attempting to get this working in Unity and then I'm planning on trying to control the size (and possibly color) of the dots by screen distance. Our level designer has some experience with shaders so I'm hoping he'll be able to help with this. Regardless, this is a great start and it's looking awesome. Thank you!

One more question; do you guys have any suggestions for further reading/learning shaders? I've been drudging through the Cg Tutorial provided by nVidia, but it has been a fairly steep learning curve for an artist with zero C/C++/C# experience. Slowly but surely I'm getting my head wrapped around it, but if there's an easier-for-newbs solution that anyone has experience with I'd love to hear about it.

Thanks again!
Offline , null, 3 Posts, Join Date Jun 2012,  
   Reply With Quote

Xoliul's Avatar
Old (#12)
I'm planning on writing exactly what you are after sometime, when I have time That doesn't help you too much now, but there's a simple article about colormath on my site already. There's also a shader DVD by Eat3D.
Offline , card carrying polycounter, 2,432 Posts, Join Date Oct 2008, Location London, UK Send a message via MSN to Xoliul  
   Reply With Quote

jerry's Avatar
Old (#13)
Hi,

I had some fun converting this to a shader you can use in Unity3D. One strange issue is that the dots aren't dots but quarter circles. I'm not as smart as Xoliul so maybe he knows what's going on.

Preview:




Download package with shader and material: Download

Would be fun to expand on this.
while(true){ MakeArt(); }
Offline , triangle, 353 Posts, Join Date Oct 2006, Location Shanghai  
   Reply With Quote

CrazyButcher's Avatar
Old (#14)
Code:
float zgrid = length(grid.xy - 0.5 * scale);
float xgrid = length(grid.yz - 0.5 * scale);
float ygrid = length(grid.xz - 0.5 * scale);
should give you points,

fmod basically chops values into segments each of the length [0,scale], the grid coordinates. Think of tiles, every tile has a local x,y axis. points within a tile go from (0,0) in one corner (scale,scale) to the other diagonal corner.

The length operation done gives you distance from origin 0,0. Because every tile has its origin in one corner, and every tile starts "freshly" you only see one quadrant.

With the step function at the end you get 1 or 0 depending if length (distance to origin) is smaller than the threshold provided (dotsize).

The code above basically ensures the origin is at center of the tile (half the tile size), therefore should give you all quadrants in the coordinate system of each tile = circles.


Depending on the normal one "tile wall" is chosen (facing x,y or z).

Last edited by CrazyButcher; 06-19-2012 at 10:47 AM..
3dsmax scripts and .fx - pixeljetstream - expressing my own opinions
Offline , dedicated polycounter, 1,346 Posts, Join Date Nov 2004, Location Germany Send a message via ICQ to CrazyButcher  
   Reply With Quote

Xoliul's Avatar
Old (#15)
yeah i know, i didn't really bother making them circles, because I though they'd be so small you wouldn't notice. Like I said, it's all a bit sloppy but it showed the point.

I tried CrazyButcher's edit and it's not working 100%, it needs an extra abs() thrown in, so the correct code for dots would be :

Quote:
float zgrid = length(abs(grid.xy) - (0.5 * scale));
float xgrid = length(abs(grid.yz) - (0.5 * scale));
float ygrid = length(abs(grid.xz) - (0.5 * scale));
This is fun

Oh and Jerry, cool to see you here again. Nice job converting! How much work is that for Unity ? I'm not familiar with their shader system/language.
Offline , card carrying polycounter, 2,432 Posts, Join Date Oct 2008, Location London, UK Send a message via MSN to Xoliul  
   Reply With Quote

jerry's Avatar
Old (#16)
Updated the package with circle dots: Download

Converting to Unity wasn't that bad, it can have blocks of CG code inside the shader files so it's pretty straightforward. I just had to look up how to get the worldnormal and worldpos and added the parameters for the inspector etc.
while(true){ MakeArt(); }
Offline , triangle, 353 Posts, Join Date Oct 2006, Location Shanghai  
   Reply With Quote

JRoman's Avatar
Old (#17)
Jerry, CrazyButcher, Xoliul! Thank you!

Jerry, I just realized I never replied to this so I wanted to make sure you knew how much I appreciated you helping me out with this. Your code conversion has been a great help in understanding the differences in Cg code, thank you for taking the time to do this.
Offline , null, 3 Posts, Join Date Jun 2012,  
   Reply With Quote

Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Copyright 1998-2012 A. Risch