DH API does not notify of texture change
Binding textures returned by the DH API as usual* results in broken code.
(usual* = how you'ld usually do it in MC modding)
The issue here is that DH doesn't use Minecraft's built-in GL State manager
RenderSystem
(yarn mappings). The problem only becomes apparent when DH reinitializes the LODRenderer
.
This action will:
1. glDeleteTextures
the old texture
2. glGenTextures
a new texture
3. On some systems the old and new texture will have the same id (valid by OpenGL Spec)
4. Call RenderSystem.bindTexture
with the same texture id.
5. RenderSystem
will not call glBindTexture
because it thinks the same old texture is still bound.
6. A deleted texture is now bound to GL_TEXTURE6
I hope my description was clear enough.
The DH API does not provide a way to notice this texture change.
Probably the only way to circumvent this issue is on my side is to do this:
This will keep MC's state management and the "real" state "in sync", but results in wasted performance and is generally not a nice solution,21 Replies
I don't understand your issue.
Are you only querying the depth texture once and assuming it will never change?
No, I query it every frame.
But when DH initializes a new
LODRenderer
(when the config is changed f.e.), the new depth texture gets the same OpenGL id as the previous one had[1] (which is permitted by the spec). So when I query it again and call RenderSystem.bindTexture(depthId)
, the state manger fails to detect that the texture has changed, since the id stayed the same.
[1] this is not guaranteed, but it can and does happen.
i.e.
The issue is that the id stayed the same, so the new texture is never bound. And there is no way for me to know when the texture changed.Why not just use GL11.BindTexture() then?
Otherwise I could potentially add events for when the LodRenderer has been created/destroyed.
GL11.BindTexture has two drawbacks:
- I still have to bind the texture every frame, even if it is still bound from the previous frame.
- RenderSystem won't be aware of the updated binding. Meaning that I also would have to 1) query the previously bound texture 2) bind the depth texture 3) restore the previously bound texture
It would be better if I could only bind the texture when it isn't already bound. But since the texture id is not reliable to detect such a change, I can't.
I think an event would be the best solution. Alternatively DH could also use
RenderSystem
(or the underlying GlStateManger
), instead of the current solution (GLState.saveState
and restore
).
This would also somewhat improve the performance of DH, because currently, as I see it, GLState.saveState
does a bunch of glGet
calls every frame, which can be rather slow on some systems.
But I'm not sure it would be worth the effort.I don't think re-binding the texture every frame is that big of an issue. We have to bind and unbind a number of things every frame to prevent modifying Minecraft's GL state.
We are very intentionally not using MC's RenderSystem or GlStateManager since we try to keep our systems as separate from MC as possible.
Again, I can look into adding an API event that would fire when the renderer is created/destroyed or when the textures are (re)created.
I have to agree, re-binding the texture every frame is not such a big deal, but still. An event would be much appreciated.
If you'll be adding an event, I'ld suggest a ResourceChanged or RenderTargetChanged event, rather than a LodRenderer related one, since that is what's actually of interest. Knowing when the LodRenderer is initialized is not very useful by itself.
My current plan is something along the lines of Lod Depth/Color Textures Created Event
Yeah, something like that would be great. But does that mean you'll finally have to update the modrinth page 😄?
Once the next stable build of DH has been released, yes 😉
So, I just realized Better Clouds still has this issue. So what is the correct solution now? Listen to the
DhApiBeforeTextureClearEvent
, set a flag, and call glBindTexture
in addition to GlStateManager._bindTexture
to make the two sync up, if the flag is set?Please refresh my memory. What issue specifically are you referencing?
Also as of the latest DH version we are firing MC’s GL state manager alongside manually firing the underlying GL calls, so those should be synced up now.
The issue is that, if I remember it correctly, DH generates a new texture, but that happens to have the same ID as the old one. GlStateManager tracks which texture is bound to what unit and doesn't rebind if the ID is the same. So the new texture is never bound.
The "correct" way would be to use
_deleteTexture
when DH deletes the old texture, since that clears GlStateManager's internal state for all units to which the ID was bound to.
Also, why don't people ever report such bugs. This has been an issue with Better Clouds and DH since over a year, and I only just found out about it because I used both together myself. ðŸ˜
I'm on the latest version (1.21.5) of DH btwWe are calling MC’s delete texture (unless I just forgot to replace a call somewhere).
https://gitlab.com/distant-horizons-team/distant-horizons/-/blob/main/common/src/main/java/com/seibel/distanthorizons/common/wrappers/minecraft/MinecraftGLWrapper.java
GitLab
common/src/main/java/com/seibel/distanthorizons/common/wrappers/min...
This is a mod that adds a Level Of Detail (LOD) system to Minecraft. This implementation renders simplified chunks outside of the normal render distance allowing for an...
Something fishy is going on. Simply subscribing to
DhApiBeforeTextureClearEvent
makes the issue go away (it's also never called?). I guess I need to dig deeper.
Nevermind, that had a different cause.
Rights so DhApiBeforeTextureClearEvent
is not what I thought it was. DhApiColorDepthTextureCreatedEvent
is maybe the right one.Yes, seems you did

I assume this will be fixed, but for backwards compatability, would you say
DhApiColorDepthTextureCreatedEvent
is the correct event to fix the GlStateManager state?Fair enough, I’ll have to get those fixed at some point.
I don’t understand the question.
If I'm going to fix this DH issue in my mod, so that users can use older versions of DH without my mod breaking, then I need to fix up the GlStateManager state. Is
DhApiColorDepthTextureCreatedEvent
the correct event to do that?
Basically I would sync up the GlStateManager
texture binding state after every time that this even is fired. Just want to be sure that this event covers all cases when DH's depth texture is (re)created.Gotcha.
Dang it past me, why did you fire that event before the texture is created instead of after, that makes it basically useless…
I’ll have to fix that someday.
As a temporary fix DhApiBeforeTextureClearEvent looks to be your best bet.
Nah,
DhApiBeforeTextureClearEvent
is fired every frame. I mistakenly assumed different. But DhApiColorDepthTextureCreatedEvent
seems fine if I delay the syncing to the next time my render code is called.
Anyway, thanks for the responses! I'm happy I'm finally able to fix this issue after I forgot about it for a year 😅lol happy I was able to help.
I’ll have to look into cleaning up those API methods at some point, although I was planning on going on vacation for a bit, so we’ll see when that happens.