+ //if (VectorLength2(rtlight->photoncolor) == 0.0f)
+ // rtlight->photons = 0;
+ }
+ // the user provided an intensityperphoton value which we try to use
+ // if that results in too many photons to shoot this frame, then we cap it
+ // which causes photons to appear/disappear from frame to frame, so we don't
+ // like doing that in the typical case
+ normalphotonscaling = 1.0f / max(0.0001f, r_shadow_bouncegrid_intensityperphoton.value);
+ maxphotonscaling = (float)settings->maxphotons / max(1, photoncount);
+ *photonscaling = min(normalphotonscaling, maxphotonscaling);
+}
+
+static void R_Shadow_BounceGrid_ClearPixels(void)
+{
+ int pixelband;
+ for (pixelband = 0;pixelband < r_shadow_bouncegrid_state.pixelbands;pixelband++)
+ {
+ if (pixelband == 1)
+ memset(r_shadow_bouncegrid_state.pixels + pixelband * r_shadow_bouncegrid_state.bytesperband, 128, r_shadow_bouncegrid_state.bytesperband);
+ else
+ memset(r_shadow_bouncegrid_state.pixels + pixelband * r_shadow_bouncegrid_state.bytesperband, 0, r_shadow_bouncegrid_state.bytesperband);
+ }
+ memset(r_shadow_bouncegrid_state.highpixels, 0, r_shadow_bouncegrid_state.numpixels * sizeof(float[4]));
+}
+
+static void R_Shadow_BounceGrid_ConvertPixelsAndUpload(void)
+{
+ unsigned char *pixels = r_shadow_bouncegrid_state.pixels;
+ unsigned char *pixel;
+ float *highpixels = r_shadow_bouncegrid_state.highpixels;
+ float *highpixel;
+ unsigned int pixelbands = r_shadow_bouncegrid_state.pixelbands;
+ unsigned int pixelband;
+ unsigned int x, y, z;
+ unsigned int index;
+ unsigned int resolution[3];
+ int c[4];
+ VectorCopy(r_shadow_bouncegrid_state.resolution, resolution);
+ // generate pixels array from highpixels array
+ //
+ // skip first and last columns, rows, and layers as these are blank
+ //
+ // the pixel[3] value was deliberately written along with highpixels
+ // updates, so we can use it to detect only pixels that need to be
+ // converted, the rest were already memset to neutral values.
+ for (pixelband = 0;pixelband < pixelbands;pixelband++)
+ {
+ for (z = 1;z < resolution[2]-1;z++)
+ {
+ for (y = 1;y < resolution[1]-1;y++)
+ {
+ x = 1;
+ index = ((pixelband*resolution[2]+z)*resolution[1]+y)*resolution[0]+x;
+ pixel = pixels + 4*index;
+ highpixel = highpixels + 4*index;
+ for (;x < resolution[0]-1;x++, pixel += 4, highpixel += 4)
+ {
+ // only convert pixels that were hit by photons
+ if (pixel[3] == 255)
+ {
+ // normalize the bentnormal...
+ if (pixelband == 1)
+ {
+ VectorNormalize(highpixel);
+ c[0] = (int)(highpixel[0]*128.0f+128.0f);
+ c[1] = (int)(highpixel[1]*128.0f+128.0f);
+ c[2] = (int)(highpixel[2]*128.0f+128.0f);
+ c[3] = (int)(highpixel[3]*128.0f+128.0f);
+ }
+ else
+ {
+ c[0] = (int)(highpixel[0]*256.0f);
+ c[1] = (int)(highpixel[1]*256.0f);
+ c[2] = (int)(highpixel[2]*256.0f);
+ c[3] = (int)(highpixel[3]*256.0f);
+ }
+ pixel[2] = (unsigned char)bound(0, c[0], 255);
+ pixel[1] = (unsigned char)bound(0, c[1], 255);
+ pixel[0] = (unsigned char)bound(0, c[2], 255);
+ pixel[3] = (unsigned char)bound(0, c[3], 255);
+ }
+ }
+ }
+ }
+ }
+
+ if (!r_shadow_bouncegrid_state.createtexture)
+ R_UpdateTexture(r_shadow_bouncegrid_state.texture, pixels, 0, 0, 0, resolution[0], resolution[1], resolution[2]*pixelbands);
+ else
+ {
+ if (r_shadow_bouncegrid_state.texture)
+ R_FreeTexture(r_shadow_bouncegrid_state.texture);
+ r_shadow_bouncegrid_state.texture = R_LoadTexture3D(r_shadow_texturepool, "bouncegrid", resolution[0], resolution[1], resolution[2]*pixelbands, pixels, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_ALPHA | TEXF_FORCELINEAR, 0, NULL);