-
Hello!
I have an interesting problem, maybe it's just my old video card. I'm trying to create a custom font renderer (using sf::Sprite with shaders). The problem is that if I draw 3700 sprite without shaders, it runs at 300-400 FPS, but if I turn on the very basic shaders the FPS drops to 9. The vertex shader does nothing, but on the fragment, I just do some simple calculation.
uniform sampler2D texture;
void main()
{
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
if(pixel == vec4(1.0, 0.0, 1.0, 1.0))
{
pixel = vec4(vec3(0.0, 0.0, 0.66666), 1.0);
}
else
{
pixel = vec4(vec3(1.0, 1.0, 0.3), 1.0);
}
gl_FragColor = pixel;
}
Any idea? I thought about the lot of texture swap, but then it won't run with 300 - 400 fps without shaders.
-
Try to avoid the conditional jump (if-else). What possible colors can the texture have, and how should it be manipulated depending on them?
Minor issues are the useless operations: why packing a vec3 inside a vec4, and why the intermediate assignment to pixel instead of gl_FragColor?
Furthermore, test how the code behaves with vertex arrays instead of sprites.
-
I packing the vec3 into a vec4, because I had some uniforms to modify the color of the fonts. But I commented them out, and deleted from the source. On the other hand, I'm checking if the texture is transparent(255,0,255 color), and I set that pixel to the background color (now vec3(0.0, 0.0, 0.66666)), then set the other pixels color to the other color.
-
On the other hand, I'm checking if the texture is transparent(255,0,255 color), and I set that pixel to the background color (now vec3(0.0, 0.0, 0.66666)), then set the other pixels color to the other color.
But to check whether the pixel is transparent, it suffices to look at the alpha channel. Assuming the alpha component is either 0 or 1, you can use multiplication instead of a branch:
const vec4 result1 = vec4(...);
const vec4 result2 = vec4(...);
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
gl_FragColor = pixel.a * result1 + (1-pixel.a) * result2;
Just to show the principle, I don't know how well drivers can optimize here. You can reduce the number of needed operations even further:
const vec4 result1 = vec4(...);
const vec4 result2 = vec4(...);
const vec4 diff = result1 - result2; // or hardcode this directly
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
gl_FragColor = result2 + pixel.a * diff;
-
But could it be a shader problem? On the other hand, I haven't tried yet, what happens if I use vbos, because I just couldn't drop GLEW into the project. ><
EDIT: I modified the shader not to use branching, only got +1 FPS.
-
By any chance, could it be that you're loading the shader from file every single frame? Also, what kind of graphics card do you have? Does it run the shaders' example smoothly?
-
Should we guess further? If not, come up with a complete and minimal example (http://en.sfml-dev.org/forums/index.php?topic=5559.msg36368#msg36368), to make sure there are no mistakes like the one mentioned by upseen.
-
http://pastebin.com/9trE982C (http://pastebin.com/9trE982C) <- here is my code
The code of the shader:
uniform sampler2D texture;
const vec4 res1 = vec4(1.0, 1.0, 0.3, 1.0);
const vec4 res2 = vec4(0.0, 0.0, 0.66666, 1.0);
void main()
{
vec4 pixel = texture2D(texture, gl_TexCoord[0].xy);
gl_FragColor = pixel.a * res1 + (1.0 - pixel.a) * res2;
}
The shader examples are running smooth, maybe the old and slow VGA is the problem.