matiasah / shadows

Shädows - A Shadows & Lights engine for löve
MIT License
169 stars 9 forks source link

Incorrect behavior of shadow when highdpi is enabled #30

Open zwirec opened 5 years ago

zwirec commented 5 years ago

OS: MacOS 10.14.2 (18C54)

I have a simple code snippet similar to code located in wiki page https://github.com/matiasah/shadows/wiki/Standard-Demonstration

There is my code:

local Shadows = require("shadows")
local LightWorld = require("shadows.LightWorld")
local Light = require("shadows.Light")
local Body = require("shadows.Body")
local PolygonShadow = require("shadows.ShadowShapes.PolygonShadow")
local CircleShadow = require("shadows.ShadowShapes.CircleShadow")

love.window.setMode(1280, 1280, { highdpi = true })

-- Create a light world
newLightWorld = LightWorld:new()

-- Create a light on the light world, with radius 300
newLight = Light:new(newLightWorld, 300)

-- Set the light's color to white
newLight:SetColor(255, 255, 255, 255)

-- Set the light's position
newLight:SetPosition(400, 400)

-- Create a body
newBody = Body:new(newLightWorld)

-- Set the body's position and rotation
newBody:SetPosition(300, 300)
newBody:SetAngle(-15)

-- Create a polygon shape on the body with the given points
PolygonShadow:new(newBody, -10, -10, 10, -10, 10, 10, -10, 10)

-- Create a circle shape on the body at (-30, -30) with radius 16
CircleShadow:new(newBody, -30, -30, 16)

function love.draw()
    -- Clear the screen
    love.graphics.setColor(255, 255, 255, 255)
    love.graphics.rectangle("fill", 0, 0, love.graphics.getDimensions())

    -- Draw the light world with white color
    newLightWorld:Draw()
end

function love.update()
    -- Move the light to the mouse position with altitude 1.1
    newLight:SetPosition(love.mouse.getX(), love.mouse.getY(), 1.1)

    -- Recalculate the light world
    newLightWorld:Update()
end

function love.mousepressed()
    -- Create a new light with radius 300
    newLight = Light:new(newLightWorld, 300)

    -- Set the light's color randomly
    newLight:SetColor(math.random(0, 255), math.random(0, 255), math.random(0, 255), math.random(0, 255))
end

I set options highdpi for window to true and I got

image

With highdpi=false everything looks as it should be:

image
matiasah commented 5 years ago

Uh, unfortunately I don't have the hardware nor software to recreate this scenario, I'm not sure how could I solve this problem or help you out on your issue. I ran your code on my computer (which also uses Windows) but the problem does not seem to show up to me. Sorry.

Skeletonxf commented 5 years ago

I tried to reproduce this as well on my Linux laptop and I cannot reproduce - I get the correct behavior in the second screenshot without modifying the highdpi to false

I am using f8d1c8c89fe621447d066ea6c2cdea306cf988c2 and LOVE 11.1 (Mysterious Mysteries)

zwirec commented 5 years ago

I guess this effect is appear by reason of Mac Retina mode

Anyway I would be glad if someone would help me

Skeletonxf commented 5 years ago

It would seem this is a Mac specific flag in Love anyway so it will not be reproducible elsewhere.

https://love2d.org/wiki/love.window.getDPIScale

matiasah commented 5 years ago
the window may take up the same physical size as an 800x600 window, but the area inside the window uses 1600x1200 pixels

Which means, I would have to multiply the canvas size that is being sent to the shader (before it actually is sent to the shader), by the DPI scale.

Edit: Or either use this. https://love2d.org/wiki/love.graphics.getPixelDimensions

What do you guys suggest?

matiasah commented 5 years ago

This issue brings a lot of changes, as most of the things that are being sent to the shaders are erroneous

Skeletonxf commented 5 years ago

I think another concern is that you cannot cache the DPI scale as it might be changed while the application is running. I think multiplying by love.graphics.getDPIScale() everywhere would be more clear when reading the code - however it also seems not all units reported by Love need scaling.

The units of love.graphics.getWidth, love.graphics.getHeight, love.mouse.getPosition, mouse events, love.touch.getPosition, and touch events are always in DPI-scaled units rather than pixels. In LÖVE 0.10 and older they were in pixels.