zoukankan      html  css  js  c++  java
  • 用 Love2D 实现法线贴图的例程(到最新版本 0.10.1)

    用 Love2D 实现法线贴图的例程(到最新版本 0.10.1)

    概述

    一般来说, 复杂的光照模型会被用在 3D 游戏中, 以产生逼真的效果, 不过也有些开发者研究出一些代码可以在 2D 游戏中使用这些光照模型, 这里就有两个在 2D 场景中使用法线贴图的 Love2D 例程, 不过是前几年写的, 用的是 Love2D 的旧版本, 到了今天最新版本的 Love2D 的很多函数都发生了变化, 本文的目标就是修改这些函数到最新的 Love2D 版本 0.10.1.

    例程1

    这是一个用来演示 2D 场景下使用光照模型的例程, 原始下载链接 PixelArtCelShading.love

    对 .love 文件解包

    OSX 下很简单, 先新建一个目录 shader1, 接着把 PixelArtCelShading.love 文件拷贝进去, 然后执行 unzip 命令, 就可以得到这个 love2d 项目的全部源文件了, 因为我们有两个例程, 所以还要新建一个目录 shader2, 把 PixelCelShadingAmbientOcclusion2.love 拷贝进去, 如下:

    Air:lua admin$ mv PixelCelShadingAmbientOcclusion2.love ./shader2
    Air:lua admin$ cd shader2
    Air:shader2 admin$ ls
    PixelCelShadingAmbientOcclusion2.love
    Air:shader2 admin$ unzip ./ PixelCelShadingAmbientOcclusion2.love 
    unzip: cannot find or open ./, ./.zip or ./.ZIP.
    Air:shader2 admin$ unzip ./PixelCelShadingAmbientOcclusion2.love 
    Archive: ./PixelCelShadingAmbientOcclusion2.love
    inflating: globe.png 
    inflating: main.lua 
    extracting: pithos.png 
    inflating: pixel_font.png 
    inflating: shader.glsl 
    Air:shader2 admin$ ls
    PixelCelShadingAmbientOcclusion2.love	main.lua	pixel_font.png
    globe.png	pithos.png	shader.glsl
    Air:shader2 admin$
    

    具体修改

    love 命令加载, 出现了如下错误:

    Air:shader2 admin$ love ../shader1
    Error: main.lua:25: attempt to call field 'setDefaultImageFilter' (a nil value)
    stack traceback:
    main.lua:25: in function 'load'
    [string "boot.lua"]:439: in function <[string "boot.lua"]:435>
    [C]: in function 'xpcall'
    Air:shader2 admin$ love ../shader1
    Error: main.lua:31: attempt to call field 'newPixelEffect' (a nil value)
    stack traceback:
    main.lua:31: in function 'load'
    [string "boot.lua"]:439: in function <[string "boot.lua"]:435>
    [C]: in function 'xpcall'
    Air:shader2 admin$ love ../shader1
    Error: main.lua:50: attempt to call method 'clear' (a nil value)
    stack traceback:
    main.lua:50: in function 'draw'
    [string "boot.lua"]:467: in function <[string "boot.lua"]:435>
    [C]: in function 'xpcall'
    Air:shader2 admin$
    

    修改方法也很简单, 打开 Love2D官网Wiki文档, 查看 love.graphics 模块的函数 setDefaultImageFilter, 发现在版本 0.10.0 之后就改名为 setDefaultFilter 了, 后面的 newPixelEffect 也被改为 newShader``, 顺手把 setPixelEffect 也改成 setShader.

    关于 clear() 方法稍微不同, 因为它是 Canvas 对象的一个方法, 查询 Canvas, 发现它的 clear() 方法被 love.graphics.clear() 取代了, 直接改过去, 发现不起作用, 会出现很多拖影, 如下图:

    说明没起作用, 再仔细阅读一遍文档, 发现要跟 love.graphics.setCanvas(fb) 配合使用, 也就是说要把这条清除语句放在 love.graphics.setCanvas(fb) 语句后面, 修改顺序为:

    G.setCanvas(fb)
    G.clear(0,0,0,0)
    

    果然起作用了, 拖影被消掉了, 如下图:

    更新后代码

    修改后的 main.lua 文件代码如下:

    local function captionf (...)
    G.setCaption(string.format(...))
    end
    
    local function distance (x1, y1, x2, y2)
    return ((x1 - x2)^2 + (y1 - y2)^2)^0.5
    end
    
    local sz = 3
    local z = 30
    local function update_light_vector ()
    local x, y = love.mouse.getPosition()
    y = 600 - y -- glsl works from bottom left rather than top left
    x = x/sz
    y = y/sz
    mouse = {x=x, y=600/sz-y}
    effect:send("light_vec", {x, y, z})
    end
    
    function love.load ()
    G = love.graphics
    G.setDefaultFilter("nearest", "nearest")
    G.setBackgroundColor(35, 30, 65)
    stump = G.newImage "treestump.png"
    stump_lines = G.newImage "treestump_lines.png"
    stump_diffuse = G.newImage "treestump_diffuse.png"
    globe = G.newImage "globe.png"
    effect = G.newShader "gooch.glsl"
    G.setShader(effect)
    update_light_vector()
    fb = G.newCanvas(800/sz, 600/sz)
    fb:setFilter("nearest", "nearest")
    effect:send("diffuse", stump_diffuse)
    end
    
    time = 0
    function love.update (dt)
    update_light_vector()
    
    time = time+dt
    z = z + math.cos(time)/3
    end
    
    local r = math.random
    function love.draw ()
    G.setColor(255, 255, 255, 255)
    
    G.setCanvas(fb)
    G.clear(0,0,0,0)
    
    math.randomseed(2)
    G.setShader(effect)
    for x = 20, (800-34)/sz, 34 do
    for y = 20, (600-34)/sz, 34 do
    if r() > 0.7 then
    G.draw(stump, x, y, 0, 1, 1, 16, 16)
    G.setShader()
    local q = 0.3
    G.setColor(145*q, 75*q, 39*q)
    G.draw(stump_lines, x, y, 0, 1, 1, 16, 16)
    G.setShader(effect)
    end
    end
    end
    G.setShader()
    G.setColor(255, 255, 255)
    G.draw(globe, mouse.x, mouse.y-z, 0, 1, 1, 8, 8)
    G.setCanvas()
    G.draw(fb, 0, 0, 0, sz, sz)
    end
    

    打包

    如果想打包成 .love 的形式, 以便发布, 可以用命令 zip -0 -r -X -q, 操作纪录如下:

    Air:lua admin$ cd shader1
    Air:shader1 admin$ zip -0 -r -X -q ../shader1.love ./*
    Air:shader1 admin$ cd ..
    Air:lua admin$ ls -al
    total 152
    drwxr-xr-x 18 admin staff 612 7 5 15:13 .
    drwxr-xr-x 15 admin staff 510 7 4 09:55 ..
    -rw-r--r--@ 1 admin staff 12292 7 5 14:41 .DS_Store
    drwxr-xr-x 6 admin staff 204 7 1 21:11 2048
    -rw-r--r--@ 1 admin staff 7691 7 5 10:05 Pixel1
    -rw-r--r--@ 1 admin staff 7691 9 27 2012 PixelArtCelShading.love
    -rw-r--r--@ 1 admin staff 10471 9 27 2012 PixelCelShadingAmbientOcclusion2.love
    drwxr-xr-x 6 admin staff 204 7 4 00:01 c-test
    drwxr-xr-x 5 admin staff 170 7 1 21:12 love
    drwxr-xr-x 6 admin staff 204 7 1 21:06 particle
    drwxr-xr-x 8 admin staff 272 7 5 15:05 shader1
    -rw-r--r-- 1 admin staff 10095 7 5 15:13 shader1.love
    drwxr-xr-x 7 admin staff 238 7 5 15:04 shader2
    -rw-r--r-- 1 admin staff 2128 6 29 00:23 spider.lua
    -rw-r--r-- 1 admin staff 884 6 18 16:31 test1.lua
    -rw-r--r-- 1 admin staff 1568 6 18 16:31 test2.lua
    -rw-r--r-- 1 admin staff 1769 6 18 16:32 test3.lua
    -rw-r--r-- 1 admin staff 279 6 19 10:32 timeProfile.lua
    Air:lua admin$ 
    

    我们看到新生成了一个名为 shader1.love 的文件, 只要你的电脑上安装了 Love2D, 就可以双击运行这个文件.

    例程2

    这是另一个用来演示 2D 场景下使用光照模型的例程, 原始下载链接 PixelCelShadingAmbientOcclusion2.love

    对 .love 文件解包

    整个操作过程跟第一个例程一样,

    Air:lua admin$ cd shader2
    Air:shader2 admin$ love ../shader2
    Error: main.lua:12: attempt to call field 'setCaption' (a nil value)
    stack traceback:
    main.lua:12: in function 'load'
    [string "boot.lua"]:439: in function <[string "boot.lua"]:435>
    [C]: in function 'xpcall'
    Air:shader2 admin$ love ../shader2
    Error: main.lua:75: attempt to call field 'drawq' (a nil value)
    stack traceback:
    main.lua:75: in function 'draw'
    main.lua:59: in function 'draw'
    [string "boot.lua"]:467: in function <[string "boot.lua"]:435>
    [C]: in function 'xpcall'
    Air:shader2 admin$ love ../shader2
    Air:shader2 admin$ 
    

    依次解决错误函数, 跟第一个例程的错误大同小异, 相同的地方就不多说了, 说两个新错误: G.setCaption 改为 love.window.setTitle, G.drawq 改为 G.draw.

    更新后代码

    修改后的 main.lua 文件代码如下:

    
    s = [=[
    ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.,:;'"?/[](){}<>1234567890!@#$%^&*_-+=~`|
    ]=]
    
    s = s.."	"
    
    local G, W, H
    local sz = 2
    function love.load ()
    G = love.graphics
    W = G.getWidth
    H = G.getHeight
    love.window.setTitle "Ambient occlusion test"
    G.setBackgroundColor(35, 30, 65)
    
    ao_toggle = 1 -- ao_toggle starts on
    z = 30
    time = 0
    
    font_img = G.newImage "pixel_font.png"
    font = G.newImageFont(font_img, s)
    G.setFont(font)
    
    G.setDefaultFilter("nearest", "nearest")
    globe = G.newImage "globe.png"
    img = G.newImage "pithos.png"
    diffuse = G.newQuad(0, 0, 32, 43, 96, 43)
    
    canvas = G.newCanvas(W()/sz, H()/sz)
    canvas:setFilter("nearest", "nearest")
    
    effect = G.newShader "shader.glsl"
    effect:send("ao_toggle", ao_toggle)
    end
    
    function love.update (dt)
    time = time + dt
    z = z + math.cos(time)/3
    
    local x, y = love.mouse.getPosition()
    x = x/sz
    y = y/sz
    mouse = {x=x, y=y}
    y = H()/sz - y
    effect:send("light_pos", {x, y, z})
    end
    
    function love.mousepressed ()
    ao_toggle = (ao_toggle + 1)%2
    effect:send("ao_toggle", ao_toggle)
    end
    
    function love.draw ()
    
    G.setCanvas(canvas)
    G.clear(0,0,0,0)
    
    draw()
    G.setCanvas()
    G.setShader()
    G.draw(canvas, 0, 0, 0, sz, sz)
    end
    
    function printf (...)
    G.print(string.format(...), 20, 10)
    end
    
    function draw ()
    G.setShader()
    G.setColor(220, 190, 0)
    printf("Click toggles ambient occlusion.
    Currently: %s.", ao_toggle == 1 and "on" or "off")
    G.setShader(effect)
    G.setColor(255, 255, 255)
    G.draw(img, diffuse, W()/sz/2 - 34, H()/sz/2 - 18, 0, 1, 1, 16, 27)
    G.draw(img, diffuse, W()/sz/2 + 34, H()/sz/2 + 18, 0, 1, 1, 16, 27)
    G.setShader()
    G.draw(globe, mouse.x, mouse.y-z, 0, 1, 1, 9, 9)
    end
    

    运行截图如下:

    打包

    Air:shader2 admin$ zip -0 -r -X -q ../shader2.love ./*
    Air:shader2 admin$ cd ..
    Air:lua admin$ ls -al
    total 184
    drwxr-xr-x 19 admin staff 646 7 5 15:35 .
    drwxr-xr-x 15 admin staff 510 7 4 09:55 ..
    -rw-r--r--@ 1 admin staff 12292 7 5 14:41 .DS_Store
    drwxr-xr-x 6 admin staff 204 7 1 21:11 2048
    -rw-r--r--@ 1 admin staff 7691 7 5 10:05 Pixel1
    -rw-r--r--@ 1 admin staff 7691 9 27 2012 PixelArtCelShading.love
    -rw-r--r--@ 1 admin staff 10471 9 27 2012 PixelCelShadingAmbientOcclusion2.love
    drwxr-xr-x 6 admin staff 204 7 4 00:01 c-test
    drwxr-xr-x 5 admin staff 170 7 1 21:12 love
    drwxr-xr-x 6 admin staff 204 7 1 21:06 particle
    drwxr-xr-x 8 admin staff 272 7 5 15:21 shader1
    -rw-r--r-- 1 admin staff 10095 7 5 15:13 shader1.love
    drwxr-xr-x 7 admin staff 238 7 5 15:31 shader2
    -rw-r--r-- 1 admin staff 13104 7 5 15:35 shader2.love
    -rw-r--r-- 1 admin staff 2128 6 29 00:23 spider.lua
    -rw-r--r-- 1 admin staff 884 6 18 16:31 test1.lua
    -rw-r--r-- 1 admin staff 1568 6 18 16:31 test2.lua
    -rw-r--r-- 1 admin staff 1769 6 18 16:32 test3.lua
    -rw-r--r-- 1 admin staff 279 6 19 10:32 timeProfile.lua
    Air:lua admin$ 
    

    成功生成 shader2.love 文件, 双击运行正常.

    参考

    Pixel art with GLSL cel shade lighting concept

  • 相关阅读:
    java
    Java 自定义异常(转载)
    java中更新文件时,指定原文件的编码格式,防止编码格式不对,造成乱码
    tar命令压缩和解压
    微服务之服务注册与发现--Consul(转载)
    git push 时:报missing Change-Id in commit message footer的错误
    git 版本回退
    item 快捷键
    mac下mysql的卸载和安装
    JAVA正则表达式:Pattern类与Matcher类详解(转)
  • 原文地址:https://www.cnblogs.com/freeblues/p/5687746.html
Copyright © 2011-2022 走看看