View Full Version : Gradients on perspective projected Images..

Nils Pipenbrinck

03-24-2006, 09:39 AM

There's something I stumbled over while testing some gradients:

The gradients inherit the transform of the objects they are applied to. That makes perfect sense for me. In the spec this is only defined for the pathes, but ok - it makes sense to do the same for images as well.

However, the spec clearly states that paint transforms are affine only, and image transforms might be projective.

Now if I apply a gradient paint on a image drawn with perspective projection I don't know what results to expect. The reference implementation draws something, but it's hard to find out/guess how exactly the gradient should be drawn.

Question:

Do we have to mimic the behaviour of the reference implementation for this special case? After all it's not defined in the spec.

[/*:m:xeh44fix]

If so - how exactly should the gradient sampling work? Do we really have to sample the gradient projective?

[/*:m:xeh44fix]

If we have to sample the gradient affine, how should we get rid of the projective transform?[/*:m:xeh44fix]

Hope someone can help me with these issues. After all - there's little to none traffic on this board..

Thanks,

Nils Pipenbrinck

Nils Pipenbrinck

03-24-2006, 10:00 AM

Here's a bit of code. draws a test image with radial gradient in perspective and affine mode.

void Gradient_WTF (void)

{

VGfloat stops[10] =

{

0, 0.8,0.2,0.1,1,

1, 0.1,0.2,0.8,1,

};

VGfloat gradient[5] =

{

128,128,128,128,60,

};

VGfloat ImageMatrix[9] =

{

-0.4477, 0.8941, 0.0015,

-0.8941, -0.4477, 0.0018,

370, 140, 1,

};

// make checkerboard image:

VGImage img = vgCreateImage (VG_sL_8, 256, 256, VG_IMAGE_QUALITY_BETTER);

for (VGint y=0; y<256; y+=32)

for (VGint x=0; x<256; x+=32)

{

VGfloat white[4] = { 1,1,1,1 };

VGfloat gray[4] = { 0.4,0.4,0.4,1 };

vgSetfv (VG_CLEAR_COLOR, 4, (x^y)&32 ? white:gray);

vgClearImage (img, x,y,32,32);

}

// make paint:

VGPaint paint = vgCreatePaint();

vgSetPaint (paint, VG_FILL_PATH);

vgSetParameteri (paint, VG_PAINT_TYPE, VG_PAINT_TYPE_RADIAL_GRADIENT);

vgSetParameteri (paint, VG_PAINT_COLOR_RAMP_SPREAD_MODE, VG_COLOR_RAMP_SPREAD_REPEAT);

vgSetParameterfv (paint, VG_PAINT_COLOR_RAMP_STOPS, 10, stops);

vgSetParameterfv (paint, VG_PAINT_RADIAL_GRADIENT, 5, gradient);

// draw projective image:

vgSeti (VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY);

vgSeti (VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);

vgLoadMatrix (ImageMatrix);

vgDrawImage (img);

// draw affine image:

vgLoadIdentity ();

vgTranslate (400, 10);

vgDrawImage (img);

vgDestroyImage (img);

vgDestroyPaint (paint);

}

Nils Pipenbrinck

03-30-2006, 03:29 AM

anyone?

Nils Pipenbrinck

03-30-2006, 05:04 AM

Ok - if anyone is ever interested, this is what the reference implementation does:

Projective image matrices become unprojected before multiplication with the paint matrix. The unprojection works like this:

build 3 vectors that form a unit coordinate system in 2d:

vector v[3];

v[0] = vector(0,0);

v[1] = vector(1,0);

v[2] = vector(0,1);

transform these vectors by the image matrix (extend 2d vectors to homogenous 2d vectors by adding an implicit z=1). after transformation divide out the vectors x,y by z.

Then subtract projected origin from projected axis:

v[1] -= v[0];

v[2] -= v[0];

The output matrix directly built from these 3 vectors.

- translational part is equal to v[0],

- first column of upper 2x2 submatrix equals to v[1]

- second column of upper 2x2 submatrix equals to v[2]

- projective part becomes 0, 0, 1 (as usual for affine matrices)

I still scratch my head if this is fine with the standard.

muratmat

03-30-2006, 08:12 AM

...

I still scratch my head if this is fine with the standard.

OpenVG specifications do not clarify the correct behavior for perspective image matrixes coupled with a paint.

For radial gradient, i think that the correct result should be, in your case, that gradient circles had to "fit" (perspectively) the image outline.

Nils Pipenbrinck

03-31-2006, 06:44 AM

...

I still scratch my head if this is fine with the standard.

OpenVG specifications do not clarify the correct behavior for perspective image matrixes coupled with a paint.

For radial gradient, i think that the correct result should be, in your case, that gradient circles had to "fit" (perspectively) the image outline.

Hm..

I doubt that this is intended.. For pattern images that wouldn't be such a big deal since it simplifies down to just a perspective image mapping, but the radial gradients are already hard enough to calculate.

Making them perspective correct would make almost all good optimizations impossible (e.g precomputed dda-method for scanlines).

muratmat

03-31-2006, 08:19 AM

Hm..

I doubt that this is intended.. For pattern images that wouldn't be such a big deal since it simplifies down to just a perspective image mapping, but the radial gradients are already hard enough to calculate.

Making them perspective correct would make almost all good optimizations impossible (e.g precomputed dda-method for scanlines).

I was talking about the correct behaviour that every user could expect, and that i think is the most correct one.

From an implementation point of view, it's normal to accept some compromises to not loose too much speed.

Anyway, i think that guys who wrote OpenVG specifications did not consider a such case, and that's why in my vector graphics framework (Amanith, do you know it?) i left gradient/pattern matrix independent from the "modelview" matrix.

Espen

12-13-2006, 08:26 AM

When there is a projective transform on an image, the image mode falls back to normal mode.

Powered by vBulletin® Version 4.2.5 Copyright © 2018 vBulletin Solutions Inc. All rights reserved.