Can I turn something off in the default render script so that the game stops trying to hide my 3d animated models based on where the camera is looking?
Right now, my game is hiding my 3d animated .glb models aggressively based on where camera is pointing. They get hidden when the animated 3d character moves closer to the camera. When the camera looks up or looks to the side, with model still visible on screen, the model gets hidden. My character is in multiple meshes and the game hides her eyeballs first but still shows her body for a moment before hiding her body. It’s not fixed by adjusting the camera minZ or by scaling down my models. I think this is called culling or frustum culling?
I think its caused by the render script because when I use the operator plugin’s render script this problem doesn’t happen. I think there’s something in the regular render script that causes this aggressive hiding but I don’t understand what is causing it. I want to make it stop hiding my 3d animated models so I can use render scripts similar to the default one. If I can do something quick and dirty to make it never hide character that would be great.
Operator render script:
--[[
example.render_script
github.com/astrochili/defold-operator
Copyright (c) 2022 Roman Silin
MIT license. See LICENSE for details.
--]]
--
-- Lifecycle
function init(self)
self.sky_color = vmath.vector4(0.67, 0.80, 0.94, 1)
self.scene = {
predicate = render.predicate({ 'model' }),
view = vmath.matrix4(),
projection = vmath.matrix4()
}
This file has been truncated. show original
Default render script:
-- Copyright 2020-2025 The Defold Foundation
-- Copyright 2014-2020 King
-- Copyright 2009-2014 Ragnar Svensson, Christian Murray
-- Licensed under the Defold License version 1.0 (the "License"); you may not use
-- this file except in compliance with the License.
--
-- You may obtain a copy of the License, together with FAQs at
-- https://www.defold.com/license
--
-- Unless required by applicable law or agreed to in writing, software distributed
-- under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-- CONDITIONS OF ANY KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations under the License.
--
-- message constants
--
local MSG_CLEAR_COLOR = hash("clear_color")
local MSG_WINDOW_RESIZED = hash("window_resized")
local MSG_SET_VIEW_PROJ = hash("set_view_projection")
This file has been truncated. show original
Vantage render script (similar to default):
--
-- projection that centers content with maintained aspect ratio and optional zoom
--
local function fixed_projection(near, far, zoom)
local projected_width = render.get_window_width() / (zoom or 1)
local projected_height = render.get_window_height() / (zoom or 1)
local xoffset = -(projected_width - render.get_width()) / 2
local yoffset = -(projected_height - render.get_height()) / 2
return vmath.matrix4_orthographic(xoffset, xoffset + projected_width, yoffset, yoffset + projected_height, near, far)
end
--
-- projection that centers and fits content with maintained aspect ratio
--
local function fixed_fit_projection(near, far)
local width = render.get_width()
local height = render.get_height()
local window_width = render.get_window_width()
local window_height = render.get_window_height()
local zoom = math.min(window_width / width, window_height / height)
return fixed_projection(near, far, zoom)
This file has been truncated. show original
It’s not a problem, it’s actually a very useful feature called frustum culling . It’s the recommended way to render objects efficiently.
If you don’t want to use it, you can turn it off by setting use_frustum = false
on this line:
local function set_camera_world(state)
local camera_components = camera.get_cameras()
-- This will set the last enabled camera from the stack of camera components
if #camera_components > 0 then
for i = #camera_components, 1, -1 do
if camera.get_enabled(camera_components[i]) then
local camera_component = state.cameras.camera_component
camera_component.camera = camera_components[i]
render.set_camera(camera_component.camera, { use_frustum = true })
-- The frustum will be overridden by the render.set_camera call,
-- so we don't need to return anything here other than an empty table.
return camera_component.options
end
end
end
-- If no active camera was found, we use the default main "camera world" camera
local camera_world = state.cameras.camera_world
render.set_view(camera_world.view)
However, disabling it may lead to performance issues that you’ll need to address yourself.
Other render scripts actually have to implement this feature.
1 Like