c32f saving revision
[csRadar.git] / ext_csr_substance.c
1 // Copyright (C) 2021 Harry Godden (hgn)
2
3 // Basic buffers-only version of csRadar
4 //=======================================================================================================================
5
6 #include "csRadar.h"
7
8 float min_height = 0.f;
9 v4f remapping_range;
10
11 // GBuffer shader
12 void frag_gbuffer( void *dest, vmf_vert tri[3], float bca, float bcb, float bcc );
13 void frag_gbuffer_clear( void *dest );
14
15 csr_shader shader_gbuffer =
16 {
17 .stride = sizeof(float)*8, // (origin) x,y, (actual height) z
18 .frag = frag_gbuffer,
19 .clear = frag_gbuffer_clear
20 };
21
22 // Main drawing function
23 void draw_buffers( csr_api *api, int bounds_only );
24
25 // Extension implementation
26 // =========================================================================================================
27
28 // API ENTRY
29 void csr_ext_main( csr_api *api )
30 {
31 if( !csr_init( api ) )
32 return;
33
34 csr_create_target( &api->target, api->resolution, api->resolution, api->sampling_mode, &shader_gbuffer );
35 csr_rt_clear( &api->target );
36
37 // Compute bounds, collect models
38 draw_buffers( api, 1 );
39 csr_auto_fit( &api->target, api->padding );
40 vmf_load_models( api->map );
41
42 min_height = api->target.bounds[0][2];
43 v2_copy( api->target.bounds[0], remapping_range );
44 v2_sub( api->target.bounds[1], api->target.bounds[0], &remapping_range[2] );
45
46 api->target.bounds[0][2] = api->min_z;
47 api->target.bounds[1][2] = api->max_z;
48
49 // Draw everything
50 draw_buffers( api, 0 );
51 }
52
53 void csr_ext_exit( csr_api *api )
54 {
55 csr_rt_free( &api->target );
56 }
57
58 void save_layers( csr_api *api, const char *layer )
59 {
60 char output[512];
61 strcpy( output, api->output_path );
62 strcat( output, "_" );
63 strcat( output, layer );
64
65 char *ext = output + strlen( output );
66
67 strcpy( ext, ".pfm" );
68 csr_rt_save_c32f( &api->target, output, 0 );
69
70 strcpy( ext, ".tga" );
71 csr_rt_save_tga( &api->target, output, 3*sizeof(float), 4 );
72 }
73
74 void draw_buffers( csr_api *api, int bounds_only )
75 {
76 csr_filter filter = { .compute_bounds_only = bounds_only };
77 vmf_map *map = api->map;
78
79 if( api->num_strings == 1 )
80 {
81 // Draw everything
82 csr_vmf_render( &api->target, map, map->root, &filter, NULL, NULL );
83
84 if( !bounds_only )
85 {
86 save_layers( api, "all" );
87 }
88 }
89 else
90 {
91 // Draw groups
92 for( int i = 1; i < api->num_strings; i ++ )
93 {
94 csr_filter_update_from_strings( &filter, &api->strings[i] );
95
96 csr_vmf_render( &api->target, map, map->root, &filter, NULL, NULL );
97
98 if( !bounds_only )
99 {
100 save_layers( api, api->strings[i].str );
101 csr_rt_clear( &api->target );
102 }
103 }
104 }
105 }
106
107 void frag_gbuffer( void *dest, vmf_vert tri[3], float bca, float bcb, float bcc )
108 {
109 float *dest_colour = (float *)dest;
110
111 // Position
112 v2_sub( tri[0].origin, remapping_range, dest_colour );
113 v2_div( dest_colour, &remapping_range[2], dest_colour );
114
115 dest_colour[2] = tri[0].co[2]*bca + tri[1].co[2]*bcb + tri[2].co[2]*bcc;
116
117 // Normals
118 v3_muls( tri[0].nrm, bca, dest_colour+3 );
119 v3_muladds( dest_colour+3, tri[1].nrm, bcb, dest_colour+3 );
120 v3_muladds( dest_colour+3, tri[2].nrm, bcc, dest_colour+3 );
121
122 v3_muls( dest_colour+3, 0.5f, dest_colour+3 );
123 v3_add( (v3f){0.5f,0.5f,0.5f}, dest_colour+3, dest_colour+3 );
124
125 // Mask
126 dest_colour[6] = 1.f;
127 }
128
129 void frag_gbuffer_clear( void *dest )
130 {
131 float *dest_colour = (float *)dest;
132 dest_colour[0] = 0.f;
133 dest_colour[1] = 0.f;
134 dest_colour[2] = min_height;
135
136 dest_colour[3] = 0.5f;
137 dest_colour[4] = 0.5f;
138 dest_colour[5] = 1.0f;
139
140 dest_colour[6] = 0.f;
141 }