Browse Source

add Image::bumpmap_to_normalmap conversion function

Neil Graham 7 years ago
parent
commit
bc7db7a08d
2 changed files with 43 additions and 0 deletions
  1. 42 0
      core/image.cpp
  2. 1 0
      core/image.h

+ 42 - 0
core/image.cpp

@@ -2271,6 +2271,7 @@ void Image::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("premultiply_alpha"), &Image::premultiply_alpha);
 	ClassDB::bind_method(D_METHOD("srgb_to_linear"), &Image::srgb_to_linear);
 	ClassDB::bind_method(D_METHOD("normalmap_to_xy"), &Image::normalmap_to_xy);
+	ClassDB::bind_method(D_METHOD("bumpmap_to_normalmap","bump_scale"), &Image::bumpmap_to_normalmap, DEFVAL(1.0));
 
 	ClassDB::bind_method(D_METHOD("blit_rect", "src", "src_rect", "dst"), &Image::blit_rect);
 	ClassDB::bind_method(D_METHOD("blit_rect_mask", "src", "mask", "src_rect", "dst"), &Image::blit_rect_mask);
@@ -2379,6 +2380,47 @@ void Image::normalmap_to_xy() {
 	convert(Image::FORMAT_LA8);
 }
 
+void Image::bumpmap_to_normalmap(float bump_scale) {
+	ERR_FAIL_COND(!_can_modify(format));
+	convert(Image::FORMAT_RF);
+
+	PoolVector<uint8_t> result_image;  //rgba output
+	result_image.resize(width * height* 4);
+
+	{
+		PoolVector<uint8_t>::Read rp = data.read();
+		PoolVector<uint8_t>::Write wp = result_image.write();
+
+		unsigned char *write_ptr = wp.ptr();
+		float *read_ptr = (float*) rp.ptr();
+
+		for (int ty = 0; ty < height; ty++) {
+			int py = ty+1;
+			if (py >= height) py-=height;
+
+			for (int tx = 0; tx < width; tx++) {
+				int px=tx+1;
+				if (px >= width) px-=width;
+				float here = read_ptr[ty*width + tx];
+				float to_right= read_ptr[ty*width + px];
+				float above= read_ptr[py*width + tx];
+				Vector3 up = Vector3(0,1,(here-above)*bump_scale);
+				Vector3 across = Vector3(1,0,(to_right-here)*bump_scale);
+
+				Vector3 normal = across.cross(up);
+				normal.normalize();
+
+				write_ptr[ ((ty*width + tx) <<2) +0 ]= (128.0 + normal.x * 127.0);
+				write_ptr[ ((ty*width + tx) <<2) +1 ]= (128.0 + normal.y * 127.0);
+				write_ptr[ ((ty*width + tx) <<2) +2 ]= (128.0 + normal.z * 127.0);
+				write_ptr[ ((ty*width + tx) <<2) +3 ]= 255;
+			}
+		}
+	}
+	format=FORMAT_RGBA8;
+	data=result_image;
+}
+
 void Image::srgb_to_linear() {
 
 	if (data.size() == 0)

+ 1 - 0
core/image.h

@@ -284,6 +284,7 @@ public:
 	void premultiply_alpha();
 	void srgb_to_linear();
 	void normalmap_to_xy();
+	void bumpmap_to_normalmap(float bump_scale=1.0);
 
 	void blit_rect(const Ref<Image> &p_src, const Rect2 &p_src_rect, const Point2 &p_dest);
 	void blit_rect_mask(const Ref<Image> &p_src, const Ref<Image> &p_mask, const Rect2 &p_src_rect, const Point2 &p_dest);