Botania

Botania

133M Downloads

LightningHandler modifies ModelView matrix without restoring it

Gwani opened this issue ยท 1 comments

commented

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:
mc1
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:
mc2
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.

commented

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.