00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "film.h"
00025 #include "dynload.h"
00026 #include "paramset.h"
00027 #include "tonemap.h"
00028 #include "stats.h"
00029
00030 namespace lux
00031 {
00032
00033
00034 void ApplyImagingPipeline(float *rgb, int xResolution,
00035 int yResolution, float *yWeight,
00036 float bloomRadius, float bloomWeight,
00037 const char *toneMapName,
00038 const ParamSet *toneMapParams,
00039 float gamma, float dither, int maxDisplayValue) {
00040 int nPix = xResolution * yResolution ;
00041
00042 if (bloomRadius > 0.f && bloomWeight > 0.f) {
00043
00044 int bloomSupport = Float2Int(bloomRadius *
00045 max(xResolution, yResolution));
00046 int bloomWidth = bloomSupport / 2;
00047
00048 float *bloomFilter = new float[bloomWidth * bloomWidth];
00049 for (int i = 0; i < bloomWidth * bloomWidth; ++i) {
00050 float dist = sqrtf(float(i)) / float(bloomWidth);
00051 bloomFilter[i] = powf(max(0.f, 1.f - dist), 4.f);
00052 }
00053
00054 float *bloomImage = new float[3*nPix];
00055 ProgressReporter prog(yResolution, "Bloom filter");
00056 for (int y = 0; y < yResolution; ++y) {
00057 for (int x = 0; x < xResolution; ++x) {
00058
00059
00060 int x0 = max(0, x - bloomWidth);
00061 int x1 = min(x + bloomWidth, xResolution - 1);
00062 int y0 = max(0, y - bloomWidth);
00063 int y1 = min(y + bloomWidth, yResolution - 1);
00064 int offset = y * xResolution + x;
00065 float sumWt = 0.;
00066 for (int by = y0; by <= y1; ++by)
00067 for (int bx = x0; bx <= x1; ++bx) {
00068
00069 int dx = x - bx, dy = y - by;
00070 if (dx == 0 && dy == 0) continue;
00071 int dist2 = dx*dx + dy*dy;
00072 if (dist2 < bloomWidth * bloomWidth) {
00073 int bloomOffset = bx + by * xResolution;
00074 float wt = bloomFilter[dist2];
00075 sumWt += wt;
00076 for (int j = 0; j < 3; ++j)
00077 bloomImage[3*offset+j] += wt * rgb[3*bloomOffset+j];
00078 }
00079 }
00080 bloomImage[3*offset ] /= sumWt;
00081 bloomImage[3*offset+1] /= sumWt;
00082 bloomImage[3*offset+2] /= sumWt;
00083 }
00084 prog.Update();
00085 }
00086 prog.Done();
00087
00088 for (int i = 0; i < 3 * nPix; ++i)
00089 rgb[i] = Lerp(bloomWeight, rgb[i], bloomImage[i]);
00090
00091 delete[] bloomFilter;
00092 delete[] bloomImage;
00093 }
00094
00095 ToneMap *toneMap = NULL;
00096 if (toneMapName)
00097 toneMap = MakeToneMap(toneMapName,
00098 toneMapParams ? *toneMapParams : ParamSet());
00099 if (toneMap) {
00100 float maxDisplayY = 100.f;
00101 float *scale = new float[nPix], *lum = new float[nPix];
00102
00103 float stdYWeight[3] = { 0.212671f, 0.715160f, 0.072169f };
00104 if (!yWeight) yWeight = stdYWeight;
00105 for (int i = 0; i < nPix; ++i)
00106 lum[i] = 683.f * (yWeight[0] * rgb[3*i] +
00107 yWeight[1] * rgb[3*i+1] + yWeight[2] * rgb[3*i+2]);
00108 toneMap->Map(lum, xResolution, yResolution,
00109 maxDisplayY, scale);
00110
00111 float displayTo01 = 683.f / maxDisplayY;
00112 for (int i = 0; i < xResolution * yResolution; ++i) {
00113 rgb[3*i ] *= scale[i] * displayTo01;
00114 rgb[3*i+1] *= scale[i] * displayTo01;
00115 rgb[3*i+2] *= scale[i] * displayTo01;
00116 }
00117 delete[] scale;
00118 delete[] lum;
00119 delete toneMap;
00120 }
00121
00122 for (int i = 0; i < nPix; ++i) {
00123 float m = max(rgb[3*i], max(rgb[3*i+1], rgb[3*i+2]));
00124 if (m > 1.f)
00125 for (int j = 0; j < 3; ++j)
00126 rgb[3*i+j] /= m;
00127 }
00128
00129 if (gamma != 1.f) {
00130 float invGamma = 1.f / gamma;
00131 for (int i = 0; i < 3*nPix; ++i)
00132 rgb[i] = powf(rgb[i], invGamma);
00133 }
00134
00135 for (int i = 0; i < 3*nPix; ++i)
00136 rgb[i] *= maxDisplayValue;
00137
00138 if (dither > 0.f)
00139 for (int i = 0; i < 3*nPix; ++i)
00140 rgb[i] += 2.f * dither * (lux::random::floatValueP() - .5f);
00141 }
00142
00143 }
00144