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

Author Topic: Use Shader With Text  (Read 4974 times)

0 Members and 1 Guest are viewing this topic.

kryx

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Use Shader With Text
« on: May 12, 2014, 11:20:19 pm »
Hi,

First: sorry for my bad English^^

Here is my problem: I would like to enable antialiasing on renderTexture. It seems to be impossible. So, Laurent Gomila say me to use shaders.
But they don't work...
I test with that shader:

uniform sampler2D texture;
uniform float blink_alpha;

void main()
{
    vec4 pixel = gl_Color;
    pixel.a = blink_alpha;
        gl_FragColor = pixel;
}

And here is my shader loading:

public static Shader FXAA;
if (!Shader.isAvailable()) {
        Log.OutError("Impossible de prendre en charge les shader...");
}
                       
FXAA = new Shader();
Path ShaderPath = FileSystems.getDefault().getPath("blink.frag");
FXAA.loadFromFile(ShaderPath, Shader.Type.FRAGMENT);
FXAA.setParameter("blink_alpha", 125);

RenderTexture.draw(obj, new RenderStates(FXAA));

But i get a black screen. Without shader, all is fine.
If I use the shader test of jsfml :

void main()
{
    //Compute level of gray
    float gray = dot(gl_Color.rgb, vec3(0.299, 0.587, 0.114));

    //Write destination color
    gl_FragColor = vec4(gray, gray, gray, gl_Color.a);
}

I get this: All is good, but not the text:



Really thanks to you to help me...
« Last Edit: May 12, 2014, 11:30:37 pm by Laurent »

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1380
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Use Shader With Text
« Reply #1 on: May 12, 2014, 11:50:47 pm »
If you don't sample the texture for data in your fragment shader, it can't render the text glyphs properly...
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

kryx

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Re: Use Shader With Text
« Reply #2 on: May 12, 2014, 11:52:45 pm »
How can i do that?

I have tried this:

states = new RenderStates(FXAA);
                        states.texture = RenderTexture;

but "texture" is a final member of states

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32097
    • View Profile
    • SFML's website
    • Email
Re: Use Shader With Text
« Reply #3 on: May 12, 2014, 11:59:20 pm »
Did you read the tutorials? For example this one:
https://github.com/pdinklag/JSFML/wiki/Drawables-and-RenderStates

And you told me that even the "shaders" official example didn't work, so even if we find errors in your own code there may be something wrong with JSFML or your environment.
Laurent Gomila - SFML developer

kryx

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Re: Use Shader With Text
« Reply #4 on: May 13, 2014, 12:06:18 am »
hoooo,

I understand nothing now... I'm so tired... I go sleep, I'll see that tomorrow... Thx Laurent, and sorry

kryx

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Re: Use Shader With Text
« Reply #5 on: May 13, 2014, 10:09:24 am »
No, I don't understand.

I check the samples :

// ... (create window)

//Ensure that shaders are available on this system
if(!Shader.isAvailable()) {
    System.err.println("Sorry, your hardware does not support shaders!");
    return;
}

//Create the shader and attempt to load the program
Shader grayscale = new Shader();
try {
    grayscale.loadFromFile(new File("grayscale.frag"), Shader.Type.FRAGMENT);
} catch(IOException|ShaderSourceException ex) {
    ex.printStackTrace();
    return;
}

//Attempt to create the render texture
RenderTexture rtex = new RenderTexture();
try {
    rtex.create(window.getSize().x, window.getSize().y);
} catch(TextureCreationException ex) {
    ex.printStackTrace();
    return;
}

//Create a sprite with the result texture
Sprite resultSprite = new Sprite(rtex.getTexture());

//Main loop
while(window.isOpen()) {
    rtex.clear();
    rtex.display();

    //Draw the result sprite on the window using the grayscale shader
    window.clear();
    window.draw(resultSprite, grayscale);
    window.display();
}

