Scirra / Construct-bugs

Public bug report submissions for Construct 3 and Construct Animate. Please read the guidelines then click the 'Issues' tab to get started.
https://www.construct.net
108 stars 83 forks source link

Bumpmapping Effect spatial issues #7449

Closed Everade closed 7 months ago

Everade commented 11 months ago

Problem description

The current Bumpmapping effect isn't compatible with OpenGL/WebGL normal maps. Instead it's compatible with DirectX compatible Normal maps, which have an inverted green color channel.

I've used WebGL compatible normal maps for this test.

Attach a .c3p

bumpmappingIssue.zip

Steps to reproduce

  1. Open project and start preview or
  2. Import an openGL comptaible normal map sphere graphic
  3. Apply the official C3 bumpmapping effect to it
  4. Set the light position to the center of the sphere
  5. Adjust z height (1-100%) and intensity (150-500%) so the warping issue becomes visible
  6. Compare the WebGL and WebGPU effects

Observed result

WebGL image

WebGPU image

Expected result

I would expect a WebGL effect to support WebGL compatible normal maps. Note: This example only shows the extruded version, and please ignore the contrast differences. What this is all about is the light shape on how it's shining onto a sphere. image

More details

WebGPU also doesn't seem be able to render the intrusion version. This works fine in WebGL.

Here's a good resource for spatial correct bump mapping, (just ignore the additional complexity for ambient, attenuation and so on), it's at its core very similar on how C3's bumpmapping effect was built. https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson6

Affected browsers/platforms: Chrome

First affected release: I assume the effect has always been like this.

System details

View details Platform information Product: Construct 3 r361 (beta) Browser: Chrome 117.0.5938.134 Browser engine: Chromium Context: webapp Operating system: Windows 11 Device type: desktop Device pixel ratio: 1 Logical CPU cores: 32 Approx. device memory: 8 GB User agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36 Language setting: en-US Local storage Storage quota (approx): 503 gb Storage usage (approx): 144 mb (0%) Persistant storage: No Browser support notes This list contains missing features that are not required, but could improve performance or user experience if supported. Nothing is missing. Everything is OK! WebGPU information Renderer: WebGPU Supports GPU profiling: no Major performance caveat: no Maximum texture size: 8192 Adapter vendor: nvidia Adapter architecture: ampere Adapter device: (unavailable) Adapter description: (unavailable) Adapter features: bgra8unorm-storage depth-clip-control depth32float-stencil8 indirect-first-instance rg11b10ufloat-renderable texture-compression-bc Audio information System sample rate: 48000 Hz Output channels: 2 Output interpretation: speakers Supported decode formats: WebM Opus (audio/webm; codecs=opus) Ogg Opus (audio/ogg; codecs=opus) WebM Vorbis (audio/webm; codecs=vorbis) Ogg Vorbis (audio/ogg; codecs=vorbis) MPEG-4 AAC (audio/mp4; codecs=mp4a.40.5) MP3 (audio/mpeg) FLAC (audio/flac) PCM WAV (audio/wav; codecs=1) Supported encode formats: WebM Opus (audio/webm; codecs=opus) Video information Supported decode formats: WebM AV1 (video/webm; codecs=av01.0.00M.08) MP4 AV1 (video/mp4; codecs=av01.0.00M.08) WebM VP9 (video/webm; codecs=vp9) WebM VP8 (video/webm; codecs=vp8) Ogg Theora (video/ogg; codecs=theora) H.265 (video/mp4; codecs=hev1.1.2.L93.B0) H.264 (video/mp4; codecs=avc1.42E01E) Supported encode formats: WebM AV1 (video/webm; codecs=av1) WebM VP9 (video/webm; codecs=vp9) WebM VP8 (video/webm; codecs=vp8)
Everade commented 11 months ago

@AshleyScirra New findings: When porting NormalMap32 to WGSL we've had similar issues. light.y is most likely inverted (thanks @MikalDev). This should hopefully fix the light warp:

//after light normalization
light.y = 0.0 - light.y;

Since DirectX normal maps have an inverted green channel, i assume that the effect was originally tested against DirectX compatible normal maps. However i would assume a WebGL renderer to support OpenGL/WebGL normal maps instead.

Everade commented 11 months ago

@AshleyScirra Although unrelated to this bug, it's still bump mapping related, so i feel like it fits well in here.

Right now your bump mapping effect doesn't account for sprite modifications such as stretching, roations, scaling flipping or other distortions. However since you've added WebGL2 support, this becomes possible by using derivatives.

But it seems that C3 has a fundamental issue so that even when using derivatives with normal mapping, as it's still distorted during sprite rotations in WebGPU. And there are even further weird bugs when testing in WebGL. I'm still not sure why this is exactly happening, but it could possibly be related to C3 bounding box scaling during rotations messing up WebGPU rotational computations, because shaders are not running on the geometry directly but on a proxy buffer instead?!

This makes it rather hard to work with normal mapping in C3. I've been running tests on this ever since WebGL2 support release with no avail.

It can be applied to your bump mapping effect right after the normal map normalization: https://github.com/XorDev/Shader-Derivatives/blob/main/ShaderDerivatives/shaders/shd_3_normalmap/shd_3_normalmap.fsh

WebGPU

    // Compute the texture coordinates derivatives.
    let dx : vec2<f32> = dpdx(input.fragUV);
    let dy : vec2<f32> = dpdy(input.fragUV);
    let rot : vec4<f32> = vec4(dx, dy);

    // Correct normal with texture orientation.
    let m : mat2x2<f32> = mat2x2<f32>(normalize(rot.xz), -normalize(rot.yw));
    normal.x = dot(normal.xy, m[0]);
    normal.y = 0.0 - dot(normal.xy, m[1]);

WebGL2

    vec2 dx = dFdx(vTex);
    vec2 dy = dFdy(vTex);
    vec4 rot = vec4(dx, dy);

    normal.xy *= mat2(normalize(rot.xz), -normalize(rot.yw));

Would be great to get your insight on this problem. And hopefully raise your interest into improving the C3 bump mapping effect.

AshleyScirra commented 7 months ago

The main issue here is asking to change the format of normal maps used for the existing bumpmapping shader. That's not something we can do because of backwards compatibility: I think that effect has been around for at least 10 years, and so any existing projects using it going back years will have already imported DirectX compatible normal maps, and changing how the effect works will change how all those projects work. So we won't change how the existing bumpmapping shader works, but you can always write a custom bumpmapping shader to support other formats or cases.

I did notice even with the latest code the bumpmapping effect wasn't rendering the same as WebGL in WebGPU mode - that is fixed for the next beta.

Two more points: