mieki256's diary



2017/12/21(木) [n年前の日記]

#1 [love2d] love2dのShaderで惑星をグルグル回す感じのソレを試したり

球を相手にアレコレ考えているうちに、某STGのどピンクな背景上でグルグル回ってたアレを love2d の Shader でもできるのではないかと思えてきたので試してみたり。

とりあえず、こんな感じに。

shader_test12_planet_ss01.gif

更に、向きを90度変えて(xとyを入れ替えて)、テクスチャを変えて、ついでに雲のテクスチャも別途回してみたらこんな感じに。



その手の地図(メルカトル図法?)を扱う時と同様に、南極・北極のあたりが怪しいことになってるけど…。でもまあ、例えば2Dゲームの背景として表示して雰囲気作りに使う分にはこれでもイケそうな。

画像とソース。 :

使った画像は以下。

_grid_bg_480x480.png
_planet_tex_480x480.png
_planet_cloud_only_496x496.png

ソースは以下。

_conf.lua
function love.conf(t)
  t.window.title = "Shader test 12 planet"
  t.window.vsync = true
  t.window.resizable = true
  t.window.width = 640
  t.window.height = 480
  -- t.window.fullscreen = true
  -- t.window.fullscreentype = "exclusive"
end

_main.lua
-- Shader test 12 planet

function love.load()
  love.graphics.setDefaultFilter("nearest", "nearest")
  scr_w, scr_h = 640, 480
  canvas = love.graphics.newCanvas(scr_w, scr_h)

  img = love.graphics.newImage("grid_bg_480x480.png")
  img:setFilter("linear", "linear")

  -- make shader
  local shadercode = [[
    extern number start_x;
    extern number start_y;
    const float PI = 3.14159265;

    vec4 effect( vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords ) {
      // float sx = (screen_coords.x - (love_ScreenSize.x / 2)) / love_ScreenSize.y;
      // float sy = (screen_coords.y - (love_ScreenSize.y / 2)) / love_ScreenSize.y;
      float tx = texture_coords.x - 0.5;
      float ty = texture_coords.y - 0.5;
      float a = asin(ty * 2);
      float v = a / PI;
      float r = cos(a);
      float b = asin(tx * 2 / r);
      float u = b / PI;
      texture_coords.x = mod((u + start_x) + 0.5, 1.0);
      texture_coords.y = mod((v + start_y) + 0.5, 1.0);
      vec4 texcolor = Texel(texture, texture_coords);
      texcolor.a = (tx * 2 > r)? 0.0 : texcolor.a;
      texcolor.a = (tx * 2 < -r)? 0.0 : texcolor.a;
      return texcolor * color;
    }
  ]]

  myshader = love.graphics.newShader(shadercode)
  myshader:send("start_x", 0.0)
  myshader:send("start_y", 0.0)

  ang = 0.0
  px = (scr_w - img:getWidth()) / 2
  py = (scr_h - img:getHeight()) / 2
end

function love.update(dt)
  ang = ang + 0.1 * dt
  myshader:send("start_x", ang)
end

function love.draw()
  love.graphics.setCanvas(canvas)
  love.graphics.clear(24, 64, 176, 255)

  love.graphics.setColor(255, 255, 255)
  love.graphics.setShader(myshader)
  love.graphics.draw(img, px, py)
  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_ox = (wdw_w - (scr_w * scr_scale)) / 2
  scr_oy = (wdw_h - (scr_h * scr_scale)) / 2
  love.graphics.setColor(255, 255, 255)
  love.graphics.draw(canvas, scr_ox, scr_oy, 0, scr_scale, scr_scale)

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

function love.keypressed(key, isrepeat)
  if key == "escape" then
    -- ESC to exit
    love.event.quit()
  elseif key == "f11" then
    -- toggle fullscreen
    if love.window.getFullscreen() then
      love.window.setFullscreen(false)
    else
      love.window.setFullscreen(true)
    end
  end
end

向きを変えて、雲レイヤー(?)も追加した版のソースは以下。

_conf.lua
_main.lua

画像もソースも、License : CC0 / Public Domain ってことで。

考え方。 :

処理の考え方をメモ。

