commit 1a7f735de69ab7a15c8882be01da6e3fcb257e51
parent 6534f3bef1dbee2a6f00f12cb9783d6ff3dadf8c
Author: Michael Savage <mikejsavage@gmail.com>
Date: Sat, 4 Nov 2017 14:40:18 +0200
Sobel filter normalmap in pp2
Diffstat:
pp2.cc | | | 71 | ++++++++++++++++++++++++++++++++++++++++++++++++----------------------- |
1 file changed, 48 insertions(+), 23 deletions(-)
diff --git a/pp2.cc b/pp2.cc
@@ -58,32 +58,57 @@ static void compute_horizons(
}
}
+static v3 simple_normal( const array2d< u16 > heightmap, size_t x, size_t y ) {
+ size_t x_plus_one = x + 1;
+ size_t x_minus_one = x - 1;
+ size_t y_plus_one = y + 1;
+ size_t y_minus_one = y - 1;
+
+ if( x == 0 ) x_minus_one = x;
+ if( x == heightmap.w - 1 ) x_plus_one = x;
+ if( y == 0 ) y_minus_one = y;
+ if( y == heightmap.h - 1 ) y_plus_one = y;
+
+ v3 tangent(
+ checked_cast< float >( x_plus_one - x_minus_one ),
+ 0,
+ heightmap( x_plus_one, y ) / 256.0f - heightmap( x_minus_one, y ) / 256.0f );
+ v3 bitangent(
+ 0,
+ checked_cast< float >( y_plus_one - y_minus_one ),
+ heightmap( x, y_plus_one ) / 256.0f - heightmap( x, y_minus_one ) / 256.0f );
+
+ return normalize( cross( tangent, bitangent ) );
+}
+
+static v3 compute_normal( const array2d< u16 > heightmap, size_t x, size_t y ) {
+ if( x == 0 || x == heightmap.w - 1 || y == 0 || y == heightmap.h - 1 ) {
+ return simple_normal( heightmap, x, y );
+ }
+
+ float mm = heightmap( x - 1, y - 1 ) / 256.0f;
+ float me = heightmap( x - 1, y + 0 ) / 256.0f;
+ float mp = heightmap( x - 1, y + 1 ) / 256.0f;
+ float em = heightmap( x + 0, y - 1 ) / 256.0f;
+ // float ee = heightmap( x + 0, y + 0 ) / 256.0f;
+ float ep = heightmap( x + 0, y + 1 ) / 256.0f;
+ float pm = heightmap( x + 1, y - 1 ) / 256.0f;
+ float pe = heightmap( x + 1, y + 0 ) / 256.0f;
+ float pp = heightmap( x + 1, y + 1 ) / 256.0f;
+
+ float grad_y = -( mm + 2.0f * em + pm - ( mp + 2.0f * ep + pp ) ) / 8.0f;
+ float grad_x = -( mm + 2.0f * me + mp - ( pm + 2.0f * pe + pp ) ) / 8.0f;
+
+ v3 tangent = v3( 1, 0, grad_x );
+ v3 bitangent = v3( 0, 1, grad_y );
+
+ return normalize( cross( tangent, bitangent ) );
+}
+
static void compute_normals( const array2d< u16 > heightmap, array2d< v3 > normals ) {
- // TODO: sobel operator?
- // estimate the gradient at each point by doing central differences on
- // each axis, then cross the tangent and bitangent to find the normal
for( size_t y = 0; y < heightmap.h; y++ ) {
for( size_t x = 0; x < heightmap.w; x++ ) {
- size_t x_plus_one = x + 1;
- size_t x_minus_one = x - 1;
- size_t y_plus_one = y + 1;
- size_t y_minus_one = y - 1;
-
- if( x == 0 ) x_minus_one = x;
- if( x == heightmap.w - 1 ) x_plus_one = x;
- if( y == 0 ) y_minus_one = y;
- if( y == heightmap.h - 1 ) y_plus_one = y;
-
- v3 tangent(
- checked_cast< float >( x_plus_one - x_minus_one ),
- 0,
- heightmap( x_plus_one, y ) / 256.0f - heightmap( x_minus_one, y ) / 256.0f );
- v3 bitangent(
- 0,
- checked_cast< float >( y_plus_one - y_minus_one ),
- heightmap( x, y_plus_one ) / 256.0f - heightmap( x, y_minus_one ) / 256.0f );
-
- normals( x, y ) = normalize( cross( tangent, bitangent ) );
+ normals( x, y ) = compute_normal( heightmap, x, y );
}
}
}