Closed tatref closed 3 years ago
Some context on how sampler variables work (apologies if this is stuff you already know, just want to be clear!) - in OpenGL, you have several slots you can bind textures to, called 'texture units'. Setting a sampler2D
uniform to a number is how you tell the shader which texture unit each variable corresponds to.
Tetra currently binds all textures to texture unit 0, so we always set u_texture
to 0 as well. There'd be nothing to stop you adding another sampler2D
to your texture and setting it to a different number, but there's no way in Tetra's API currently to actually bind a texture to the corresponding texture unit - that's the bit that's missing.
This is definitely something I'd like to add at some point, as there's lots of cool uses for binding multiple textures - I just need to figure out what the API would look like. Not sure how high/low level an interface Tetra should be exposing.
I don't know much about OpenGL, so thanks for the explanation ;-)
So if we want to add that that functionality, we'd need to change bind_texture
to something like
fn bind_texture(&mut self, texture: Option<&RawTexture>, texture_unit: u32)
However, RawTexture
is not public, and maybe texture unit 0 should be reserved?
I'll try to play a bit with this.
Yeah, that sounds about right. The state caching for texture bindings would also have to be rewritten, so that we don't end up rebinding more times than we need to (avoiding redundant GL calls is really important for performance).
My main concern is that I don't want any of this complexity to 'bleed out' into the rest of the framework. If someone's game doesn't make use of multiple texture bindings, they shouldn't have to care about the existence of texture units, etc. It's an advanced feature, so it should be opt-in, in my opinion.
I think I need to go and have a look at how other frameworks handle this kind of thing 😄
Finally did a bit more looking at how Love and Raylib handle this, and it's pretty much what I expected - texture unit 0
is reserved for the default texture, and setting a uniform to a texture actually just binds a texture unit behind the scenes. So I think this is doable, it'd just require a bit of a rework of some of the GL state caching.
I did a bit of playing around with making shaders 'magically' rebind textures, but it feels like a lot of added complexity for something not many people are going to use. I actually kinda think just adding a bind_texture
function to tetra::graphics
is probably all we need for now. I'll probably reserve 0
for use by Tetra, as I think it could get confusing if people set that and then it immediately unsets itself.
Never mind, found a nicer way of doing it - this functionality is now available on the main
branch, and will be in the next version of Tetra 🎊
Summary:
UniformValue
is not implemented for texture-like values (2D maps).The shaders are provided with a default
u_texture
sampler2D
, but we can't add our own textures.This is here, but the value 0 is hardcoded: https://github.com/17cupsofcoffee/tetra/blob/8d59084e3754bf757aaa59dc841a321f53c6f6b0/src/platform/device_gl.rs#L281
Can I bind my own textures? Why does this work with value
0
?Why is this needed? This could be used for normal lights (see https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson6)