GithubHelp home page GithubHelp logo

Comments (38)

stevinz avatar stevinz commented on May 25, 2024 1

This is not related to the issue, but I wanted to mention it while I was thinking about it. Since you're working with sRGB encoded textures, and then doing some manual rebuilding into a texture atlas and working with THREE.Color, you should let Three.js know or you may end with colors that look off. Somewhere, when you load Three.js, you should include:

THREE.ColorManagement.legacyMode = false;

After setting legacyMode to false, while using THREE.Color functions (setRGB, getHex, etc.), they will automatically encode / decode values into the sRGB space. You may already be aware of this, just thought I'd mention it.

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024 1

Got it. Thanks so much for the help!

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

Thanks!

The examples in this repo use WboitPass as a stand-alone renderer, however, it is designed as a Pass for EffectComposer. WebGLRenderer.outputEncoding is only respected when rendering to screen. EffectComposer (and in turn WboitPass) use render targets encoded in the linear space. EffectComposer expects processing in the linear space to reduce color conversions during every pass. (source) (further reading). When using post processing, it is possible to use a gamma correction pass at the end of your pass chain to ensure a sRGB encoded output (source).

I have added an example (https://stevinz.github.io/three-wboit/EffectComposer.html) that uses this EffectComposer workflow to demonstrate. You can cycle the gamma correction ShaderPass on / off in the options. Hope this helps.

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

Thank you for the detailed explanation!

I added in the gamma correction shader, but things appear lighter than they used to be. Do you have any idea why this is happening?

Before:
Screenshot 2022-12-10 at 2 45 23 PM

After (with wOIT and gamma correction)
Screenshot 2022-12-10 at 2 44 14 PM

I tried changing the weight from 0 to 1, but it didn't help.

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

That is interesting. Initial thoughts is that the textures on the trees aren't sRGB encoded, or that lighting is enabled on the tree material? I have updated the EffectComposer.html example (source - live link) to use sRGB encoded textures.

I am having trouble trying to recreate the issue. I would be willing to spend more time looking into it if you could provide a minimal example demonstrating the problem. (codepen, jsfiddle, etc.)

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

Thanks for the response! I just found out something weird... The screenshot I produced is on one of my dual monitor setups. I switched it to the other monitor, and everything looked correct. What could be the cause of this?

Screenshot 2022-12-12 at 3 18 00 PM

Things look great on this monitor.

Link to the monitor that creates weird looking leaves.

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

Hmm, tricky. Monitors have encoding settings as well. I know on mine when I open the monitor settings with the physical buttons on the side / rear of the monitors, under 'Color Settings' I can select 'sRGB', 'P3', 'Warm', 'Cool', etc. Could be a hardware setting? These settings are external of the computer / OS / graphics card...

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

Weird... I can't seem to find color settings by pressing the buttons. I do see an "input color format" of "YCbCr", does that have to do with the issue?

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

Hard to say, even with different monitor settings the difference you posted the first time looks pretty extreme. Ignoring the monitor issue for a moment... When you're using wboit + gamma correction do you have renderer.outputEncoding set to Linear or sRGB? Now that the sRGB encoding is happening in the Effect Composer the renderer should be set to Linear, otherwise it's possible the encoding is happening twice in some cases.

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

I just checked and I do have it on sRGBEncoding, but after changing it to LinearEncoding, the effects still persist. Below is my custom shader material:

const material = new ShaderMaterial({
  vertexColors: true,
  fragmentShader,
  vertexShader,
  uniforms: {
    ...UniformsUtils.clone(ShaderLib.basic.uniforms),
    // map: this.uniforms.atlas,
    uSunlightIntensity: this.uniforms.sunlightIntensity,
    uAOTable: this.uniforms.ao,
    uMinBrightness: this.uniforms.minBrightness,
    uFogNear: this.uniforms.fogNear,
    uFogFar: this.uniforms.fogFar,
    uFogColor: this.uniforms.fogColor,
    uTime: this.uniforms.time,
    ...uniforms,
  },
}) as CustomShaderMaterial;

WboitUtils.patch(material);
export const DEFAULT_CHUNK_SHADERS = {
  vertex: ShaderLib.basic.vertexShader
    .replace(
      "#include <common>",
      `
attribute int light;

varying float vAO;
varying vec4 vLight;
varying vec4 vWorldPosition;
uniform vec4 uAOTable;
uniform float uTime;

vec4 unpackLight(int l) {
  float r = float((l >> 8) & 0xF) / 15.0;
  float g = float((l >> 4) & 0xF) / 15.0;
  float b = float(l & 0xF) / 15.0;
  float s = float((l >> 12) & 0xF) / 15.0;
  return vec4(r, g, b, s);
}

#include <common>
`
    )
    .replace(
      "#include <color_vertex>",
      `
#include <color_vertex>

int ao = light >> 16;

vAO = ((ao == 0) ? uAOTable.x :
    (ao == 1) ? uAOTable.y :
    (ao == 2) ? uAOTable.z : uAOTable.w) / 255.0; 

vLight = unpackLight(light & ((1 << 16) - 1));
`
    )
    .replace(
      "#include <worldpos_vertex>",
      `
vec4 worldPosition = vec4( transformed, 1.0 );
#ifdef USE_INSTANCING
  worldPosition = instanceMatrix * worldPosition;
#endif
worldPosition = modelMatrix * worldPosition;
vWorldPosition = worldPosition;
`
    ),
  fragment: ShaderLib.basic.fragmentShader
    .replace(
      "#include <common>",
      `
uniform vec3 uFogColor;
uniform float uFogNear;
uniform float uFogFar;
uniform float uSunlightIntensity;
uniform float uMinBrightness;
uniform float uTime;
varying float vAO;
varying vec4 vLight; 
varying vec4 vWorldPosition;

#include <common>
`
    )
    .replace(
      "#include <envmap_fragment>",
      `
#include <envmap_fragment>

// Intensity of light is wavelength ** 2 
float s = min(vLight.a * vLight.a * uSunlightIntensity * (1.0 - uMinBrightness) + uMinBrightness, 1.0);
float scale = 2.0;

outgoingLight.rgb *= vec3(s + pow(vLight.r, scale), s + pow(vLight.g, scale), s + pow(vLight.b, scale));
outgoingLight *= vAO;
`
    )
    .replace(
      "#include <fog_fragment>",
      `
vec3 fogOrigin = cameraPosition;

float depth = sqrt(pow(vWorldPosition.x - fogOrigin.x, 2.0) + pow(vWorldPosition.z - fogOrigin.z, 2.0));
float fogFactor = smoothstep(uFogNear, uFogFar, depth);

gl_FragColor.rgb = mix(gl_FragColor.rgb, uFogColor, fogFactor);
`
    ),
};

For all the textures used in the project, I made sure that they had encoding set as sRGBEncoding.

This is the link to the shader source, and this (and this) is to the material code.

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

I don't think the shader code matters. I just tried using a MeshBasicMaterial with the same texture atlas and the weird brightness still exists. Could this be related to using CanvasTexture for the generated texture atlas?

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

It could be, is the CanvasTexture encoding set to sRGB?

Now that you're using an EffectComposer workflow, try replacing the WboitPass with a standard render pass and see if the problem persists. That would at least isolate the problem between WboitPass and something else...

import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
// replace
// composer.addPass( new WboitPass( renderer, scene, camera ) );

// with
composer.addPass( new RenderPass( scene, camera ) );

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

Things look normal with a RenderPass:
image
The CanvasTexture is also set to sRGB 🤔

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

After running WboitUtils.patch(material), if you then set material.wboitEnabled = false, does the problem still occur on transparent objects? During the WboitPass, normal transparent objects and wboitEnabled transparent objects are rendered separately, I'm wondering if it could be a blending issue.

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

This is interesting... The problem still occurs on transparent objects.

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

Hmm, another thought. Are you doing any passes in EffectComposer before the WboitPass? If not, you should probably have WboitPass clear the write buffer by setting a clear color (if you're not already). In order to have WboitPass perform a clear, you need to pass a THREE.Color the constructor. For clearing to black it would simply be:

const wboitPass = new WboitPass( renderer, scene, camera, new THREE.Color() );

Does that make a difference?

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

I do not have any passes before the WboitPass, and passing a clear color didn't change anything :(

The only two passes I have are these:
image

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

Seems like this problem happens to other people too. This is @donmccurdy's solution: link. I will try to dig deeper into three-wboit's WboitPass and convert it into postprocessing's syntax locally.

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

I'm not sure that is the same issue, your colors seem off differently than the colors in that post. Do you have a link to a specific texture that you are having this issue with? It would be nice to have a minimal example...

It shouldn't be necessary, or desired, but someone also suggested to try setting EffectComposer's render target's encoding:

composer.renderTarget1.texture.encoding = THREE.sRGBEncoding;
composer.renderTarget2.texture.encoding = THREE.sRGBEncoding;

I would be curious if that made a difference. You could try changing the encoding on the main render target in WboitPass:

const wboitPass = new WboitPass( renderer, scene, camera );
wboitPass.baseTarget.texture.encoding = THREE.sRGBEncoding;

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

Okay, I think I've solved it.

The blending methods used in WboitPass result in visually accurate colors, but with alpha value's that vary. For the sRGB conversion the color values should have an alpha value of 1.0... I have created a new shader to encode from Linear space to sRGB space that premultiplies the alpha. I'm almost positive it will fix your issue.

I have updated the library and the build on npm. To use:

import { sRGBShader } from 'three-wboit';
// replace
// composer.addPass( new ShaderPass( GammaCorrectionShader ) );

// with
composer.addPass( new ShaderPass( sRGBShader ) );

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

Thanks for your help so far!

I just tried out the sRGBShader replacing it with the GammaCorrectionShader, but it seems like transparent objects have turned black, and I'm not sure why :/

Screenshot 2022-12-13 at 3 06 43 PM

Here's the source code for my example:

Let me see if I can setup a minimized example somewhere so it's easier to reproduce the problem.

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

Very interesting..

It could be an issue with WboitUtils.patch. I haven't tested it with ShaderMaterial. I can check it out, but in the meantime you could try adding the shader code directly into you shader chuck. When you build your shader material, add uniforms renderStage and weight

At then in your fragment shader (shaders.ts)

Add the uniforms:

    uniform float renderStage;
    uniform float weight;

And at the very end, add the wboit code:

    if ( renderStage == 1.0 ) {
       vec4 accum = gl_FragColor.rgba;

	#ifndef PREMULTIPLIED_ALPHA
	    accum.rgb *= accum.a;
	#endif

	float z = gl_FragCoord.z;
        float scaleWeight = 0.7 + ( 0.3 * weight );
        float w = clamp( pow( ( accum.a * 8.0 + 0.001 ) * ( - z * scaleWeight + 1.0 ), 3.0 ) * 1000.0, 0.001, 300.0 );
        gl_FragColor = accum * w;
    } else if ( renderStage == 2.0 ) {
        gl_FragColor = vec4( gl_FragColor.a * gl_FragCoord.z );
    }

And then in index.ts, change

// Old
// WboitUtils.patch(material);

// New
material.wboitEnabled = true;

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

Hmm, well I just tested it with ShaderMaterial and that's not it...

Does the darkness / blackness go away if you set opacity to a lower value, like 0.5?

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

Let me try. I'm creating a tiny project and am trying to reproduce the problem. Thanks for your help man 💯

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

For my actual project, setting opacity to 0.5 doesn't change. I'm starting to wonder whether or not it's the TextureAtlas class's fault 🤔

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

Ok here's the project: link

image

On the left is using the same texture generated from the texture atlas, but without doing patch. On the right is wboit patched.

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

Okay, thanks I'll take a look

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

Okay, so using the original GammaCorrectionShader I do see what you were talking about. The object on the right (the Wboit patched object) looks a little lighter / brighter.

However, I think that's because in your file style.css you have background-color: #242424;. Wboit rendering uses special blend modes and the final rendered image has partially transparent pixels, it needs the background to be black. When I changed it to background-color: #000000;, the colors look identical between the two objects. Does that work for you?

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

Hmm, that's weird. I removed the background color and pretty much everything in the styles.css, and this is what I got:

image

The mesh on the right is too bright to be visible. BTW, I've pushed my changes to the same repo.
Do you see the same effect?

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

The background has to be black, not white. Try adding at top of style.css:

:root {
  background-color: #000000;
}

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

Here's what it looks like in black:
image

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

Interesting, here's on my machine:
wboit-leaves

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

And lighter background for comparison:
leaves-light

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

Hmmm.. I see on your machine the one on the right is also slightly brighter. Could it be that my monitor gets affected more by the Wboit pass? I found out that if I turn the material to double side, it would become even brighter, but when I turn the opacity down a bit it isn't as bright.

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

It is strange.

But, the one on the right is brighter because the renderer's write buffer has partially transparent pixels from the WboitPass and the background color is mixing with the renderers output. That's why setting the background to black should fix the issue.

It's possible your monitor is then taking the resulting pixels and applying more correction on them. Even though visually the two objects should look the same on a black background. The one on the left has an alpha value of 1.0, where the one on the right varies, but in that picture has an alpha value of 0.5. In which case for two pixels to look the same with different alpha values the RGB values must be greater, and then in turn get affected more by any correction your monitor is doing after. The point of the sRGBShader I added was to convert the alpha value to 1. I am going back to it and working on some more tests...

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

Alright, how does (https://stevinz.github.io/three-wboit/vox/VoxTest.html) look on your machine? Try adjusting the opacity slider as well.

from three-wboit.

shaoruu avatar shaoruu commented on May 25, 2024

Wait it looks exactly the same on both sides! How is this done?

from three-wboit.

stevinz avatar stevinz commented on May 25, 2024

Well, the blending methods used in wboit create alpha values that are different then standard blending. They seemed to be causing a problem on your monitor (and I'm guessing others would have the same issue).

So before doing gamma correction in the sRGBShader, I am setting the alpha channel to fully opaque (1.0).

I have temporarily put the source on the repo (https://github.com/stevinz/three-wboit/tree/master/example/vox)

from three-wboit.

Related Issues (5)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.