2018/01/15(月) [n年前の日記]
#1 [love2d] love2dのShaderでパレット書き換えっぽい処理
love2d の Shader を使ってパレット書き換えっぽい処理を書いているけど、高速化・最適化できないか試したり。
環境は以下。
5種類の書き方を試したけど、結果はこんな感じで。
せいぜい、1FPS程度変わるか変わらないか、ぐらいの違いしか出てこなかった。
- GLSLはif文が重いという話があるらしいので、if文を無くしたり、三項演算子を無くしたり。
- A * (1.0 - f) + B * f を mix()関数で置き換えてみたり。
- A * (1.0 - f) + B * f を、A - A * f + B * f に置き換えてみたり。
- (A.r == C.r && A.g = C.g && A.b == C.b) を (A.rgb == C.rgb) に置き換えてみたり。
環境は以下。
- Raspberry Pi Zero W
- raspbian jessie
- love2d 0.10.2
- SDL2 2.0.5(OpenGL ES有効化)
5種類の書き方を試したけど、結果はこんな感じで。
Shader kind | FPS |
---|---|
1 | 7 |
2 | 7 - 8 |
3 | 7 |
4 | 6 - 7 |
5 | 7 - 8 |
◎ ソースと画像。 :
使用画像は以下。
_colorblock.png
ソースは以下。
_conf.lua
_main.lua
_colorblock.png
ソースは以下。
_conf.lua
function love.conf(t) t.window.title = "Shader test 04 palette change modoki" t.window.vsync = true t.window.resizable = true t.window.width = 1280 t.window.height = 720 -- t.window.fullscreen = true -- t.window.fullscreentype = "exclusive" end
_main.lua
-- Shader test 04 -- palette change modoki loop_count = 32 function love.load() love.graphics.setDefaultFilter("nearest", "nearest") scr_w, scr_h = 1280, 720 canvas = love.graphics.newCanvas(scr_w, scr_h) -- load image img = love.graphics.newImage("colorblock.png") local shadercode1 = [[ extern number factor; extern vec3 checkcolor; extern vec3 replacecolor; vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ vec4 pixel = Texel(texture, texture_coords); if (pixel.r == checkcolor.r && pixel.g == checkcolor.g && pixel.b == checkcolor.b) { pixel.r = pixel.r * (1.0 - factor) + replacecolor.r * factor; pixel.g = pixel.g * (1.0 - factor) + replacecolor.g * factor; pixel.b = pixel.b * (1.0 - factor) + replacecolor.b * factor; } return pixel * color; } ]] myshader1 = love.graphics.newShader(shadercode1) myshader1:send("checkcolor", {1.0, 0.0, 0.0}) -- R,G,B myshader1:send("replacecolor", {0.0, 0.0, 0.0}) -- R,G,B local shadercode2 = [[ extern number factor; extern number checkcolor; extern vec4 replacecolor; vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ vec4 pixel = Texel(texture, texture_coords); float nowcol = pixel.r * 16711680.0 + pixel.g * 65280.0 + pixel.b * 255.0; float fac = (checkcolor == nowcol)? factor : 0.0; return mix(pixel, replacecolor, fac) * color; } ]] myshader2 = love.graphics.newShader(shadercode2) -- checkcolor : 0xRRGGBB = (R << 16) + (G << 8) + B local checkcolor = ((1.0 * 65536) + (0.0 * 256) + 0.0) * 255.0 myshader2:send("checkcolor", checkcolor) myshader2:send("replacecolor", {0.0, 0.0, 0.0, 1.0}) -- R,G,B,A local shadercode3 = [[ extern number factor; extern number checkcolor; extern vec4 replacecolor; vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ vec4 pixel = Texel(texture, texture_coords); float nowcol = pixel.r * 16711680.0 + pixel.g * 65280.0 + pixel.b * 255.0; float fac = (1.0 - sign(abs(nowcol - checkcolor))) * factor; return mix(pixel, replacecolor, fac) * color; } ]] myshader3 = love.graphics.newShader(shadercode3) local checkcolor = ((1.0 * 65536) + (0.0 * 256) + 0.0) * 255.0 myshader3:send("checkcolor", checkcolor) myshader3:send("replacecolor", {0.0, 0.0, 0.0, 1.0}) -- R,G,B,A local shadercode4 = [[ extern number factor; extern vec4 checkcolor; extern vec4 replacecolor; vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ vec4 pixel = Texel(texture, texture_coords); return mix(pixel, replacecolor, ((pixel == checkcolor)? factor : 0.0)) * color; } ]] myshader4 = love.graphics.newShader(shadercode4) myshader4:send("checkcolor", {1.0, 0.0, 0.0, 1.0}) -- R,G,B myshader4:send("replacecolor", {0.0, 0.0, 0.0, 1.0}) -- R,G,B local shadercode5 = [[ extern number factor; extern vec3 checkcolor; extern vec3 replacecolor; vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ){ vec4 pixel = Texel(texture, texture_coords); if (pixel.rgb == checkcolor.rgb) { pixel.r = pixel.r - pixel.r * factor + replacecolor.r * factor; pixel.g = pixel.g - pixel.g * factor + replacecolor.g * factor; pixel.b = pixel.b - pixel.b * factor + replacecolor.b * factor; } return pixel * color; } ]] myshader5 = love.graphics.newShader(shadercode5) myshader5:send("checkcolor", {1.0, 0.0, 0.0}) -- R,G,B myshader5:send("replacecolor", {0.0, 0.0, 0.0}) -- R,G,B myshaders = { myshader1, myshader2, myshader3, myshader4, myshader5 } myshader_kind = 1 angle = 0 end function love.update(dt) angle = (angle + 90 * dt) % 360.0 local v = 1.0 - math.abs(math.sin(math.rad(angle))) myshaders[myshader_kind]:send("factor", v) -- set 0.0 - 1.0 px = (scr_w - img:getWidth()) / 2 py = (scr_h - img:getHeight()) / 2 end function love.draw() love.graphics.setCanvas(canvas) love.graphics.clear(0, 0, 0, 255) love.graphics.setShader(myshaders[myshader_kind]) love.graphics.setColor(255, 255, 255, 255) for i=1,loop_count do love.graphics.draw(img, px, py, 0, 1.0, 1.0, 0, 0) end love.graphics.setShader() love.graphics.setCanvas() -- draw canvas to window wdw_w, wdw_h = love.graphics.getDimensions() scr_scale = math.min((wdw_w / scr_w), (wdw_h / scr_h)) scr_ofsx = (wdw_w - (scr_w * scr_scale)) / 2 scr_ofsy = (wdw_h - (scr_h * scr_scale)) / 2 love.graphics.setColor(255, 255, 255) love.graphics.draw(canvas, scr_ofsx, scr_ofsy, 0, scr_scale, scr_scale) love.graphics.print("FPS: "..tostring(love.timer.getFPS()), 10, 10) love.graphics.print("Shader Kind: "..tostring(myshader_kind), 10, 30) end function love.keypressed(key, isrepeat) if key == "escape" then -- ESC to exit love.event.quit() elseif key == "f11" then -- toggle fullscreen mode if love.window.getFullscreen() then love.window.setFullscreen(false) else love.window.setFullscreen(true) end elseif key == "down" then myshader_kind = myshader_kind - 1 if myshader_kind <= 0 then myshader_kind = #myshaders end elseif key == "up" then myshader_kind = myshader_kind + 1 if myshader_kind > #myshaders then myshader_kind = 1 end end end
[ ツッコむ ]
以上です。