light sources demo
This commit is contained in:
parent
87b6a8469b
commit
d975e7f463
BIN
assets/masks/circle.png
Normal file
BIN
assets/masks/circle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 572 B |
BIN
assets/masks/noise.png
Normal file
BIN
assets/masks/noise.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
BIN
assets/masks/star8.png
Normal file
BIN
assets/masks/star8.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 748 B |
18
assets/shaders/blur.glsl
Normal file
18
assets/shaders/blur.glsl
Normal file
@ -0,0 +1,18 @@
|
||||
extern vec2 direction; // (1.0, 0.0) для X, (0.0, 1.0) для Y
|
||||
extern number radius; // радиус размытия
|
||||
|
||||
vec4 effect(vec4 vcolor, Image tex, vec2 texture_coords, vec2 screen_coords)
|
||||
{
|
||||
vec4 sum = vec4(0.0);
|
||||
float weightTotal = 0.0;
|
||||
|
||||
for (int i = -10; i <= 10; i++) {
|
||||
float offset = float(i);
|
||||
float weight = exp(-offset * offset / (2.0 * radius * radius));
|
||||
vec2 shift = direction * offset / love_ScreenSize.xy;
|
||||
sum += Texel(tex, texture_coords + shift) * weight;
|
||||
weightTotal += weight;
|
||||
}
|
||||
|
||||
return sum / weightTotal;
|
||||
}
|
||||
30
assets/shaders/light.glsl
Normal file
30
assets/shaders/light.glsl
Normal file
@ -0,0 +1,30 @@
|
||||
extern vec3 color;
|
||||
extern number time;
|
||||
|
||||
vec4 effect(vec4 vcolor, Image tex, vec2 texture_coords, vec2 screen_coords)
|
||||
{
|
||||
vec4 texColor = Texel(tex, texture_coords);
|
||||
|
||||
float mask = texColor.r;
|
||||
|
||||
vec2 uv = texture_coords - 0.5;
|
||||
float dist = length(uv * 2.0);
|
||||
|
||||
float t = time;
|
||||
|
||||
float wave = sin((uv.x + uv.y) * 6.0 + t * 1.5) * 0.03;
|
||||
float ripple = sin(length(uv) * 20.0 - t * 2.0) * 0.02;
|
||||
float flicker = sin(t * 2.5) * 0.02;
|
||||
|
||||
dist += wave + ripple + flicker;
|
||||
|
||||
float intensity = 1.0 - smoothstep(0.0, 1.0, dist);
|
||||
intensity = pow(intensity, 2.0);
|
||||
|
||||
float colorShift = sin(t * 3.0) * 0.1;
|
||||
vec3 flickerColor = color + vec3(colorShift, colorShift * 0.5, -colorShift * 0.3);
|
||||
|
||||
vec3 finalColor = flickerColor * intensity * mask;
|
||||
|
||||
return vec4(finalColor, mask * intensity);
|
||||
}
|
||||
@ -1,14 +1,21 @@
|
||||
__LightSource = {
|
||||
position = Vec3 {},
|
||||
power = 0, -- in meters
|
||||
color = Vec3 {} --r, g, b
|
||||
color = Vec3 {}, --r, g, b
|
||||
seed = 0, -- random float to make every light unique,
|
||||
shader = nil,
|
||||
mask = nil
|
||||
}
|
||||
|
||||
function LightSource(position, power, color)
|
||||
function LightSource(position, power, color, shader, mask)
|
||||
local l = {
|
||||
position = position,
|
||||
power = power,
|
||||
color = color
|
||||
color = color,
|
||||
seed = math.random() * math.pi * 2,
|
||||
shader = shader or AssetBundle.files.shaders.light,
|
||||
mask = mask or AssetBundle.files.masks.circle
|
||||
|
||||
}
|
||||
return setmetatable(l, { __index = __LightSource })
|
||||
end
|
||||
|
||||
106
main.lua
106
main.lua
@ -9,11 +9,7 @@ PIXELS_PER_METER = 48
|
||||
P = nil
|
||||
|
||||
Entities = {}
|
||||
Lights = {
|
||||
LightSource(Vec3 { 1, 1 }, 5),
|
||||
-- LightSource(Vec3 { 300, 200 }, 5),
|
||||
-- LightSource(Vec3 { 400, 200 }, 5)
|
||||
}
|
||||
Lights = nil
|
||||
|
||||
function love.conf(t)
|
||||
t.console = true
|
||||
@ -21,13 +17,18 @@ end
|
||||
|
||||
function love.load()
|
||||
AssetBundle:load()
|
||||
love.window.setMode(1080, 720, { resizable = true, msaa = 4 })
|
||||
love.window.setMode(1080, 720, { resizable = true, msaa = 4, vsync = true })
|
||||
|
||||
Lights = { LightSource(Vec3 { 1, 1 }, 3, Vec3 { 0.5, 0.2, 1.0 }),
|
||||
LightSource(Vec3 { 4, 1 }, 10, Vec3 { 0.3, 0.7, 1.0 }, nil, AssetBundle.files.masks.noise),
|
||||
LightSource(Vec3 { 7, 1 }, 3, Vec3 { 0.8, 0.3, 1.0 }), }
|
||||
|
||||
P = Player('fox')
|
||||
P.entity.position = Vec3 { 7, 7 }
|
||||
Entities.player = P.entity
|
||||
|
||||
Camera.position = Vec3 { 0, 0 }
|
||||
|
||||
print('ready')
|
||||
end
|
||||
|
||||
@ -44,41 +45,85 @@ local function worldToScreen(worldPos)
|
||||
end
|
||||
|
||||
|
||||
local function drawShadow(entity, light, radius)
|
||||
local shadow_vec = light - entity.position
|
||||
local function drawShadow(entity, light)
|
||||
local shadow_vec = light.position - entity.position
|
||||
local dist = shadow_vec:length()
|
||||
if dist > radius then return end
|
||||
if dist > light.power then return end
|
||||
|
||||
|
||||
love.graphics.setColor(0, 0, 0, math.min(0.5, 1 - (dist / radius)))
|
||||
love.graphics.setColor(0, 0, 0, math.min(0.5, 1 - (dist / light.power)))
|
||||
local tex, quad = entity:spriteFromAngle(shadow_vec:direction())
|
||||
|
||||
love.graphics.draw(tex, quad,
|
||||
worldToScreen(entity.position).x,
|
||||
worldToScreen(entity.position).y - 10,
|
||||
math.step_floor(shadow_vec:direction() - math.pi / 2, math.pi / 4),
|
||||
shadow_vec:direction() - math.pi / 2,
|
||||
1, math.sin(20), tex:getHeight() / 2, tex:getHeight())
|
||||
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
local function drawLight(light)
|
||||
local shader = light.shader
|
||||
|
||||
local pos = worldToScreen(light.position)
|
||||
shader:send("color", { light.color.x, light.color.y, light.color.z })
|
||||
shader:send("time", love.timer.getTime() + light.seed)
|
||||
|
||||
local scale = light.power * PIXELS_PER_METER / 64
|
||||
love.graphics.setShader(shader)
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
love.graphics.draw(light.mask,
|
||||
pos.x - light.power * PIXELS_PER_METER,
|
||||
pos.y - light.power * PIXELS_PER_METER,
|
||||
0,
|
||||
scale,
|
||||
scale)
|
||||
love.graphics.setShader()
|
||||
end
|
||||
|
||||
|
||||
local function applyBlur(input, output, radius)
|
||||
local blurShader = AssetBundle.files.shaders.blur
|
||||
|
||||
-- Горизонтальный проход
|
||||
blurShader:send("direction", { 1.0, 0.0 })
|
||||
blurShader:send("radius", radius)
|
||||
|
||||
output:renderTo(function()
|
||||
love.graphics.setShader(blurShader)
|
||||
love.graphics.draw(input)
|
||||
love.graphics.setShader()
|
||||
end)
|
||||
|
||||
-- Вертикальный проход
|
||||
input:renderTo(function()
|
||||
love.graphics.setShader(blurShader)
|
||||
blurShader:send("direction", { 0.0, 1.0 })
|
||||
love.graphics.draw(output)
|
||||
love.graphics.setShader()
|
||||
end)
|
||||
end
|
||||
|
||||
function love.draw()
|
||||
love.graphics.clear(1, 1, 1)
|
||||
local spriteCanvas = love.graphics.newCanvas()
|
||||
local width, height = spriteCanvas:getDimensions()
|
||||
spriteCanvas:setFilter("linear", "linear")
|
||||
local width, height = love.graphics.getDimensions()
|
||||
love.graphics.clear(0.1, 0.1, 0.1, 1.0)
|
||||
|
||||
love.graphics.setCanvas(spriteCanvas)
|
||||
love.graphics.clear(1, 1, 1)
|
||||
local spriteCanvas = love.graphics.newCanvas()
|
||||
local shadowCanvas = love.graphics.newCanvas()
|
||||
local lightCanvas = love.graphics.newCanvas()
|
||||
|
||||
love.graphics.clear(0.1, 0.1, 0.1, 1.0)
|
||||
|
||||
love.graphics.push()
|
||||
love.graphics.translate(width / 2, height / 2) -- теперь экранный ноль координат будет в центре экрана
|
||||
for _, e in pairs(Entities) do
|
||||
for _, l in pairs(Lights) do
|
||||
drawShadow(e, l.position, l.power)
|
||||
love.graphics.setCanvas(shadowCanvas)
|
||||
drawShadow(e, l)
|
||||
end
|
||||
|
||||
love.graphics.setCanvas(spriteCanvas)
|
||||
local tex, quad = e:spriteFromAngle(math.pi / 2)
|
||||
love.graphics.draw(tex, quad,
|
||||
worldToScreen(e.position).x,
|
||||
@ -88,17 +133,28 @@ function love.draw()
|
||||
end
|
||||
|
||||
|
||||
love.graphics.setColor(1, 0, 0, 1)
|
||||
love.graphics.push()
|
||||
love.graphics.translate(worldToScreen(Lights[1].position).x, worldToScreen(Lights[1].position).y)
|
||||
love.graphics.circle("fill", 0, 0, 0.1 * PIXELS_PER_METER)
|
||||
love.graphics.pop()
|
||||
love.graphics.pop()
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
love.graphics.setCanvas(lightCanvas)
|
||||
love.graphics.clear(0, 0, 0, 1)
|
||||
|
||||
for _, light in ipairs(Lights) do
|
||||
drawLight(light)
|
||||
end
|
||||
|
||||
love.graphics.setCanvas()
|
||||
|
||||
|
||||
|
||||
love.graphics.pop()
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
love.graphics.setCanvas()
|
||||
|
||||
applyBlur(shadowCanvas, love.graphics.newCanvas(), 10.0) -- тени мягче
|
||||
love.graphics.draw(shadowCanvas)
|
||||
love.graphics.draw(spriteCanvas)
|
||||
|
||||
love.graphics.setBlendMode("add", "premultiplied")
|
||||
love.graphics.draw(lightCanvas)
|
||||
love.graphics.setBlendMode("alpha")
|
||||
|
||||
love.graphics.setColor(1, 1, 1, 1)
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user