文档章节

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

FreeBlues
 FreeBlues
发布于 2016/07/05 15:43
字数 1869
阅读 133
收藏 0

用 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.."\t"

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.\nCurrently: %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

© 著作权归作者所有

共有 人打赏支持
FreeBlues
粉丝 98
博文 280
码字总数 493678
作品 0
其它
程序员
私信 提问
Mac 下安装使用 Love2D

Mac 下安装使用 Love2D 概述 是一款开源的 开发引擎, 使用 , 支持,,,以及多种平台, 在国外的游戏开发者中很受欢迎, 官网地址, 今天试用了一下, 感觉非常简单, 很好上手. 需要注意的一点是, 在...

FreeBlues
2016/06/29
76
0
翻译:GLSL的顶点位移贴图

翻译:GLSL的顶点位移贴图 翻译自: Vertex Displacement Mapping using GLSL - 译者: FreeBlues 说明: 之所以选择这篇文档, 是因为现在但凡提到位移贴图(Displacement Mapping), 都要求设备支...

FreeBlues
2016/07/23
79
2
翻译:非常详细易懂的法线贴图(Normal Mapping)

翻译:非常详细易懂的法线贴图(Normal Mapping) - 本文翻译自: Shaders » Lesson 6: Normal Mapping 作者: Matt DesLauriers - 译者: FreeBlues 这一系列依赖于最小规模的用于着色器和渲染工...

FreeBlues
2016/08/05
199
0
【Unity3D技术文档翻译】第2.3.3.6篇 法线贴图(凹凸贴图)

上一章:【Unity3D技术文档翻译】第2.3.3.5篇 平滑度(Smoothness) 本章原文所在章节:【Unity Manual】→【Graphics】→【Graphics Overview】→【Materials, Shaders & Textures】→【Sta...

何三思
2018/06/24
0
0
Substance Painter 烘焙法线贴图:使用Cage处理UV接缝

这里SP版本为2017.3;Maya版本为2018.1。 1,准备好高模、低模、Cage 这里以Maya为例。 高模 硬边低模 低模UV,因为全部是硬边,这里全部切开 平均法线的Cage Cage的制作方式: 这里的Cage是...

玄冬Wong
2017/12/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

泛型就这么简单

前言 从今天开始进入Java基础的复习,可能一个星期会有一篇的<十道简单算法>,我写博文的未必都是正确的~如果有写错的地方请大家多多包涵并指正~ 今天要复习的是泛型,泛型在Java中也是个很...

群星纪元
46分钟前
3
0
大数据提醒你:中国这些古建筑,可能是下一个巴黎圣母院!

大家晚上好,我是今天的提笔人嗅嗅。 巴黎圣母院失火事件让我的心情很沉重,一句无关痛痒的安慰“巴黎不哭”,已经不能表达我对这场文化之殇的惋惜之痛,人类伟大的建筑在一瞬间被毁灭。 世界...

forespider
58分钟前
0
0
mysql函数substring_index的用法

substring_index 按索引字符位进行截取字符串 substring_index(“待截取的字符串”,“截取数据依据的字符”,截取字符的位置N) 第三个参数可正,可负。正数表示索引字符前面的字符串,负数...

echojson
58分钟前
3
0
好程序员web前端分享用CSS和JS打造一个简单的图片编辑器

好程序员web前端分享用CSS和JS打造一个简单的图片编辑器,本文主要是利用CSS的 filter和简单的Jquery代码来实现一个简单的图片编辑器,包括对图片的透明度,黑白,图片亮度等调节。 CSS filt...

好程序员IT
今天
2
0
浅析spring mvc的细节

spring mvc 整体结构 系统监听到请求 -> 通知tomcat -> 根据web.xml 通知相应的拦截器(spring mvc 通常指DispatcherServlet) --> 检查url是否有相匹配的请求实现 --> 拿到请求实现bean的适配...

最爱肉肉
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部