Contour Shaking

Hey everbody,

I try to implement a contour shaking for Objects.

I got the contours of a box with the cartoonEdgeFilter. Then I made an Image out of the Frambuffer.
Now I iterate over all pixels of the image and try to add an error to each pixel which simulates the shaking, with this function:

y = asin(bx+c)+r

a and b determine the range and period of the error
c is a shift
r is randomness

It should look like in this picture:

But I only get unsatisfying results, which look like this:

My Code:

                   raster = ImageRaster.create(image);
                   ImageRaster rasterDistorted = ImageRaster.create(imageDistorted);
                   ColorRGBA color;
                   Random random = new Random();
                    int randomVal = 0;

                    for (int x = 0; x < 640; x++){
                        
                        for(int y = 0; y < 480;y++){

                            randomVal =  (random.nextInt(6)-3);
                            
                            
                            int yOld = (int)(5 * Math.sin(0.2*y + 1)+ randomVal)+ y;
                            
                            int xOld = (int)(5 * Math.sin(0.2*x + 1)+ randomVal)+ x; 
                            
                           if (xOld > 639) {
                                xOld = 639;
                            }
                            if (xOld < 0) {
                                xOld = 0;
                            } 
                            if (yOld > 479) {
                                yOld = 479;
                            }
                            if (yOld < 0) {
                                yOld = 0;
                            }                       
    
                            color = raster.getPixel(xOld, yOld);
                            rasterDistorted.setPixel(x, y, color);
                            
                        }
                    }

Can someon help me with this problem ?

Where did you get the formula? Some context might be helpful.

In the first sample drawing, I can’t see how the formula would produce those nice results so evenly on both the mostly horizontal and mostly vertical edges. Ah, you use it for x and y… makes more sense.

In your second pic, it looks like things are just too random. What does it look like if you remove randomVal? Also note that with 5*sin you will vary by a full 10 pixels. And using 0.2 as the period multiplier means you go through a full sine cycle in just 30 pixels or so… which seems pretty dramatic to me.

The formula is from a paper:

Real-Time Pencil Rendering

Even if I remove the random value, I didn’t get that the line looks like a sine function:

When I calculate the pixel positions in Excel it looks good:

Therefore I used the values
a = 20
b = 0,05
c = 1
r = -3 to 3

Maybe I have a lack of understanding with the pixel positions…

As I implied, your variance is too high and too fast… so you will skip entire pixels because you’ve compressed them out of the image.

Try varying just the y and you’ll see what I mean… every teeny tiny bump is one that would have potentially been missed if x happened to bump right there also. You actually increased your (a) above which will make it even worse because now the pixels will vary by as much as 40 pixels overall… when something like a=4 (8 variance) is probably more than fine.

Bottom line: you need to start with teeny tiny numbers and slowly increase them to see what affect you get.

Edit: also I suspect the original paper might have been subsampling where as you are hitting discrete pixels. This is the kind of thing that would be better done in a shader, perhaps.

And note… I do know a little about this subject so I’m not just completely guessing…

Regular:

Drawn:

…not exactly the same effect but there are similarities.

4 Likes

Your Scene looks really awesome !

But I think my problem is not because of the values. I tested all kinds of possibilities.

Now I exchanged the y with the x in the function

int yOld = (int)(5 * (Math.sin(0.2 * x + 1)))+ y;

and get these results:

I can see sinusoidal lines but there are still empty spaces in between.

I’m not sure what this “exchange” means. I suggested that you only calculate the y offset. Leave xOld = x;

I can’t be sure what you’ve done with x in the picture so I can only guess.

The issue is that because your variances are high and you are sampling at even pixels then you will have gaps where you don’t pick up any pixels at all. If the black happens to be in those gaps then you will miss stuff.

…actually the bars on the left that are solid black definitely indicate something is wrong with some of your calculations.

With the exchange I mean, for calculating the y values, you need the sin of x and for the x values you need the sin of y.

I now found out, that the bars in the image are beacause of the negativ result of the sin function.
Everytime

5 * (Math.sin(0.2 * x + 1)

gets negativ, I did not get the correct pixel color.

So I tried with the absolute Math function:

                   yOld = Math.abs((int)(4 * (Math.sin(0.03 * x + 1))+ randomValX))+ y;
                   xOld = Math.abs((int)(4 * (Math.sin(0.03 * y + 1)) + randomValY))+ x; 

With these Functions my Box looks like this:

That’s ok, but maybe you have some suggestions to improve it

That’s weird… for negative values to have caused this issue it implies that you are sampling from the same buffer that you are filling.