And I do exaclty the same thing.
The grayscale don't take a texture in argument. So, why pass a texture in argument?
The difference is window.draw(resultSprite, grayscale); where I canno't pass a shader as 2nd argument, but a RenderStates only...

I'm really lost

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1380
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Use Shader With Text
« Reply #6 on: May 13, 2014, 10:45:22 am »
Do you even know what a shader is and does? ::) Using/Modifying the example code will only get you so far. You will actually have to do some reading to learn how to do the rest. I already told you what was "wrong" with the shader, since you obviously took it from the example and expected it to magically work in your scenario as well. If you didn't understand my post, then you really should do a bit more reading about shaders in general and the SFML shader API.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

kryx

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Re: Use Shader With Text
« Reply #7 on: May 13, 2014, 11:42:31 am »
Are you doing allusion to the setParameter of shader?

It's the first time I use Shaders, yes... I'm a little lost...

Can you link maybe a good tutorial website?

I've already read some texts, but they don't help me.
I think that I have understood how they work, but not why greyscale fail...
Ok for the first, I have forgotten to link the texture, I know it now, but for the second shader?

kryx

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Re: Use Shader With Text
« Reply #8 on: May 13, 2014, 03:37:57 pm »
Ok...

There is an full example:

The shader:

void main()
{
    //Compute level of gray
    float gray = dot(gl_Color.rgb, vec3(0.299, 0.587, 0.114));

    //Write destination color
    gl_FragColor = vec4(gray, gray, gray, gl_Color.a);
}

package main;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.jsfml.graphics.Color;
import org.jsfml.graphics.Font;
import org.jsfml.graphics.RectangleShape;
import org.jsfml.graphics.RenderStates;
import org.jsfml.graphics.RenderTexture;
import org.jsfml.graphics.RenderWindow;
import org.jsfml.graphics.Shader;
import org.jsfml.graphics.Sprite;
import org.jsfml.graphics.Text;
import org.jsfml.window.ContextSettings;
import org.jsfml.window.VideoMode;
import org.jsfml.window.WindowStyle;

public class Main
{
        public static Font FONT = new Font();
       
        public static RenderWindow window = new RenderWindow();
        public static RenderTexture rdrTxt = new RenderTexture();
        public static Text text;
       
        public static Shader FXAA;
       
        public static void main(String[] args)
        {
                try {
                        FONT.loadFromFile(Paths.get("fonts/arial.ttf"));
                        window.setKeyRepeatEnabled(false);
                        ContextSettings settings = new ContextSettings(8);
                        window.create(new VideoMode(680,560), "test Shader", WindowStyle.RESIZE, settings);
                        window.setVerticalSyncEnabled(true);
                       
                        if (!Shader.isAvailable()) {
                                System.out.println("shader no available");
                        }
                       
                        FXAA = new Shader();
                        Path ShaderPath = FileSystems.getDefault().getPath("shadertest.txt");
                        FXAA.loadFromFile(ShaderPath, Shader.Type.FRAGMENT);
                        //FXAA.setParameter("blink_alpha", 125);

                        text = new Text("Ceci est un test", FONT);
                        text.setColor(Color.RED);
                        rdrTxt.create(680, 560);
                        rdrTxt.draw(text, new RenderStates(FXAA));
                        rdrTxt.display();
                        Sprite result = new Sprite(rdrTxt.getTexture());
                       
                       
                        while (window.isOpen()) {
                                rdrTxt.clear();
                                rdrTxt.draw(text, new RenderStates(FXAA));
                            rdrTxt.display();

                           
                            window.clear();
                            window.draw(result);
                            window.display();
                        }
                       
                } catch (Exception e) {
                        System.out.println("rtrt");
                        StringWriter errors = new StringWriter();
                        e.printStackTrace(new PrintWriter(errors));
                        window.close();
                }
        }
}
 

and the result without shader:



with shader:



Where is the error?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32097
    • View Profile
    • SFML's website
    • Email
