Path: blob/master/thirdparty/msdfgen/core/render-sdf.cpp
9903 views
1#include "render-sdf.h"23#include "arithmetics.hpp"4#include "DistanceMapping.h"5#include "pixel-conversion.hpp"6#include "bitmap-interpolation.hpp"78namespace msdfgen {910static float distVal(float dist, DistanceMapping mapping) {11return (float) clamp(mapping(dist)+.5);12}1314void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 1> &sdf, Range sdfPxRange, float sdThreshold) {15Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height);16if (sdfPxRange.lower == sdfPxRange.upper) {17for (int y = 0; y < output.height; ++y) {18for (int x = 0; x < output.width; ++x) {19float sd;20interpolate(&sd, sdf, scale*Point2(x+.5, y+.5));21*output(x, y) = float(sd >= sdThreshold);22}23}24} else {25sdfPxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height);26DistanceMapping distanceMapping = DistanceMapping::inverse(sdfPxRange);27float sdBias = .5f-sdThreshold;28for (int y = 0; y < output.height; ++y) {29for (int x = 0; x < output.width; ++x) {30float sd;31interpolate(&sd, sdf, scale*Point2(x+.5, y+.5));32*output(x, y) = distVal(sd+sdBias, distanceMapping);33}34}35}3637}3839void renderSDF(const BitmapRef<float, 3> &output, const BitmapConstRef<float, 1> &sdf, Range sdfPxRange, float sdThreshold) {40Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height);41if (sdfPxRange.lower == sdfPxRange.upper) {42for (int y = 0; y < output.height; ++y) {43for (int x = 0; x < output.width; ++x) {44float sd;45interpolate(&sd, sdf, scale*Point2(x+.5, y+.5));46float v = float(sd >= sdThreshold);47output(x, y)[0] = v;48output(x, y)[1] = v;49output(x, y)[2] = v;50}51}52} else {53sdfPxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height);54DistanceMapping distanceMapping = DistanceMapping::inverse(sdfPxRange);55float sdBias = .5f-sdThreshold;56for (int y = 0; y < output.height; ++y) {57for (int x = 0; x < output.width; ++x) {58float sd;59interpolate(&sd, sdf, scale*Point2(x+.5, y+.5));60float v = distVal(sd+sdBias, distanceMapping);61output(x, y)[0] = v;62output(x, y)[1] = v;63output(x, y)[2] = v;64}65}66}67}6869void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 3> &sdf, Range sdfPxRange, float sdThreshold) {70Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height);71if (sdfPxRange.lower == sdfPxRange.upper) {72for (int y = 0; y < output.height; ++y) {73for (int x = 0; x < output.width; ++x) {74float sd[3];75interpolate(sd, sdf, scale*Point2(x+.5, y+.5));76*output(x, y) = float(median(sd[0], sd[1], sd[2]) >= sdThreshold);77}78}79} else {80sdfPxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height);81DistanceMapping distanceMapping = DistanceMapping::inverse(sdfPxRange);82float sdBias = .5f-sdThreshold;83for (int y = 0; y < output.height; ++y) {84for (int x = 0; x < output.width; ++x) {85float sd[3];86interpolate(sd, sdf, scale*Point2(x+.5, y+.5));87*output(x, y) = distVal(median(sd[0], sd[1], sd[2])+sdBias, distanceMapping);88}89}90}91}9293void renderSDF(const BitmapRef<float, 3> &output, const BitmapConstRef<float, 3> &sdf, Range sdfPxRange, float sdThreshold) {94Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height);95if (sdfPxRange.lower == sdfPxRange.upper) {96for (int y = 0; y < output.height; ++y) {97for (int x = 0; x < output.width; ++x) {98float sd[3];99interpolate(sd, sdf, scale*Point2(x+.5, y+.5));100output(x, y)[0] = float(sd[0] >= sdThreshold);101output(x, y)[1] = float(sd[1] >= sdThreshold);102output(x, y)[2] = float(sd[2] >= sdThreshold);103}104}105} else {106sdfPxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height);107DistanceMapping distanceMapping = DistanceMapping::inverse(sdfPxRange);108float sdBias = .5f-sdThreshold;109for (int y = 0; y < output.height; ++y) {110for (int x = 0; x < output.width; ++x) {111float sd[3];112interpolate(sd, sdf, scale*Point2(x+.5, y+.5));113output(x, y)[0] = distVal(sd[0]+sdBias, distanceMapping);114output(x, y)[1] = distVal(sd[1]+sdBias, distanceMapping);115output(x, y)[2] = distVal(sd[2]+sdBias, distanceMapping);116}117}118}119}120121void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 4> &sdf, Range sdfPxRange, float sdThreshold) {122Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height);123if (sdfPxRange.lower == sdfPxRange.upper) {124for (int y = 0; y < output.height; ++y) {125for (int x = 0; x < output.width; ++x) {126float sd[4];127interpolate(sd, sdf, scale*Point2(x+.5, y+.5));128*output(x, y) = float(median(sd[0], sd[1], sd[2]) >= sdThreshold);129}130}131} else {132sdfPxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height);133DistanceMapping distanceMapping = DistanceMapping::inverse(sdfPxRange);134float sdBias = .5f-sdThreshold;135for (int y = 0; y < output.height; ++y) {136for (int x = 0; x < output.width; ++x) {137float sd[4];138interpolate(sd, sdf, scale*Point2(x+.5, y+.5));139*output(x, y) = distVal(median(sd[0], sd[1], sd[2])+sdBias, distanceMapping);140}141}142}143}144145void renderSDF(const BitmapRef<float, 4> &output, const BitmapConstRef<float, 4> &sdf, Range sdfPxRange, float sdThreshold) {146Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height);147if (sdfPxRange.lower == sdfPxRange.upper) {148for (int y = 0; y < output.height; ++y) {149for (int x = 0; x < output.width; ++x) {150float sd[4];151interpolate(sd, sdf, scale*Point2(x+.5, y+.5));152output(x, y)[0] = float(sd[0] >= sdThreshold);153output(x, y)[1] = float(sd[1] >= sdThreshold);154output(x, y)[2] = float(sd[2] >= sdThreshold);155output(x, y)[3] = float(sd[3] >= sdThreshold);156}157}158} else {159sdfPxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height);160DistanceMapping distanceMapping = DistanceMapping::inverse(sdfPxRange);161float sdBias = .5f-sdThreshold;162for (int y = 0; y < output.height; ++y) {163for (int x = 0; x < output.width; ++x) {164float sd[4];165interpolate(sd, sdf, scale*Point2(x+.5, y+.5));166output(x, y)[0] = distVal(sd[0]+sdBias, distanceMapping);167output(x, y)[1] = distVal(sd[1]+sdBias, distanceMapping);168output(x, y)[2] = distVal(sd[2]+sdBias, distanceMapping);169output(x, y)[3] = distVal(sd[3]+sdBias, distanceMapping);170}171}172}173}174175void simulate8bit(const BitmapRef<float, 1> &bitmap) {176const float *end = bitmap.pixels+1*bitmap.width*bitmap.height;177for (float *p = bitmap.pixels; p < end; ++p)178*p = pixelByteToFloat(pixelFloatToByte(*p));179}180181void simulate8bit(const BitmapRef<float, 3> &bitmap) {182const float *end = bitmap.pixels+3*bitmap.width*bitmap.height;183for (float *p = bitmap.pixels; p < end; ++p)184*p = pixelByteToFloat(pixelFloatToByte(*p));185}186187void simulate8bit(const BitmapRef<float, 4> &bitmap) {188const float *end = bitmap.pixels+4*bitmap.width*bitmap.height;189for (float *p = bitmap.pixels; p < end; ++p)190*p = pixelByteToFloat(pixelFloatToByte(*p));191}192193}194195196