[ioquake3] 12/21: Fix floating point precision loss in renderer [part 1]

Simon McVittie smcv at debian.org
Fri Aug 4 20:39:13 UTC 2017


This is an automated email from the git hooks/post-receive script.

smcv pushed a commit to branch debian/master
in repository ioquake3.

commit 30fdd88c9fecd152080044360fc33bbc65500b5d
Author: Zack Middleton <zack at cloemail.com>
Date:   Wed Aug 2 22:39:27 2017 -0500

    Fix floating point precision loss in renderer [part 1]
    
    Patch for https://bugzilla.icculus.org/show_bug.cgi?id=5931 by
    Eugene C. from 2013 plus recent fix for tcMod rotate.
    
    I merged the changes into the OpenGL2 renderer though the fix for
    tcMod turb doesn't translate.
---
 code/renderergl1/tr_backend.c    |  9 ++++++---
 code/renderergl1/tr_local.h      | 18 +++++++++---------
 code/renderergl1/tr_shade.c      |  9 ++++++---
 code/renderergl1/tr_shade_calc.c | 20 +++++++++++---------
 code/renderergl2/tr_backend.c    |  9 ++++++---
 code/renderergl2/tr_local.h      | 18 +++++++++---------
 code/renderergl2/tr_shade.c      |  9 ++++++---
 code/renderergl2/tr_shade_calc.c | 18 ++++++++++--------
 8 files changed, 63 insertions(+), 47 deletions(-)

diff --git a/code/renderergl1/tr_backend.c b/code/renderergl1/tr_backend.c
index 41fe47a..22ec048 100644
--- a/code/renderergl1/tr_backend.c
+++ b/code/renderergl1/tr_backend.c
@@ -509,7 +509,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
 	int				i;
 	drawSurf_t		*drawSurf;
 	int				oldSort;
-	float			originalTime;
+	double			originalTime;
 
 	// save original time for entity shader offsets
 	originalTime = backEnd.refdef.floatTime;
