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

Texture lod bias #26564

Open
Aloalo opened this issue Aug 10, 2023 · 4 comments
Open

Texture lod bias #26564

Aloalo opened this issue Aug 10, 2023 · 4 comments

Comments

@Aloalo
Copy link
Contributor

Aloalo commented Aug 10, 2023

Description

Are there any plans to add a texture lod bias option to textures and materials?

It seems that WebGL2 specification doesn't contain TEXTURE_LOD_BIAS​ parameter for sampler objects, which makes this feature difficult.
The only way to do this in WebGL seems to be manually passing the bias into the texture2D function calls in shaders? Hopefully someone has a better idea?

If I wanted to do this today I'd have to create my own material shaders which pass the lod bias uniform to every call to texture2D in all shaders.

Solution

Texture and Material objects have a textureLodBias parameter which biases mipmap selection when sampling textures.

Alternatives

For my use case a global texture load bias applied to all material shaders would work as well.

Additional context

No response

@Mugen87
Copy link
Collaborator

Mugen87 commented Aug 10, 2023

IMO, the use cases which require a manual bias parameter are very limited. A typical one in the past was #20522 which is about adding a LOD bias for alpha maps.

But because of the specific character of LOD bias, I don't think it's appropriate to introduce a new texture (or material) property. With a naive implementation we would end up with more uniforms that are not required most of the time. To prevent this, we would have to implement additional branches in JS and the GLSL chunks which increases complexity and maintainability.

A global setting seems problematic as well since a texture LOD bias is usually not something that is equal for all textures in an app.

Do you mind describing in more detail why you need control over what mipmap is going to be sampled? Is this control restricted to specific type of textures (like alpha maps)?

@Aloalo
Copy link
Contributor Author

Aloalo commented Aug 10, 2023

Sure, I need it for SSAA (implementation similar to three's SSAARenderPass).

Rendering SSAA in this manner with 2^n samples should be equivalent to rendering into a render target scaled by a factor of 2^sqrt(n) and then down scaling that render target to the original size with a linear filter.
When rendering a mesh into a render target that's scaled by a factor of 2^sqrt(n) the UV derivatives at a given pixel would be scaled by 2^-sqrt(n). The mipmap selection bias compared to rendering without scaling would then be the log of the exponent: log2(-sqrt(n))=-log2(n)/2.

So, in order to achieve the same effect as rendering into a larger render target I'd like to introduce this texture lod bias of -log2(n)/2 when rendering individual samples in SSAA.

Hopefully my explanation is clear enough

@Mugen87
Copy link
Collaborator

Mugen87 commented Aug 11, 2023

Thanks for the additional details.

I do not yet understand why you need a new texture property though. Do you modify built-in shaders for your SSAA implementation?

@Aloalo
Copy link
Contributor Author

Aloalo commented Aug 11, 2023

SSAA doesn't use any custom shader. It just renders the scene 2^n times with a slight camera view offset each time and averages the results. If I wanted to incorporate the load bias I'd have to modify a lot of internal shaders (pretty much every material texture sample).

The (very loose) pseudo code would be something like this:

scene.setGlobalTextureLodBias(-Math.log2(viewOffsets.length) / 2); // This is the thing I'd like to be able to do but can't currently
const viewOffsets = [...];
for (const viewOffset of viewOffsets) {
  camera.setViewOffset(viewOffset);
  
  webglRenderer.setRenderTarget(sceneRt);
  webglRenderer.clear();
  webglRenderer.render(scene, camera);

  // ...copy sceneRt into an accumulationRt with AdditiveBlending and opacity of 1.0 / viewOffsets.length
}

A way this could work is by replacing all texture2D calls in material shaders with something like:

vec4 textureSample(in sampler2D sampler, in vec2 uv) {
  return texture2D(sampler, uv, TEXTURE_LOD_BIAS);
}

Where TEXTURE_LOD_BIAS is a define that defaults to 0. Scene.setGlobalTextureLodBias would set this to the specified value.

If WebGL2 supported the TEXTURE_LOD_BIAS​ sampler parameter this would be much simpler to do as the property could be set on sampler objects and shaders wouldn't have to be touched. But alas it doesn't, and there are no extensions for it. WebGPU also douesn't support it.

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

No branches or pull requests

2 participants