Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [SOLVED] Using shader to apply fake 3D rotation effect on a sf::Text  (Read 2566 times)

0 Members and 2 Guests are viewing this topic.

Esteban

  • Newbie
  • *
  • Posts: 6
    • View Profile
Hello everyone,
i am working on a game project and i face difficulties understanding how to use shader on sf::Text.
What i wanted to do is in the title and i dont realize if this is possible or not. I wanted to spin a text to have a fake 3D rotation effect. I Found a shader that does the spin effect in shadertoy and adapt it  :
.frag
precision mediump float;

#define Mouse_Rotation ( Max_Rotation - Max_Rotation * 2.0 * (iMouse.xy / iResolution.xy) )
#define RotationCenter vec3(0.000, 0.000, 0.000)
#define Max_Rotation 0.65

/*
   A simple rotating effect of a textured plane in 3D space.
   I'm basically using a ray for each pixel that intersects the plane
   as drawn in a 2D view below.

   Created By Jaap Boerhof (Dec. 2017)
   Forked by yohjimane (Jul. 2023)

   Positioning                             Positioning at a certain angle:
   at zero degrees rotation:
   
   |------plane-----|  coords:                              __--|
   \                /  (-1.0..1.0, 0.0)                 __--   /  
    \              /                                __--      /  
     \            /                             __--         /
      \          /                         \ _--            /  
       \        /                          |\              /  
        \      /                             \            /    
         \    /                               \          /      
          \  /                                 \        /      
           \/          Camera                   \      /  
                       position                  \    /  
                       at (0.0, -1.0)             \  /
                                                   \/
*/

uniform vec2 u_resolution;
uniform float u_time;
uniform sampler2D texture;
vec2 rotate(vec2 v, vec2 o, float a) {
    float s = sin(a);
    float c = cos(a);
    mat2 m = mat2(c, -s, s, c);
    return m * (v-o) + o;
}

vec3 rotateZ(vec3 v, vec3 o, float a) {
    float s = sin(a);
    float c = cos(a);
    mat2 m = mat2(c, -s, s, c);
    return vec3(m * (v.xy - o.xy) + o.xy, v.z);
}

vec2 TransformPlane(vec2 uv, vec3 center, float XRot, float YRot, float ZRot) {
    // First Rotate around Y axis
    vec2 RayDirection =  vec2(uv.x, 0.0);
    vec2 A1 = vec2(0.0, -1.0);
    vec2 B1 = RayDirection - A1;
    vec2 C1 = rotate(vec2(-1.0, 0.0), vec2(center.x, 0.0), YRot);
    vec2 D1 = rotate(vec2(1.0, 0.0), vec2(center.x, 0.0), YRot) - C1;

    // calculate intersection point
    float u = ( (C1.y + 1.0) * D1.x - C1.x * D1.y ) / (D1.x*B1.y-D1.y*B1.x);

    // position on the XY plane after Y-axis rotation
    float sx = u * B1.x;
    float sy = u * uv.y;

    // Now Rotate around X axis
    RayDirection = vec2(sy, 0.0);
    vec2 B2 = RayDirection - A1;
    vec2 C2 = rotate(vec2(-1.0, 0.0), vec2(center.y, 0.0), XRot);
    vec2 D2 = rotate(vec2(1.0, 0.0), vec2(center.y, 0.0), XRot) - C2;

    // calculate intersection point
    float v = ( (C2.y + 1.0) * D2.x - C2.x * D2.y ) / (D2.x*B2.y-D2.y*B2.x);

    // the position after x and y rotations
    vec3 pos = vec3(v * sx, v * B2.x, 0.0 );
   
    // Now rotate the position around Z axis
    vec3 finalPos = rotateZ(pos, center, ZRot);

    // final position on the 3D plane after Z-axis rotation
    return finalPos.xy;
}

void main()
{
    vec2 uv = -1.0 + 2.0 * gl_FragCoord.xy / u_resolution.xy;
    float R_X = 0.;
    float R_Y =  u_time;
    float R_Z = 0.; // Adjust the value for Z-axis rotation
    vec3 MyCoords = vec3(TransformPlane(uv, RotationCenter, R_X, R_Y, R_Z), 0.0);
    vec2 MyTexCoord = (MyCoords.xy + vec2(1.0)) / 2.0;

    //vec4 image1 = texture2D(texture, MyTexCoord);
    //vec4 image2 = texture(iChannel1, MyTexCoord);
    //fragColor = mix(image1, image2, (sin(iTime * 0.5) + 1.0) / 2.0);
     gl_FragColor = texture2D(texture, MyTexCoord);
}

The shader looks fine and seems to work on a sprite but i don't know if i can use it to spin a text.
I tried to use a rendertexture and make a sprite out of it but with this i have a black background on my text
sf::RenderTexture rendertexture;
rendertexture.create(SCREEN_WIDTH,SCREEN_HEIGHT);
rendertexture.clear();
rendertexture.draw(myText);
sf::Sprite sprite(rendertexture.getTexture());
//window.draw(myText,&testRotation); This doesnt work
window.draw(sprite,&testRotation);
This doesnt work, i dont know if i need to use deeper things as vertex and stuff like that.
Thanks for reading this and let me know if you need sample of code or smthing else
« Last Edit: May 13, 2024, 03:20:16 pm by Esteban »

kojack

  • Sr. Member
  • ****
  • Posts: 343
  • C++/C# game dev teacher.
    • View Profile
Re: Using shader to apply fake 3D rotation effect on a sf::Text
« Reply #1 on: May 12, 2024, 11:29:28 pm »
Render textures need to have display() called on them after drawing on them for them to update correctly.
So after rendertexture.draw(myText); put a rendertexture.display(); and see if that helps.

Esteban

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Using shader to apply fake 3D rotation effect on a sf::Text
« Reply #2 on: May 13, 2024, 08:28:21 am »
Render textures need to have display() called on them after drawing on them for them to update correctly.
So after rendertexture.draw(myText); put a rendertexture.display(); and see if that helps.
Thanks for you answer,i did it previously but it dont change the behaviour (which is kinda weird because yes i didnt display anything on the screen yet) but it result on the same black background.

https://blog.rubenwardy.com/2020/05/12/sfml-drop-shadow/
I used this tutorial to help me use my shader on the text but i couldn't figure it out
« Last Edit: May 13, 2024, 08:37:42 am by Esteban »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Re: Using shader to apply fake 3D rotation effect on a sf::Text
« Reply #3 on: May 13, 2024, 08:29:09 am »
Not sure it will give you the wanted effect, but you can pass the shader as render state during the draw call of the text object itself: window.draw(text, shader) (this should implicitly construct a sf::RenderState).

but with this i have a black background on my text
You'll need to clear the RenderTexture with a transparent color (alpha = 0).
You may then want to render the text without any blending (i.e. without alpha blending) to prevent colored outlines.

Alternatively, you can also take a look at Hapax's Spinning card: https://github.com/Hapaxia/SelbaWard/wiki/Spinning-Card
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Esteban

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Using shader to apply fake 3D rotation effect on a sf::Text
« Reply #4 on: May 13, 2024, 08:36:03 am »
that the effect i want to get thanks for your answer ! And thanks for you work on sfml this is huge