Re: Use Shader With Text
« Reply #9 on: May 13, 2014, 03:41:53 pm »
As already stated, this shader only uses the diffuse color of the glyphs (the one you give with text.setColor), it doesn't use the font's texture at all. It's a very simple shader that is not meant to be used with textured entities.
Laurent Gomila - SFML developer

kryx

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Re: Use Shader With Text
« Reply #10 on: May 13, 2014, 04:05:40 pm »
Oooook, I don't have understand that, sorry

I'm going to do more tests with other shaders so

kryx

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Re: Use Shader With Text
« Reply #11 on: May 13, 2014, 05:25:38 pm »
Ok, now, i try to use this shader:

#version 120
#define FXAA_REDUCE_MIN (1.0/128.0)
#define FXAA_REDUCE_MUL (1.0/8.0)
#define FXAA_SPAN_MAX 8.0
uniform sampler2D sampler0;
uniform vec2 resolution;

void main(){
   vec2 inverse_resolution=vec2(1.0/resolution.x,1.0/resolution.y);
   vec3 rgbNW = texture2D(sampler0, (gl_FragCoord.xy + vec2(-1.0,-1.0)) * inverse_resolution).xyz;
   vec3 rgbNE = texture2D(sampler0, (gl_FragCoord.xy + vec2(1.0,-1.0)) * inverse_resolution).xyz;
   vec3 rgbSW = texture2D(sampler0, (gl_FragCoord.xy + vec2(-1.0,1.0)) * inverse_resolution).xyz;
   vec3 rgbSE = texture2D(sampler0, (gl_FragCoord.xy + vec2(1.0,1.0)) * inverse_resolution).xyz;
   vec3 rgbM  = texture2D(sampler0,  gl_FragCoord.xy  * inverse_resolution).xyz;
   vec3 luma = vec3(0.299, 0.587, 0.114);
   float lumaNW = dot(rgbNW, luma);
   float lumaNE = dot(rgbNE, luma);
   float lumaSW = dot(rgbSW, luma);
   float lumaSE = dot(rgbSE, luma);
   float lumaM  = dot(rgbM,  luma);
   float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
   float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
   vec2 dir;
   dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
   dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));
   float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL),FXAA_REDUCE_MIN);
   float rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);
   dir = min(vec2( FXAA_SPAN_MAX,  FXAA_SPAN_MAX),max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),dir * rcpDirMin)) * inverse_resolution;
   vec3 rgbA = 0.5 * (texture2D(sampler0,   gl_FragCoord.xy  * inverse_resolution + dir * (1.0/3.0 - 0.5)).xyz + texture2D(sampler0,   gl_FragCoord.xy  * inverse_resolution + dir * (2.0/3.0 - 0.5)).xyz);
   vec3 rgbB = rgbA * 0.5 + 0.25 * (texture2D(sampler0,  gl_FragCoord.xy  * inverse_resolution + dir *  - 0.5).xyz + texture2D(sampler0,  gl_FragCoord.xy  * inverse_resolution + dir * 0.5).xyz);
   float lumaB = dot(rgbB, luma);
   if((lumaB < lumaMin) || (lumaB > lumaMax)) {
      gl_FragColor = vec4(rgbA,1.0);
   } else {
      gl_FragColor = vec4(rgbB,1.0);
   }
}

and the code of my application is now:

package main;

//import

public
class Main
{
        public static Font FONT = new Font();
       
        public static RenderWindow window = new RenderWindow();
        public static RenderTexture rdrTxt = new RenderTexture();
        public static Text text;
        public static CircleShape cir;
       
        public static Shader FXAA;
       
