Screen has black borders if it's bigger than project's default resolution

Hey there!

We have 1920/1080 resolution set in our game.project file. But it only resizes (stretches) to resolutions smaller than 1920/1080. If we try to stretch it to 4k, it seems like it stretches correctly, but everything beyond that 1920/1080 is black, i.e. our game is running in 1/4 corner of a black screen.

Actually, the render script was the first thing we made in our game. And seems like it’s a total mess)

:slight_smile:

So you’re able to sort the issue on your own then?

Not so sure about that( We still can’t remove the black border. In one case it appears in the right part of the screen, in other case it’s on top…

Maybe some example might help. We checking few examples right now, but not sure if they will help in our case. Will be extremely grateful for some desktop resolutions example.

Seems like I’ve just fixed that. But absolutely have no idea what’s happened…

2 Likes

Nope. Fixed almost everything and now the game layer stretches correctly as it should. But still everything beyond workspace (1920x1080) is pitch black, i.e. 4k looks like this.

here’s our render script

local function fixed_projection(self)
    local projected_width = render.get_width()-- / zoom / resZoomX
    local projected_height = render.get_height()-- / zoom / resZoom
    local xoffset = - (projected_width)/2 --(projected_width - render.get_width()) - 240 --480
    local yoffset = - (projected_height)/2  --(projected_height - render.get_height()) - 180 --320
    return vmath.matrix4_orthographic(xoffset, xoffset + projected_width, yoffset, yoffset + projected_height, -1000, 5000)
end

function update(self, dt)
    render.clear({[render.BUFFER_COLOR_BIT] = vmath.vector4(0,0,0,0), [render.BUFFER_DEPTH_BIT] = 1, [render.BUFFER_STENCIL_BIT] = 0})
    
    render.set_depth_mask(true)
    render.set_stencil_mask(0xff)

    render.set_viewport(0, 0, window_width, window_height)
    render.set_view(self.view)

    render.set_depth_mask(false)
    render.disable_state(render.STATE_DEPTH_TEST)
    render.disable_state(render.STATE_STENCIL_TEST)
    render.enable_state(render.STATE_BLEND)
    render.set_blend_func(render.BLEND_SRC_ALPHA, render.BLEND_ONE_MINUS_SRC_ALPHA)
    render.disable_state(render.STATE_CULL_FACE)

    --render to buffer
    render.set_projection(fixed_projection())
    render.enable_render_target(self.sbuffer)

    
    --draw gfx
    render.draw(self.background_pred)
    render.draw(self.tiles_pred)
    render.draw(self.twode_pred)
    render.draw(self.mist_pred)


    render.disable_render_target(self.sbuffer)

    --send buffer to screen
    print(render.get_window_width(), render.get_window_height(), window_width, window_height, resZoom, zoom)

    render.set_view(vmath.matrix4())
    render.set_viewport(0, 0, window_width / resZoomX, window_height / resZoom)
    render.set_projection(vmath.matrix4())

    render.enable_texture(0, self.sbuffer, render.BUFFER_COLOR_BIT)
    render.draw(self.quad_pred)
    render.disable_texture(0, self.sbuffer, render.BUFFER_COLOR_BIT)

    --render Lights
    render.set_viewport(0, 0, window_width, window_height)
    render.set_view(self.view)
    render.draw(self.lights_pred)

    -- render GUI
    render.set_view(vmath.matrix4())
    render.set_viewport(0, 0, window_width, window_height)
    render.set_projection(vmath.matrix4_orthographic(0, window_width, 0, window_height, -1, 1))

    render.enable_state(render.STATE_STENCIL_TEST)
    render.draw(self.gui_pred)
    render.draw(self.text_pred)
    render.disable_state(render.STATE_STENCIL_TEST)
    render.draw(self.cursors_pred)
end

What is the window width/height at this point?

window_width, window_height - is active screen resolution from game settings, i.e. it’s 3840 and 2160 for 4k.

resZoom = settings.resolution.y / 1080
resZoomX = settings.resolution.x / 1920
window_width = settings.resolution.x
window_height = settings.resolution.y

Isn’t this the problem?
What do you actually set the viewport to here? What are the values?
Shouldn’t it me window width/height?
Doc for glViewport

Changed to render.set_viewport(0, 0, window_width, window_height)
Now it looks like this. It’s a test resolution of 2560x1000

Adding render.set_viewport(0, 0, window_width, window_height / resZoom) gives correct height.
resZoom = window_height(1000) / workspace_height(1080)

OK, that’s where I came to)

I’m setting the projection to workspace/gamecamera resolution (1920x1080) with

local function fixed_projection(self)
    local projected_width = render.get_width()
    local projected_height = render.get_height()
    local xoffset = - projected_width / 2
    local yoffset = - projected_height / 2
    return vmath.matrix4_orthographic(xoffset, xoffset + projected_width, yoffset, yoffset + projected_height, -1000, 5000)
end

Then I render all game/camera layers to some sbuffer, and then scale it to game window with

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

    render.enable_texture(0, self.sbuffer, render.BUFFER_COLOR_BIT)
    render.draw(self.quad_pred)
    render.disable_texture(0, self.sbuffer, render.BUFFER_COLOR_BIT)

And here how game/camera layer looks on 720p, 1080p and testing resolution 2560 x 1000

image

Looks like it definitely lacks some index on a final stage. So when I add that index

resZoomX = render.get_width() / render.get_window_width()
resZoom = render.get_height() / render.get_window_height()
render.set_viewport(0, 0, render.get_window_width() * resZoomX, render.get_window_height() * resZoom)

Done. That’s the correct stretch to final window in all resolutions. But it paints black everything that is beyond workspace /gamecamera resolution (1920x1080). And I don’t know where that black border came from.

Solved! Made a repo for Alexey, now everything fits exactly as it should.

Huge thanks!

3 Likes

Great to hear!

For the benefit of the users of the forum, could you explain a bit about the solution? (while it’s fresh in memory :slight_smile: )

1 Like

Well, for me it might still take some effort to sort it all out :grin:
Alex remade all screen render target calculations and moved them to separate function, and now it works fine.

Maybe Alexey @AGulev will find a minute to briefly describe where the problem was.

2 Likes

Long story short:

  • it’s important to change RT size when window size changed, to be able to draw pixels 1 to 1
  • We should know the size of the quad we use for texture drawing and take it into account for the quad projection
  • In my case, I have 0, 0 in the bottom left, but in @kidkiedis case, they have 0, 0 in the screen center (it should be taken into account in projections)
  • and some other small fixes like RT clear, set_depth_mask(false), etc

I can’t share the render script I sent to @kidkiedis (it’s not my project), but here is my old render_script from Solitaire I made all the fixes based on it:
render.zip (4.9 KB)

4 Likes