8#include "physfsrwops.h"
10#define CGLTF_IMPLEMENTATION
17#include "opengl_shader.h"
20#include "shader_min.h"
21#define gl_contextSet()
22#define gl_contextUnset()
28#define SHADOWMAP_SIZE_LOW 128
29#define SHADOWMAP_SIZE_HIGH 512
32#define STR_HELPER( x ) #x
33#define STR( x ) STR_HELPER( x )
44static SDL_mutex *cache_lock = NULL;
51typedef struct ShaderLight_ {
76 .colour = { .v = { 1., 1., 1. } },
81 .pos = { .v = { -3., 2.75, -3. } },
92 .colour = { .v = { 1., 1., 1. } },
98 .pos = { .v = { 10., 11.5, 7. } },
120 .colour = { .v = { 1., 1., 1. } },
122 .pos = { .v = { -3., 2.75, -3. } },
127 .colour = { .v = { 1., 1., 1. } },
129 .pos = { .v = { 10., 11.5, 7. } },
137static GLuint light_fbo_low[MAX_LIGHTS];
139 light_tex_low[MAX_LIGHTS];
140static GLuint light_fbo_high[MAX_LIGHTS];
142static GLuint light_tex_high[MAX_LIGHTS];
144static GLuint shadowmap_size = SHADOWMAP_SIZE_LOW;
145static GLuint *light_fbo = light_fbo_low;
146static GLuint *light_tex = light_tex_low;
147static mat4 light_mat_def[MAX_LIGHTS];
148static mat4 light_mat_alt[MAX_LIGHTS];
149static mat4 *light_mat = light_mat_def;
154typedef struct Shader_ {
158 GLuint vertex_normal;
166 GLuint baseColour_tex;
167 GLuint baseColour_texcoord;
169 GLuint metallic_texcoord;
172 GLuint normal_texcoord;
174 GLuint metallicFactor;
175 GLuint roughnessFactor;
181 GLuint clearcoat_roughness;
185 GLuint emissive_texcoord;
186 GLuint occlusion_tex;
187 GLuint occlusion_texcoord;
196static Shader shadow_shader;
201static Texture tex_ones = { .tex = 0, .texcoord = 0, .strength = 1. };
204static GLuint shadow_vbo;
205static GLuint shadow_fbo_low;
206static GLuint shadow_fbo_high;
207static GLuint shadow_tex_low;
208static GLuint shadow_tex_high;
209static GLuint *shadow_fbo = &shadow_fbo_low;
210static GLuint *shadow_tex = &shadow_tex_low;
211static Shader shadow_shader_blurX;
212static Shader shadow_shader_blurY;
215static int use_normal_mapping = 1;
216static int use_ambient_occlusion = 1;
217static int max_tex_size = 0;
220static int cache_cmp(
const void *p1,
const void *p2 );
221static GltfObject *cache_get(
const char *filename,
int *
new );
223static void gltf_applyAnim(
GltfObject *obj, GLfloat time );
238 const SDL_PixelFormatEnum fmt = SDL_PIXELFORMAT_ABGR8888;
240 SDL_Surface *surface = NULL;
243 GLint internalformat;
250 if ( ( ctex == NULL ) || ( ctex->texture == NULL ) ) {
257 otex->
strength = ctex->transform.scale[0];
260 path = ( ctex->texture->has_webp ) ? ctex->texture->webp_image->uri
261 : ctex->texture->image->uri;
262 if ( path == NULL ) {
263 DEBUG(
"Buffer textures not supported yet!" );
269 snprintf( filepath,
sizeof( filepath ),
"%s/%s", obj->
path, path );
271 snprintf( filepath,
sizeof( filepath ),
"%s", path );
278 int flags = OPENGL_TEX_MIPMAPS;
280 flags |= OPENGL_TEX_NOTSRGB;
284 otex->
tex = otex->gtex->texture;
290 rw = PHYSFSRWOPS_openRead( filepath );
292 WARN( _(
"Unable to open '%s': %s" ), filepath, SDL_GetError() );
296 surface = IMG_Load_RW( rw, 1 );
297 if ( surface == NULL ) {
298 WARN( _(
"Unable to load surface '%s': %s" ), filepath, SDL_GetError() );
305 glGenTextures( 1, &tex );
306 glBindTexture( GL_TEXTURE_2D, tex );
309 if ( ctex->texture->sampler != NULL ) {
310 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
311 ctex->texture->sampler->mag_filter );
312 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
313 ctex->texture->sampler->min_filter );
314 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
315 ctex->texture->sampler->wrap_s );
316 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
317 ctex->texture->sampler->wrap_t );
319 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
320 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
321 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
322 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
325 if ( surface != NULL ) {
326 has_alpha = surface->format->Amask;
328 internalformat = has_alpha ? GL_RGBA : GL_RGB;
330 internalformat = has_alpha ? GL_SRGB_ALPHA : GL_SRGB;
331 if ( surface->format->format != fmt ) {
332 SDL_Surface *temp = surface;
333 surface = SDL_ConvertSurfaceFormat( temp, fmt, 0 );
334 SDL_FreeSurface( temp );
337 SDL_LockSurface( surface );
338 glPixelStorei( GL_UNPACK_ALIGNMENT,
339 MIN( surface->pitch & -surface->pitch, 8 ) );
341 glTexImage2D( GL_TEXTURE_2D, 0, internalformat, surface->w, surface->h,
342 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
344 glTexImage2D( GL_TEXTURE_2D, 0, internalformat, surface->w, surface->h,
345 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels );
346 glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
347 SDL_UnlockSurface( surface );
359 if ( ( max_tex_size > 0 ) && ( surface != NULL ) &&
360 (
MAX( surface->w, surface->h ) > max_tex_size ) ) {
361 GLuint fbo, downfbo, downtex;
365 gl_fboCreate( &downfbo, &downtex, max_tex_size, max_tex_size );
368 glGenTextures( 1, &downtex );
369 glBindTexture( GL_TEXTURE_2D, downtex );
370 glTexImage2D( GL_TEXTURE_2D, 0, internalformat, max_tex_size,
371 max_tex_size, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
374 glGenFramebuffers( 1, &downfbo );
375 glBindFramebuffer( GL_FRAMEBUFFER, downfbo );
378 glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
379 GL_TEXTURE_2D, downtex, 0 );
382 status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
383 if ( status != GL_FRAMEBUFFER_COMPLETE )
384 WARN( _(
"Error setting up framebuffer!" ) );
387 glGenFramebuffers( 1, &fbo );
388 glBindFramebuffer( GL_FRAMEBUFFER, fbo );
389 glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
390 GL_TEXTURE_2D, tex, 0 );
393 glBindFramebuffer( GL_READ_FRAMEBUFFER, fbo );
394 glBindFramebuffer( GL_DRAW_FRAMEBUFFER, downfbo );
395 glBlitFramebuffer( 0, 0, surface->w, surface->h, 0, 0, max_tex_size,
396 max_tex_size, GL_COLOR_BUFFER_BIT, GL_LINEAR );
397 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
400 glDeleteTextures( 1, &tex );
401 glDeleteFramebuffers( 1, &downfbo );
402 glDeleteFramebuffers( 1, &fbo );
404 glBindTexture( GL_TEXTURE_2D, tex );
407 if ( ctex->texture->sampler != NULL ) {
408 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
409 ctex->texture->sampler->mag_filter );
410 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
411 ctex->texture->sampler->min_filter );
412 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
413 ctex->texture->sampler->wrap_s );
414 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
415 ctex->texture->sampler->wrap_t );
417 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
418 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
419 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
420 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
427 glGenerateMipmap( GL_TEXTURE_2D );
430 SDL_FreeSurface( surface );
432 glBindTexture( GL_TEXTURE_2D, 0 );
439 otex->gtex->texture = tex;
451 const GLfloat white[4] = { 1., 1., 1., 1. };
453 if ( cmat && cmat->has_pbr_metallic_roughness ) {
454 mat->
metallicFactor = cmat->pbr_metallic_roughness.metallic_factor;
457 &cmat->pbr_metallic_roughness.base_color_texture,
461 cmat->pbr_metallic_roughness.base_color_factor,
467 &cmat->pbr_metallic_roughness.metallic_roughness_texture, &tex_ones,
475 mat->normal_tex = tex_zero;
480 if ( cmat && cmat->has_sheen ) {
481 memcpy( mat->sheen, cmat->sheen.sheen_color_factor,
482 sizeof( mat->sheen ) );
483 mat->sheen_roughness = cmat->sheen.sheen_roughness_factor;
485 memset( mat->sheen, 0,
sizeof( mat->sheen ) );
486 mat->sheen_roughness = 0.;
490 if ( cmat && cmat->has_clearcoat ) {
491 mat->clearcoat = cmat->clearcoat.clearcoat_factor;
492 mat->clearcoat_roughness = cmat->clearcoat.clearcoat_roughness_factor;
495 mat->clearcoat_roughness = 0.;
501 memcpy( mat->emissiveFactor, cmat->emissive_factor,
502 sizeof( GLfloat ) * 3 );
503 gltf_loadTexture( obj, &mat->emissive_tex, &cmat->emissive_texture,
505 if ( use_ambient_occlusion )
506 gltf_loadTexture( obj, &mat->occlusion_tex, &cmat->occlusion_texture,
509 mat->occlusion_tex = tex_ones;
510 if ( use_normal_mapping )
511 gltf_loadTexture( obj, &mat->normal_tex, &cmat->normal_texture,
514 mat->normal_tex = tex_ones;
515 mat->
blend = ( cmat->alpha_mode == cgltf_alpha_mode_blend );
517 mat->
unlit = cmat->unlit;
519 memset( mat->emissiveFactor, 0,
sizeof( GLfloat ) * 3 );
520 mat->emissive_tex = tex_ones;
521 mat->occlusion_tex = tex_ones;
522 mat->normal_tex = tex_ones;
526 if ( cmat && cmat->has_emissive_strength ) {
527 for (
int i = 0; i < 3; i++ )
528 mat->emissiveFactor[i] *= cmat->emissive_strength.emissive_strength;
532 if ( cmat && data ) {
533 char buf[STRMAX_SHORT];
534 cgltf_size len =
sizeof( buf );
535 cgltf_copy_extras_json( data, &cmat->extras, buf, &len );
539 int r = jsmn_parse( &p, buf, len, t,
sizeof( t ) /
sizeof( jsmntok_t ) );
540 for (
int j = 0; j < r; j++ ) {
541 const jsmntok_t *tj = &t[j];
542 const char *str =
"NAEV_noShadows";
543 if ( strncmp( str, &buf[tj->start],
545 (
size_t)( tj->end - tj->start ) ) ) == 0 ) {
558 for (
size_t i=0; i<cmat->extensions_count; i++) {
560 if (strcmp(ext->name,
"NAEV_ext")!=0)
565 int r = jsmn_parse( &p, ext->data, strlen(ext->data), t,
sizeof(t)/
sizeof(jsmntok_t) );
566 for (
int j=0; j<r; j++) {
567 jsmntok_t *tj = &t[j];
568 const char *str =
"waxFactor";
569 if (strncmp( str, &ext->data[tj->start],
MIN(strlen(str),(
size_t)(tj->end-tj->start)) )==0) {
572 mat->waxiness = atof(&ext->data[t[j+1].start]);
589static GLuint gltf_loadVBO(
const cgltf_accessor *acc, cgltf_float **data,
590 cgltf_size *datasize )
593 cgltf_size num = cgltf_accessor_unpack_floats( acc, NULL, 0 );
594 cgltf_float *dat = calloc( num,
sizeof( cgltf_float ) );
595 cgltf_accessor_unpack_floats( acc, dat, num );
596 if ( data != NULL ) {
603 glGenBuffers( 1, &vid );
604 glBindBuffer( GL_ARRAY_BUFFER, vid );
605 glBufferData( GL_ARRAY_BUFFER,
sizeof( cgltf_float ) * num, dat,
607 glBindBuffer( GL_ARRAY_BUFFER, 0 );
625 for (
size_t i = 0; i < cmesh->primitives_count; i++ ) {
629 cgltf_float *rawdata = NULL;
636 cgltf_size num = cgltf_num_components( acc->type ) * acc->count;
637 GLuint *idx = calloc( num,
sizeof( cgltf_uint ) );
638 for (
size_t j = 0; j < num; j++ )
639 cgltf_accessor_read_uint( acc, j, &idx[j], 1 );
642 if ( cprim->material != NULL )
643 prim->
material = cgltf_material_index( data, cprim->material );
649 glGenBuffers( 1, &prim->
vbo_idx );
650 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, prim->
vbo_idx );
651 glBufferData( GL_ELEMENT_ARRAY_BUFFER,
sizeof( cgltf_uint ) * num, idx,
653 prim->
nidx = acc->count;
654 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
659 for (
size_t j = 0; j < cprim->attributes_count; j++ ) {
661 switch ( attr->type ) {
662 case cgltf_attribute_type_position:
663 prim->
vbo_pos = gltf_loadVBO( attr->data, &rawdata, &datasize );
666 case cgltf_attribute_type_normal:
667 prim->
vbo_nor = gltf_loadVBO( attr->data, NULL, NULL );
670 case cgltf_attribute_type_texcoord:
671 if ( attr->index == 0 )
672 prim->
vbo_tex0 = gltf_loadVBO( attr->data, NULL, NULL );
674 prim->
vbo_tex1 = gltf_loadVBO( attr->data, NULL, NULL );
678 case cgltf_attribute_type_color:
679 case cgltf_attribute_type_tangent:
686 if ( rawdata != NULL ) {
688 for (
size_t n = 0; n < obj->
nnodes; n++ ) {
690 if ( cmesh != data->nodes[n].mesh )
693 cgltf_node_transform_world( &data->nodes[n], H.ptr );
694 for (
unsigned int di = 0; di < datasize; di += 3 ) {
696 for (
unsigned int dj = 0; dj < 3; dj++ )
697 d.v[dj] = rawdata[di + dj];
718 cgltf_node_transform_local( cnode, node->
Horig.ptr );
722 if ( cnode->has_rotation )
723 memcpy( node->
nt.
r.q, cnode->rotation,
sizeof( cnode->rotation ) );
725 node->
nt.
r.q[0] = 0.;
726 node->
nt.
r.q[1] = 0.;
727 node->
nt.
r.q[3] = 0.;
728 node->
nt.
r.q[3] = 1.;
730 if ( cnode->has_translation )
731 memcpy( node->
nt.
t.v, cnode->translation,
sizeof( cnode->translation ) );
733 node->
nt.
t.v[0] = 0.;
734 node->
nt.
t.v[1] = 0.;
735 node->
nt.
t.v[2] = 0.;
737 if ( cnode->has_scale )
738 memcpy( node->
nt.
s.v, cnode->scale,
sizeof( cnode->scale ) );
740 node->
nt.
s.v[0] = 1.;
741 node->
nt.
s.v[1] = 1.;
742 node->
nt.
s.v[2] = 1.;
747 if ( cnode->mesh != NULL )
748 node->
mesh = cgltf_mesh_index( data, cnode->mesh );
753 if ( cnode->extras.data != NULL ) {
754 char buf[STRMAX_SHORT];
755 cgltf_size len =
sizeof( buf );
756 cgltf_copy_extras_json( data, &cnode->extras, buf, &len );
760 int r = jsmn_parse( &p, buf, len, t,
sizeof( t ) /
sizeof( jsmntok_t ) );
761 for (
int j = 0; j < r; j++ ) {
762 const jsmntok_t *tj = &t[j];
764 const char *strtrail =
"NAEV_trail_generator";
765 if ( strncmp( strtrail, &buf[tj->start],
766 MIN( strlen( strtrail ),
767 (
size_t)( tj->end - tj->start ) ) ) == 0 ) {
777 trail.
generator = calloc( 1, t[j + 1].end - t[j + 1].start + 1 );
778 strncpy( trail.
generator, &cnode->extras.data[t[j + 1].start],
779 t[j + 1].end - t[j + 1].start );
780 trail.
generator[t[j + 1].end - t[j + 1].start] =
'\0';
781 cgltf_node_transform_world( cnode, H.ptr );
783 if ( obj->
trails == NULL )
789 const char *strmount =
"NAEV_weapon_mount";
790 if ( strncmp( strmount, &buf[tj->start],
791 MIN( strlen( strmount ),
792 (
size_t)( tj->end - tj->start ) ) ) == 0 ) {
802 mount.
id = atoi( &cnode->extras.data[t[j + 1].start] );
803 cgltf_node_transform_world( cnode, H.ptr );
805 if ( obj->
mounts == NULL )
816 node->
children = calloc( cnode->children_count,
sizeof(
size_t ) );
817 for ( cgltf_size i = 0; i < cnode->children_count; i++ )
818 node->
children[i] = cgltf_node_index( data, cnode->children[i] );
828 for ( cgltf_size i = 0; i < canim->samplers_count; i++ ) {
833 switch ( csamp->interpolation ) {
834 case cgltf_interpolation_type_linear:
835 samp->
interp = ANIM_INTER_LINEAR;
837 case cgltf_interpolation_type_step:
838 samp->
interp = ANIM_INTER_STEP;
841 WARN( _(
"Unsupported interpolation type %d!" ),
842 csamp->interpolation );
846 samp->
n = cgltf_accessor_unpack_floats( csamp->input, NULL, 0 );
847 samp->
time = calloc( samp->
n,
sizeof( cgltf_float ) );
848 cgltf_accessor_unpack_floats( csamp->input, samp->
time, samp->
n );
849 samp->
max = samp->
time[samp->
n - 1];
851 samp->
l = cgltf_num_components( csamp->output->type );
852 n = cgltf_accessor_unpack_floats( csamp->output, NULL, 0 );
853 if ( cgltf_num_components( csamp->output->type ) * samp->
n != n )
854 WARN( _(
"Wrong number of elements. Got %lu, but expected %lu!" ),
855 samp->
n * cgltf_num_components( csamp->output->type ), n );
856 samp->
data = calloc( n,
sizeof( cgltf_float ) );
857 cgltf_accessor_unpack_floats( csamp->output, samp->
data, n );
862 for ( cgltf_size i = 0; i < canim->channels_count; i++ ) {
867 ->
samplers[cgltf_animation_sampler_index( canim, cchan->sampler )];
868 chan->
target = &obj->
nodes[cgltf_node_index( data, cchan->target_node )];
869 switch ( cchan->target_path ) {
870 case cgltf_animation_path_type_translation:
871 chan->
type = ANIM_TYPE_TRANSLATION;
873 case cgltf_animation_path_type_rotation:
874 chan->
type = ANIM_TYPE_ROTATION;
876 case cgltf_animation_path_type_scale:
877 chan->
type = ANIM_TYPE_SCALE;
880 WARN( _(
"Uknown animation type %d!" ), cchan->target_path );
887static void shadow_matrix(
mat4 *m,
const Light *light )
889 const vec3 up = { .v = { 0., 1., 0. } };
890 const vec3 center = { .v = { 0., 0., 0. } };
894 vec3_normalize( &light_pos );
900 const vec3 light_pos = light->
pos;
902 const float norm = vec3_length( &light_pos );
903 const mat4 O =
mat4_ortho( -r, r, -r, r, norm - 1.0, norm + 1.0 );
911static void renderMeshPrimitiveShadow(
const GltfObject *obj,
916 const Shader *shd = &shadow_shader;
923 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->
vbo_idx );
926 glBindBuffer( GL_ARRAY_BUFFER, mesh->
vbo_pos );
927 glVertexAttribPointer( shd->vertex, 3, GL_FLOAT, GL_FALSE, 0, NULL );
928 glEnableVertexAttribArray( shd->vertex );
930 glUniformMatrix4fv( shd->Hmodel, 1, GL_FALSE, H->ptr );
931 glDrawElements( GL_TRIANGLES, mesh->
nidx, GL_UNSIGNED_INT, 0 );
933static void renderMeshShadow(
const GltfObject *obj,
const Mesh *mesh,
937 renderMeshPrimitiveShadow( obj, &mesh->
primitives[i], H );
943static void renderMeshPrimitive(
const GltfObject *obj,
947 const Shader *shd = &gltf_shader;
950 mat = &material_default;
954 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, mesh->
vbo_idx );
957 glBindBuffer( GL_ARRAY_BUFFER, mesh->
vbo_pos );
958 glVertexAttribPointer( shd->vertex, 3, GL_FLOAT, GL_FALSE, 0, NULL );
959 glEnableVertexAttribArray( shd->vertex );
961 glBindBuffer( GL_ARRAY_BUFFER, mesh->
vbo_nor );
962 glVertexAttribPointer( shd->vertex_normal, 3, GL_FLOAT, GL_FALSE, 0,
964 glEnableVertexAttribArray( shd->vertex_normal );
968 glBindBuffer( GL_ARRAY_BUFFER, mesh->
vbo_tex0 );
969 glVertexAttribPointer( shd->vertex_tex0, 2, GL_FLOAT, GL_FALSE, 0, NULL );
970 glEnableVertexAttribArray( shd->vertex_tex0 );
974 glBindBuffer( GL_ARRAY_BUFFER, mesh->
vbo_tex1 );
975 glVertexAttribPointer( shd->vertex_tex1, 2, GL_FLOAT, GL_FALSE, 0, NULL );
976 glEnableVertexAttribArray( shd->vertex_tex1 );
981 glUseProgram( shd->program );
985 mat3_from_mat4( &Hnormal, H );
986 mat3_invert( &Hnormal );
987 mat3_transpose( &Hnormal );
990 glUniformMatrix4fv( shd->Hmodel, 1, GL_FALSE, H->ptr );
991 glUniformMatrix3fv( shd->Hnormal, 1, GL_FALSE, Hnormal.ptr );
997 glUniform3f( shd->sheenTint, mat->sheen[0], mat->sheen[1], mat->sheen[2] );
998 glUniform1f( shd->sheen, mat->sheen_roughness );
999 glUniform1f( shd->clearcoat, mat->clearcoat );
1000 glUniform1f( shd->clearcoat_roughness, mat->clearcoat_roughness );
1002 glUniform3f( shd->emissive, mat->emissiveFactor[0], mat->emissiveFactor[1],
1003 mat->emissiveFactor[2] );
1004 glUniform1i( shd->blend, mat->
blend );
1005 if ( use_normal_mapping ) {
1006 glUniform1i( shd->u_has_normal, ( mat->normal_tex.
tex != tex_zero.tex ) );
1007 glUniform1f( shd->normal_scale, mat->normal_tex.
strength );
1008 glUniform1i( shd->normal_texcoord, mat->normal_tex.
texcoord );
1014 glUniform1i( shd->emissive_texcoord, mat->emissive_tex.
texcoord );
1015 if ( use_ambient_occlusion )
1016 glUniform1i( shd->occlusion_texcoord, mat->occlusion_tex.
texcoord );
1020 glActiveTexture( GL_TEXTURE1 );
1022 glUniform1i( shd->metallic_tex, 1 );
1023 glActiveTexture( GL_TEXTURE2 );
1024 glBindTexture( GL_TEXTURE_2D, mat->emissive_tex.
tex );
1025 glUniform1i( shd->emissive_tex, 2 );
1026 if ( use_normal_mapping ) {
1027 glActiveTexture( GL_TEXTURE3 );
1028 glBindTexture( GL_TEXTURE_2D, mat->normal_tex.
tex );
1029 glUniform1i( shd->normal_tex, 3 );
1031 if ( use_ambient_occlusion ) {
1032 glActiveTexture( GL_TEXTURE4 );
1033 glBindTexture( GL_TEXTURE_2D, mat->occlusion_tex.
tex );
1034 glUniform1i( shd->occlusion_tex, 4 );
1037 glActiveTexture( GL_TEXTURE0 );
1039 glUniform1i( shd->baseColour_tex, 0 );
1043 glDisable( GL_CULL_FACE );
1045 glDepthMask( GL_FALSE );
1046 glDrawElements( GL_TRIANGLES, mesh->
nidx, GL_UNSIGNED_INT, 0 );
1048 glEnable( GL_CULL_FACE );
1050 glDepthMask( GL_TRUE );
1055 renderMeshPrimitive( obj, &mesh->
primitives[i], H );
1061static void gltf_renderNodeShadow(
const GltfObject *obj,
const Node *node,
1070 if ( node->
mesh >= 0 )
1071 renderMeshShadow( obj, &obj->
meshes[node->
mesh], &HH );
1074 for (
size_t i = 0; i < node->
nchildren; i++ )
1075 gltf_renderNodeShadow( obj, &obj->
nodes[node->
children[i]], &HH );
1083static void gltf_renderNodeMesh(
const GltfObject *obj,
const Node *node,
1093 mat3_from_mat4( &m, &HH );
1094 glFrontFace( ( mat3_det( &m ) < 0. ) ? GL_CW : GL_CCW );
1097 if ( node->
mesh >= 0 )
1098 renderMesh( obj, &obj->
meshes[node->
mesh], &HH );
1101 for (
size_t i = 0; i < node->
nchildren; i++ )
1102 gltf_renderNodeMesh( obj, &obj->
nodes[node->
children[i]], &HH );
1107static void gltf_renderShadow(
const GltfObject *obj,
int scene,
const mat4 *H,
1108 const Light *light,
int i )
1111 const Shader *shd = &shadow_shader;
1114 glBindFramebuffer( GL_FRAMEBUFFER, light_fbo[i] );
1115 glClear( GL_DEPTH_BUFFER_BIT );
1116 glViewport( 0, 0, shadowmap_size, shadowmap_size );
1119 glUseProgram( shd->program );
1120 glUniformMatrix4fv( shd->Hshadow, 1, GL_FALSE, light_mat[i].ptr );
1122 for (
size_t j = 0; j < obj->
scenes[scene].
nnodes; j++ )
1125 glDisable( GL_CULL_FACE );
1131 shd = &shadow_shader_blurX;
1132 glBindFramebuffer( GL_FRAMEBUFFER, *shadow_fbo );
1133 glClear( GL_DEPTH_BUFFER_BIT );
1134 glUseProgram( shd->program );
1136 glBindBuffer( GL_ARRAY_BUFFER, shadow_vbo );
1137 glVertexAttribPointer( shd->vertex, 2, GL_FLOAT, GL_FALSE, 0, NULL );
1138 glEnableVertexAttribArray( shd->vertex );
1140 glActiveTexture( GL_TEXTURE0 );
1141 glBindTexture( GL_TEXTURE_2D, light_tex[i] );
1143 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
1146 shd = &shadow_shader_blurY;
1147 glBindFramebuffer( GL_FRAMEBUFFER, light_fbo[i] );
1148 glClear( GL_DEPTH_BUFFER_BIT );
1150 glUseProgram( shd->program );
1152 glBindBuffer( GL_ARRAY_BUFFER, shadow_vbo );
1153 glVertexAttribPointer( shd->vertex, 2, GL_FLOAT, GL_FALSE, 0, NULL );
1154 glEnableVertexAttribArray( shd->vertex );
1156 glActiveTexture( GL_TEXTURE0 );
1157 glBindTexture( GL_TEXTURE_2D, *shadow_tex );
1159 glDrawArrays( GL_TRIANGLE_STRIP, 0, 4 );
1161 glBindBuffer( GL_ARRAY_BUFFER, 0 );
1162 glDisableVertexAttribArray( shd->vertex );
1163 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
1164 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
1169static void gltf_renderMesh(
const GltfObject *obj,
int scene,
const mat4 *H,
1173 const Shader *shd = &gltf_shader;
1174 glUseProgram( shd->program );
1175 glUniform3f( shd->u_ambient, L->ambient_r, L->ambient_g, L->
ambient_b );
1176 glUniform1i( shd->nlights, L->
nlights );
1177 for (
int i = 0; i < L->
nlights; i++ ) {
1182 glUniform1i( sl->sun, l->
sun );
1186 vec3_normalize( &light_pos );
1187 glUniform3f( sl->position, light_pos.v[0], light_pos.v[1],
1190 glUniform3f( sl->position, l->
pos.v[0], l->
pos.v[1], l->
pos.v[2] );
1195 glUniformMatrix4fv( sl->Hshadow, 1, GL_FALSE, light_mat[i].ptr );
1198 glActiveTexture( GL_TEXTURE5 + i );
1199 glBindTexture( GL_TEXTURE_2D, light_tex[i] );
1200 glUniform1i( shd->lights[i].shadowmap_tex, 5 + i );
1205 glEnable( GL_CULL_FACE );
1206 for (
size_t i = 0; i < obj->
scenes[scene].
nnodes; i++ )
1209 glBindTexture( GL_TEXTURE_2D, 0 );
1210 glBindBuffer( GL_ARRAY_BUFFER, 0 );
1211 glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
1219 for (
size_t j = 0; j < anim->
nchannels; j++ ) {
1224 GLfloat t = fmod( time, samp->
max );
1235 for (
size_t i = 0; i < samp->
n; i++ ) {
1236 if ( samp->
time[i] < t ) {
1241 ni = ( pi + 1 ) % samp->
n;
1246 switch ( samp->
interp ) {
1247 case ANIM_INTER_LINEAR:
1248 mix = ( t - p ) / ( n - p );
1250 case ANIM_INTER_STEP:
1256 switch ( chan->
type ) {
1257 case ANIM_TYPE_ROTATION:
1258 quat_slerp( node->
nt.
r.q, &samp->
data[pi * samp->
l],
1259 &samp->
data[ni * samp->
l], mix );
1261 case ANIM_TYPE_TRANSLATION:
1262 for (
size_t i = 0; i < samp->
l; i++ )
1263 node->
nt.
t.v[i] = samp->
data[pi * samp->
l + i] * ( 1. - mix ) +
1264 samp->
data[ni * samp->
l + i] * mix;
1266 case ANIM_TYPE_SCALE:
1267 for (
size_t i = 0; i < samp->
l; i++ )
1268 node->
nt.
s.v[i] = samp->
data[pi * samp->
l + i] * ( 1. - mix ) +
1269 samp->
data[ni * samp->
l + i] * mix;
1275static void gltf_applyAnim(
GltfObject *obj, GLfloat time )
1280 for (
size_t i = 0; i < obj->
nnodes; i++ )
1283 gltf_applyAnimNode( obj, &obj->
animations[i], time );
1284 for (
size_t i = 0; i < obj->
nnodes; i++ ) {
1298void gltf_render( GLuint fb,
GltfObject *obj,
const mat4 *H, GLfloat time,
1301 return gltf_renderScene( fb, obj, obj->
scene_body, H, time, size, 0 );
1304void gltf_renderScene( GLuint fb,
GltfObject *obj,
int scene,
const mat4 *H,
1305 GLfloat time,
double size,
const Lighting *L )
1309 const GLfloat sca = 1.0 / obj->
radius;
1310 const mat4 Hscale = { .m = { { sca, 0.0, 0.0, 0.0 },
1311 { 0.0, sca, 0.0, 0.0 },
1312 { 0.0, 0.0, -sca, 0.0 },
1313 { 0.0, 0.0, 0.0, 1.0 } } };
1317 if ( size > 255. ) {
1318 shadowmap_size = SHADOWMAP_SIZE_HIGH;
1319 light_fbo = light_fbo_high;
1320 light_tex = light_tex_high;
1321 shadow_fbo = &shadow_fbo_high;
1322 shadow_tex = &shadow_tex_high;
1324 shadowmap_size = SHADOWMAP_SIZE_LOW;
1325 light_fbo = light_fbo_low;
1326 light_tex = light_tex_low;
1327 shadow_fbo = &shadow_fbo_low;
1328 shadow_tex = &shadow_tex_low;
1340 gltf_applyAnim( obj, time );
1345 light_mat = light_mat_def;
1348 for (
int i = 0; i < L->
nlights; i++ )
1349 shadow_matrix( &light_mat_alt[i], &L->
lights[i] );
1350 light_mat = light_mat_alt;
1354 glEnable( GL_BLEND );
1355 glBlendFuncSeparate( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,
1356 GL_ONE_MINUS_SRC_ALPHA );
1359 glEnable( GL_DEPTH_TEST );
1360 glDepthFunc( GL_LESS );
1363 glCullFace( GL_FRONT );
1364 for (
int i = 0; i < L->
nlights; i++ )
1365 gltf_renderShadow( obj, scene, &Hptr, &L->
lights[i], i );
1368 glViewport( 0, 0, size, size );
1369 glBindFramebuffer( GL_FRAMEBUFFER, fb );
1370 gltf_renderMesh( obj, scene, &Hptr, L );
1373 glDisable( GL_CULL_FACE );
1374 glDisable( GL_DEPTH_TEST );
1384 cgltf_size *size,
void **data )
1387 PHYSFS_Stat path_stat;
1389 void *( *memory_alloc )(
void *, cgltf_size ) =
1390 memory_options->alloc_func ? memory_options->alloc_func
1391 : &cgltf_default_alloc;
1392 void ( *memory_free )(
void *,
void * ) = memory_options->free_func
1393 ? memory_options->free_func
1394 : &cgltf_default_free;
1396 if ( !PHYSFS_stat( path, &path_stat ) ) {
1397 WARN( _(
"File '%s' not found!" ), path );
1398 return cgltf_result_file_not_found;
1401 cgltf_size file_size = size ? *size : 0;
1402 if ( file_size == 0 )
1403 file_size = path_stat.filesize;
1406 (
char *)memory_alloc( memory_options->user_data, file_size );
1408 return cgltf_result_out_of_memory;
1410 PHYSFS_file *pfile = PHYSFS_openRead( path );
1411 if ( pfile == NULL ) {
1412 WARN( _(
"Unable to open '%s' for reading: %s" ), path,
1413 PHYSFS_getErrorByCode( PHYSFS_getLastErrorCode() ) );
1414 return cgltf_result_file_not_found;
1416 cgltf_size read_size = PHYSFS_readBytes( pfile, file_data, file_size );
1417 PHYSFS_close( pfile );
1419 if ( read_size != file_size ) {
1420 memory_free( memory_options->user_data, file_data );
1421 return cgltf_result_io_error;
1429 return cgltf_result_success;
1434static _Thread_local
const GltfObject *cmp_obj;
1435static int cmp_node(
const void *p1,
const void *p2 )
1437 const Node *n1 = &cmp_obj->nodes[*(
size_t *)p1];
1438 const Node *n2 = &cmp_obj->nodes[*(
size_t *)p2];
1442 if ( n1->
mesh >= 0 ) {
1443 const Mesh *m = &cmp_obj->meshes[n1->
mesh];
1447 b1 |= cmp_obj->materials[mat].blend;
1450 if ( n2->
mesh >= 0 ) {
1451 const Mesh *m = &cmp_obj->meshes[n2->
mesh];
1455 b2 |= cmp_obj->materials[mat].blend;
1463static int cmp_mesh(
const void *p1,
const void *p2 )
1467 int b1 = ( m1->
material >= 0 ) ? cmp_obj->materials[m1->
material].blend : -1;
1468 int b2 = ( m2->
material >= 0 ) ? cmp_obj->materials[m2->
material].blend : -1;
1474static int cmp_mount(
const void *p1,
const void *p2 )
1478 return m1->
id - m2->
id;
1480static int cmp_trail(
const void *p1,
const void *p2 )
1484 double d = t1->
pos.v[1] - t2->
pos.v[1];
1492static const char *gltf_error_str( cgltf_result result )
1495 case cgltf_result_success:
1496 return p_(
"cgltf",
"success" );
1497 case cgltf_result_data_too_short:
1498 return p_(
"cgltf",
"data too short" );
1499 case cgltf_result_unknown_format:
1500 return p_(
"cgltf",
"unknown format" );
1501 case cgltf_result_invalid_json:
1502 return p_(
"cgltf",
"invalid json" );
1503 case cgltf_result_invalid_gltf:
1504 return p_(
"cgltf",
"invalid gltf" );
1505 case cgltf_result_invalid_options:
1506 return p_(
"cgltf",
"invalid options" );
1507 case cgltf_result_file_not_found:
1508 return p_(
"cgltf",
"file not found" );
1509 case cgltf_result_io_error:
1510 return p_(
"cgltf",
"io error" );
1511 case cgltf_result_out_of_memory:
1512 return p_(
"cgltf",
"out of memory" );
1513 case cgltf_result_legacy_gltf:
1514 return p_(
"cgltf",
"legacy gltf" );
1526GltfObject *gltf_loadFromFile(
const char *filename )
1534 memset( &opts, 0,
sizeof( opts ) );
1537 obj = cache_get( filename, &
new );
1546 dirpath = strdup( filename );
1548 SDL_asprintf( &obj->
path,
"%s", dirname( dirpath ) );
1551 snprintf( mountpath,
sizeof( mountpath ),
"%s/%s",
1552 PHYSFS_getRealDir( filename ), dirname( dirpath ) );
1553 PHYSFS_mount( mountpath,
"/", 0 );
1554 obj->
path = strdup( mountpath );
1559 opts.file.read = gltf_read;
1560 res = cgltf_parse_file( &opts, filename, &data );
1561 if ( res != cgltf_result_success ) {
1562 WARN( _(
"Error loading GLTF file '%s': %s" ), filename,
1563 gltf_error_str( res ) );
1569 res = cgltf_validate( data );
1570 if ( res != cgltf_result_success ) {
1571 WARN( _(
"Error loading GLTF file '%s': %s" ), filename,
1572 gltf_error_str( res ) );
1578 res = cgltf_load_buffers( &opts, data, filename );
1579 if ( res != cgltf_result_success ) {
1580 WARN( _(
"Error loading GLTF file '%s': %s" ), filename,
1581 gltf_error_str( res ) );
1588 for (
size_t i = 0; i < data->materials_count; i++ )
1589 gltf_loadMaterial( obj, &obj->
materials[i], &data->materials[i], data );
1592 obj->
nodes = calloc( data->nodes_count,
sizeof(
Node ) );
1593 obj->
nnodes = data->nodes_count;
1594 for (
size_t n = 0; n < obj->
nnodes; n++ ) {
1597 gltf_loadNode( obj, data, node, cnode );
1605 gltf_loadAnimation( obj, data, &obj->
animations[i],
1606 &data->animations[i] );
1613 obj->
meshes = calloc( data->meshes_count,
sizeof(
Mesh ) );
1614 obj->
nmeshes = data->meshes_count;
1615 for (
size_t i = 0; i < data->meshes_count; i++ )
1616 gltf_loadMesh( obj, data, &obj->
meshes[i], &data->meshes[i] );
1619 obj->
scenes = calloc( data->scenes_count,
sizeof(
Scene ) );
1620 obj->
nscenes = data->scenes_count;
1623 for (
size_t s = 0; s < obj->
nscenes; s++ ) {
1628 if ( cscene->name != NULL ) {
1629 scene->
name = strdup( cscene->name );
1630 if ( strcmp( scene->
name,
"body" ) == 0 )
1632 else if ( strcmp( scene->
name,
"engine" ) == 0 )
1637 scene->
nodes = calloc( cscene->nodes_count,
sizeof(
size_t ) );
1638 scene->
nnodes = cscene->nodes_count;
1639 for (
size_t i = 0; i < scene->
nnodes; i++ )
1640 scene->
nodes[i] = cgltf_node_index( data, cscene->nodes[i] );
1644 for (
size_t i = 0; i < obj->
nnodes; i++ )
1649 for (
size_t i = 0; i < obj->
nmeshes; i++ ) {
1653 for (
size_t s = 0; s < obj->
nscenes; s++ ) {
1655 qsort( scene->
nodes, scene->
nnodes,
sizeof(
size_t ), cmp_node );
1666 vec3_scale( &t->
pos, 1. / obj->
radius );
1673 vec3_scale( &m->
pos, 1. / obj->
radius );
1675 WARN( _(
"gltf warning '%s': expected mount with id=%d, but got %d!" ),
1676 filename, i, m->
id );
1680 LOG(
"Loaded %s", filename );
1684 PHYSFS_unmount( obj->
path );
1693static void gltf_freeMesh(
Mesh *mesh )
1698 glDeleteBuffers( 1, &mp->
vbo_idx );
1700 glDeleteBuffers( 1, &mp->
vbo_pos );
1702 glDeleteBuffers( 1, &mp->
vbo_nor );
1704 glDeleteBuffers( 1, &mp->
vbo_tex0 );
1706 glDeleteBuffers( 1, &mp->
vbo_tex1 );
1712static void gltf_freeNode(
Node *node )
1718static void gltf_freeAnimation(
Animation *anim )
1721 for (
size_t i = 0; i < anim->
nsamplers; i++ ) {
1730static void gltf_freeTex(
Texture *tex )
1733 if ( ( tex == NULL ) || ( tex->
tex == tex_zero.tex ) ||
1734 ( tex->
tex == tex_ones.tex ) )
1740 glDeleteTextures( 1, &tex->
tex );
1752 c = cache_dec( obj );
1758 for (
size_t i = 0; i < obj->
nmeshes; i++ ) {
1760 gltf_freeMesh( mesh );
1764 for (
size_t i = 0; i < obj->
nnodes; i++ ) {
1766 gltf_freeNode( node );
1772 gltf_freeAnimation( anim );
1776 for (
size_t s = 0; s < obj->
nscenes; s++ ) {
1778 free( scene->
name );
1779 free( scene->
nodes );
1783 for (
size_t i = 0; i < obj->
nmaterials; i++ ) {
1787 gltf_freeTex( &m->normal_tex );
1788 gltf_freeTex( &m->occlusion_tex );
1789 gltf_freeTex( &m->emissive_tex );
1804int gltf_init(
void )
1806 const GLubyte data_zero[4] = { 0, 0, 0, 0 };
1807 const GLubyte data_ones[4] = { 255, 255, 255, 255 };
1808 const GLfloat b[4] = { 1., 1., 1., 1. };
1811 const char *prepend_fix =
"#define MAX_LIGHTS " STR( MAX_LIGHTS )
"\n";
1812 char prepend[STRMAX];
1814 cache_lock = SDL_CreateMutex();
1817 L_default = L_default_const;
1818 for (
int i = 0; i < L_default.nlights; i++ )
1819 shadow_matrix( &light_mat_def[i], &L_default.lights[i] );
1822 use_normal_mapping = !conf.low_memory;
1823 use_ambient_occlusion = !conf.low_memory;
1824 max_tex_size = ( conf.low_memory ? conf.max_3d_tex_size : 0 );
1827 snprintf( prepend,
sizeof( prepend ),
1828 "%s\n#define HAS_NORMAL %d\n#define HAS_AO %d\n", prepend_fix,
1829 use_normal_mapping, use_ambient_occlusion );
1832 glGenTextures( 1, &tex_zero.tex );
1833 glBindTexture( GL_TEXTURE_2D, tex_zero.tex );
1834 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1836 glGenTextures( 1, &tex_ones.tex );
1837 glBindTexture( GL_TEXTURE_2D, tex_ones.tex );
1838 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1840 glBindTexture( GL_TEXTURE_2D, 0 );
1844 gltf_loadMaterial( NULL, &material_default, NULL, NULL );
1847 const GLfloat vbo_data[8] = { 0., 0., 1., 0., 0., 1., 1., 1. };
1848 glGenBuffers( 1, &shadow_vbo );
1849 glBindBuffer( GL_ARRAY_BUFFER, shadow_vbo );
1850 glBufferData( GL_ARRAY_BUFFER,
sizeof( GLfloat ) * 8, vbo_data,
1852 glBindBuffer( GL_ARRAY_BUFFER, 0 );
1854 for (
int l = 0; l < 2; l++ ) {
1856 shadowmap_size = SHADOWMAP_SIZE_LOW;
1857 light_fbo = light_fbo_low;
1858 light_tex = light_tex_low;
1859 shadow_fbo = &shadow_fbo_low;
1860 shadow_tex = &shadow_tex_low;
1862 shadowmap_size = SHADOWMAP_SIZE_HIGH;
1863 light_fbo = light_fbo_high;
1864 light_tex = light_tex_high;
1865 shadow_fbo = &shadow_fbo_high;
1866 shadow_tex = &shadow_tex_high;
1870 glGenTextures( 1, shadow_tex );
1871 glBindTexture( GL_TEXTURE_2D, *shadow_tex );
1872 glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, shadowmap_size,
1873 shadowmap_size, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL );
1874 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
1875 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1876 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );
1877 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );
1878 glTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, b );
1879 glBindTexture( GL_TEXTURE_2D, 0 );
1881 glGenFramebuffers( 1, shadow_fbo );
1882 glBindFramebuffer( GL_FRAMEBUFFER, *shadow_fbo );
1883 glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
1884 GL_TEXTURE_2D, *shadow_tex, 0 );
1885 glDrawBuffer( GL_NONE );
1886 glReadBuffer( GL_NONE );
1887 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
1888 status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
1889 if ( status != GL_FRAMEBUFFER_COMPLETE )
1890 WARN( _(
"Error setting up shadowmap framebuffer!" ) );
1893 glGenTextures( MAX_LIGHTS, light_tex );
1894 glGenFramebuffers( MAX_LIGHTS, light_fbo );
1895 for (
int i = 0; i < MAX_LIGHTS; i++ ) {
1897 glBindTexture( GL_TEXTURE_2D, light_tex[i] );
1898 glTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, shadowmap_size,
1899 shadowmap_size, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL );
1900 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
1901 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1902 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
1903 GL_CLAMP_TO_BORDER );
1904 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
1905 GL_CLAMP_TO_BORDER );
1906 glTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, b );
1907 glBindTexture( GL_TEXTURE_2D, 0 );
1909 glBindFramebuffer( GL_FRAMEBUFFER, light_fbo[i] );
1910 glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
1911 GL_TEXTURE_2D, light_tex[i], 0 );
1912 glDrawBuffer( GL_NONE );
1913 glReadBuffer( GL_NONE );
1914 glBindFramebuffer( GL_FRAMEBUFFER, 0 );
1915 status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
1916 if ( status != GL_FRAMEBUFFER_COMPLETE )
1917 WARN( _(
"Error setting up shadowmap framebuffer!" ) );
1922 shd = &shadow_shader;
1923 memset( shd, 0,
sizeof(
Shader ) );
1925 gl_program_backend(
"shadow.vert",
"shadow.frag", NULL, prepend );
1926 if ( shd->program == 0 )
1928 glUseProgram( shd->program );
1930 shd->vertex = glGetAttribLocation( shd->program,
"vertex" );
1932 shd->Hshadow = glGetUniformLocation( shd->program,
"u_shadow" );
1933 shd->Hmodel = glGetUniformLocation( shd->program,
"u_model" );
1936 shd = &shadow_shader_blurX;
1937 memset( shd, 0,
sizeof(
Shader ) );
1939 gl_program_backend(
"blur.vert",
"blurX.frag", NULL, prepend );
1940 if ( shd->program == 0 )
1942 glUseProgram( shd->program );
1944 shd->vertex = glGetAttribLocation( shd->program,
"vertex" );
1946 shd->baseColour_tex = glGetUniformLocation( shd->program,
"sampler" );
1947 glUniform1i( shd->baseColour_tex, 0 );
1950 shd = &shadow_shader_blurY;
1951 memset( shd, 0,
sizeof(
Shader ) );
1953 gl_program_backend(
"blur.vert",
"blurY.frag", NULL, prepend );
1954 if ( shd->program == 0 )
1956 glUseProgram( shd->program );
1958 shd->vertex = glGetAttribLocation( shd->program,
"vertex" );
1960 shd->baseColour_tex = glGetUniformLocation( shd->program,
"sampler" );
1964 memset( shd, 0,
sizeof(
Shader ) );
1966 gl_program_backend(
"gltf.vert",
"gltf_pbr.frag", NULL, prepend );
1967 if ( shd->program == 0 )
1969 glUseProgram( shd->program );
1971 shd->vertex = glGetAttribLocation( shd->program,
"vertex" );
1972 shd->vertex_normal = glGetAttribLocation( shd->program,
"vertex_normal" );
1973 shd->vertex_tex0 = glGetAttribLocation( shd->program,
"vertex_tex0" );
1974 shd->vertex_tex1 = glGetAttribLocation( shd->program,
"vertex_tex1" );
1976 shd->Hmodel = glGetUniformLocation( shd->program,
"u_model" );
1977 shd->Hnormal = glGetUniformLocation( shd->program,
"u_normal" );
1979 shd->blend = glGetUniformLocation( shd->program,
"u_blend" );
1980 shd->u_ambient = glGetUniformLocation( shd->program,
"u_ambient" );
1981 shd->baseColour_tex = glGetUniformLocation( shd->program,
"baseColour_tex" );
1982 shd->baseColour_texcoord =
1983 glGetUniformLocation( shd->program,
"baseColour_texcoord" );
1984 shd->metallic_tex = glGetUniformLocation( shd->program,
"metallic_tex" );
1985 shd->metallic_texcoord =
1986 glGetUniformLocation( shd->program,
"metallic_texcoord" );
1987 if ( use_normal_mapping ) {
1988 shd->u_has_normal = glGetUniformLocation( shd->program,
"u_has_normal" );
1989 shd->normal_tex = glGetUniformLocation( shd->program,
"normal_tex" );
1990 shd->normal_texcoord =
1991 glGetUniformLocation( shd->program,
"normal_texcoord" );
1992 shd->normal_scale = glGetUniformLocation( shd->program,
"normal_scale" );
1994 shd->metallicFactor = glGetUniformLocation( shd->program,
"metallicFactor" );
1995 shd->roughnessFactor =
1996 glGetUniformLocation( shd->program,
"roughnessFactor" );
1997 shd->baseColour = glGetUniformLocation( shd->program,
"baseColour" );
1999 shd->sheenTint = glGetUniformLocation( shd->program,
"sheenTint" );
2000 shd->sheen = glGetUniformLocation( shd->program,
"sheen" );
2001 shd->clearcoat = glGetUniformLocation( shd->program,
"clearcoat" );
2002 shd->clearcoat_roughness =
2003 glGetUniformLocation( shd->program,
"clearcoat_roughness" );
2005 shd->emissive = glGetUniformLocation( shd->program,
"emissive" );
2006 if ( use_ambient_occlusion ) {
2007 shd->occlusion_tex =
2008 glGetUniformLocation( shd->program,
"occlusion_tex" );
2009 shd->occlusion_texcoord =
2010 glGetUniformLocation( shd->program,
"occlusion_texcoord" );
2012 shd->emissive_tex = glGetUniformLocation( shd->program,
"emissive_tex" );
2013 shd->emissive_texcoord =
2014 glGetUniformLocation( shd->program,
"emissive_texcoord" );
2018 for (
int i = 0; i < MAX_LIGHTS; i++ ) {
2021 snprintf( buf,
sizeof( buf ),
"u_lights[%d].position", i );
2022 sl->position = glGetUniformLocation( shd->program, buf );
2023 snprintf( buf,
sizeof( buf ),
"u_lights[%d].sun", i );
2024 sl->sun = glGetUniformLocation( shd->program, buf );
2025 snprintf( buf,
sizeof( buf ),
"u_lights[%d].colour", i );
2026 sl->colour = glGetUniformLocation( shd->program, buf );
2027 snprintf( buf,
sizeof( buf ),
"u_lights[%d].intensity", i );
2028 sl->intensity = glGetUniformLocation( shd->program, buf );
2029 snprintf( buf,
sizeof( buf ),
"shadowmap_tex[%d]", i );
2030 sl->shadowmap_tex = glGetUniformLocation( shd->program, buf );
2031 snprintf( buf,
sizeof( buf ),
"u_shadow[%d]", i );
2032 sl->Hshadow = glGetUniformLocation( shd->program, buf );
2034 shd->nlights = glGetUniformLocation( shd->program,
"u_nlights" );
2043void gltf_exit(
void )
2046 if ( tex_zero.tex == 0 )
2049 SDL_DestroyMutex( cache_lock );
2050 for (
int i = 0; i <
array_size( obj_cache ); i++ ) {
2051 WARN( _(
"Object Cache '%s' not properly freed (refcount=%d)!" ),
2052 obj_cache[i].name, obj_cache[i].refcount );
2053 free( obj_cache->name );
2057 glDeleteBuffers( 1, &shadow_vbo );
2058 glDeleteTextures( 1, &shadow_tex_high );
2059 glDeleteTextures( 1, &shadow_tex_low );
2060 glDeleteFramebuffers( 1, &shadow_fbo_high );
2061 glDeleteFramebuffers( 1, &shadow_fbo_low );
2062 glDeleteTextures( MAX_LIGHTS, light_tex_low );
2063 glDeleteFramebuffers( MAX_LIGHTS, light_fbo_low );
2064 glDeleteTextures( MAX_LIGHTS, light_tex_high );
2065 glDeleteFramebuffers( MAX_LIGHTS, light_fbo_high );
2066 glDeleteTextures( 1, &tex_zero.tex );
2067 glDeleteTextures( 1, &tex_ones.tex );
2068 glDeleteProgram( gltf_shader.program );
2069 glDeleteProgram( shadow_shader.program );
2075void gltf_lightReset(
void )
2077 L_default = L_default_const;
2086int gltf_lightSet(
int idx,
const Light *L )
2088 int n = L_default_const.nlights +
2090 if ( n >= MAX_LIGHTS ) {
2091 WARN( _(
"Trying to set more lights than MAX_LIGHTS allows!" ) );
2094 L_default.nlights =
MAX( L_default.nlights, n + 1 );
2095 L_default.lights[n] = *L;
2096 shadow_matrix( &light_mat_def[n], &L_default.lights[n] );
2103void gltf_lightAmbient(
double r,
double g,
double b )
2105 const double factor = 1.0 / M_PI;
2106 L_default.ambient_r = r * factor;
2107 L_default.ambient_g = g * factor;
2108 L_default.ambient_b = b * factor;
2114void gltf_lightAmbientGet(
double *r,
double *g,
double *b )
2116 *r = L_default.ambient_r * M_PI;
2117 *g = L_default.ambient_g * M_PI;
2118 *b = L_default.ambient_b * M_PI;
2124void gltf_lightIntensity(
double strength )
2126 L_default.intensity = strength;
2132double gltf_lightIntensityGet(
void )
2134 return L_default.intensity;
2142 for (
int i = 0; i < L->
nlights; i++ ) {
2147 mat3_from_mat4( &h, H );
2148 mat3_mul_vec( &l->
pos, &h, &v );
2159GLuint gltf_shadowmap(
int light )
2161 return light_tex[light];
2167static int cache_cmp(
const void *p1,
const void *p2 )
2171 return strcmp( o1->
name, o2->
name );
2181static GltfObject *cache_get(
const char *filename,
int *
new )
2183 SDL_mutexP( cache_lock );
2185 .name = (
char *)filename,
2190 if ( hit == NULL ) {
2192 .name = strdup( filename ),
2196 if ( obj_cache == NULL )
2203 SDL_mutexV( cache_lock );
2209 SDL_mutexV( cache_lock );
2222 SDL_mutexP( cache_lock );
2223 for (
int i = 0; i <
array_size( obj_cache ); i++ ) {
2225 if (
c->obj != obj )
2229 if (
c->refcount <= 0 ) {
2232 SDL_mutexV( cache_lock );
2235 SDL_mutexV( cache_lock );
2238 WARN( _(
"GltfObject '%s' not found in cache!" ), obj->
path );
2239 SDL_mutexV( cache_lock );
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
void mat4_apply(mat4 *lhs, const mat4 *rhs)
Applies a transformation to another, storing the result in the left hand side.
mat4 mat4_lookat(const vec3 *eye, const vec3 *center, const vec3 *up)
Creates a matrix with a transformation to look at a center point from an eye with an up vector.
void mat4_mul_vec(vec3 *out, const mat4 *m, const vec3 *v)
Multiplies a matrix with a vector (out = m * v);.
void mat4_mul(mat4 *out, const mat4 *m1, const mat4 *m2)
Multiplies two matrices (out = m1 * m2).
void mat4_trs(mat4 *m, const vec3 *t, const quat *r, const vec3 *s)
Creates a homogeneous transform matrix from a translation, rotation, and scaling. Uses T*R*S order.
mat4 mat4_ortho(double left, double right, double bottom, double top, double nearVal, double farVal)
Creates an orthographic projection matrix.
Header file with generic functions and naev-specifics.
int nfile_simplifyPath(char path[static 1])
Simplifies the path removing things like ".." or consecutive "/".
USE_RESULT glTexture * gl_texExistsOrCreate(const char *path, unsigned int flags, int sx, int sy, int *created)
Check to see if a texture matching a path already exists.
int gl_fboCreate(GLuint *fbo, GLuint *tex, GLsizei width, GLsizei height)
Creates a framebuffer and its associated texture.
void gl_freeTexture(glTexture *texture)
Frees a texture.
AnimationSampler * sampler
AnimationInterpolation interp
AnimationChannel * channels
AnimationSampler * samplers
Defines a complete object.
Simple point/sun light model.
PBR Material of an object.
Represents the underlyig 3D data and associated material.
Represents a mesh that can be made of multiple primitives.
MeshPrimitive * primitives
Represents a node of an object. Each node can have multiple meshes and children nodes with an associa...
Simple caching for GLTF objects to avoid double loads.
Represents a scene that can have multiple nodes.
Simple point light model for shaders.
Shader to use witha material.