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