This is my first question here and I hope to find someone that have good knowledge about Love2D graphics and shaders.
I'm actually working on a minimalistic light system for my game but actually I'm building it for the Love2D community, but not ready for release yet. That's why I'm asking here this question...
So I have this shader :
Code: Select all
#define NUM_LIGHTS 32
struct Light {
vec2 position;
vec3 diffuse;
float power;
bool enabled;
};
extern Light lights[NUM_LIGHTS];
extern vec2 screen;
extern vec3 ambientLightColor = vec3(0);
const float constant = 1.0;
const float linear = 0.09;
const float quadratic = 0.032;
vec4 effect(vec4 color, Image image, vec2 uvs, vec2 screen_coords){
vec4 pixel = Texel(image, uvs);
pixel *= color;
vec2 norm_screen = screen_coords / screen;
vec3 diffuse = ambientLightColor;
for (int i = 0; i < NUM_LIGHTS; i++) {
if (lights[i].enabled) {
Light light = lights[i];
vec2 norm_pos = light.position / screen;
float distance = length(norm_pos - norm_screen) / (light.power / 1000);
float attenuation = 1.0 / (constant + linear * distance + quadratic * (distance * distance));
diffuse += light.diffuse * attenuation;
}
}
diffuse = clamp(diffuse, 0.0, 1.0);
return pixel * vec4(diffuse, 1.0);
}
In my game I have a camera like this :
Code: Select all
local Camera = {}
Camera.x = 0
Camera.y = 0
Camera.scaleX = 1
Camera.scaleY = 1
Camera.rotation = 0
Camera.shakeDuration = 0
Camera.shakeMagnitude = 0
function Camera:set()
love.graphics.push()
love.graphics.rotate(-self.rotation)
love.graphics.scale(1 / self.scaleX, 1 / self.scaleY)
love.graphics.translate(-self.x, -self.y)
end
function Camera:update(dt)
if (self.shakeDuration > 0) then
self.shakeDuration = self.shakeDuration - dt
end -- if
end -- function
function Camera:draw()
if (self.shakeDuration > 0) then
local dx = love.math.random(-self.shakeMagnitude, self.shakeMagnitude)
local dy = love.math.random(-self.shakeMagnitude, self.shakeMagnitude)
love.graphics.translate(dx, dy)
end -- if
end -- function
function Camera:unset()
love.graphics.pop()
end
function Camera:move(dx, dy)
self.x = self.x + (dx or 0)
self.y = self.y + (dy or 0)
end
function Camera:rotate(dr)
self.rotation = self.rotation + dr
end
function Camera:scale(sx, sy)
sx = sx or 1
self.scaleX = self.scaleX * sx
self.scaleY = self.scaleY * (sy or sx)
end
function Camera:setPosition(x, y)
self.x = x or self.x
self.y = y or self.y
end
function Camera:setScale(sx, sy)
self.scaleX = sx or self.scaleX
self.scaleY = sy or self.scaleY
end
function Camera:startShake(duration, magnitude)
self.shakeDuration = duration
self.shakeMagnitude = magnitude
end -- function
return Camera
I define a light in my shader at the position of my player, and I never update it's position (fixed light). Sadly the light will always "follow" the camera or screen. and the light will not appear correctly on the player. So I assume there is a "coordinates system" problem.
My actual understanding of the issue is that I should do some math with the global TransformProjectionMatrix variable (https://www.love2d.org/wiki/Shader_Variables) to be able to get the coordinates based on the graphics current translate or something like that.
I really hope that make any sens for somebody
I don't ask somebody to solve the math for me but just to know if I'm on the correct "path" for solving my issue. I already tried a whole lot of thing in the shader but literally I've just found tons of ways of doing always the same thing...
Don't even hesitate to answer, I need reflection about the subject so even if you're not aware of a solution, if you think of something, please let me know!
I really hope to be able to bring my light engine to the love2D community, I love this framework and it's the last real obstacle for me to let you guys add easy lights to your games.
As a side note (not for promoting) here's the trello of the project : https://trello.com/b/4kLFwfyV
Regards