-
Notifications
You must be signed in to change notification settings - Fork 44
/
Copy path15-shadowmaps_simple.lua
250 lines (211 loc) · 7.13 KB
/
15-shadowmaps_simple.lua
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
package.cpath = "bin/?.dll"
local iup = require "iuplua"
local bgfx = require "bgfx"
local bgfxu = require "bgfx.util"
local util = require "util"
local math3d = require "math3d"
local ctx = {
canvas = iup.canvas {},
}
local dlg = iup.dialog {
ctx.canvas,
title = "15-shadowmaps_simple",
size = "HALFxHALF",
}
local RENDER_SHADOW_PASS_ID = 0
local RENDER_SCENE_PASS_ID = 1
local vec0 = math3d.vector()
local time = 0
local function mainloop()
math3d.reset()
time = time + 0.01
bgfx.touch(0)
-- Setup lights.
local lightPos = math3d.vector (
-math.cos(time),
-1,
-math.sin(time),
0)
bgfx.set_uniform(ctx.u_lightPos, lightPos)
-- Setup instance matrices.
local mtxFloor = math3d.matrix { s = 30 }
local mtxBunny = math3d.matrix { s = 5, r = { 0, math.pi - time, 0}, t={15,5,0} }
local mtxHollowcube = math3d.matrix { s = 2.5, r = { 0.0, 1.56 - time, 0.0 }, t = { 0.0, 10.0, 0.0 } }
local mtxCube = math3d.matrix { s = 2.5 , r = { 0.0, 1.56 - time, 0.0 }, t = { -15.0, 5.0, 0.0 } }
-- Define matrices.
local lightView = math3d.lookat ( math3d.sub( vec0, lightPos ) , vec0)
local area = 30.0
local lightProj = math3d.projmat { ortho = true, l = -area, r = area, b = -area, t = area, n = -100, f = 100 }
bgfx.set_view_rect(RENDER_SHADOW_PASS_ID, 0, 0, ctx.m_shadowMapSize, ctx.m_shadowMapSize)
bgfx.set_view_frame_buffer(RENDER_SHADOW_PASS_ID, ctx.m_shadowMapFB)
bgfx.set_view_transform(RENDER_SHADOW_PASS_ID, lightView, lightProj)
bgfx.set_view_rect(RENDER_SCENE_PASS_ID, 0, 0, ctx.width, ctx.height)
bgfx.set_view_transform(RENDER_SCENE_PASS_ID, ctx.view, ctx.proj)
-- Clear backbuffer and shadowmap framebuffer at beginning.
bgfx.set_view_clear(RENDER_SHADOW_PASS_ID, "CD",0x303030ff, 1.0, 0)
bgfx.set_view_clear(RENDER_SCENE_PASS_ID, "CD",0x303030ff, 1.0, 0)
local mtxTmp =math3d.mul(ctx.mtxCrop, lightProj)
local mtxShadow = math3d.mul(mtxTmp, lightView)
local lightMtx = math3d.mul(mtxShadow, mtxFloor)
-- Floor.
local cached = bgfx.set_transform(mtxFloor)
for pass =1, 2 do
local st = ctx.m_state[pass]
bgfx.set_transform_cached(cached)
for _,texture in ipairs(st.textures) do
bgfx.set_texture(texture.stage, texture.sampler, texture.texture, texture.flags)
end
bgfx.set_uniform(ctx.u_lightMtx, lightMtx)
bgfx.set_index_buffer(ctx.m_ibh)
bgfx.set_vertex_buffer(ctx.m_vbh)
bgfx.set_state(st.state)
bgfx.submit(st.viewId, st.program)
end
-- Bunny.
lightMtx = math3d.mul(mtxShadow , mtxBunny)
bgfx.set_uniform(ctx.u_lightMtx, lightMtx)
util.meshSubmitState(ctx.m_bunny, ctx.m_state[1], mtxBunny)
bgfx.set_uniform(ctx.u_lightMtx, lightMtx)
util.meshSubmitState(ctx.m_bunny, ctx.m_state[2], mtxBunny)
-- Hollow cube.
lightMtx = math3d.mul(mtxShadow, mtxHollowcube)
bgfx.set_uniform(ctx.u_lightMtx, lightMtx)
util.meshSubmitState(ctx.m_hollowcube, ctx.m_state[1], mtxHollowcube)
bgfx.set_uniform(ctx.u_lightMtx, lightMtx)
util.meshSubmitState(ctx.m_hollowcube, ctx.m_state[2], mtxHollowcube)
-- Cube.
lightMtx = math3d.mul(mtxShadow, mtxCube)
bgfx.set_uniform(ctx.u_lightMtx, lightMtx)
util.meshSubmitState(ctx.m_cube, ctx.m_state[1], mtxCube)
bgfx.set_uniform(ctx.u_lightMtx, lightMtx)
util.meshSubmitState(ctx.m_cube, ctx.m_state[2], mtxCube)
bgfx.frame()
end
function ctx.init()
-- Uniforms.
ctx.s_shadowMap = bgfx.create_uniform("s_shadowMap", "s")
ctx.u_lightPos = bgfx.create_uniform("u_lightPos", "v4")
ctx.u_lightMtx = bgfx.create_uniform("u_lightMtx", "m4")
-- When using GL clip space depth range [-1, 1] and packing depth into color buffer, we need to
-- adjust the depth range to be [0, 1] for writing to the color buffer
ctx.u_depthScaleOffset = bgfx.create_uniform("u_depthScaleOffset", "v4")
if util.caps.homogeneousDepth then
bgfx.set_uniform(ctx.u_depthScaleOffset, math3d.vector(1, 0, 0, 0))
else
bgfx.set_uniform(ctx.u_depthScaleOffset, math3d.vector(0.5, 0.5, 0, 0))
end
-- Create vertex stream declaration.
ctx.vdecl = bgfx.vertex_layout {
{ "POSITION", 3, "FLOAT" },
{ "NORMAL", 4, "UINT8", true, true },
}
-- Meshes.
ctx.m_bunny = util.meshLoad "meshes/bunny.bin"
ctx.m_cube = util.meshLoad "meshes/cube.bin"
ctx.m_hollowcube = util.meshLoad "meshes/hollowcube.bin"
local encodeNormalRgba8 = bgfxu.encodeNormalRgba8
ctx.m_vbh = bgfx.create_vertex_buffer( bgfx.memory_buffer( "fffd",
{
-1.0, 0.0, 1.0, encodeNormalRgba8(0.0, 1.0, 0.0),
1.0, 0.0, 1.0, encodeNormalRgba8(0.0, 1.0, 0.0),
-1.0, 0.0, -1.0, encodeNormalRgba8(0.0, 1.0, 0.0),
1.0, 0.0, -1.0, encodeNormalRgba8(0.0, 1.0, 0.0),
} ) , ctx.vdecl)
ctx.m_ibh = bgfx.create_index_buffer {
0, 1, 2,
1, 3, 2,
}
-- Render targets.
ctx.m_shadowMapSize = 512
-- Shadow samplers are supported at least partially supported if texture
-- compare less equal feature is supported.
ctx.m_shadowSamplerSupported = util.caps.supported.TEXTURE_COMPARE_LEQUAL
local shadowMapTexture
if ctx.m_shadowSamplerSupported then
-- Depth textures and shadow samplers are supported.
ctx.m_progShadow = util.programLoad("vs_sms_shadow", "fs_sms_shadow")
ctx.m_progMesh = util.programLoad("vs_sms_mesh", "fs_sms_mesh")
shadowMapTexture = bgfx.create_texture2d(
ctx.m_shadowMapSize
, ctx.m_shadowMapSize
, false
, 1
, "D16"
, "rtc[" -- BGFX_TEXTURE_RT | BGFX_TEXTURE_COMPARE_LEQUAL
)
ctx.m_shadowMapFB = bgfx.create_frame_buffer({shadowMapTexture}, true)
else
-- Depth textures and shadow samplers are not supported. Use float
-- depth packing into color buffer instead.
ctx.m_progShadow = util.programLoad("vs_sms_shadow_pd", "fs_sms_shadow_pd")
ctx.m_progMesh = util.programLoad("vs_sms_mesh", "fs_sms_mesh_pd")
shadowMapTexture = bgfx.create_texture2d(
ctx.m_shadowMapSize
, ctx.m_shadowMapSize
, false
, 1
, "BGRA8"
, "rt" -- BGFX_TEXTURE_RT
)
local fbtextures = {
shadowMapTexture,
bgfx.create_texture2d(
ctx.m_shadowMapSize
, ctx.m_shadowMapSize
, false
, 1
, "D16"
, "rw" -- BGFX_TEXTURE_RT_WRITE_ONLY
)
}
ctx.m_shadowMapFB = bgfx.create_frame_buffer(fbtextures, true)
end
ctx.m_state = {}
ctx.m_state[1] = {
state = bgfx.make_state {
WRITE_MASK = "RGBAZ",
DEPTH_TEST = "LESS",
CULL = "CCW",
MSAA = true,
},
program = ctx.m_progShadow,
viewId = RENDER_SHADOW_PASS_ID,
textures = {}
}
ctx.m_state[2] = {
state = bgfx.make_state {
WRITE_MASK = "RGBAZ",
DEPTH_TEST = "LESS",
CULL = "CCW",
MSAA = true,
},
program = ctx.m_progMesh,
viewId = RENDER_SCENE_PASS_ID,
textures = {{
flags = nil,
stage = 0,
sampler = ctx.s_shadowMap,
texture = shadowMapTexture
}},
}
local sy = util.caps.originBottomLeft and 0.5 or -0.5
local sz = util.caps.homogeneousDepth and 0.5 or 1
local tz = util.caps.homogeneousDepth and 0.5 or 0
ctx.mtxCrop = math3d.ref(math3d.matrix (
0.5, 0.0, 0.0, 0.0,
0.0, sy, 0.0, 0.0,
0.0, 0.0, sz, 0.0,
0.5, 0.5, tz, 1.0
))
end
function ctx.resize(w,h)
ctx.width = w
ctx.height = h
bgfx.reset(ctx.width,ctx.height, "vmx")
ctx.view = math3d.ref(math3d.lookat( { 0,30,-60 }, { 0,5,0 }))
ctx.proj = math3d.ref(math3d.projmat { fov = 60, aspect = w/h, n = 0.1, f = 100 })
end
util.init(ctx)
dlg:showxy(iup.CENTER,iup.CENTER)
dlg.usersize = nil
util.run(mainloop)