blob: 543a09504b297d2b6e8e83b9a96f9586ac5acfb1 [file] [log] [blame]
import 'dart:math';
import '../color.dart';
import '../image.dart';
/// Generate a normal map from a heightfield bump image.
///
/// The red channel of the [src] image is used as an input, 0 represents a low
/// height and 1 a high value. The optional [strength] parameter allows to set
/// the strength of the normal image.
Image bumpToNormal(Image src, {double strength = 2.0}) {
Image dest = Image.from(src);
for (var y = 0; y < src.height; ++y) {
for (var x = 0; x < src.width; ++x) {
final height = getRed(src.getPixel(x, y)) / 255.0;
var du = (height -
getRed(src.getPixel(x < src.width - 1 ? x + 1 : x, y)) / 255.0) *
strength;
var dv = (height -
getRed(src.getPixel(x, y < src.height - 1 ? y + 1 : y)) / 255.0) *
strength;
final z = du.abs() + dv.abs();
if (z > 1) {
du /= z;
dv /= z;
}
final dw = sqrt(1.0 - du * du - dv * dv);
final nX = du * 0.5 + 0.5;
final nY = dv * 0.5 + 0.5;
final nZ = dw;
dest.setPixelRGBA(
x, y, (255 * nX).floor(), (255 * nY).floor(), (255 * nZ).floor());
}
}
return dest;
}