diff --git a/src/engine/renderer/glsl_source/vertexSkinning_vp.glsl b/src/engine/renderer/glsl_source/vertexSkinning_vp.glsl index 71121ef2d3..4427374ef3 100644 --- a/src/engine/renderer/glsl_source/vertexSkinning_vp.glsl +++ b/src/engine/renderer/glsl_source/vertexSkinning_vp.glsl @@ -41,8 +41,20 @@ void VertexFetch(out vec4 position, const float scale = 1.0 / 256.0; localBasis inLB; - ivec4 idx = 2 * ( ivec4(attr_BoneFactors) >> 8 ); - vec4 weights = ( ivec4(attr_BoneFactors) & 0xFF ) / 255.0; + #if __VERSION__ > 120 + /* This code works on GL 3 GPUs and later including the + Nvidia proprietary driver but does not work on GL 2 GPUs. + See https://github.com/DaemonEngine/Daemon/issues/490 */ + ivec4 idx = 2 * ( ivec4(attr_BoneFactors) >> 8 ); + vec4 weights = ( ivec4(attr_BoneFactors) & 0xFF ) / 255.0; + #else + /* This code works on GL 2 GPUs and later but the Nvidia + proprietary driver is affected by a bug starting with GL 3 GPUs. + See https://github.com/DaemonEngine/Daemon/issues/472 */ + ivec4 idx = 2 * ivec4( floor( attr_BoneFactors * scale ) ); + vec4 weights = fract( attr_BoneFactors * scale ); + weights.x = 1.0 - weights.x; + #endif vec4 quat = u_Bones[ idx.x ]; vec4 trans = u_Bones[ idx.x + 1 ]; diff --git a/src/engine/renderer/tr_vbo.cpp b/src/engine/renderer/tr_vbo.cpp index e51185d5ac..a2a8b0e0a0 100644 --- a/src/engine/renderer/tr_vbo.cpp +++ b/src/engine/renderer/tr_vbo.cpp @@ -304,11 +304,28 @@ static void R_SetVBOAttributeLayouts( VBO_t *vbo ) } } -// index has to be in range 0-255, weight has to be >= 0 and <= 1 static inline unsigned short boneFactor( int index, float weight ) { - int scaledWeight = lrintf( weight * 255.0 ); - return (unsigned short)( ( index << 8 ) | scaledWeight ); + if ( glConfig.driverType == glDriverType_t::GLDRV_OPENGL3 ) + { + /* This code works on GL 3 GPUs and later including the + Nvidia proprietary driver but does not work on GL 2 GPUs. + See https://github.com/DaemonEngine/Daemon/issues/490 */ + + // index has to be in range 0-255, weight has to be >= 0 and <= 1 + int scaledWeight = lrintf( weight * 255.0 ); + return (unsigned short)( ( index << 8 ) | scaledWeight ); + } + else + { + /* This code works on GL 2 GPUs and later but the Nvidia + proprietary driver is affected by a bug starting with GL 3 GPUs. + See https://github.com/DaemonEngine/Daemon/issues/472 */ + + // index has to be in range 0-255, weight has to be >= 0 and < 1 + int scaledWeight = lrintf( weight * 256.0 ); + return (unsigned short)( ( index << 8 ) | std::min( scaledWeight, 255 ) ); + } } static void R_CopyVertexData( VBO_t *vbo, byte *outData, vboData_t inData ) @@ -369,8 +386,26 @@ static void R_CopyVertexData( VBO_t *vbo, byte *outData, vboData_t inData ) if ( ( vbo->attribBits & ATTR_BONE_FACTORS ) ) { uint32_t j; + int start; + + if ( glConfig.driverType == glDriverType_t::GLDRV_OPENGL3 ) + { + /* This code works on GL 3 GPUs and later including the + Nvidia proprietary driver but does not work on GL 2 GPUs. + See https://github.com/DaemonEngine/Daemon/issues/490 */ + start = 0; + } + else + { + /* This code works on GL 2 GPUs and later but the Nvidia + proprietary driver is affected by a bug starting with GL 3 GPUs. + See https://github.com/DaemonEngine/Daemon/issues/472 */ + ptr[ v ].boneFactors[ 0 ] = boneFactor( inData.boneIndexes[ v ][ 0 ], + 1.0f - inData.boneWeights[ v ][ 0 ]); + start = 1; + } - for ( j = 0; j < 4; j++ ) { + for ( j = start; j < 4; j++ ) { ptr[ v ].boneFactors[ j ] = boneFactor( inData.boneIndexes[ v ][ j ], inData.boneWeights[ v ][ j ] ); }