-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathmain.cpp
More file actions
139 lines (116 loc) · 3.69 KB
/
main.cpp
File metadata and controls
139 lines (116 loc) · 3.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
float const MATH_PI = 3.14159265359f;
unsigned const SAMPLE_NUM = 10000;
struct Vec3
{
float x;
float y;
float z;
};
float dot( Vec3 a, Vec3 b )
{
return a.x * b.x + a.y * b.y + a.z * b.z;
}
void SaveTGA( char const* path, unsigned width, unsigned height, void const* data )
{
#pragma pack( push, 1 )
struct STGAHeader
{
char idlength;
char colourmaptype;
char datatypecode;
short int colourmaporigin;
short int colourmaplength;
char colourmapdepth;
short int x_origin;
short int y_origin;
short width;
short height;
char bitsperpixel;
char imagedescriptor;
};
#pragma pack( pop )
FILE* f = nullptr;
fopen_s( &f, path, "wb" );
if ( !f )
{
return;
}
STGAHeader header;
memset( &header, 0, sizeof( header ) );
header.width = width;
header.height = height;
header.datatypecode = 2;
header.bitsperpixel = 24;
header.imagedescriptor = 1 << 5;
fwrite( &header, sizeof( header ), 1, f );
fwrite( data, width * height * 3, 1, f );
fclose( f );
}
Vec3 RandomConeRays[ SAMPLE_NUM ];
void GenerateRandomConeRays( float coneAngle )
{
float const cosConeAngle = cosf( 0.5f * ( coneAngle * MATH_PI / 180.0f ) );
for ( unsigned iSample = 0; iSample < SAMPLE_NUM; ++iSample )
{
float cosTheta = ( (float) rand() / RAND_MAX ) * ( 1.0f - cosConeAngle ) + cosConeAngle;
float sinTheta = sqrtf( 1.0f - cosTheta * cosTheta );
float phi = MATH_PI * ( (float) rand() / RAND_MAX ) * 2.0f - 1.0f;
float cosPhi = cosf( phi );
float sinPhi = sinf( phi );
RandomConeRays[ iSample ] = { sinTheta * cosPhi, sinTheta * sinPhi, cosTheta };
}
}
float Occlusion( float occluderAngleSin, float occluderToBeamAngleCos )
{
float const occluderToBeamAngleSin = sqrtf( 1.0f - occluderToBeamAngleCos * occluderToBeamAngleCos );
float const occluderAngleCos = sqrtf( 1.0f - occluderAngleSin * occluderAngleSin );
Vec3 const occluderDir = { occluderToBeamAngleSin, 0.0f, occluderToBeamAngleCos };
unsigned hitNum = 0;
for ( unsigned iSample = 0; iSample < SAMPLE_NUM; ++iSample )
{
if ( dot( occluderDir, RandomConeRays[ iSample ] ) > occluderAngleCos )
{
++hitNum;
}
}
return 1.0f - hitNum / (float) SAMPLE_NUM;
}
int main( int argc, char** argv )
{
if ( argc < 4 )
{
printf( "Incorrect params\n" );
printf( "Usage: ConeSphereOcclusionLUT.exe lut_width lut_height cone_angle_in_degress\n" );
printf( "ConeSphereOcclusionLUT.exe 128 64 30\n" );
return 1;
}
float coneAngle = 30.0f;
unsigned lutWidth = 128;
unsigned lutHeight = 64;
sscanf_s( argv[ 1 ], "%u", &lutWidth );
sscanf_s( argv[ 2 ], "%u", &lutHeight );
sscanf_s( argv[ 3 ], "%f", &coneAngle );
uint8_t* lutData = new uint8_t[ lutWidth * lutHeight * 3 ];
GenerateRandomConeRays( coneAngle );
for ( unsigned iSinTheta = 0; iSinTheta < lutHeight; ++iSinTheta ) // angle subtended by the occluder [0;1]
{
float const sinTheta = iSinTheta / ( lutHeight - 1.0f );
for ( unsigned iCosPhi = 0; iCosPhi < lutWidth; ++iCosPhi ) // angle between the cone axis and the vector pointing towards the occluder (sphere) center [-1;1]
{
float const cosPhi = 2.0f * ( iCosPhi / ( lutWidth - 1.0f ) ) - 1.0f;
float const sampleValue = Occlusion( sinTheta, cosPhi );
uint8_t sampleU8 = uint8_t( sampleValue * 255.0f + 0.5f );
lutData[ iCosPhi * 3 + iSinTheta * lutWidth * 3 + 0 ] = sampleU8;
lutData[ iCosPhi * 3 + iSinTheta * lutWidth * 3 + 1 ] = sampleU8;
lutData[ iCosPhi * 3 + iSinTheta * lutWidth * 3 + 2 ] = sampleU8;
}
}
SaveTGA( "cone_sphere_occlusion_lut.tga", lutWidth, lutHeight, lutData );
delete[] lutData;
return 0;
}