mirror of
https://github.com/DrBeef/ioq3quest.git
synced 2024-11-22 20:11:40 +00:00
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.
This commit is contained in:
parent
9c4c363ccc
commit
30fdd88c9f
8 changed files with 63 additions and 47 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue