godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.75k stars 20.12k forks source link

Blur shader doesn't work in WebGL 2.0 #91717

Open vicguedez opened 4 months ago

vicguedez commented 4 months ago

Tested versions

Tested in Godot v4.2.1.stable.official and v4.3.dev6.official

System information

Godot v4.2.1.stable - Pop!_OS 22.04 LTS - X11 - Vulkan (Mobile) - integrated AMD Radeon Vega 8 Graphics (RADV RAVEN) () - AMD Ryzen 5 3500U with Radeon Vega Mobile Gfx (8 Threads)

Issue description

DISCLAIMER: I'm a shader noob.

Blur shader works in editor but not in web export.

shader_type canvas_item;

uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, repeat_enable, filter_linear_mipmap;

uniform float lod: hint_range(0.0, 5.0) = 1.5;

void fragment(){
    vec4 color = textureLod(SCREEN_TEXTURE, SCREEN_UV, lod);
    COLOR = color;
}

This is how it looks in editor -also when I click play-

imagen

This is how it looks both in Firefox 125.0.2 (64-bit) and Chrome 124.0.6367.155 (64-bit)

imagen

Firefox errors with:

WebGL warning: drawArraysInstanced: Framebuffer not complete. (status: 0x8cd6) COLOR_ATTACHMENT0: Attached mip level is invalid for texture.

And Chrome with:

[.WebGL-0x2e14101d7f00] GL_INVALID_FRAMEBUFFER_OPERATION: Framebuffer is incomplete: Attachment level is not in the [base level, max level] range.

I also tested with a TextureRect instead of a ColorRect, attached a 2048x2048 white-filled texture, tried reimporting the texture with different compression modes and mipmaps enabled, nothing changed.

Steps to reproduce

Run provided MRP.

Minimal reproduction project (MRP)

webgl_blur_shader.zip

clayjohn commented 4 months ago

Tagging as a good first issue. This would be a good issue for someone who has some OpenGL/WebGL knowledge already. Particularly, you need to understand the rules about framebuffer completeness.

I think the problem comes from the fact that we sometimes don't allocate all mip levels (down to 1x1) to save on calculations. But WebGL might require all mip levels be allocated

2nafish117 commented 3 months ago

Hello, I'd like to look into this issue. Im guessing RenderingDevice::_draw_list_setup_framebuffer is a good place to start. Since this issue happens only on a exported game, what would be the best way to debug it? good old prints?

clayjohn commented 3 months ago

Hello, I'd like to look into this issue. Im guessing RenderingDevice::_draw_list_setup_framebuffer is a good place to start. Since this issue happens only on a exported game, what would be the best way to debug it? good old prints?

Since this issue is specific to WebGL, you won't need to look at the RenderingDevice code at all.

You should start by looking at how the backbuffer is formed here: https://github.com/godotengine/godot/blob/557f63d03796db78255f055b6d06cb5f9195ff7e/drivers/gles3/storage/texture_storage.cpp#L2138

and then go from there.

For example, this line is pretty suspicious: https://github.com/godotengine/godot/blob/557f63d03796db78255f055b6d06cb5f9195ff7e/drivers/gles3/storage/texture_storage.cpp#L2143 We seem to be allocating 4 less mipmap levels than the "required amount"

Nihlus commented 3 months ago

I'm also encountering this bug in both 4.2.1 and 4.2.2 - not in 4.1.1, however, so it appears to be some type of regression.

2nafish117 commented 3 months ago

Ive attempted a fix for this, but webgl still complains one of the color attachments on the framebuffers to be not complete. renderdoc shows 4 framebuffers, two of them have no attachments, one has a depth and color attachments, other has just a color attachment. Does anyone have any idea why it doesn't work?

Maybe i need to have atleast one color attachment on the 2 framebuffers that have no attachments? How would i go about finding out where those framebuffers are being created?