        public static void main(String[] args)
        {
                try {
                        FONT.loadFromFile(Paths.get("fonts/arial.ttf"));
                        window.setKeyRepeatEnabled(false);
                        ContextSettings settings = new ContextSettings(8);
                        window.create(new VideoMode(680,560), "Crazy-Colors", WindowStyle.RESIZE, settings);
                        window.setVerticalSyncEnabled(true);
                       
                        if (!Shader.isAvailable()) {
                                System.out.println("shader no available");
                        }
                       
                        FXAA = new Shader();
                        Path ShaderPath = FileSystems.getDefault().getPath("FXAA3.txt");
                        FXAA.loadFromFile(ShaderPath, Shader.Type.FRAGMENT);
                        try{
                                FXAA.setParameter("sampler0", Shader.CURRENT_TEXTURE);
                                FXAA.setParameter("resolution", 1,1);
                        }
                        catch (Exception e) {
                                System.out.println("erreur d'argument");
                        }

                        text = new Text("Ceci est un test", FONT);
                        text.setColor(Color.RED);
                        cir = new CircleShape();
                        cir.setRadius(100);
                        cir.setFillColor(Color.BLUE);
                        cir.setPointCount(16);
                        cir.setPosition(50, 50);
                        rdrTxt.draw(cir, new RenderStates(FXAA));
                        rdrTxt.create(680, 560);
                        rdrTxt.draw(text, new RenderStates(FXAA));
                        rdrTxt.display();
                        Sprite result = new Sprite(rdrTxt.getTexture());
                       
                       
                        while (window.isOpen()) {
                                rdrTxt.clear();
                                rdrTxt.draw(cir, new RenderStates(FXAA));
                                rdrTxt.draw(text, new RenderStates(FXAA));
                            rdrTxt.display();

                            window.clear();
                            window.draw(result/*, new RenderStates(FXAA)*/);
                            window.display();
                        }
                       
                } catch (Exception e) {
                        StringWriter errors = new StringWriter();
                        e.printStackTrace(new PrintWriter(errors));
                        System.out.println(errors.toString());
                        window.close();
                }
        }
}
 

but my circle doesn't appear (it appear without the shader).
Any idea?
Do I have pass the good arguments to the shader?
« Last Edit: May 13, 2014, 10:23:13 pm by kryx »

kryx

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Re: Use Shader With Text
« Reply #12 on: May 13, 2014, 10:22:37 pm »
hum, I have try another shader, found on this forum:

uniform sampler2D samp;

void main()
{
    vec4 texel = texture2D(samp,gl_TexCoord[0].st);
    vec4 pixel = texel * gl_Color;

    // On calcule son niveau de gris
    float gray = pixel.r * 0.39 + pixel.g * 0.50 + pixel.b * 0.11;

    // On écrit enfin le pixel final, en utilisant 50% du pixel de l'écran et 50% de sa version colorée

    gl_FragColor = vec4(gray,gray,gray,pixel.a);
}

My text is gray! It's ok!
But my circle became fully black :/

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32097
    • View Profile
    • SFML's website
    • Email
Re: Use Shader With Text
« Reply #13 on: May 13, 2014, 10:31:03 pm »
Because your circle has no texture. Which produces black (I think it's undefined) when the shader tries to read from the texture.

You're trying to play with things you know nothing about, you'll hardly get the desired result this way.

There are only three solutions to your problem:
- learn how to write and use shaders
- ask someone to write it for you, this may work or not
- wait until we add support for antialiasing in sf::RenderTexture; if you find an open discussion or issue about it, you can add a word so that we know that this is important for you
Laurent Gomila - SFML developer

kryx

  • Jr. Member
  • **
  • Posts: 67
    • View Profile
Re: Use Shader With Text
« Reply #14 on: May 13, 2014, 10:39:16 pm »
:D

You response when I find the solution!
Yes, I've found that Shapes don't have texture, and so my code works now.

I have discovered Shaders yesterday, and I'm very intersted... I'm learning step by step.
I know now how that work in graphic card, how pass parameter, how load it in app, I must learn how write in glsl, but I can do some things now^^

Ask to someone is contrary to my thoughts, I prefer learning.
Wait for implements of antialiasing may be very long, last report is of 2011....

Thx for your response, I continue to learn so!

 

anything