shader_planet_about01.png

そこに球があるとして、y方向の角度 a、x方向の角度 b を、テクスチャの v,u 値として利用することにする。

Shader の texture_coords.x、texture_coords.y には、0.0〜1.0 の値が入ってくるけど、それを -0.5 〜 +0.5 にした tx,ty があるとして。

y方向の角度 a は、
a = asin(ty * 2)
で求められる。

また、ty の高さには、上から見て cos(a) を半径とする円がそこにあるはずで。なので、x方向の角度 b は、
b = asin(tx * 2 / r)
で求められる…かなと。

asin() が返してくる値はラジアン単位だから…。π(PI)で割ってやれば、-0.5 〜 0.5 の値になってくれるので、テクスチャの u,v値として使い易いはず。180度 = πラジアン、360度 = 2πラジアンだから。
u = b / PI
v = a / PI

このままだと、球の外側に相当する部分も描画されてしまうので…。tx と r = cos(a) を利用して、球の外側を処理してるなら描画する点のアルファ値を0に、球の内側を処理してるならアルファ値を本来のアルファ値にすることで、球だけを描画してるように見せかける。
texcolor.a = (tx * 2 > r)? 0.0 : texcolor.a;
texcolor.a = (tx * 2 < -r)? 0.0 : texcolor.a;

こんな感じで合ってる…のかな。どうなんだ。自信無し。

元ネタは全然違うっぽい。 :

ここまでやってから _元ネタ を確認してみたら、見た目からして違う処理をしていた…。さて、これはどういう処理をすればいいんだろう? もうちょっと考えてみないと…。

待てよ。もしかしてコレ、テクスチャのスクロールする方向を横じゃなくて縦にすればいいのかな。



どうだろう。似てるような、ビミョーに何か違うような…。

使ったテクスチャは以下。

_planet_tex_480x480_3.png

このテクスチャ画像は、 _File:Full moon.jpeg - Wikimedia Commons で公開されてる画像を加工して作ったのだけど、Wikipediaのソレは Public Domain となってるように見えるから、この画像も Public Domain ってことで。

#2 [nitijyou] 灯油ファンヒーターが壊れた

部屋で使ってた corona製灯油ファンヒーターが壊れてしまった。電源を入れても、しばらくするとLED表示部分に「E1」と表示されて動かない。

ググってみたら、「E1」表示は電気系統の故障という意味の表示らしいけど、実際には燃焼室(?)でススが溜まってショートしてる場合が多いそうで、分解して該当パーツを清掃したら復活した事例も少なくないらしい。もちろん分解してそんなことしたら保証は無くなるけど。ちなみに、セーブモードで使い続けるとススが溜まりやすいそうで。自分、ずっとセーブモードで使い続けてた…。失敗した。更に、DAINICHI製は違う構造になっていて、似たような表示になったら部品交換するしかないから自分で直せない、という話も見かけた。

親父さん達に相談したところ、少し前に追加購入したファンヒーターをとりあえず使ってしのげないか、という話に。しばらく前に、1階洋間で使っていたファンヒーターも壊れてしまって、買い替えてみたものの、何故かうっかり火力が弱い製品を買ってしまったそうで。追加でもう1つファンヒーターを買った、という状況なので、1階には2つファンヒーターがあるわけで。

とりあえず、1階から借りてきたファンヒーターの型番をメモ。 _CORONA FH-G3217Y 。木造9畳までを想定した製品。今まで使ってた製品は10畳までを想定したスペックだったから、そんなに違いはないだろう…。消費電力は、点火時は650W食うけど、燃焼中は20W程度と取扱説明書に書いてあった。今まで使ってた製品と比べて本体は随分と小さい。それでいてタンクは大きいし容量も結構多い。随分と進歩してるのだなあと。いや、今まで使ってた製品が「コレいつの製品なんだよ…」と不安になるぐらい昔の製品だったからアレなのだけど。この手の製品って、近年はそれほど変わってないよな…。

以上、1 日分です。

過去ログ表示

Prev - 2017/12 -
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
31

カテゴリで表示

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


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

Powered by hns-2.19.6, HyperNikkiSystem Project