From 26697d3286230efbd32f3cb528253f9d4b93b6c6 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 5 Nov 2022 12:05:17 +0100 Subject: [PATCH 1/6] renderer: use correct f16vecN_t types instead of i16vecN_t ones in many places tr_local: define a simple f16_t type tr_local: shaderVertex_t.texCoords is f16vec4_t because it is the output of floatToHalf tr_local: make it more obvious that f16vec4_t is i16vec4_t tr_local: R_CalcTangents expects f16vec2_t not i16vec2_t tr_model_iqm: IQModel_t.texcoords is f16vec2_t because it is the output of floatToHalf tr_local,tr_model_md3,tr_model_skel: vboData_t.st is f16vec2_t because it is the output of floatToHalf tr_local: vboData_t.spriteOrientation is f16vec4_t because it is the output of floatToHalf tr_local: order data like everywhere else in code --- src/engine/renderer/tr_local.h | 21 ++++++++++++--------- src/engine/renderer/tr_main.cpp | 2 +- src/engine/renderer/tr_model_iqm.cpp | 6 +++--- src/engine/renderer/tr_model_md3.cpp | 2 +- src/engine/renderer/tr_model_skel.cpp | 2 +- src/engine/renderer/tr_surface.cpp | 2 +- src/engine/renderer/tr_vbo.cpp | 4 ++-- 7 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 4a5fc38c8a..174bf4be37 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -44,7 +44,10 @@ using i16vec4_t = int16_t[4]; using u16vec4_t = uint16_t[4]; using i16vec2_t = int16_t[2]; using u16vec2_t = uint16_t[2]; -using f16vec4_t = int16_t[4]; // half float vector + +using f16_t = int16_t; // half float +using f16vec2_t = f16_t[2]; // half float vector +using f16vec4_t = f16_t[4]; // half float vector // GL conversion helpers static inline float unorm8ToFloat(byte unorm8) { @@ -114,13 +117,13 @@ static inline void snorm16ToFloat( const i16vec4_t in, vec4_t out ) out[ 3 ] = snorm16ToFloat( in[ 3 ] ); } -static inline int16_t floatToHalf( float in ) { +static inline f16_t floatToHalf( float in ) { static float scale = powf(2.0f, 15 - 127); floatint_t fi; fi.f = in * scale; - return (int16_t)(((fi.ui & 0x80000000) >> 16) | ((fi.ui & 0x0fffe000) >> 13)); + return (f16_t)(((fi.ui & 0x80000000) >> 16) | ((fi.ui & 0x0fffe000) >> 13)); } static inline void floatToHalf( const vec4_t in, f16vec4_t out ) { @@ -129,7 +132,7 @@ static inline void floatToHalf( const vec4_t in, f16vec4_t out ) out[ 2 ] = floatToHalf( in[ 2 ] ); out[ 3 ] = floatToHalf( in[ 3 ] ); } -static inline float halfToFloat( int16_t in ) { +static inline float halfToFloat( f16_t in ) { static float scale = powf(2.0f, 127 - 15); floatint_t fi; @@ -813,10 +816,10 @@ static inline void glFboSetExt() vec3_t *xyz; i16vec4_t *qtangent; u8vec4_t *color; - union { i16vec2_t *st; i16vec4_t *stpq; vec2_t *stf; }; + union { f16vec2_t *st; f16vec4_t *stpq; vec2_t *stf; }; int (*boneIndexes)[ 4 ]; vec4_t *boneWeights; - vec4_t *spriteOrientation; + f16vec4_t *spriteOrientation; int numFrames; int numVerts; @@ -2394,10 +2397,10 @@ static inline void glFboSetExt() // vertex data float *positions; - int16_t *texcoords; float *normals; float *tangents; float *bitangents; + f16_t *texcoords; byte *blendIndexes; byte *blendWeights; byte *colors; @@ -3181,7 +3184,7 @@ inline bool checkGLErrors() void R_CalcTangents( vec3_t tangent, vec3_t binormal, const vec3_t v0, const vec3_t v1, const vec3_t v2, - const i16vec2_t t0, const i16vec2_t t1, const i16vec2_t t2 ); + const f16vec2_t t0, const f16vec2_t t1, const f16vec2_t t2 ); /* * QTangent representation of tangentspace: @@ -3398,7 +3401,7 @@ inline bool checkGLErrors() i16vec4_t qtangents; f16vec4_t spriteOrientation; }; - i16vec4_t texCoords; + f16vec4_t texCoords; }; #ifdef GL_ARB_sync diff --git a/src/engine/renderer/tr_main.cpp b/src/engine/renderer/tr_main.cpp index 6afcd5631e..8d466e1c9b 100644 --- a/src/engine/renderer/tr_main.cpp +++ b/src/engine/renderer/tr_main.cpp @@ -102,7 +102,7 @@ void R_CalcTangents( vec3_t tangent, vec3_t binormal, void R_CalcTangents( vec3_t tangent, vec3_t binormal, const vec3_t v0, const vec3_t v1, const vec3_t v2, - const i16vec2_t t0, const i16vec2_t t1, const i16vec2_t t2 ) + const f16vec2_t t0, const f16vec2_t t1, const f16vec2_t t2 ) { vec2_t t0f, t1f, t2f; diff --git a/src/engine/renderer/tr_model_iqm.cpp b/src/engine/renderer/tr_model_iqm.cpp index f2a461eb0c..b221dafcde 100644 --- a/src/engine/renderer/tr_model_iqm.cpp +++ b/src/engine/renderer/tr_model_iqm.cpp @@ -480,7 +480,7 @@ bool R_LoadIQModel( model_t *mod, void *buffer, int filesize, size += header->num_vertexes * 3 * sizeof(float); // normals size += header->num_vertexes * 3 * sizeof(float); // tangents size += header->num_vertexes * 3 * sizeof(float); // bitangents - size += header->num_vertexes * 2 * sizeof(int16_t); // texcoords + size += header->num_vertexes * 2 * sizeof(f16_t); // texcoords size += header->num_vertexes * 4 * sizeof(byte); // blendIndexes size += header->num_vertexes * 4 * sizeof(byte); // blendWeights size += header->num_vertexes * 4 * sizeof(byte); // colors @@ -540,7 +540,7 @@ bool R_LoadIQModel( model_t *mod, void *buffer, int filesize, IQModel->bitangents = (float *)ptr; ptr = IQModel->bitangents + 3 * header->num_vertexes; - IQModel->texcoords = (int16_t *)ptr; + IQModel->texcoords = (f16_t *)ptr; ptr = IQModel->texcoords + 2 * header->num_vertexes; IQModel->blendIndexes = (byte *)ptr; @@ -803,7 +803,7 @@ bool R_LoadIQModel( model_t *mod, void *buffer, int filesize, vboData.qtangent = qtangentbuf; vboData.numFrames = 0; vboData.color = (u8vec4_t *)IQModel->colors; - vboData.st = (i16vec2_t *)IQModel->texcoords; + vboData.st = (f16vec2_t *)IQModel->texcoords; vboData.noLightCoords = true; vboData.boneIndexes = (int (*)[4])indexbuf; vboData.boneWeights = (vec4_t *)weightbuf; diff --git a/src/engine/renderer/tr_model_md3.cpp b/src/engine/renderer/tr_model_md3.cpp index 56884b258b..c9dd4155f8 100644 --- a/src/engine/renderer/tr_model_md3.cpp +++ b/src/engine/renderer/tr_model_md3.cpp @@ -259,7 +259,7 @@ bool R_LoadMD3( model_t *mod, int lod, void *buffer, const char *modName ) data.xyz = ( vec3_t * ) ri.Hunk_AllocateTempMemory( sizeof( *data.xyz ) * mdvModel->numFrames * surf->numVerts ); data.qtangent = ( i16vec4_t * ) ri.Hunk_AllocateTempMemory( sizeof( i16vec4_t ) * mdvModel->numFrames * surf->numVerts ); data.numFrames = mdvModel->numFrames; - data.st = ( i16vec2_t * ) ri.Hunk_AllocateTempMemory( sizeof( i16vec2_t ) * surf->numVerts ); + data.st = ( f16vec2_t * ) ri.Hunk_AllocateTempMemory( sizeof( f16vec2_t ) * surf->numVerts ); data.noLightCoords = true; data.numVerts = surf->numVerts; diff --git a/src/engine/renderer/tr_model_skel.cpp b/src/engine/renderer/tr_model_skel.cpp index d1aa765470..8d07bd9f64 100644 --- a/src/engine/renderer/tr_model_skel.cpp +++ b/src/engine/renderer/tr_model_skel.cpp @@ -131,7 +131,7 @@ void AddSurfaceToVBOSurfacesList( growList_t *vboSurfaces, growList_t *vboTriang data.qtangent = ( i16vec4_t * ) ri.Hunk_AllocateTempMemory( sizeof( i16vec4_t ) * vertexesNum ); data.boneIndexes = ( int (*)[ 4 ] ) ri.Hunk_AllocateTempMemory( sizeof( *data.boneIndexes ) * vertexesNum ); data.boneWeights = ( vec4_t * ) ri.Hunk_AllocateTempMemory( sizeof( *data.boneWeights ) * vertexesNum ); - data.st = ( i16vec2_t * ) ri.Hunk_AllocateTempMemory( sizeof( i16vec2_t ) * vertexesNum ); + data.st = ( f16vec2_t * ) ri.Hunk_AllocateTempMemory( sizeof( f16vec2_t ) * vertexesNum ); data.noLightCoords = true; data.numVerts = vertexesNum; diff --git a/src/engine/renderer/tr_surface.cpp b/src/engine/renderer/tr_surface.cpp index 81dba71140..7a872e6d6c 100644 --- a/src/engine/renderer/tr_surface.cpp +++ b/src/engine/renderer/tr_surface.cpp @@ -1317,7 +1317,7 @@ void Tess_SurfaceIQM( srfIQModel_t *surf ) { float *modelNormal = model->normals + 3 * firstVertex; float *modelTangent = model->tangents + 3 * firstVertex; float *modelBitangent = model->bitangents + 3 * firstVertex; - int16_t *modelTexcoord = model->texcoords + 2 * firstVertex; + f16_t *modelTexcoord = model->texcoords + 2 * firstVertex; shaderVertex_t *tessVertex = tess.verts + tess.numVertexes; shaderVertex_t *lastVertex = tessVertex + surf->num_vertexes; diff --git a/src/engine/renderer/tr_vbo.cpp b/src/engine/renderer/tr_vbo.cpp index 1fafd6f2bd..b5c6c33b21 100644 --- a/src/engine/renderer/tr_vbo.cpp +++ b/src/engine/renderer/tr_vbo.cpp @@ -32,7 +32,7 @@ struct fmtVertexAnim1 { const GLsizei sizeVertexAnim1 = sizeof( struct fmtVertexAnim1 ); // interleaved texcoords and colour in part 2 struct fmtVertexAnim2 { - i16vec2_t texcoord; + f16vec2_t texcoord; Color::Color32Bit colour; }; const GLsizei sizeVertexAnim2 = sizeof( struct fmtVertexAnim2 ); @@ -40,7 +40,7 @@ const GLsizei sizeVertexAnim2 = sizeof( struct fmtVertexAnim2 ); // interleaved data: position, texcoord, colour, qtangent, bonefactors struct fmtSkeletal { i16vec4_t position; - i16vec2_t texcoord; + f16vec2_t texcoord; Color::Color32Bit colour; i16vec4_t qtangents; u16vec4_t boneFactors; From b4df935675c7b2b107fff2cf8481d7357a9687c1 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 5 Nov 2022 20:45:22 +0100 Subject: [PATCH 2/6] tr_model_md5,tr_model_skel,tr_surface: rename md5vertex_t.texCoords as texCoordsF as it's the only one to use float --- src/engine/renderer/tr_local.h | 2 +- src/engine/renderer/tr_model_md5.cpp | 8 ++++---- src/engine/renderer/tr_model_skel.cpp | 4 ++-- src/engine/renderer/tr_surface.cpp | 8 ++------ 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index 174bf4be37..e9ca2dfe9d 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -2267,7 +2267,7 @@ static inline void glFboSetExt() vec4_t tangent; vec4_t binormal; vec4_t normal; - vec2_t texCoords; + vec2_t texCoordsF; uint32_t firstWeight; uint32_t numWeights; diff --git a/src/engine/renderer/tr_model_md5.cpp b/src/engine/renderer/tr_model_md5.cpp index e59652fce2..bda5307585 100644 --- a/src/engine/renderer/tr_model_md5.cpp +++ b/src/engine/renderer/tr_model_md5.cpp @@ -325,7 +325,7 @@ bool R_LoadMD5( model_t *mod, void *buffer, const char *modName ) for (unsigned k = 0; k < 2; k++ ) { token = COM_ParseExt2( &buf_p, false ); - v->texCoords[ k ] = atof( token ); + v->texCoordsF[ k ] = atof( token ); } // skip ) @@ -518,9 +518,9 @@ bool R_LoadMD5( model_t *mod, void *buffer, const char *modName ) v1 = surf->verts[ tri->indexes[ 1 ] ].position; v2 = surf->verts[ tri->indexes[ 2 ] ].position; - t0 = surf->verts[ tri->indexes[ 0 ] ].texCoords; - t1 = surf->verts[ tri->indexes[ 1 ] ].texCoords; - t2 = surf->verts[ tri->indexes[ 2 ] ].texCoords; + t0 = surf->verts[ tri->indexes[ 0 ] ].texCoordsF; + t1 = surf->verts[ tri->indexes[ 1 ] ].texCoordsF; + t2 = surf->verts[ tri->indexes[ 2 ] ].texCoordsF; R_CalcFaceNormal( normal, v0, v1, v2 ); R_CalcTangents( tangent, binormal, v0, v1, v2, t0, t1, t2 ); diff --git a/src/engine/renderer/tr_model_skel.cpp b/src/engine/renderer/tr_model_skel.cpp index 8d07bd9f64..beae801678 100644 --- a/src/engine/renderer/tr_model_skel.cpp +++ b/src/engine/renderer/tr_model_skel.cpp @@ -168,8 +168,8 @@ void AddSurfaceToVBOSurfacesList( growList_t *vboSurfaces, growList_t *vboTriang R_TBNtoQtangents( surf->verts[ j ].tangent, surf->verts[ j ].binormal, surf->verts[ j ].normal, data.qtangent[ j ] ); - data.st[ j ][ 0 ] = floatToHalf( surf->verts[ j ].texCoords[ 0 ] ); - data.st[ j ][ 1 ] = floatToHalf( surf->verts[ j ].texCoords[ 1 ] ); + data.st[ j ][ 0 ] = floatToHalf( surf->verts[ j ].texCoordsF[ 0 ] ); + data.st[ j ][ 1 ] = floatToHalf( surf->verts[ j ].texCoordsF[ 1 ] ); for (unsigned k = 0; k < MAX_WEIGHTS; k++ ) { diff --git a/src/engine/renderer/tr_surface.cpp b/src/engine/renderer/tr_surface.cpp index 7a872e6d6c..21d10f70ba 100644 --- a/src/engine/renderer/tr_surface.cpp +++ b/src/engine/renderer/tr_surface.cpp @@ -1147,9 +1147,7 @@ static void Tess_SurfaceMD5( md5Surface_t *srf ) VectorCopy( position, tessVertex->xyz ); - Vector2Set( tessVertex->texCoords, - floatToHalf( surfaceVertex->texCoords[ 0 ] ), - floatToHalf( surfaceVertex->texCoords[ 1 ] ) ); + floatToHalf( surfaceVertex->texCoordsF, tessVertex->texCoords ); } } else @@ -1192,9 +1190,7 @@ static void Tess_SurfaceMD5( md5Surface_t *srf ) R_TBNtoQtangents( tangent, binormal, normal, tessVertex->qtangents ); - Vector2Set( tessVertex->texCoords, - floatToHalf( surfaceVertex->texCoords[ 0 ] ), - floatToHalf( surfaceVertex->texCoords[ 1 ] ) ); + floatToHalf( surfaceVertex->texCoordsF, tessVertex->texCoords ); } } From 75245c275c14c27338a5cf534dcc0100dd07d9d3 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 5 Nov 2022 19:45:22 +0100 Subject: [PATCH 3/6] tr_shade_calc: convert 0 to half float before setting f16vec4_t spriteOrientation --- src/engine/renderer/tr_shade_calc.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/engine/renderer/tr_shade_calc.cpp b/src/engine/renderer/tr_shade_calc.cpp index 8168489376..30cff2afd5 100644 --- a/src/engine/renderer/tr_shade_calc.cpp +++ b/src/engine/renderer/tr_shade_calc.cpp @@ -543,7 +543,10 @@ static void AutospriteDeform( int firstVertex, int numVertexes, int numIndexes ) for ( j = 0; j < 4; j++ ) { VectorCopy( mid, v[ j ].xyz ); Vector4Set( v[ j ].spriteOrientation, - 0, 0, 0, floatToHalf( radius ) ); + floatToHalf( 0 ), + floatToHalf( 0 ), + floatToHalf( 0 ), + floatToHalf( radius ) ); } } } From 62d008a5a3cb7b7b233d756b23cbe3b2d5cb59ff Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Sat, 5 Nov 2022 19:45:22 +0100 Subject: [PATCH 4/6] tr_shade_calc: multiply float with float --- src/engine/renderer/tr_shade_calc.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/renderer/tr_shade_calc.cpp b/src/engine/renderer/tr_shade_calc.cpp index 30cff2afd5..bd4b386d41 100644 --- a/src/engine/renderer/tr_shade_calc.cpp +++ b/src/engine/renderer/tr_shade_calc.cpp @@ -667,7 +667,7 @@ static void Autosprite2Deform( int firstVertex, int numVertexes, int numIndexes k = 1; VectorSubtract( v1->xyz, mid[ k ], minor ); - if ( ( DotProduct( cross, minor ) * v1->texCoords[ 3 ] ) < 0 ) { + if ( ( DotProduct( cross, minor ) * halfToFloat( v1->texCoords[ 3 ] ) ) < 0 ) { VectorNegate( major, orientation ); } else { VectorCopy( major, orientation ); From c71f11a40f375f4964612ba11a888b855735e134 Mon Sep 17 00:00:00 2001 From: slipher Date: Sat, 5 Nov 2022 16:38:50 -0500 Subject: [PATCH 5/6] tr_local: define a half-float struct f16_t for type safety --- src/engine/renderer/tr_local.h | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index e9ca2dfe9d..ee77bf8582 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -45,7 +45,12 @@ using u16vec4_t = uint16_t[4]; using i16vec2_t = int16_t[2]; using u16vec2_t = uint16_t[2]; -using f16_t = int16_t; // half float +// The struct has the same memory layout as a half-float +struct f16_t +{ + uint16_t bits; +}; + using f16vec2_t = f16_t[2]; // half float vector using f16vec4_t = f16_t[4]; // half float vector @@ -123,7 +128,7 @@ static inline f16_t floatToHalf( float in ) { fi.f = in * scale; - return (f16_t)(((fi.ui & 0x80000000) >> 16) | ((fi.ui & 0x0fffe000) >> 13)); + return { uint16_t(((fi.ui & 0x80000000) >> 16) | ((fi.ui & 0x0fffe000) >> 13)) }; } static inline void floatToHalf( const vec4_t in, f16vec4_t out ) { @@ -136,7 +141,7 @@ static inline float halfToFloat( f16_t in ) { static float scale = powf(2.0f, 127 - 15); floatint_t fi; - fi.ui = (((unsigned int)in & 0x8000) << 16) | (((unsigned int)in & 0x7fff) << 13); + fi.ui = (((unsigned int)in.bits & 0x8000) << 16) | (((unsigned int)in.bits & 0x7fff) << 13); return fi.f * scale; } static inline void halfToFloat( const f16vec4_t in, vec4_t out ) From 31d1339f79c3a0979ba055c5bb8d6e4bd95ccfd3 Mon Sep 17 00:00:00 2001 From: slipher Date: Sat, 5 Nov 2022 16:38:50 -0500 Subject: [PATCH 6/6] tr_shade_calc: use half float sign bit to avoid calling halfToFloat --- src/engine/renderer/tr_shade_calc.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/renderer/tr_shade_calc.cpp b/src/engine/renderer/tr_shade_calc.cpp index bd4b386d41..1ccc5959c1 100644 --- a/src/engine/renderer/tr_shade_calc.cpp +++ b/src/engine/renderer/tr_shade_calc.cpp @@ -667,7 +667,8 @@ static void Autosprite2Deform( int firstVertex, int numVertexes, int numIndexes k = 1; VectorSubtract( v1->xyz, mid[ k ], minor ); - if ( ( DotProduct( cross, minor ) * halfToFloat( v1->texCoords[ 3 ] ) ) < 0 ) { + // I guess this works, since the sign bit is the MSB for both floating point and integers + if ( ( DotProduct( cross, minor ) * static_cast(v1->texCoords[ 3 ].bits) ) < 0 ) { VectorNegate( major, orientation ); } else { VectorCopy( major, orientation );