Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Renderbuffer #442

Draft
wants to merge 24 commits into
base: master
Choose a base branch
from
Draft

Renderbuffer #442

wants to merge 24 commits into from

Conversation

iceiix
Copy link
Owner

@iceiix iceiix commented Dec 25, 2020

glTexImage2DMultisample is officially unavailable in glow (porting in #262) because it is not available on WebGL, see: #262 (comment) - as a replacement should either:

See also this previous issue (one of the earliest fixed) with NUM_SAMPLES: #5 (comment)

or a third option (temporary to unblock #262):

  • (workaround implemented) 3. bypass glow for the glTexImage2DMultisample call, calling the OpenGL backend directly (in gl46.rs)

iceiix added a commit that referenced this pull request Dec 25, 2020
iceiix added a commit that referenced this pull request Dec 25, 2020
Replaces the use of gl_generator with the glow wrapper:

* Add glow dependency, based on glow 0.6.1

* Pin version of glow fork for iceiix/glow#1 until #442 renderbuffer

* Remove gl module, steven_gl

Porting details:
* Initialize glow in src/gl/mod.rs
* Call gl methods on glow context
* glow uses camelcase
* Import glow::HasContext trait, finds draw_elements etc.
* Fix mismatched types, glow uses Option and &str instead of raw pointers
* Fix uniform_location, glow already returns Some(u32)
* uniform_location: convert i32 to u32 for Uniform
* Fix attribute_location
* Fix shader creation Result u32 type 
* Fix passing GLvoid and 2d/3d
* Fix missing Options type mismatches
* Offsets are i32 in glow, not GLvoid
* Fix clear_buffer using _f32_slice
* Delete methods are singular not plural
* glBufferData -> buffer_data_u8_slice
* buffer_sub_data_u8_slice
* Update more glow method wrapper names found by reviewing glow native platform
* Remove unused multi_draw_elements, can be replaced by draw_elements in a loop and it has no WebGL equivalent
* glow implements glMapBufferRange
* Remove unused read_buffer
* glow's deletes automatically pass 1 and take no reference
* shader_source() accepts &str directly; removes last of std::ptr
* Pass uniform Option<u32>
* Fix bool passing normalized parameter
* Fix draw_buffers parameter
* Stop unnecessarily returning context from gl::init
* Getting shader info is unsafe 
* Unwrapping static mut is unsafe
* Use unsafe raw pointers for global mutable context
* Fix initializing GL objects wrappers from glow wrappers
* Unbinding framebuffers uses None
* Uppercase global to fix warning
* Shaders return Some instead of None
* Unbox the context to a raw pointer
* Use tex_image_2d_multisample added in glow fork 
* Implement uniform_location, fixing unwrap None failed
* Add tex_sub_image_3d, using PixelUnpackData::Slice
* set_matrix4: transmute the Matrix4 since it is repr(C)
* get_pixels -> get_tex_image -> glGetTexImage, with PixelPackData::Slice
* Wrap sub_image_2d (glTexSubImage2D) and fix warnings
* Implement set_float_multi_raw and set_matrix4_multi, using from_raw_parts
@iceiix
Copy link
Owner Author

iceiix commented Dec 27, 2020

With #262 #444, this problem now manifests itself with this error running under wasm, WebGL: ERROR: 0:7: 'sampler2DMS' : Illegal use of reserved word:

Screen Shot 2020-12-26 at 7 34 05 PM

sampler2DMS will also have to be removed for WebGL. https://learnopengl.com/Advanced-OpenGL/Anti-Aliasing explains:

It is possible to directly pass a multisampled texture image to a fragment shader instead of first resolving it. GLSL gives us the option to sample the texture image per subsample so we can create our own custom anti-aliasing algorithms.

...this passing of the multisampled texture image to the fragment shader is an implementation of a custom anti-aliasing algorithm, texelFetch(tcolor, C, i) fetching the ith subsample:

// src/render/shaders/trans_frag.glsl
uniform sampler2DMS tcolor;

uniform int samples;
...
    for (int i = 1; i < samples; i++) {
        col += texelFetch(tcolor, C, i);
    }
    col /= float(samples);

do we really need a custom AA algorithm? It was in Steven since the earliest commits.

ryanisaacg/quicksilver#476 has some more background: "WASM doesn't support MSAA except when rendering to a framebuffer", including http://www.realtimerendering.com/blog/webgl-2-new-features/ "New features: Multisampled Renderbuffers".

Previously, if we wanted antialiasing we would either have to render it to the default backbuffer or perform our own post-process AA (such as FXAA or SMAA) on content rendered to a texture.

Now, with Multisampled Renderbuffers, we can use the general rendering pipeline in WebGL to provide multisampled antialiasing (MSAA):

pre-z pass –> rendering pass to FBO –> postprocessing pass –> render to window

renderbufferStorageMultisample is the relevant function here.

Pay attention to the fact that the multisample renderbuffers cannot be directly bound to textures, but they can be resolved to single-sample textures using the blitFramebuffer call. This is a new feature in WebGL 2 as well

FXAA: Fast Approximate Anti-Aliasing and SMAA: Enhanced Subpixel Morphological Antialiasing are both post-processing techniques, operating on the rendered pixels. Not strictly necessary, FXAA or SMAA can be added on later. But the immediate problem of removing the use of glTexImage2DMultisample for web support (#446) remains...

@iceiix
Copy link
Owner Author

iceiix commented Dec 27, 2020

Back to working on disabling multisampling. Got past the incomplete framebuffer error, but now hits glGetError = 1282 (Invalid operation). glow's gl46 https://docs.rs/gl46/0.1.3/gl46/ says it has these useful features for debugging:

debug_trace_calls: if cfg!(debug_assertions), any call to a GL function will trace! what was called and with what args.
debug_automatic_glGetError: If cfg!(debug_assertions), this will automatically call glGetError after every call to any other GL function. If an error code occurs it's shown via error! along with the name of the function that had the error.

but glow = { git = "https://github.com/iceiix/glow", rev = "b354346dee69ff0ca7ccef67f7580dfbb697423b", features = ["debug_trace_calls", "debug_automatic_glGetError"] } fails with no such features, not piped through gl46 to glow? First enabled debug-assertions (since we set opt-level = 1, and have to in order to avoid #443, which disables debug-assertions by default), then glow = { path = "../glow" } and modified glow/Cargo.toml:

diff --git a/Cargo.toml b/Cargo.toml
index 699e63f..48b4c35 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -28,8 +28,10 @@ name = "glow"
 path = "src/lib.rs"
 
 [features]
-default = ["web-sys"]
+default = ["web-sys", "debug_trace_calls", "debug_automatic_glGetError"]
 web-sys = ["web_sys", "js-sys", "wasm-bindgen"]
+debug_trace_calls = []
+debug_automatic_glGetError = []
 
 [target.'cfg(not(any(target_arch = "wasm32")))'.dependencies]
 glutin = { version = "0.24", optional = true }

This works in a pinch to log all the calls and check each for errors. Lots of output, but the first few errors are:

calling gl.BindTexture(0xDE1, 2);
calling gl.GetError();
calling gl.TexSubImage2D(0xDE1, 0, 0, 0, 512, 512, 0x1903, 0x1401, 0x7feb78040000);
calling gl.GetError();
calling gl.Uniform1i(12, 1);
calling gl.GetError();
calling gl.BindVertexArray(2);
calling gl.GetError();
calling gl.DrawArrays(0x0, 0, 102400);
calling gl.GetError();
calling gl.UseProgram(7);
calling gl.GetError();
calling gl.UniformMatrix4fv(1, 1, 0, 0x7feb869910a0);
calling gl.GetError();
calling gl.UniformMatrix4fv(5, 1, 0, 0x7feb869910e0);
calling gl.GetError();
calling gl.Uniform1i(11, 0);
calling gl.GetError();
calling gl.Uniform1f(10, 0.8);
calling gl.GetError();
calling gl.Uniform1f(9, 0.7051707);
calling gl.GetError();
calling gl.BindFramebuffer(0x8CA8, 2);
calling gl.GetError();
calling gl.BindFramebuffer(0x8CA9, 1);
calling gl.GetError();
calling gl.BlitFramebuffer(0, 0, 1708, 960, 0, 0, 1708, 960, 256, 0x2600);
calling gl.GetError();
Invalid Operation to glBlitFramebuffer.

glBlitFramebuffer, then glBindTexture:

calling gl.ActiveTexture(0x84C2);
calling gl.GetError();
calling gl.BindTexture(0x9100, 6);
calling gl.GetError();
Invalid Operation to glBindTexture.

and glBlitFramebuffer, glBindTexture, glBlitFramebuffer, glBindTexture, repeatedly. Only call to blit is in src/render/mod.rs tick() to copy the depth buffer:

        // Copy the depth buffer
        trans.main.bind_read();
        trans.trans.bind_draw();
        gl::blit_framebuffer(
            0,
            0,
            physical_width as i32,
            physical_height as i32,
            0,
            0,
            physical_width as i32,
            physical_height as i32,
            gl::ClearFlags::Depth,
            gl::NEAREST,
        );

Is fb_depth created correctly? Was using gl::DEPTH_COMPONENT format/internalformat and gl::FLOAT type (image_2d_sample didn't require type). Fixed by matching parameters of image_2d_ex same as trans_depth. Next failure was glBindTexture, set breakpoint in src/gl46.rs:4265, step up, found it was a missing gl::TEXTURE_2D_MULTISAMPLE in draw(). Correcting to TEXTURE_2D, works!

@iceiix
Copy link
Owner Author

iceiix commented Dec 27, 2020

Multisampling disabled, after:

Screen Shot 2020-12-26 at 9 18 00 PM

before (with MSAA, master branch):

Screen Shot 2020-12-26 at 9 19 27 PM

any significant difference? The fire is different between these two frames but it is animated, so... either way doesn't seem to be too significant of a change with MSAA disabled.

@iceiix
Copy link
Owner Author

iceiix commented Dec 27, 2020

Testing wasm now, gets further but WebGL doesn't like the clouds shaders:

Screen Shot 2020-12-26 at 9 27 19 PM

"invalid shader type", I bet this is because of src/render/shaders/clouds_geo.glsl, used by src/render/clouds.rs for a gl::GEOMETRY_SHADER. https://learnopengl.com/Advanced-OpenGL/Geometry-Shader. https://news.ycombinator.com/item?id=13893412 confirms WebGL 2 doesn't have: geometry shaders, compute shaders, tessellation shaders. Will have to do without...

As for this specific pull request, the choice now is to either merge the MSAA removal now, or work on renderbuffer MSAA first...

iceiix added a commit that referenced this pull request Dec 27, 2020
Steven used multisampled textures from the beginning, but this caused
incompatibilities: Thinkofname/steven#74.
Subsequently fixed by increasing the number of samples, but increasing
it beyond the limit caused more incompatibilities, so it was clamped to
the maximum samples reported as supported by the system.

Fast-forward to now, as part of adding WebGL support (#446), the use of
multisampled textures via the glTexImage2DMultisample() call is
unsupported on this platform. Replace the following:

* glTexImage2DMultisample -> glTexImage2D
* TEXTURE_2D_MULTISAMPLE -> TEXTURE_2D
* sampler2DMS -> sampler2D

This disables the custom multisampling anti-aliasing algorithm (MSAA)
implemented in the chunk fragment shader, increasing compatibility:

* Update to glow release, remove image_2d_sample()

MSAA may be added back at a later date using multisampled renderbuffers
instead, see #442.
iceiix added a commit that referenced this pull request Dec 27, 2020
Steven used multisampled textures from the beginning, but this caused
incompatibilities: Thinkofname/steven#74.
Subsequently fixed by increasing the number of samples, but increasing
it beyond the limit caused more incompatibilities, so it was clamped to
the maximum samples reported as supported by the system.

Fast-forward to now, as part of adding WebGL support (#446), the use of
multisampled textures via the glTexImage2DMultisample() call is
unsupported on this platform. Replace the following:

* glTexImage2DMultisample -> glTexImage2D
* TEXTURE_2D_MULTISAMPLE -> TEXTURE_2D
* sampler2DMS -> sampler2D

This disables the custom multisampling anti-aliasing algorithm (MSAA)
implemented in the chunk fragment shader, increasing compatibility:

* Update to glow release, remove image_2d_sample()

MSAA may be added back at a later date using multisampled renderbuffers
instead, see #442.
iceiix added a commit that referenced this pull request Dec 27, 2020
No clouds on wasm since no geo shaders on WebGL
Needed for 🕸️ Web support #446, to fix "invalid shader type", see #442 (comment)
@iceiix
Copy link
Owner Author

iceiix commented Dec 27, 2020

First trying to use renderbuffers without multisampling to get the hang of it (then should be straightforward to increase the samples, glRenderbufferStorage is the same as glRenderbufferStorageMultisample with samples = 0). The status quo:

main (Framebuffer):

  • fb_color (Texture)
  • fb_depth (Texture)

trans (Framebuffer):

  • accum (Texture)
  • revealage (Texture)
  • trans_depth (Texture)

these objects are encapsulated in TransInfo. Changing fb_color and fb_depth to Renderbuffers... compiles but nothing renders, there is a problem: renderbuffers, unlike textures, cannot be accessed from shaders. trans_frag.glsl accesses taccum, trevealage, and tcolor, as sampler2D. Only textures can be accessed from shaders. That is, this doesn't work:

main (Framebuffer):

  • fb_color (Renderbuffer)
  • fb_depth (Renderbuffer)

A way around this it to create another framebuffer, backed by textures, then blit from the backed-by-renderbuffer framebuffer to the backed-by-textures renderbuffer. Not familiar enough with the existing rendering pipeline to know how to implement this, exactly.. also further complicated by the need to render non-transparent and transparent separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant