1
Graphics / Re: Shader moves seperately from view / actual position of shaded object
« on: May 19, 2019, 11:44:21 am »You probably need to feed the shader with actual pixel coordinates instead of view positions
Here is how I do something similar:
sf::Vector2i pos = window.mapCoordsToPixel(sf::Vector2f(light.x, light.y));
shader.setParameter("light_position", pos.x, pos.y);
Have a look at these two:
Vector2f mapPixelToCoords (const Vector2i &point) const
Vector2i mapCoordsToPixel (const Vector2f &point) const
here:
https://www.sfml-dev.org/documentation/2.5.1/classsf_1_1RenderTarget.php
I tried both of those but I wasn't able to get the shader to align properly still. I did figure it out though! I added a viewPosition uniform to my shader and it works just like expected now.
Here's the updated code from my light render function:
sf::RectangleShape lightShape;
lightShape.setSize(sf::Vector2f(radius * 2, radius * 2));
lightShape.setPosition(position - lightShape.getSize() / 2.f);
sf::RectangleShape colorOverlay;
colorOverlay.setSize(lightShape.getSize());
colorOverlay.setPosition(lightShape.getPosition());
colorOverlay.setFillColor(color);
lightFrag->setUniform("viewPosition", sf::Vector2f(view.getCenter().x - view.getSize().x / 2.f, invertCoordinateY(view.getCenter().y + view.getSize().y / 2.f, view.getSize().y)));
lightFrag->setUniform("viewportRes", lightShape.getSize() / 2.f);
lightFrag->setUniform("origin", sf::Vector2f(position.x, invertCoordinateY(position.y, view.getSize().y)));
lightMap.draw(lightShape, lightStates);
lightMap.draw(colorOverlay, sf::BlendMultiply);
lightShape.setSize(sf::Vector2f(radius * 2, radius * 2));
lightShape.setPosition(position - lightShape.getSize() / 2.f);
sf::RectangleShape colorOverlay;
colorOverlay.setSize(lightShape.getSize());
colorOverlay.setPosition(lightShape.getPosition());
colorOverlay.setFillColor(color);
lightFrag->setUniform("viewPosition", sf::Vector2f(view.getCenter().x - view.getSize().x / 2.f, invertCoordinateY(view.getCenter().y + view.getSize().y / 2.f, view.getSize().y)));
lightFrag->setUniform("viewportRes", lightShape.getSize() / 2.f);
lightFrag->setUniform("origin", sf::Vector2f(position.x, invertCoordinateY(position.y, view.getSize().y)));
lightMap.draw(lightShape, lightStates);
lightMap.draw(colorOverlay, sf::BlendMultiply);
And the updated shader:
uniform vec2 viewportRes;
uniform vec2 origin;
uniform vec4 color;
uniform vec2 viewPosition;
void main( out vec4 fragColor, in vec2 fragCoord )
{
// pixel coords
vec2 xy = vec2(gl_FragCoord.x, gl_FragCoord.y);
xy += viewPosition;
// pixel distance from center
vec2 vecDistance = vec2((origin.x - xy.x) * (origin.x - xy.x),
(origin.y - xy.y) * (origin.y - xy.y));
float distanceToCenter = sqrt(vecDistance.x + vecDistance.y);
float distancePercent = distanceToCenter / viewportRes.x;
// output to screen
color = vec4(1.0 - distancePercent, 1.0 - distancePercent, 1.0 - distancePercent, 1.0 - distancePercent);
fragColor = vec4(color);
}
uniform vec2 origin;
uniform vec4 color;
uniform vec2 viewPosition;
void main( out vec4 fragColor, in vec2 fragCoord )
{
// pixel coords
vec2 xy = vec2(gl_FragCoord.x, gl_FragCoord.y);
xy += viewPosition;
// pixel distance from center
vec2 vecDistance = vec2((origin.x - xy.x) * (origin.x - xy.x),
(origin.y - xy.y) * (origin.y - xy.y));
float distanceToCenter = sqrt(vecDistance.x + vecDistance.y);
float distancePercent = distanceToCenter / viewportRes.x;
// output to screen
color = vec4(1.0 - distancePercent, 1.0 - distancePercent, 1.0 - distancePercent, 1.0 - distancePercent);
fragColor = vec4(color);
}
I simply had to add the viewPosition to the fragment coord for it to properly move around on the screen. I also solved the last question I posted about. The fragColor had 1.0 in alpha which obviously caused issues so after subtracting that with distancePercent like the other color values, there's no more "fighting" between the lights.