Closed Triazic closed 1 year ago
I think this is more of a general raylib question, but billboards are "always facing camera", so might not work the same. Maybe try DrawTextureRec
(as in the reddit answer) with a negative-width Rectangle
? For 3D, you may have to billboard it yourself (aim it at camera) and reverse the image yourself.
While the syntax is not identical, here is original 2D idea in a codepen (to play around with it):
The text on my shirt is reversed in original image, so it appears to be working.
The more 3D-way to do this are render-to-texture or portal-rendering. See this SO answer for some nice links. (The question is for java, but the theory still applies here.)
yeah, my guess is that it's disappearing due to opengl 'backface culling', if you're giving it a plane that's effectively facing away from the screen (opengl determines this by looking at the order of vertices of a triangle) it will assume the face is not visible to the camera and skip drawing it, for performance in 3d scenes.
you could check if you are able to disable culling, or if not, use the Image functions to generate mirrored versions of the textures when you load them, and use those instead of a negative x
I ending up inventing a vertex shader that accepts the source rect as a uniform and translates stuff accordingly.
#version 330
// Input vertex attributes
in vec3 vertexPosition;
in vec2 vertexTexCoord;
in vec3 vertexNormal;
in vec4 vertexColor;
// Input uniform values
uniform mat4 mvp;
uniform sampler2D texture0;
uniform vec4 source;
// Output vertex attributes (to fragment shader)
out vec2 fragTexCoord;
out vec4 fragColor;
void main()
{
// Send vertex attributes to fragment shader
fragTexCoord = vertexTexCoord;
// invert the x co-ordinate of the texture/sprite
float textureWidth = textureSize(texture0, 0).x;
float sourceWidth = source.z;
float left = source.x;
float right = left + sourceWidth;
float flippedX = (right - (fragTexCoord.x * textureWidth - left)) / textureWidth;
fragTexCoord.x = flippedX;
fragColor = vertexColor;
// Calculate final vertex position
gl_Position = mvp*vec4(vertexPosition, 1.0);
}
const shader = flipped ? assets.flippedShader: assets.defaultShader;
BeginShaderMode(shader);
if (flipped) {
// pass the source rect to the flipped shader..
//@ts-ignore
r.SetShaderVec4(shader, GetShaderLocation(shader, "source"), { x: source.x, y: source.y, z: source.width, w: source.height });
}
DrawBillboardPro(camera, tex, source, position, camera.up, defaultSizeVector, noRotationVector, 0, RAYWHITE);
EndShaderMode();
Worth noting that in C# this also does not work so it's probably a raylib thing. Needed to use my shader there as well.
that was my suspicion too - if you were interested in fixing it (or requesting for it to be fixed) on raylib's side - the solution would be to have DrawBillboard check for negative width or height objects, and instead of mirroring the vertex positions, mirror the texture sample coordinates
oh actually - @Triazic , you may try a rectangle like this too, it may do what you are thinking of with flipping the UVs:
const source: Rectangle = { x: width, y: 0, width: -tex.width, height: tex.height };
Nah 99% sure I tried that too, didn't work.
On my googling I've seen that the approach to drawing flipped billboards / textures is to provide a source rectangle with the width (or height) being negative. This is not working for me?
Works (renders billboard normally):
Does not work (renders nothing - should render billboard with x flipped):
Reference: https://www.reddit.com/r/raylib/comments/nvtyqn/how_do_i_flip_a_texture/