LightningHandler modifies ModelView matrix without restoring it
Gwani opened this issue ยท 1 comments
Hello there!
I fixed some rendering glitches at distant coordinates in another mod (see MrTJP/ProjectRed#709) but when used together with Botania, the rendering breaks again:
The screenshot is taken at world coordinates X = 29 million, Z = 29 million.
I tracked down the problem to botania/client/core/handler/LightningHandler.java
where the method onRenderWorldLast()
modifies the current ModelView matrix without a corresponding glPushMatrix()
/glPopMatrix()
pair. The modified matrix is then used by other mods whose rendering handlers are called after Botania's LightningHandler, thus causing the glitch in the above image due to floating point round-off errors.
The round-of errors are caused by those two translations:
GL11.glTranslated(-interpPosX, -interpPosY, -interpPosZ);
GL11.glTranslated(interpPosX, interpPosY, interpPosZ);
This may not look suspicious at first glance, both translations should cancel out each other and leave the ModelView matrix as it was before onRenderWorldLast()
was called - but this is not quite true:
Floating point variables lose precision when their values are high (world coordinates at 29 million) and calling GL11.glTranslated()
does not simply add/subtract the values, but actually multiplies them (multiplies ModelView matrix with translation matrix derived from translation values). This introduces significant round-off errors to the ModelView matrix, which might then also be used by other mods.
I have fixed the problem by simply enclosing the translations in a glPushMatrix()
/glPopMatrix()
pair, and a test shows that the halo boxes in ProjectRed are now indeed rendered correctly:
I'll be creating a pull request for my fix. Please note that due to the glPopMatrix()
call, the last translation (GL11.glTranslated(interpPosX, interpPosY, interpPosZ);
) might not be needed anymore, but i left it there because i wanted to change as little code as possible.
Cheers,
Gwani
PS: Glancing over Botania's code i conclude that it might also suffer from rendering glitches at distant coordinates just like ProjectRed. It's generally advisable to avoid high-value floating point (float and double alike) values in calculations if you need a lot of precision after the decimal point (thats definitely the case for all OpenGL vertex transformations). I solved this for ProjectRed by working with local camera coordinates (relative to the player view) instead of absolute world coordinates.
Interesting. I wasn't aware of this. I actually got the code from here https://github.com/Chicken-Bones/WirelessRedstone/blob/40c6a7eba793e924234cf0f03b89482b0e0c20bf/src/codechicken/wirelessredstone/core/RenderWirelessBolt.java back in 1.4 and have been adapting it each version, so I definitely might have missed that. I'll pull the PR you made.