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
[ ツッコむ ]
以上です。