separated shaders from startupscene + improved gazecontrol interaction

This commit is contained in:
Leon van Kammen 2026-07-01 18:46:28 +02:00
parent 6a995dd3c5
commit 0930bd7544
8 changed files with 113 additions and 60 deletions

View file

@ -1,5 +1,7 @@
-- default argument -- default argument
arg[1] = "https://snips.sh/f/_U5-XctEVE?r=1" if arg[1] == nil then
arg[1] = "https://snips.sh/f/_U5-XctEVE?r=1"
end
-- sync lovr/love positional cli arguments -- sync lovr/love positional cli arguments
if arg[0] == nil and arg[1] ~= nil then arg[0] = arg[1] end if arg[0] == nil and arg[1] ~= nil then arg[0] = arg[1] end

View file

@ -6,30 +6,68 @@ local gctl
gctl = { gctl = {
name = "gctl", name = "gctl",
enabled = false, enabled = true,
texture = {},
material = nil,
dtmax = 1, dtmax = 1,
dt = 0, dt = 0,
init = function() init = function()
lovr.mouse.setRelativeMode(true) --lovr.mouse.setRelativeMode(true)
gctl.initVisor()
gctl.extendECS()
end,
camera = {
transform = lovr.math.newMat4(), load = function()
position = vector(), gctl.texture.idle = lovr.graphics.newTexture("ext/gazecontrol/reticle_idle.png")
movespeed = 10, end,
pitch = 0,
yaw = 0 initVisor = function()
-- add visor object
gctl.visor = {
rotate = { x = 0, y = 0, z = 0},
scale = 0.1,
texture = gctl.texture.idle
} }
end, end,
update = function(dt)
end,
load = function() end,
draw = function(pass,dt) draw = function(pass,dt)
-- *TODO* render this last (as it needs to be rendered after skybox & floor)
local posx, posy, posz = lovr.headset.getPosition('head')
local dirx, diry, dirz = lovr.headset.getDirection('head')
local distance = 1
local x = posx + distance * dirx
local y = posy + distance * diry
local z = posz + distance * dirz
local angle, ax, ay, az = lovr.headset.getOrientation(device)
local rot = gctl.visor.rotate
local scale = gctl.visor.scale
pass:setMaterial(gctl.texture.idle)
pass:setShader() --'unlit')
pass:setBlendMode('alpha')
pass:setColor(1, 1, 1)
pass:setCullMode('back')
pass:plane(x, y, z, scale, scale, angle, ax, ay, az)
end, end,
-- ECS API docs: https://bakpakin.github.io/tiny-ecs/doc
extendECS = function()
local visorSystem = ecs.processingSystem({
updatethread = true,
filter = ecs.requireAll('mycomponent'),
onAdd = function(self,obj) print_r(obj) end,
onRemove = function(self,obj) end,
process = function(self,obj) end,
})
ecs.addSystem( api.world, visorSystem )
ecs.add( api.world, { visor = gctl.visor } )
--gctl.visor.commit() -- notify other systems to update entitycache
end
} }
return gctl return gctl

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -45,6 +45,8 @@ return {
-- skybox -- skybox
pass:setCullMode('back') pass:setCullMode('back')
pass:setBlendMode() pass:setBlendMode()
pass:setShader()
pass:setColor(1,1,1,1)
pass:skybox(api.world.skybox) pass:skybox(api.world.skybox)
pass:setColor(1, 1, 1) pass:setColor(1, 1, 1)
@ -53,6 +55,7 @@ return {
-- floor -- floor
--pass:setMaterial() --pass:setMaterial()
pass:setShader()
pass:setCullMode('front') pass:setCullMode('front')
pass:setBlendMode('alpha') pass:setBlendMode('alpha')
pass:setMaterial() pass:setMaterial()
@ -61,9 +64,9 @@ return {
pass:setColor( 0, 0, 0, 0.75 ) pass:setColor( 0, 0, 0, 0.75 )
pass:plane(0, 0.01, 0, 500, 500, math.pi * 0.5, 1, 0, 0, "line", 100, 100) pass:plane(0, 0.01, 0, 500, 500, math.pi * 0.5, 1, 0, 0, "line", 100, 100)
pass:setShader( lovr.shader.pbr ) --pass:setShader( lovr.shader.pbr )
pass:send('cubemap', api.world.environmentMap) --pass:send('cubemap', api.world.environmentMap)
pass:send('sphericalHarmonics', api.world.sphericalHarmonics) --pass:send('sphericalHarmonics', api.world.sphericalHarmonics)
end end
end end

View file

@ -33,7 +33,8 @@ api = {
protocol = {}, protocol = {},
ext = { -- all extensions are loaded here from disk at runtime ext = { -- all extensions are loaded here from disk at runtime
exec = function(...) util.exec(api.ext,...) end -- util function to call func on each extension exec = function(...) util.exec(api.ext,...) end -- util function to call func on each extension
} },
i = 1
} }
api = util.merge( api, runtime.api ) -- overlay api onto lovr/love-compatible runtime api api = util.merge( api, runtime.api ) -- overlay api onto lovr/love-compatible runtime api

View file

@ -5,6 +5,8 @@ end
local util = require "util" local util = require "util"
local launch = require "launch" local launch = require "launch"
require('shaders').create(api)
local iui = require "lib.iui" local iui = require "lib.iui"
local backend = require "lib.lovr-iui" local backend = require "lib.lovr-iui"
@ -92,7 +94,7 @@ function lovr.draw(pass)
iui.draw() iui.draw()
end end
if api.iui.idiom == "vr" then if api.iui.idiom == "vr" then
pass:setClear(0.5, 0.5, 0.5) pass:setClear(0.2, 0.2, 0.2)
end end
api.ext.exec("draw",pass) api.ext.exec("draw",pass)
@ -104,11 +106,14 @@ function lovr.draw(pass)
pass:sphere( interactionsUpdater.hitpoint, .01) pass:sphere( interactionsUpdater.hitpoint, .01)
end end
-- Laser pointer -- Laser pointers
local hand = vec3(lovr.headset.getPosition('hand/left/point')) local hands = {"left","right"}
local direction = quat(lovr.headset.getOrientation('hand/left/point')):direction() foreach( hands, function(k,side)
pass:setColor(1, 1, 1) local hand = vec3(lovr.headset.getPosition('hand/' .. side .. '/point'))
pass:line(hand, interactionsUpdater.selectedBox and interactionsUpdater.hitpoint or (hand + direction * 50)) local direction = quat(lovr.headset.getOrientation('hand/' .. side .. '/point')):direction()
pass:setColor(1, 1, 1)
pass:line(hand, interactionsUpdater.selectedBox and interactionsUpdater.hitpoint or (hand + direction * 50))
end)
if api.mainWindow then if api.mainWindow then
api.mainWindow:draw(pass) api.mainWindow:draw(pass)
@ -177,9 +182,12 @@ function initInteractions(ecs)
function interactionsUpdater:process(obj, dt) function interactionsUpdater:process(obj, dt)
ecs.worldPhysics:update(dt) ecs.worldPhysics:update(dt)
local ox, oy, oz = lovr.headset.getPosition('hand/left/point') local castsrc = 'hand/left/point'
local castsrc = 'head'
local direction = quat(lovr.headset.getOrientation('hand/left/point')):direction() local ox, oy, oz = lovr.headset.getPosition(castsrc)
local direction = quat(lovr.headset.getOrientation(castsrc)):direction()
if direction ~= nil then if direction ~= nil then
local dx, dy, dz = direction:mul(50):unpack() local dx, dy, dz = direction:mul(50):unpack()
local collider, shape, x, y, z = ecs.worldPhysics:raycast(ox, oy, oz, ox + dx, oy + dy, oz + dz) local collider, shape, x, y, z = ecs.worldPhysics:raycast(ox, oy, oz, ox + dx, oy + dy, oz + dz)
@ -190,6 +198,7 @@ function initInteractions(ecs)
print("buttondown") print("buttondown")
end end
if lovr.headset.wasReleased(hand, 'trigger') or interactionsUpdater['mouse']['released'] then if lovr.headset.wasReleased(hand, 'trigger') or interactionsUpdater['mouse']['released'] then
print("cast: mousedown!")
local node = collider:getUserData() local node = collider:getUserData()
interactionsUpdater.selectedBox = collider interactionsUpdater.selectedBox = collider
interactionsUpdater.hitpoint:set(x, y, z) interactionsUpdater.hitpoint:set(x, y, z)

View file

@ -7,8 +7,6 @@ modelRenderer = {
init = function(api) init = function(api)
local ecs = api.ecs local ecs = api.ecs
api.world.shader = { pbr = false } api.world.shader = { pbr = false }
lovr.shader = lovr.shader or {}
lovr.shader['pbr'] = modelRenderer.initShaderPBR()
renderer = ecs.processingSystem() renderer = ecs.processingSystem()
renderer.filter = ecs.requireAll('model') renderer.filter = ecs.requireAll('model')
@ -36,38 +34,6 @@ modelRenderer = {
end end
end end
ecs.addSystem( api.world, renderer ) ecs.addSystem( api.world, renderer )
end,
initShaderPBR = function()
return lovr.graphics.newShader([[
vec4 lovrmain() {
return DefaultPosition;
}
]], [[
uniform textureCube cubemap;
uniform sphericalHarmonics { vec3 sh[9]; };
vec4 lovrmain() {
Surface surface;
initSurface(surface);
vec3 color = vec3(0);
vec3 lightDirection = vec3(-1, -1, -1);
vec4 lightColorAndBrightness = vec4(1, 1, 1, 3);
float visibility = 1.;
color += getLighting(surface, lightDirection, lightColorAndBrightness, visibility);
color += getIndirectLighting(surface, cubemap, sh);
return vec4(color, 1);
}
]], {
flags = {
glow = true,
normalMap = true,
vertexTangents = false, -- DamagedHelmet doesn't have vertex tangents
tonemap = true
}
})
end end
} }

View file

@ -0,0 +1,34 @@
return {
create = function(api)
lovr.shader = {}
lovr.shader.pbr = lovr.graphics.newShader([[
vec4 lovrmain() {
return DefaultPosition;
}
]], [[
uniform textureCube cubemap;
uniform sphericalHarmonics { vec3 sh[9]; };
vec4 lovrmain() {
Surface surface;
initSurface(surface);
vec3 color = vec3(0);
vec3 lightDirection = vec3(-1, -1, -1);
vec4 lightColorAndBrightness = vec4(1, 1, 1, 3);
float visibility = 1.;
color += getLighting(surface, lightDirection, lightColorAndBrightness, visibility);
color += getIndirectLighting(surface, cubemap, sh);
return vec4(color, 1);
}
]], {
flags = {
glow = true,
normalMap = true,
vertexTangents = false, -- DamagedHelmet doesn't have vertex tangents
tonemap = true
}
})
end
}