MCPcopy Create free account
hub / github.com/Theverat/NormalmapGenerator / calculateNormalmap

Method calculateNormalmap

src_generators/normalmapgenerator.cpp:34–114  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

32}
33
34QImage NormalmapGenerator::calculateNormalmap(const QImage& input, Kernel kernel, double strength, bool invert, bool tileable,
35 bool keepLargeDetail, int largeDetailScale, double largeDetailHeight) {
36 this->tileable = tileable;
37
38 this->intensity = IntensityMap(input, mode, useRed, useGreen, useBlue, useAlpha);
39 if(!invert) {
40 // The default "non-inverted" normalmap looks wrong in renderers,
41 // so I use inversion by default
42 intensity.invert();
43 }
44
45 QImage result(input.width(), input.height(), QImage::Format_ARGB32);
46
47 // optimization
48 double strengthInv = 1.0 / strength;
49
50 #pragma omp parallel for // OpenMP
51 //code from http://stackoverflow.com/a/2368794
52 for(int y = 0; y < input.height(); y++) {
53 QRgb *scanline = (QRgb*) result.scanLine(y);
54
55 for(int x = 0; x < input.width(); x++) {
56
57 const double topLeft = intensity.at(handleEdges(x - 1, input.width()), handleEdges(y - 1, input.height()));
58 const double top = intensity.at(handleEdges(x - 1, input.width()), handleEdges(y, input.height()));
59 const double topRight = intensity.at(handleEdges(x - 1, input.width()), handleEdges(y + 1, input.height()));
60 const double right = intensity.at(handleEdges(x, input.width()), handleEdges(y + 1, input.height()));
61 const double bottomRight = intensity.at(handleEdges(x + 1, input.width()), handleEdges(y + 1, input.height()));
62 const double bottom = intensity.at(handleEdges(x + 1, input.width()), handleEdges(y, input.height()));
63 const double bottomLeft = intensity.at(handleEdges(x + 1, input.width()), handleEdges(y - 1, input.height()));
64 const double left = intensity.at(handleEdges(x, input.width()), handleEdges(y - 1, input.height()));
65
66 const double convolution_kernel[3][3] = {{topLeft, top, topRight},
67 {left, 0.0, right},
68 {bottomLeft, bottom, bottomRight}};
69
70 QVector3D normal(0, 0, 0);
71
72 if(kernel == SOBEL)
73 normal = sobel(convolution_kernel, strengthInv);
74 else if(kernel == PREWITT)
75 normal = prewitt(convolution_kernel, strengthInv);
76
77 scanline[x] = qRgb(mapComponent(normal.x()), mapComponent(normal.y()), mapComponent(normal.z()));
78 }
79 }
80
81 if(keepLargeDetail) {
82 //generate a second normalmap from a downscaled input image, then mix both normalmaps
83
84 int largeDetailMapWidth = (int) (((double)input.width() / 100.0) * largeDetailScale);
85 int largeDetailMapHeight = (int) (((double)input.height() / 100.0) * largeDetailScale);
86
87 //create downscaled version of input
88 QImage inputScaled = input.scaled(largeDetailMapWidth, largeDetailMapHeight, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
89 //compute downscaled normalmap
90 QImage largeDetailMap = calculateNormalmap(inputScaled, kernel, largeDetailHeight, invert, tileable, false, 0, 0.0);
91 //scale map up

Callers 1

calcNormalMethod · 0.80

Calls 3

IntensityMapClass · 0.85
invertMethod · 0.80
atMethod · 0.80

Tested by

no test coverage detected