Not there yet? Post your work in progress here to receive feedback from the users.
By jfrancis
#389986
Image

I was curious to see what would happen if I could get the gray level of the brush to be a function of the 2D direction of travel across the screen. I didn't know of any paint programs that would allow that, so I made a crude one using Processing 3 (at which I'm just beginning to learn)

If I understand Maxwell's anisotropic angle maps, black and white are basically the same angle, but beyond that, and the classic 'cafe table' texture I'm not that sure how to control them.

Image
Original

Image
Somewhat blurred before rendering
By jfrancis
#389987
int oldX = mouseX;
int oldY = mouseY;
int backCol = 127;
int brushCol = backCol;

void setup()
{
size(1024, 1024);
background(backCol);
fill(backCol);
strokeWeight(50);

}

void draw()
{
float dx = mouseX - oldX;
float dy = -1 * (mouseY - oldY);
if ((dx!=0) || (dy!=0))
{
float mouseTravelAngle = atan2(dy,dx) / PI;
if (mouseTravelAngle < 0.)
{
mouseTravelAngle = 1. + (1. - abs(mouseTravelAngle));
}
brushCol = (int) (255. * mouseTravelAngle / 2.);
}

stroke(brushCol);
if (mousePressed) {
line(oldX, oldY, mouseX, mouseY);
}
oldX = mouseX;
oldY = mouseY;
}

void keyReleased() {
saveFrame();
}
By jfrancis
#389988
It's not that sophisticated in programming style. Still learning.

Draw with the pen. Hit a key and on its release you'll save an image to disk.

Not sure how useful it is, but I wanted to see.

With some tweaking it could produce grass angle maps, I guess, if there isn't already a better solution.
By jfrancis
#389989
Image
Grass Map

Image
Maxwell Grass

-----------------------------------------
Some more klunky Processing code
-----------------------------------------

int oldX = mouseX;
int oldY = mouseY;
int brushR = 127;
int brushG = 127;
int brushB = 127;

void setup()
{
size(1024, 1024);
background(brushR, brushG, brushB);
stroke(brushR, brushG, brushB);
strokeWeight(70);

}

void draw()
{
float dx = mouseX - oldX;
float dy = mouseY - oldY;
float magnitude = sqrt(dx*dx+dy*dy);
float nx = 0.5 * dx / magnitude + 0.5;
brushR = (int) (255 * nx);
float ny = 0.5 * dy / magnitude + 0.5;
brushB = (int) (255 * ny);




stroke(brushR, brushG, brushB);
if (mousePressed) {
line(oldX, oldY, mouseX, mouseY);
}
oldX = mouseX;
oldY = mouseY;
}

void keyReleased() {
saveFrame();
}
#389996
jfrancis, are you aware that normal maps convert to angle maps? (swap the colour channels over) although that doesn't really relate to this technique which is quite different.

I wish there was a magical anglemap creation filter which, for example, could detect the woodgrain direction in a texture, but I cant even imagine how that would work. Whoever invented anglemaps (was it NL?) should provide a solution.. grumble grumble.
#390352
I made some nice aniso scratchmaps with the help of this program, thanks.

There is a small bug, in that you have to flip the mapping in X to achieve the right angles.

I changed the code so that you draw in a blue colour on a red background, then I can use darker colour as a clone method in PS to get a tileable map. By using red and blue I can save the red channel as the weightmap for the scratches and the blue channel as the angle map. (actually I do it in reverse - painting red onto blue, to save my eyes, and then I flip the channels in PS before cloning)

I also changed the code to only save the image if the s key is pressed, to make it run smoother.

I wanted to add an undo function but it was too hard for me to work it out, (I dont touch code normally)

Here is the map; http://www.mediafire.com/download/ck5z3 ... atches.psd

Render is fast, bench over 1000, scratches are well defined around sl 8-10

Image

int oldX = mouseX;
int oldY = mouseY;
int backCol = color(0, 0, 255);
int brushCol = backCol;

void setup()
{
size(1500, 1500);
background(backCol);
fill(backCol);
strokeWeight(2);

}

void draw()
{
float dx = mouseX - oldX;
float dy = -1 * (mouseY - oldY);
if ((dx!=0) || (dy!=0))
{
float mouseTravelAngle = atan2(dy,dx) / PI;
if (mouseTravelAngle < 0.)
{
mouseTravelAngle = 1. + (1. - abs(mouseTravelAngle));
}
brushCol = (int) color((255. * mouseTravelAngle / 2.), 0, 0);
}

stroke(brushCol);
if (mousePressed) {
line(oldX, oldY, mouseX, mouseY);
}
oldX = mouseX;
oldY = mouseY;
}

void keyReleased() {

if (key=='s') {
saveFrame();
}
}
#390372
Here is another revision; this version randomly varies the line width (this time more smoothly, I've edited this post)

int oldX = mouseX;
int oldY = mouseY;
int backCol = color(0, 0, 255);
int brushCol = backCol;


void setup()
{
size(2500, 1250);
background(backCol);
fill(backCol);
}

void draw()
{
float dx = mouseX - oldX;
float dy = -1 * (mouseY - oldY);
if ((dx!=0) || (dy!=0))
{
float mouseTravelAngle = atan2(dy,dx) / PI;
if (mouseTravelAngle < 0.)
{
mouseTravelAngle = 1. + (1. - abs(mouseTravelAngle));
}
brushCol = (int) color((255. * mouseTravelAngle / 2.), 0, 0);
}

stroke(brushCol);
if (mousePressed) {
float r = random(2, 3);
strokeWeight (r);
line(oldX, oldY, mouseX, mouseY);
}
oldX = mouseX;
oldY = mouseY;
}

void keyReleased() {

if (key=='s') {
saveFrame();
}
}
#390380
Thanks, Im no coder either, just using the interactive helper for syntax and googling... hardly changed Francis code.

Found a little gotcha today (hard to call it a bug as my setup was a little bit weird, I put one of my spec bsdf's in the base layer, becasue the base layer is black and so had plenty of 'space' to host bsdf's....), can anyone spot the difference between these renders?

Image
#390402
yeah, you've got some noise issues in your secondary rim reflections. maybe instead of trying to break the system you learn to work with it? i don't see any enhancement between the two other than the "broken" stuff.
render engines and Maxwell

after some more thinking and browsing, I think the[…]

Help with swimming pool water

Hi Andreas " I would say the above "fake[…]