|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//===========================================================================//
#include "tier0/platform.h"
#include <stdio.h>
#include "bitmap/float_bm.h"
#include "mathlib/mathlib.h"
#include "tier2/tier2.h"
#define BRIGHT_THRESH 0.90 // pixels within this % of average are "bright"
#define GROUND_IMPORTANCE 0.2 // weight for downward pointing skymap pixels
float Importance(Vector const &direction) { // this returns a scale factor which can be used to recurd the importance of certain
// directions. in particular, this version makes the ground a lot less important than the sky
if (direction.z>.2) return 1.0; if (direction.z>0) return FLerp(1.0,GROUND_IMPORTANCE,.2,0,direction.z); else return GROUND_IMPORTANCE;
}
void main(int argc,char **argv) { InitCommandLineProgram(argc, argv); if (argc!=2) { printf("format is %s basename\n",argv[0]); } else { FloatCubeMap_t cmap(argv[1]); // find the brightest pixel. We will consider the pixels neat this to be the
// ones contrinbuting to the light source
float max_color=cmap.BrightestColor(); float threshhold=max_color*.90; // now, find average color of non-bright pixels
float sumweights=0.0; Vector AverageColor(0,0,0); for(int f=0;f<6;f++) for(int y=0;y<cmap.face_maps[f].Height;y++) for(int x=0;x<cmap.face_maps[f].Width;x++) { Vector clr( cmap.face_maps[f].Pixel(x,y,0), cmap.face_maps[f].Pixel(x,y,1), cmap.face_maps[f].Pixel(x,y,2)); float mag=clr.Length(); if (mag<threshhold) { float weight=Importance(cmap.PixelDirection(f,x,y)); sumweights+=weight; AverageColor+=weight*clr; } } AverageColor*=(1.0/sumweights);
Vector avg_light_dir(0,0,0); Vector AverageHue(0,0,0); // now, find average direction and color of bright pixels
for(int f=0;f<6;f++) for(int y=0;y<cmap.face_maps[f].Height;y++) for(int x=0;x<cmap.face_maps[f].Width;x++) { Vector clr( cmap.face_maps[f].Pixel(x,y,0), cmap.face_maps[f].Pixel(x,y,1), cmap.face_maps[f].Pixel(x,y,2)); float mag=clr.Length(); if (mag>threshhold) { clr-=AverageColor; AverageHue+=clr; Vector pdir=cmap.PixelDirection(f,x,y); pdir*=clr.Length(); avg_light_dir+=pdir; } } VectorNormalize(AverageHue); VectorNormalize(avg_light_dir);
printf("Point light dir=%f %f %f\n",avg_light_dir.x,avg_light_dir.y,avg_light_dir.z); // printf("Point light color=%f %f %f\n",AverageHue.x,AverageHue.y,AverageHue.z);
printf("Point light color=%d %d %d 255\n", ( int )( 255 * pow( AverageHue.x, 1.0f / 2.2f ) ), ( int )( 255 * pow( AverageHue.y, 1.0f / 2.2f ) ), ( int )( 255 * pow( AverageHue.z, 1.0f / 2.2f ) ) );
// now, output ambient cube maps for image-based lighting. During this pass, we will also
// correct the ambient color
FloatCubeMap_t conv(32,32);
Vector AmbientColor(0,0,0); float sumweights_amb=0; for(int f=0;f<6;f++) for(int y=0;y<conv.face_maps[f].Height;y++) for(int x=0;x<conv.face_maps[f].Width;x++) { Vector pdir=conv.PixelDirection(f,x,y); float dot=pdir.Dot(avg_light_dir); if (dot<0) dot=0;
float sumdot=0; Vector sumlight(0,0,0); for(int f1=0;f1<6;f1++) for(int y1=0;y1<cmap.face_maps[f].Height;y1+=20) for(int x1=0;x1<cmap.face_maps[f].Width;x1+=20) { Vector sdir=cmap.PixelDirection(f1,x1,y1); float dot_sphere=sdir.Dot(pdir); if (dot_sphere>0) { sumdot+=dot_sphere; for(int comp=0;comp<3;comp++) sumlight[comp]+= dot_sphere*cmap.face_maps[f1].Pixel(x1,y1,comp); } } sumlight*=1.0/sumdot; // sumlight is the desired lighting
// use our calculated point light source to find the error
float weight=Importance(pdir); sumweights_amb+=weight; for(int comp=0;comp<3;comp++) { conv.face_maps[f].Pixel(x,y,comp)=sumlight[comp]; AmbientColor[comp]+=weight*(sumlight[comp]-dot*AverageHue[comp]); }
} AmbientColor*=1.0/sumweights_amb; conv.WritePFMs("ambient_cube_"); // printf("Ambient color=%f %f %f\n",AmbientColor.x,AmbientColor.y,AmbientColor.z);
// convert to gamma space. . .
printf("Ambient color=%d %d %d 255\n", ( int )( 255 * pow( AmbientColor.x, 1.0f/2.2f ) ), ( int )( 255 * pow( AmbientColor.y, 1.0f/2.2f ) ), ( int )( 255 * pow( AmbientColor.z, 1.0f/2.2f ) ) );
for(int f=0;f<6;f++) for(int y=0;y<cmap.face_maps[f].Height;y++) for(int x=0;x<cmap.face_maps[f].Width;x++) { Vector pdir=cmap.PixelDirection(f,x,y); float dot=pdir.Dot(avg_light_dir); if (dot<0) dot=0; dot=pow(dot,7); for(int comp=0;comp<3;comp++) cmap.face_maps[f].Pixel(x,y,comp)=AmbientColor[comp]+dot*AverageHue[comp]; } cmap.WritePFMs("directional_plus_ambient_"); }
}
|