Hi,
When we gather the 4 pixels used in bilinear sampling, shouldn't we pick different pixels based on where the sampling position is in the pixel ?
If I want the bilinear value of a pixel at ( 10, 20 ), with UV coordinates of ( 10.1, 20.1 ) when they are multiplied by the width and height of the texture; shouldn't the 4 samples be at ( 10, 20 ), ( 9, 20 ), ( 10, 19 ), ( 9, 19 ) instead of ( 10, 20 ), ( 11, 20 ), ( 10, 21 ), ( 11, 21 ) ?
What I mean is: if the sampling position in a pixel (real position - integer position) is :
- < 0.5 on x => sample left
- >= 0.5 on x => sample right
- < 0.5 on y => sample down
- >= 0.5 on y => sample up
If it helps to understand my question here's some code to illustrate my idea:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 | inline u32 bilinearSample( Bitmap* bitmap, Vector2 uv ) {
f32 pixelRealX = uv.u * bitmap->width;
f32 pixelRealY = uv.v * bitmap->height;
u32 pixelX = ( u32 ) pixelRealX;
u32 pixelY = ( u32 ) pixelRealY;
f32 offsetX = pixelRealX - pixelX;
f32 offsetY = pixelRealY - pixelY;
s32 pixelOffsetX = 1;
s32 pixelOffsetY = 1;
if ( offsetX < 0.5f ) {
pixelOffsetX = -1;
offsetX = 0.5f - offsetX;
} else {
offsetX = offsetX - 0.5f;
}
if ( offsetY < 0.5f ) {
pixelOffsetY = -1;
offsetY = 0.5f - offsetY;
} else {
offsetY = offsetY - 0.5f;
}
if ( pixelX + pixelOffsetX < 0 || pixelX + pixelOffsetX > bitmap->width ) {
pixelOffsetX = 0;
offsetX = 0.5f;
}
if ( pixelY + pixelOffsetY < 0 || pixelY + pixelOffsetY > bitmap->width ) {
pixelOffsetY = 0;
offsetY = 0.5f;
}
Vector4 pixelA = integerColorToV4( *( u32* ) ( bitmap->pixels + bitmap->pitch * pixelY + bitmap->bytesPerPixel * pixelX ) );
Vector4 pixelB = integerColorToV4( *( u32* ) ( bitmap->pixels + bitmap->pitch * pixelY + bitmap->bytesPerPixel * ( pixelX + pixelOffsetX ) ) );
Vector4 pixelC = integerColorToV4( *( u32* ) ( bitmap->pixels + bitmap->pitch * ( pixelY + pixelOffsetY ) + bitmap->bytesPerPixel * pixelX ) );
Vector4 pixelD = integerColorToV4( *( u32* ) ( bitmap->pixels + bitmap->pitch * ( pixelY + pixelOffsetY ) + bitmap->bytesPerPixel * ( pixelX + pixelOffsetX ) ) );
Vector4 pixel = lerp(
lerp( pixelA, pixelB, offsetX ),
lerp( pixelC, pixelD, offsetX ),
offsetY
);
u32 result = v4ColorToInteger( pixel );
return result;
}
|