2021/09/17(金) [n年前の日記]
#1 [love2d] love2dでテクスチャ付きポリゴンを描画したい
love2d 11.3 を使って、テクスチャ付きポリゴンを描画してみたい。
◎ polygonかと思ったら違った。 :
ググったら、love2d には love.graphics.polygon() という描画命令があるっぽい。さてはコレを使うのかなと思ったのだけど。
_love.graphics.polygon - LOVE
試してみたら、多角形を一色でベタ塗り、もしくは、多角形の線分を描画する命令だった。テクスチャ付きで描画できるわけではないらしい…。
_conf.lua
_main.lua
_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
◎ Meshがテクスチャ付きだった。 :
更にググったら、どうやら Mesh とやらがテクスチャ付きポリゴンに相当するっぽいなと。
_Mesh - LOVE
1つの頂点につき、x, y, u, v, r ,g, b, a を指定したテーブルを用意して生成するらしい。
_conf.lua
_main.lua
以下はソースで使った使用画像。
_uvcheckermap01-512.png
実行すると、こうなった。
めっちゃ歪んでる…。
どうして歪むかというと、love2d の Mesh は、多角形を三角形で分割して描画しているからで…。今回は四角形だから、三角形2つに分割されてる。前述のソースでは、Mesh の分割方法で "strip" を指定しているので、以下のような分割のされ方になっている。
そりゃ歪むわなと。こちらが期待した結果にならないのは当然。
解決策は別途考えることにする。
ちなみに、分割の仕方と言うか、三角形の並べ方は、"fan", "strip", "triangles" 等が選べるらしい。
_MeshDrawMode - LOVE
_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
実行すると、こうなった。
めっちゃ歪んでる…。
どうして歪むかというと、love2d の Mesh は、多角形を三角形で分割して描画しているからで…。今回は四角形だから、三角形2つに分割されてる。前述のソースでは、Mesh の分割方法で "strip" を指定しているので、以下のような分割のされ方になっている。
そりゃ歪むわなと。こちらが期待した結果にならないのは当然。
解決策は別途考えることにする。
ちなみに、分割の仕方と言うか、三角形の並べ方は、"fan", "strip", "triangles" 等が選べるらしい。
_MeshDrawMode - LOVE
◎ 頂点を動かしてみる。 :
ひとまず、Mesh の各頂点の位置を動かせないと使い道がなさそうなので、頂点を動かせそうか試してみる。
ググった感じでは、Mesh:setVertex() が使えそうだなと…。生成済みの Mesh 内で、特定の番号の頂点情報を変更できる模様。
_Mesh:setVertex - LOVE
以下のソースでは、1番目と2番目の頂点の、x座標だけを変更している。
_conf.lua
_main.lua
使用画像は以下。
_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() でも同じ処理ができた。
ググった感じでは、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 日分です。