@@ -562,7 +562,10 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
 
 			if ( entityNum != REFENTITYNUM_WORLD ) {
 				backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
-				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
+
+				// FIXME: e.shaderTime must be passed as int to avoid fp-precision loss issues
+				backEnd.refdef.floatTime = originalTime - (double)backEnd.currentEntity->e.shaderTime;
+
 				// we have to reset the shaderTime as well otherwise image animations start
 				// from the wrong frame
 				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
@@ -713,7 +716,7 @@ void	RB_SetGL2D (void) {
 
 	// set time for 2D shaders
 	backEnd.refdef.time = ri.Milliseconds();
-	backEnd.refdef.floatTime = backEnd.refdef.time * 0.001f;
+	backEnd.refdef.floatTime = (double)backEnd.refdef.time * 0.001f;
 }
 
 
diff --git a/code/renderergl1/tr_local.h b/code/renderergl1/tr_local.h
index 37e0e07..54279a6 100644
--- a/code/renderergl1/tr_local.h
+++ b/code/renderergl1/tr_local.h
@@ -189,10 +189,10 @@ typedef enum {
 typedef struct {
 	genFunc_t	func;
 
-	float base;
-	float amplitude;
-	float phase;
-	float frequency;
+	double base;
+	double amplitude;
+	double phase;
+	double frequency;
 } waveForm_t;
 
 #define TR_MAX_TEXMODS 4
@@ -252,7 +252,7 @@ typedef struct {
 typedef struct {
 	image_t			*image[MAX_IMAGE_ANIMATIONS];
 	int				numImageAnimations;
-	float			imageAnimationSpeed;
+	double			imageAnimationSpeed;
 
 	texCoordGen_t	tcGen;
 	vec3_t			tcGenVectors[2];
@@ -362,8 +362,8 @@ typedef struct shader_s {
 
 	void		(*optimalStageIteratorFunc)( void );
 
-  float clampTime;                                  // time this shader is clamped to
-  float timeOffset;                                 // current time offset for this shader
+  double clampTime;                                  // time this shader is clamped to
+  double timeOffset;                                 // current time offset for this shader
 
   struct shader_s *remappedShader;                  // current shader this one is remapped too
 
@@ -388,7 +388,7 @@ typedef struct {
 	byte		areamask[MAX_MAP_AREA_BYTES];
 	qboolean	areamaskModified;	// qtrue if areamask changed since last scene
 
-	float		floatTime;			// tr.refdef.time / 1000.0
+	double		floatTime;			// tr.refdef.time / 1000.0
 
 	// text messages for deform text shaders
 	char		text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH];
@@ -1217,7 +1217,7 @@ typedef struct shaderCommands_s
 	color4ub_t	constantColor255[SHADER_MAX_VERTEXES] QALIGN(16);
 
 	shader_t	*shader;
-	float		shaderTime;
+	double		shaderTime;
 	int			fogNum;
 
 	int			dlightBits;	// or together of all vertexDlightBits
diff --git a/code/renderergl1/tr_shade.c b/code/renderergl1/tr_shade.c
index d26cb1a..ab5813f 100644
--- a/code/renderergl1/tr_shade.c
+++ b/code/renderergl1/tr_shade.c
@@ -218,7 +218,8 @@ R_BindAnimatedImage
 =================
 */
 static void R_BindAnimatedImage( textureBundle_t *bundle ) {
-	int		index;
+	int64_t index;
+	double	v;
 
 	if ( bundle->isVideoMap ) {
 		ri.CIN_RunCinematic(bundle->videoMapHandle);
@@ -233,8 +234,10 @@ static void R_BindAnimatedImage( textureBundle_t *bundle ) {
 
 	// it is necessary to do this messy calc to make sure animations line up
 	// exactly with waveforms of the same frequency
-	index = ri.ftol(tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE);
-	index >>= FUNCTABLE_SIZE2;
+	//index = ri.ftol(tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE);
+	//index >>= FUNCTABLE_SIZE2;
+	v = tess.shaderTime * bundle->imageAnimationSpeed;
+	index = v;
 
 	if ( index < 0 ) {
 		index = 0;	// may happen with shader time offsets
diff --git a/code/renderergl1/tr_shade_calc.c b/code/renderergl1/tr_shade_calc.c
index 82f7c0c..34975e2 100644
--- a/code/renderergl1/tr_shade_calc.c
+++ b/code/renderergl1/tr_shade_calc.c
@@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #endif
 
 
-#define	WAVEVALUE( table, base, amplitude, phase, freq )  ((base) + table[ ri.ftol( ( ( (phase) + tess.shaderTime * (freq) ) * FUNCTABLE_SIZE ) ) & FUNCTABLE_MASK ] * (amplitude))
+#define	WAVEVALUE( table, base, amplitude, phase, freq )  ((base) + table[ (int)( ( ( (phase) + tess.shaderTime * (freq) ) * FUNCTABLE_SIZE ) ) & FUNCTABLE_MASK ] * (amplitude))
 
 static float *TableForFunc( genFunc_t func ) 
 {
@@ -920,7 +920,7 @@ void RB_CalcEnvironmentTexCoords( float *st )
 void RB_CalcTurbulentTexCoords( const waveForm_t *wf, float *st )
 {
 	int i;
-	float now;
+	double now;
 
 	now = ( wf->phase + tess.shaderTime * wf->frequency );
 
@@ -954,11 +954,13 @@ void RB_CalcScaleTexCoords( const float scale[2], float *st )
 void RB_CalcScrollTexCoords( const float scrollSpeed[2], float *st )
 {
 	int i;
-	float timeScale = tess.shaderTime;
-	float adjustedScrollS, adjustedScrollT;
+	double timeScale;
+	double adjustedScrollS, adjustedScrollT;
 
-	adjustedScrollS = scrollSpeed[0] * timeScale;
-	adjustedScrollT = scrollSpeed[1] * timeScale;
+	timeScale = tess.shaderTime;
+
+	adjustedScrollS = (double)scrollSpeed[0] * timeScale;
+	adjustedScrollT = (double)scrollSpeed[1] * timeScale;
 
 	// clamp so coordinates don't continuously get larger, causing problems
 	// with hardware limits
@@ -994,9 +996,9 @@ void RB_CalcTransformTexCoords( const texModInfo_t *tmi, float *st  )
 */
 void RB_CalcRotateTexCoords( float degsPerSecond, float *st )
 {
-	float timeScale = tess.shaderTime;
-	float degs;
-	int index;
+	double timeScale = tess.shaderTime;
+	double degs;
+	int64_t index;
 	float sinValue, cosValue;
 	texModInfo_t tmi;
 
diff --git a/code/renderergl2/tr_backend.c b/code/renderergl2/tr_backend.c
index d6ff122..4f8f3f4 100644
--- a/code/renderergl2/tr_backend.c
+++ b/code/renderergl2/tr_backend.c
@@ -433,7 +433,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
 	int				i;
 	drawSurf_t		*drawSurf;
 	int				oldSort;
-	float			originalTime;
+	double			originalTime;
 	FBO_t*			fbo = NULL;
 	qboolean		inQuery = qfalse;
 
@@ -498,7 +498,10 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
 
 			if ( entityNum != REFENTITYNUM_WORLD ) {
 				backEnd.currentEntity = &backEnd.refdef.entities[entityNum];
-				backEnd.refdef.floatTime = originalTime - backEnd.currentEntity->e.shaderTime;
+
+				// FIXME: e.shaderTime must be passed as int to avoid fp-precision loss issues
+				backEnd.refdef.floatTime = originalTime - (double)backEnd.currentEntity->e.shaderTime;
+
 				// we have to reset the shaderTime as well otherwise image animations start
 				// from the wrong frame
 				tess.shaderTime = backEnd.refdef.floatTime - tess.shader->timeOffset;
@@ -658,7 +661,7 @@ void	RB_SetGL2D (void) {
 
 	// set time for 2D shaders
 	backEnd.refdef.time = ri.Milliseconds();
-	backEnd.refdef.floatTime = backEnd.refdef.time * 0.001f;
+	backEnd.refdef.floatTime = (double)backEnd.refdef.time * 0.001f;
 }
 
 
diff --git a/code/renderergl2/tr_local.h b/code/renderergl2/tr_local.h
index dd959d5..9426ede 100644
--- a/code/renderergl2/tr_local.h
+++ b/code/renderergl2/tr_local.h
@@ -268,10 +268,10 @@ typedef enum {
 typedef struct {
 	genFunc_t	func;
 
-	float base;
-	float amplitude;
-	float phase;
-	float frequency;
+	double base;
+	double amplitude;
+	double phase;
+	double frequency;
 } waveForm_t;
 
 #define TR_MAX_TEXMODS 4
@@ -331,7 +331,7 @@ typedef struct {
 typedef struct {
 	image_t			*image[MAX_IMAGE_ANIMATIONS];
 	int				numImageAnimations;
-	float			imageAnimationSpeed;
+	double			imageAnimationSpeed;
 
 	texCoordGen_t	tcGen;
 	vec3_t			tcGenVectors[2];
@@ -471,8 +471,8 @@ typedef struct shader_s {
 
 	void		(*optimalStageIteratorFunc)( void );
 
-  float clampTime;                                  // time this shader is clamped to
-  float timeOffset;                                 // current time offset for this shader
+  double clampTime;                                  // time this shader is clamped to
+  double timeOffset;                                 // current time offset for this shader
 
   struct shader_s *remappedShader;                  // current shader this one is remapped too
 
@@ -733,7 +733,7 @@ typedef struct {
 	byte		areamask[MAX_MAP_AREA_BYTES];
 	qboolean	areamaskModified;	// qtrue if areamask changed since last scene
 
-	float		floatTime;			// tr.refdef.time / 1000.0
+	double		floatTime;			// tr.refdef.time / 1000.0
 
 	float		blurFactor;
 
@@ -1978,7 +1978,7 @@ typedef struct shaderCommands_s
 	//color4ub_t	constantColor255[SHADER_MAX_VERTEXES] QALIGN(16);
 
 	shader_t	*shader;
-	float		shaderTime;
+	double		shaderTime;
 	int			fogNum;
 	int         cubemapIndex;
 
diff --git a/code/renderergl2/tr_shade.c b/code/renderergl2/tr_shade.c
index 657f507..0fd1548 100644
--- a/code/renderergl2/tr_shade.c
+++ b/code/renderergl2/tr_shade.c
@@ -65,7 +65,8 @@ R_BindAnimatedImageToTMU
 =================
 */
 static void R_BindAnimatedImageToTMU( textureBundle_t *bundle, int tmu ) {
-	int		index;
+	int64_t index;
+	double	v;
 
 	if ( bundle->isVideoMap ) {
 		ri.CIN_RunCinematic(bundle->videoMapHandle);
@@ -81,8 +82,10 @@ static void R_BindAnimatedImageToTMU( textureBundle_t *bundle, int tmu ) {
 
 	// it is necessary to do this messy calc to make sure animations line up
 	// exactly with waveforms of the same frequency
-	index = ri.ftol(tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE);
-	index >>= FUNCTABLE_SIZE2;
+	//index = ri.ftol(tess.shaderTime * bundle->imageAnimationSpeed * FUNCTABLE_SIZE);
+	//index >>= FUNCTABLE_SIZE2;
+	v = tess.shaderTime * bundle->imageAnimationSpeed;
+	index = v;
 
 	if ( index < 0 ) {
 		index = 0;	// may happen with shader time offsets
diff --git a/code/renderergl2/tr_shade_calc.c b/code/renderergl2/tr_shade_calc.c
index cb7bcf7..c411e03 100644
--- a/code/renderergl2/tr_shade_calc.c
+++ b/code/renderergl2/tr_shade_calc.c
@@ -27,7 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #endif
 
 
-#define	WAVEVALUE( table, base, amplitude, phase, freq )  ((base) + table[ ri.ftol( ( ( (phase) + tess.shaderTime * (freq) ) * FUNCTABLE_SIZE ) ) & FUNCTABLE_MASK ] * (amplitude))
+#define	WAVEVALUE( table, base, amplitude, phase, freq )  ((base) + table[ (int)( ( ( (phase) + tess.shaderTime * (freq) ) * FUNCTABLE_SIZE ) ) & FUNCTABLE_MASK ] * (amplitude))
 
 static float *TableForFunc( genFunc_t func ) 
 {
@@ -776,16 +776,18 @@ void RB_CalcScaleTexMatrix( const float scale[2], float *matrix )
 */
 void RB_CalcScrollTexMatrix( const float scrollSpeed[2], float *matrix )
 {
-	float timeScale = tess.shaderTime;
-	float adjustedScrollS, adjustedScrollT;
+	double timeScale;
+	double adjustedScrollS, adjustedScrollT;
+
+	timeScale = tess.shaderTime;
 
 	adjustedScrollS = scrollSpeed[0] * timeScale;
 	adjustedScrollT = scrollSpeed[1] * timeScale;
 
 	// clamp so coordinates don't continuously get larger, causing problems
 	// with hardware limits
-	adjustedScrollS = adjustedScrollS - floor( adjustedScrollS );
-	adjustedScrollT = adjustedScrollT - floor( adjustedScrollT );
+	adjustedScrollS = (double)adjustedScrollS - floor( adjustedScrollS );
+	adjustedScrollT = (double)adjustedScrollT - floor( adjustedScrollT );
 
 	matrix[0] = 1.0f; matrix[2] = 0.0f; matrix[4] = adjustedScrollS;
 	matrix[1] = 0.0f; matrix[3] = 1.0f; matrix[5] = adjustedScrollT;
@@ -805,9 +807,9 @@ void RB_CalcTransformTexMatrix( const texModInfo_t *tmi, float *matrix  )
 */
 void RB_CalcRotateTexMatrix( float degsPerSecond, float *matrix )
 {
-	float timeScale = tess.shaderTime;
-	float degs;
-	int index;
+	double timeScale = tess.shaderTime;
+	double degs;
+	int64_t index;
 	float sinValue, cosValue;
 
 	degs = -degsPerSecond * timeScale;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/ioquake3.git



More information about the Pkg-games-commits mailing list