Love2D 中网格上的奇怪纹理行为,需要帮助才能实现我期望的结果

问题描述 投票:0回答:3

以下代码有这样的结果:

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

我想知道如何得到这样的结果:

graphics lua mesh love2d
3个回答
0
投票

如果不使用 3D 库,您就无法在不实现透视的情况下获得真正的深度效果。问题是多边形是由 2D 三角形组成的,并且只能应用 2D 效果,例如剪切或缩放(作为整体)。纹理中的平行线始终是平行的,但底部图像的情况并非如此,因为它们会聚向消失点。

更多阅读请参阅纹理映射的透视正确性部分

更改纹理贴图的坐标可以通过向消失点剪切而不是缩放来在视觉上最小化一些伪影。

如果纹理中的线条是单独三角形的一部分,则它们不必平行,因此添加更多三角形可以使它们相互剪切,但代价是更多剪切。

对于不同样式的纹理,修改纹理坐标和使用更多三角形都可能会出现问题,因此您可能需要根据具体情况进行调整。

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


0
投票

构建能够解决此问题的着色器的数学通常在谷歌上的许多线程中进行解释,并且有多种方法(标签:透视正确的纹理映射)。

如果您想构建自己的着色器或使用不同于 Love2D 的源着色器,请注意 Love2D 目前使用 GLSL v.1.20 并进行了一些细微的更改。

在论坛帖子中您可以获取完整的着色器文件,目前适用于 Love2D v.0.10.2。使用简单,代码注释正确。

https://www.love2d.org/forums/viewtopic.php?f=5&t=12483&start=120 由醉酒者发表 » 2017 年 4 月 26 日星期三上午 11:03


0
投票

实现此效果的另一种方法。 将四边形的顶点排列为四边形上下之字形。

透视四边形作弊

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.
© www.soinside.com 2019 - 2024. All rights reserved.