In the past I’ve had to apply a texture just a single side of a rendered mesh. I didn’t find what I’d consider a ‘cinder native’ solution and instead opted to solve the problem within the fragment shader. The shader basically tested for the surface normal and if it was a match for a certain direction, it’d render a texture. If it wasn’t a match, the shader would render a custom color.
Not particularly efficient or pretty, but it’ll work in a pinch.
I’m once again in a situation where I’d like to apply different textures to various sides of a cube and wish I had a more cinder native approach to this. Perhaps by adding various properties to a geom? I’ve looked at the cinder examples but still haven’t seen anything that places separate textures on separates sides of a geom object…?
Not strictly “cinder native”, but it’s quite common to store layers of textures in a 3D texture or texture array and then provide an index into that array via attribute data. Usually I’d go one further and provide a material index via attribute data that would point to a material struct that contains all kinds of surface specific data, be it roughness, metallic, colour, texture index, what have you.
The material structs themselves could be passed to the shader as SSBOs, UBOs or if there’s few enough, just as plain uniforms.
What is ‘cinder native’ to you? Auto-generated fragment shader? That will only get you very basic, common things.
I often have many textures that I’m sampling from in my geometry’s fragment shading, such as for a height, normal, or translucency map.
For your specifically mentioned case, storing a custom attribute per vertex that tells what texture to use in a texture array would work, though not sure I’d prefer that over building a single texture to use on the entire cube (whether at runtime or beforehand). Really depends on what you’re trying to achieve.
Cinder native means an approach that’s as much supported by the Cinder framework as possible, which at times is ambiguous, if there are multiple ways of skinning a cat.
I intend to render between 2 and 3 different textures on various surfaces on a cube, so I think the custom attribute per vertex is a good approach. Thank you very much for the input.
Looking at the various Cinder Samples, I’m still not 100% sure about how to do this, but I’m working on it. I think the approach is to turn the geom into a VboMesh, then create a separate Vbo and enter the custom values into it, and then append them together. I’ll update when I’ve made more progress.
Another good idea @paul.houx which I’ll keep in mind moving forward.
For anyone else reading along, what I’ve gathered, you can use Cinder’s Texture3d object, and set the format to GL_TEXTURE_2D_ARRAY, to use a 2d texture array.
In my case, I want one of the Cube’s textures to originate from an FBO, so using a Texture3d would likely include a costly call to update() the 3d texture every frame, making it less appealing than simply referencing a different sampler2d variable.
Last but not least for anyone wanting to use the Texture3d object, I don’t know if Cinder easily supports attaching 3d texture coordinates to its geom objects. Perhaps it’s possible to use a modifier like this:
But I reckon the approach in the forum link above only modifies existing values, rather than extend them (i.e. from 2 to 3 floats).
Last but not least, I’m still investigating why rendering an FBO texture on Cinder’s geom::cube flips it backwards:
Cheers for all the awesome ideas and approaches to multi-texturing geometry!
Thanks for highlighting another option @paul.houx - love it!
At least 4 of cubes 6 sides will remain static.
Would you still consider using a CubeMap…? My FBO is 1920x1080, and if I were to use it as part of a CubeMap then the Cube Map would have to have all sides be the same resolution I think? And furthermore, if this FBO is updated (but the other cube sides are not), I’d still need to update/overwrite some of the cubeMap, no?
I’ve not spotted a way to build the CubeMap from 6 references.
you’re free to define different texture coordinates per side, so that each side can use a smaller or larger part of the texture. The layout of a standard cube map (cross) is chosen so that adjacent sides (can) use the same coordinates, preventing issues on the edges when sampling the texture map. But nothing is stopping you from coming up with your own layout (e.g. 2 rows of 3 columns each, with different dimensions for each side). Just make sure your mesh’s texture coordinates are compatible.
Also, if only part of the texture needs to change, just render to that part of the Fbo and leave the rest untouched. The OpenGL viewport is your friend.
Sometimes all it takes is thinking outside the cube
Regarding constructing the cube map from 6 separate images: just load the images and copy them (scaling and translating if necessary) to the correct area of the Fbo.