mieki256's diary



2021/09/17(金) [n年前の日記]

#1 [love2d] love2dでテクスチャ付きポリゴンを描画したい

love2d 11.3 を使って、テクスチャ付きポリゴンを描画してみたい。

polygonかと思ったら違った。 :

ググったら、love2d には love.graphics.polygon() という描画命令があるっぽい。さてはコレを使うのかなと思ったのだけど。

_love.graphics.polygon - LOVE

試してみたら、多角形を一色でベタ塗り、もしくは、多角形の線分を描画する命令だった。テクスチャ付きで描画できるわけではないらしい…。

_conf.lua
function love.conf(t)
  t.window.title = "Love2d polygon"
  t.window.width = 640
  t.window.height = 480
  t.window.vsync = true
  t.modules.joystick = false
  -- t.window.fullscreen = true
  -- t.window.fullscreentype = "exclusive"
end

_main.lua
-- Love2d Polygon

-- init
function love.load()
  -- get window width and height
  wdw_w, wdw_h = love.graphics.getDimensions()
end

-- update
function love.update(dt)

end

-- draw
function love.draw()
  -- fill BG color
  love.graphics.setColor(0.1, 0.2, 0.4)
  love.graphics.rectangle("fill", 0, 0, wdw_w, wdw_h)

  -- draw polygon (fill)
  love.graphics.setColor(0, 1, 1)
  local x0, y0 = 250, 100
  local x1, y1 = 350, 100
  local x2, y2 = 500, 200
  local x3, y3 = 100, 200
  love.graphics.polygon("fill", x0, y0, x1, y1, x2, y2, x3, y3)

  -- draw polygon (line)
  love.graphics.setColor(1, 0, 0)
  local vertices = {250, 300, 350, 300, 500, 400, 100, 400}
  love.graphics.polygon("line", vertices)
  
  -- print FPS
  love.graphics.setColor(1, 1, 1)
  love.graphics.print("FPS: "..tostring(love.timer.getFPS()), 10, 10)
end

function love.keypressed(key, isrepeat)
  -- ESC to exit
  if key == "escape" then
    love.event.quit()
  end
end

01_polygon_ss01.png

Meshがテクスチャ付きだった。 :

更にググったら、どうやら Mesh とやらがテクスチャ付きポリゴンに相当するっぽいなと。

_Mesh - LOVE

1つの頂点につき、x, y, u, v, r ,g, b, a を指定したテーブルを用意して生成するらしい。
  • (x, y) は描画位置。
  • (u, v) はテクスチャ上の座標。0.0 - 1.0 を指定。
  • (r, g, b, a) は、赤(Red)、緑(Green)、青(Blue)、透明度(Alpha)の指定。0.0 - 1.0 を指定。

_conf.lua
function love.conf(t)
  t.window.title = "Love2d Mesh"
  t.window.width = 640
  t.window.height = 480
  t.window.vsync = true
  t.modules.joystick = false
  -- t.window.fullscreen = true
  -- t.window.fullscreentype = "exclusive"
end

_main.lua
-- Love2d Mesh

-- init
function love.load()
  -- get window width and height
  wdw_w, wdw_h = love.graphics.getDimensions()

  img = love.graphics.newImage("uvcheckermap01-512.png")

  bx, by = wdw_w / 2, wdw_h / 2
  vertices = {
    {
      -- top left
      -- x, y, u, v, r, g, b, a
      bx - 50, by - 200, 0, 0, 1, 1, 1, 1
    },
    {
      -- top right
      -- x, y, u, v, r, g, b, a
      bx + 50, by -200, 1, 0, 1, 1, 1, 1
    },
    {
      -- bottom left
      -- x, y, u, v, r, g, b, a
      bx - 300, by + 200, 0, 1, 1, 1, 1, 1
    },
    {
      -- bottom right
      -- x, y, u, v, r, g, b, a
      bx + 300, by + 200, 1, 1, 1, 1, 1, 1
    },
  }

  mesh = love.graphics.newMesh(vertices, "strip")
  mesh:setTexture(img)
end

-- update
function love.update(dt)

end

-- draw
function love.draw()
  -- fill BG color
  love.graphics.setColor(0, 0, 0)
  love.graphics.rectangle("fill", 0, 0, wdw_w, wdw_h)

  -- draw mesh
  love.graphics.setColor(1, 1, 1)
  love.graphics.draw(mesh, 0, 0)
  
  -- print FPS
  love.graphics.setColor(1, 1, 1)
  love.graphics.print("FPS: "..tostring(love.timer.getFPS()), 10, 10)
end

function love.keypressed(key, isrepeat)
  -- ESC to exit
  if key == "escape" then
    love.event.quit()
  end
end

以下はソースで使った使用画像。

_uvcheckermap01-512.png

実行すると、こうなった。

mesh_ss01.png

めっちゃ歪んでる…。

どうして歪むかというと、love2d の Mesh は、多角形を三角形で分割して描画しているからで…。今回は四角形だから、三角形2つに分割されてる。前述のソースでは、Mesh の分割方法で "strip" を指定しているので、以下のような分割のされ方になっている。

