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