buddy148
buddy148

Reputation: 167

Strange texture behavior on mesh in Love2D, Help needed to achieve the result I was expecting

The following code has this result:

enter image description here

local mesh = nil
local img = love.graphics.newImage("test_blue.png")

function love.load()
  mesh = love.graphics.newMesh(4, img, "fan")
  mesh:setVertices({
    {125, 100, 0, 0, 255, 255, 255, 255},  --Top Left
    {150, 100, 1, 0, 255, 255, 255, 255},  --Top Right
    {200, 400, 1, 1, 255, 255, 255, 255},  --Bottom Right
    {100, 400, 0, 1, 255, 255, 255, 255} --Bottom Left
  })
end

function love.draw()
  love.graphics.draw(mesh, 200, 0)
end

I'd like to know how I could get a result like this:

Upvotes: 4

Views: 1484

Answers (3)

Elliot B
Elliot B

Reputation: 1

Another way to achieve this effect. Arrange the vertices of the quad as a zigzag up and down the quad.

perspective quad cheat

zigZagCount = 11
verticesCount = zigZagCount + 3

mesh = love.graphics.newMesh(verticesCount,"strip")
local meshImage = love.graphics.newImage("uv.png")
mesh:setTexture(meshImage)

halfWidth = 100
halfHeight = 100

function love.load()
    updateMesh()
end

function love.draw()
    love.graphics.setColor(1,1,1)
    love.graphics.translate(halfWidth+20,halfWidth+20)
    love.graphics.draw(mesh)
    for i=1,verticesCount do
        love.graphics.setColor(1,i/verticesCount,0)
        local x,y = mesh:getVertex(i)
        love.graphics.circle("fill",x,y,3)
    end
end

function updateMesh()
    local topScale = .5
    local bottomScale = 1

    local topX = -halfWidth*topScale
    local bottomX = -halfWidth*bottomScale
    local uIncrement = 1/zigZagCount
    local widthPart = halfWidth*2/zigZagCount
    local topXIncrement = widthPart*topScale
    local bottomXIncrement = widthPart*bottomScale

    local u = 0
    local isTopPoint = true -- flip the zig zag with false
    
    if isTopPoint then
        mesh:setVertex(1,
            topX,-halfHeight,u,0,.5
        )
    else
        mesh:setVertex(1,
            bottomX,-halfHeight,u,.5
        )
    end

    isTopPoint = not isTopPoint

    for i=2, verticesCount-1 do

        if isTopPoint then
            mesh:setVertex(i,
                topX,-halfHeight,u,0
            )
        else 
            mesh:setVertex(i,
                bottomX,halfHeight,u,1
            )
        end

        topX =  topX+topXIncrement
        bottomX = bottomX+bottomXIncrement
        u = u+uIncrement
        isTopPoint = not isTopPoint
    end
    
    if isTopPoint then
        mesh:setVertex(verticesCount,
            topX-topXIncrement,-halfHeight,1,.5
        )
    else
        mesh:setVertex(verticesCount,
            bottomX-bottomXIncrement,halfHeight,1,1
        )
    end
end

Increase `zigZagCount` for higher accuracy.
This might have some use-cases.  Didn't end up using it but here ya'll go.

Upvotes: 0

user7003504
user7003504

Reputation:

Math to build shader able to fix this issue is commonly explained on google in many threads, and there are multiple approaches (tag: perspective correct texture mapping).

If you want to build your own shader or use shader from source different than Love2D, mind that Love2D currently uses GLSL v.1.20 with some minor changes.

There is forum thread where you can get completed shader file, currently for Love2D v.0.10.2. Simple use, code commented properly.

https://www.love2d.org/forums/viewtopic.php?f=5&t=12483&start=120 Post by drunken_munki » Wed Apr 26, 2017 11:03 am

Upvotes: 0

ryanpattison
ryanpattison

Reputation: 6251

Without using a 3D library you cannot get a true the depth effect without implementing perspective. The problem is that the polygon is made from 2D triangles and only 2D effects can be applied like shearing or scaling (as a whole). The parallel lines in the texture will always be parallel which is not the case for your bottom image since they converge toward a vanishing point.

For more reading see Perspective Correctness section of Texture Mapping

Changing the coordinate of the texture map can minimize some of the artifacts visually by clipping toward a vanishing point instead of scaling.

Lines in the texture do not have to be parallel if they are part of separate triangles and so adding more triangles allows them to shear toward one another at the cost of more clipping.

Both modifying texture coordinates and using more triangles can be problematic for different styles of texture so you may need to tune it on a case by case basis.

local mesh = nil
local img = love.graphics.newImage("test_blue.png")

function love.load()
  mesh = love.graphics.newMesh(5, img, "strip")
  local top_left  = {125, 100, .125, 0, 255, 255, 255, 255} 
  local top_right = {150, 100, .875, 0, 255, 255, 255, 255}
  local bot_right = {200, 400, 1, 1, 255, 255, 255, 255}
  local bot_left  = {100, 400, 0, 1, 255, 255, 255, 255}
  local bot_mid   = {150, 400, .5,1, 255, 255, 255, 255} 

  mesh:setVertices{
      bot_left, top_left, bot_mid, top_right, bot_right,
  }

end

function love.draw()
  love.graphics.draw(mesh, 200, 0)
end

enter image description here

Upvotes: 0

Related Questions