Apologies for the vague title, it's a little difficult to summarise in a few words. The problem is this: as far as I can tell drawables with more than a certain number for vertices have incorrect vertex data sent to the vertex shader. I noticed when trying to apply lighting to a scene that drawables such as sf::CircleShape or vertex arrays with a lot of vertices are not lit correctly in relation to the light source. sf::Sprites and quads created with a vertex array are lit fine, however. In this video the light position is set to the cursor:
The only difference between the first and second half of the videos is how the drawables are constructed. Notice in the second half the (rather dark) drawable on the right is only lit when the light source is in the top left corner, as if the drawable was sat at 0, 0. The world transform relative to the light source is not accounted for. Here is a minimal example which draws a sprite and a circle shape. The effect is more noticable: when the mouse cursor is over the sprite a small red dot is drawn - but the mouse has to be in the top left corner for the dot to appear over the circle shape. Apologies for the length of the shader, I gut it best I could.
#define SFML_NO_DEPRECATED_WARNINGS
#include <SFML/Graphics.hpp>
static const std::string vertex =
"#version 120\n"
"uniform vec3 u_pointLightPosition;\n"
"varying vec3 v_eyeDirection;\n"
"varying vec3 v_pointLightDirection;\n"
"const vec3 cameraWorldPosition = vec3(400.0, 300.0, 1780.0);\n"
"void main()\n"
"{\n" \
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n"
" gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;\n"
" gl_FrontColor = gl_Color;\n"
" vec3 viewVertex = vec3(gl_ModelViewMatrix * gl_Vertex);\n"
" v_pointLightDirection = vec3(gl_ModelViewMatrix * vec4(u_pointLightPosition, 1.0)) - viewVertex;\n"
" v_eyeDirection = ((gl_ModelViewMatrix * vec4(cameraWorldPosition, 1.0)).xyz - viewVertex);\n"
"}";
static const std::string fragment =
"#version 120\n"
"varying vec3 v_eyeDirection;\n"
"varying vec3 v_pointLightDirection;\n"
"vec4 diffuseColour;\n"
"vec3 calcLighting(vec3 normal, vec3 lightDirection, vec3 lightDiffuse, vec3 lightSpec, float falloff)\n"
"{\n"
" float diffuseAmount = max(dot(normal, lightDirection), 0.0);\n"
" diffuseAmount = pow((diffuseAmount * 0.5) + 0.5, 2.0);\n"
" vec3 mixedColour = lightDiffuse * diffuseColour.rgb * diffuseAmount * falloff;\n"
" return mixedColour;\n"
"}\n"
"void main()\n"
"{\n"
" diffuseColour = gl_Color;\n"
" vec3 normalVector = vec3(0.0, 0.0, 1.0);\n"
" vec3 blendedColour = diffuseColour.rgb * vec3(0.2, 0.2, 0.2);\n"
" vec3 pointLightDir = v_pointLightDirection * 0.001;\n"
" float falloff = clamp(1.0 - sqrt(dot(pointLightDir, pointLightDir)), 0.0, 1.0);\n"
" blendedColour += calcLighting(normalVector, normalize(v_pointLightDirection), vec3(1.0, 0.0, 0.0), vec3(1.0), falloff);\n"
" gl_FragColor.rgb = blendedColour;\n"
" gl_FragColor.a = diffuseColour.a;\n"
"}";
int main()
{
sf::RenderWindow rw;
rw.create({ 800, 600 }, "Buns");
sf::Texture texture;
texture.loadFromFile("whiteSquare.png");
sf::Sprite sprite(texture);
sprite.setPosition(100.f, 500.f);
sf::CircleShape circle(50.f);
circle.setTexture(&texture);
circle.setPosition(600.f, 500.f);
sf::Shader shader;
shader.loadFromMemory(vertex, fragment);
while (rw.isOpen())
{
sf::Event evt;
while (rw.pollEvent(evt))
{
if (evt.type == sf::Event::Closed)
{
rw.close();
}
}
auto pos = rw.mapPixelToCoords(sf::Mouse::getPosition(rw));
shader.setParameter("u_pointLightPosition", sf::Vector3f(pos.x, pos.y, 10.f));
rw.clear(sf::Color::Blue);
rw.draw(sprite, &shader);
rw.draw(circle, &shader);
rw.display();
}
return 0;
}