mesh_ss02.png

そりゃ歪むわなと。こちらが期待した結果にならないのは当然。

解決策は別途考えることにする。

ちなみに、分割の仕方と言うか、三角形の並べ方は、"fan", "strip", "triangles" 等が選べるらしい。

_MeshDrawMode - LOVE

頂点を動かしてみる。 :

ひとまず、Mesh の各頂点の位置を動かせないと使い道がなさそうなので、頂点を動かせそうか試してみる。

ググった感じでは、Mesh:setVertex() が使えそうだなと…。生成済みの Mesh 内で、特定の番号の頂点情報を変更できる模様。

_Mesh:setVertex - LOVE

以下のソースでは、1番目と2番目の頂点の、x座標だけを変更している。

_conf.lua
function love.conf(t)
  t.window.title = "Love2d Mesh"
  t.window.width = 640
  t.window.height = 480
  t.window.vsync = true
  t.modules.joystick = false
  -- t.window.fullscreen = true
  -- t.window.fullscreentype = "exclusive"
end

_main.lua
-- Love2d Mesh

-- init
function love.load()
  -- get window width and height
  wdw_w, wdw_h = love.graphics.getDimensions()

  img = love.graphics.newImage("uvcheckermap01-512.png")

  bx, by = wdw_w / 2, wdw_h / 2
  v = {
    {
      -- top left
      -- x, y, u, v, r, g, b
      bx - 50, by - 200, 0.0, 0.0, 1.0, 1.0, 1.0
    },
    {
      -- top right
      -- x, y, u, v, e, g, b
      bx + 50, by -200, 1.0, 0.0, 1.0, 1.0, 1.0
    },
    {
      -- bottom left
      -- x, y, u, v, e, g, b
      bx - 300, by + 200, 0.0, 1.0, 1.0, 1.0, 1.0
    },
    {
      -- bottom right
      -- x, y, u, v, e, g, b
      bx + 300, by + 200, 1.0, 1.0, 1.0, 1.0, 1.0
    },
  }

  mesh = love.graphics.newMesh(v, "strip")
  mesh:setTexture(img)

  ang = 0
end

-- update
function love.update(dt)
  ang = ang + 180 * dt
  local d = 150 + 100 * math.sin(math.rad(ang))

  -- mesh:setVertex(index, x, y, u, v, r, g, b, a)
  local i = 1
  mesh:setVertex(i, (bx - d), v[i][2], v[i][3], v[i][4], v[i][5], v[i][6], v[i][7], v[i][8])
  i = 2
  mesh:setVertex(i, (bx + d), v[i][2], v[i][3], v[i][4], v[i][5], v[i][6], v[i][7], v[i][8])

  -- v[1][1] = bx - d
  -- v[2][1] = bx + d
  -- mesh:setVertex(1, v[1])
  -- mesh:setVertex(2, v[2])
end

-- draw
function love.draw()
  -- fill BG color
  love.graphics.setColor(0.1, 0.2, 0.4)
  love.graphics.rectangle("fill", 0, 0, wdw_w, wdw_h)

  -- draw mesh
  love.graphics.setColor(1, 1, 1)
  love.graphics.draw(mesh, 0, 0)

  -- print FPS
  love.graphics.setColor(1, 1, 1)
  love.graphics.print("FPS: "..tostring(love.timer.getFPS()), 10, 10)
end

function love.keypressed(key, isrepeat)
  -- ESC to exit
  if key == "escape" then
    love.event.quit()
  end
end

使用画像は以下。

_uvcheckermap01-512.png

実行してみると、こうなった。




ということで、Mesh の頂点を動かすことは一応できそうだなと…。

さておき。Mesh:setVertex() は、x, y, u, v, r, g, b, a、頂点が持つ全部のパラメータを指定しないといけないようで。試しに x だけ指定してみたら、残りのパラメータは全部 0.0 になってしまった…。

もしかすると、Mesh:setVertexAttribute() を使えば、(x, y) だけとか、(u, v)だけとか、特定の属性のみを変更できるのかもしれない…?

_Mesh:setVertexAttribute - LOVE

試してみたところ、Mesh:setVertexAttribute() でも同じ処理ができた。
  • attributeindex = 1 なら (x, y) を変更 ... Mesh:setVertexAttribute(index, 1, x, y) と記述。
  • attributeindex = 2 なら (u, v) を変更 ... Mesh:setVertexAttribute(index, 2, u, v) と記述。
  • attributeindex = 3 なら (r, g, b, a) を変更 ... Mesh:setVertexAttribute(index, 3, r, g, b, a) と記述。

-- update
function love.update(dt)
  ang = ang + 180 * dt
  local d = 150 + 100 * math.sin(math.rad(ang))

  -- change vertex x, y
  mesh:setVertexAttribute(1, 1, (bx - d), v[1][2])
  mesh:setVertexAttribute(2, 1, (bx + d), v[2][2])
end

以上、1 日分です。

過去ログ表示

Prev - 2021/09 - Next
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project