Incorrect 3D depth testing when using render target, why? (SOLVED)

Hi,

So I set up my rendering pipeline to render 3D objects, all works fine, except when I want to add some post processing. I modify the script according to the grading tutorial, but my meshes are rendered incorrectly this way and I can’t understand why.

At this point postprocessing is just copying the original.

Postprocessing disabled (correct look).

Postprocessing enabled (incorrect look).

Notice how grey buildings are messed up and how trees are behind the ground they are standing on.

Here is my render script.

local camera = require('libs.camera')
local hashed = require('libs.hashed')

function init(self)
	camera.width = render.get_window_width()
	camera.height = render.get_window_height()
    
	self.gui_pred = render.predicate({'gui'})
	self.model_pred = render.predicate({'model'})
	self.background_pred = render.predicate({'background'})
	self.postprocessing_pred = render.predicate({'postprocessing'})

	self.clear_color = vmath.vector4(0, 0, 0, 0)
	self.clear_color.x = sys.get_config('render.clear_color_red', 0)
	self.clear_color.y = sys.get_config('render.clear_color_green', 0)
	self.clear_color.z = sys.get_config('render.clear_color_blue', 0)
	self.clear_color.w = sys.get_config('render.clear_color_alpha', 0)

	self.view = vmath.matrix4()

	local target_params = {
		[render.BUFFER_COLOR_BIT] = {
			format = render.FORMAT_RGBA,
			width = render.get_width(),
			height = render.get_height()
		}
	}

	self.target = render.render_target('original', target_params)
end

function update(self)
	render.enable_render_target(self.target)
	
	render.enable_state(render.STATE_DEPTH_TEST)
	render.set_depth_mask(true)
	render.clear({[render.BUFFER_COLOR_BIT] = self.clear_color, [render.BUFFER_DEPTH_BIT] = 1, [render.BUFFER_STENCIL_BIT] = 0})
	render.set_viewport(0, 0, render.get_window_width(), render.get_window_height())

	-- Render 2D space.
	render.set_view(self.view)
	render.set_projection(vmath.matrix4_orthographic(0, render.get_window_width(), 0, render.get_window_height(), -1, 1))
	render.draw(self.background_pred)
    
    -- Create an orbit camera.
	local camera_boom = vmath.vector3(0, 0, camera.distance)
	local camera_rotation = vmath.quat_rotation_y(-camera.alpha) * vmath.quat_rotation_x(camera.beta)
	local camera_position = camera.target + vmath.rotate(camera_rotation, camera_boom)
	local camera_up = vmath.rotate(camera_rotation, vmath.vector3(0,1,0))
	local view_mtx = vmath.matrix4_look_at(camera_position, camera.target, camera_up)
	render.set_view(view_mtx)
	local ortho_w = camera.view_width
	local ortho_h = ortho_w * render.get_window_height() / render.get_window_width()
	local projection_mtx = vmath.matrix4_orthographic(-ortho_w, ortho_w, -ortho_h, ortho_h, 1, 1000)
	render.set_projection(projection_mtx)
	camera.view = view_mtx
	camera.projection = projection_mtx
	camera.width = render.get_window_width()
	camera.height = render.get_window_height()
    
	-- Render 3D space.
	--render.enable_state(render.STATE_DEPTH_TEST)
	--render.set_depth_mask(true)
	render.enable_state(render.STATE_CULL_FACE)
	render.draw(self.model_pred)
	--render.draw_debug3d()
	render.disable_state(render.STATE_CULL_FACE)
	render.disable_state(render.STATE_DEPTH_TEST)
	render.set_depth_mask(false)

	render.disable_render_target(self.target)
    
	-- Postprocessing.
	render.clear({[render.BUFFER_COLOR_BIT] = self.clear_color})

	render.set_viewport(0, 0, render.get_window_width(), render.get_window_height())
	render.set_view(vmath.matrix4())
	render.set_projection(vmath.matrix4())

	render.enable_texture(0, self.target, render.BUFFER_COLOR_BIT)
	render.draw(self.postprocessing_pred)
	render.disable_texture(0, self.target)
end

function on_message(self, message_id, message)
	if message_id == hashed.clear_color then
		self.clear_color = message.color
	end
end

I’d appreciate the help.
Thanks.

1 Like

I think you just are missing a depth buffer in your render target! :slight_smile:
Have a look here: https://www.defold.com/ref/render/#render.render_target:name-parameters
So, something like this in your case:

	local target_params = {
		[render.BUFFER_COLOR_BIT] = {
			format = render.FORMAT_RGBA,
			width = render.get_width(),
			height = render.get_height()
		},
		[render.BUFFER_DEPTH_BIT] = {
			format = render.FORMAT_DEPTH,
			width = render.get_width(),
			height = render.get_height()
		}
	}

	self.target = render.render_target('original', target_params)

3 Likes

Thanks, Sven! That indeed fixes everything.

3 Likes