You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
4.9 KiB
169 lines
4.9 KiB
//========= 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_"); |
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|