Skip to content

Commit

Permalink
Add anisotropy property to renderer and material for configuring it g…
Browse files Browse the repository at this point in the history
…lobally and per material respectively (#5309)

Co-authored-by: Noeri Huisman <[email protected]>
  • Loading branch information
mrxz and mrxz authored Jun 20, 2023
1 parent 96a3e7d commit 93b500e
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 2 deletions.
2 changes: 2 additions & 0 deletions docs/components/material.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ Here is an example of using an example custom material:

[flat]: #flat
[standard]: #standard
[renderer]: ./renderer.md

The material component has some base properties. More properties are available
depending on the material type applied.
Expand All @@ -74,6 +75,7 @@ depending on the material type applied.
| visible | Whether material is visible. Raycasters will ignore invisible materials. | true |
| blending | The blending mode for the material's RGB and Alpha sent to the WebGLRenderer. Can be one of `none`, `normal`, `additive`, `subtractive` or `multiply`. | normal |
| dithering | Whether material is dithered with noise. Removes banding from gradients like ones produced by lighting. | true |
| anisotropy | The anisotropic filtering sample rate to use for the textures. A value of 0 means the default value will be used, see [renderer][renderer] | 0 |

## Events

Expand Down
1 change: 1 addition & 0 deletions docs/components/renderer.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ It also configures presentation attributes when entering WebVR/WebXR.
| alpha | Whether the canvas should contain an alpha buffer. | true |
| toneMapping | Type of toneMapping to use, one of: 'no', 'ACESFilmic', 'linear', 'reinhard', 'cineon' | 'no' |
| exposure | When any toneMapping other than "no" is used this can be used to make the overall scene brighter or darker | 1 |
| anisotropy | Default anisotropic filtering sample rate to use for textures | 1 |

> **NOTE:** Once the scene is initialized, none of these properties may no longer be changed apart from "exposure" and "toneMapping" which can be set dynamically.
Expand Down
3 changes: 2 additions & 1 deletion src/components/material.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ module.exports.Component = registerComponent('material', {
vertexColorsEnabled: {default: false},
visible: {default: true},
blending: {default: 'normal', oneOf: ['none', 'normal', 'additive', 'subtractive', 'multiply']},
dithering: {default: true}
dithering: {default: true},
anisotropy: {default: 0, min: 0}
},

init: function () {
Expand Down
2 changes: 2 additions & 0 deletions src/systems/renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module.exports.System = registerSystem('renderer', {
exposure: {default: 1, if: {toneMapping: ['ACESFilmic', 'linear', 'reinhard', 'cineon']}},
toneMapping: {default: 'no', oneOf: ['no', 'ACESFilmic', 'linear', 'reinhard', 'cineon']},
precision: {default: 'high', oneOf: ['high', 'medium', 'low']},
anisotropy: {default: 1},
sortObjects: {default: false},
colorManagement: {default: true},
alpha: {default: true},
Expand All @@ -34,6 +35,7 @@ module.exports.System = registerSystem('renderer', {
renderer.sortObjects = data.sortObjects;
renderer.useLegacyLights = !data.physicallyCorrectLights;
renderer.toneMapping = THREE[toneMappingName + 'ToneMapping'];
THREE.Texture.DEFAULT_ANISOTROPY = data.anisotropy;

THREE.ColorManagement.enabled = data.colorManagement;
renderer.outputColorSpace = data.colorManagement ? THREE.SRGBColorSpace : THREE.LinearSRGBColorSpace;
Expand Down
8 changes: 7 additions & 1 deletion src/utils/material.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ function setTextureProperties (texture, data) {
var offset = data.offset || {x: 0, y: 0};
var repeat = data.repeat || {x: 1, y: 1};
var npot = data.npot || false;
var anisotropy = data.anisotropy || 0;
// To support NPOT textures, wrap must be ClampToEdge (not Repeat),
// and filters must not use mipmaps (i.e. Nearest or Linear).
if (npot) {
Expand All @@ -37,6 +38,11 @@ function setTextureProperties (texture, data) {
if (offset.x !== 0 || offset.y !== 0) {
texture.offset.set(offset.x, offset.y);
}

// Only set anisotropy if it isn't 0, which indicates that the default value should be used.
if (anisotropy !== 0) {
texture.anisotropy = anisotropy;
}
}
module.exports.setTextureProperties = setTextureProperties;

Expand Down Expand Up @@ -83,7 +89,7 @@ module.exports.updateMapMaterialFromData = function (materialName, dataName, sha
// Load texture for the new material src.
// (And check if we should still use it once available in callback.)
el.sceneEl.systems.material.loadTexture(src,
{src: src, repeat: data.repeat, offset: data.offset, npot: data.npot},
{src: src, repeat: data.repeat, offset: data.offset, npot: data.npot, anisotropy: data.anisotropy},
checkSetMap);
}

Expand Down
28 changes: 28 additions & 0 deletions tests/components/material.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,4 +344,32 @@ suite('material', function () {
assert.equal(el.components.material.material.blending, THREE.MultiplyBlending);
});
});

suite('anisotropy', function () {
test('defaults to THREE.Texture.DEFAULT_ANISOTROPY', function (done) {
var imageUrl = 'base/tests/assets/test.png';
el.setAttribute('material', '');
assert.notOk(el.components.material.material.texture);
el.setAttribute('material', 'src: url(' + imageUrl + ')');
el.addEventListener('materialtextureloaded', function (evt) {
var loadedTexture = evt.detail.texture;
assert.ok(el.components.material.material.map === loadedTexture);
assert.strictEqual(loadedTexture.anisotropy, THREE.Texture.DEFAULT_ANISOTROPY);
done();
});
});

test('can set specific anisotropic filtering sample rate', function (done) {
var imageUrl = 'base/tests/assets/test.png';
el.setAttribute('material', '');
assert.notOk(el.components.material.material.texture);
el.setAttribute('material', 'src: url(' + imageUrl + '); anisotropy: 8');
el.addEventListener('materialtextureloaded', function (evt) {
var loadedTexture = evt.detail.texture;
assert.ok(el.components.material.material.map === loadedTexture);
assert.strictEqual(loadedTexture.anisotropy, 8);
done();
});
});
});
});
18 changes: 18 additions & 0 deletions tests/systems/renderer.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ suite('renderer', function () {
assert.strictEqual(rendererSystem.physicallyCorrectLights, false);
assert.strictEqual(rendererSystem.sortObjects, false);
assert.strictEqual(rendererSystem.colorManagement, true);
assert.strictEqual(rendererSystem.anisotropy, 1);

// Verify properties that are transferred from the renderer system to the rendering engine.
var renderingEngine = sceneEl.renderer;
assert.strictEqual(renderingEngine.outputColorSpace, THREE.SRGBColorSpace);
assert.notOk(renderingEngine.sortObjects);
assert.strictEqual(renderingEngine.useLegacyLights, true);
assert.strictEqual(THREE.Texture.DEFAULT_ANISOTROPY, 1);
done();
});
document.body.appendChild(sceneEl);
Expand Down Expand Up @@ -81,6 +83,22 @@ suite('renderer', function () {
document.body.appendChild(sceneEl);
});

test('change renderer anisotropy', function (done) {
var sceneEl = createScene();
sceneEl.setAttribute('renderer', 'anisotropy: 16');
sceneEl.addEventListener('loaded', function () {
var rendererSystem = sceneEl.getAttribute('renderer');
assert.strictEqual(rendererSystem.anisotropy, 16);
assert.strictEqual(THREE.Texture.DEFAULT_ANISOTROPY, 16);

// verify that textures inherit it
var texture = new THREE.Texture();
assert.strictEqual(texture.anisotropy, 16);
done();
});
document.body.appendChild(sceneEl);
});

suite('Set WebXR Frame Rates', function () {
var xrTargetFrameRate;
var xrSession;
Expand Down

0 comments on commit 93b500e

Please sign in to comment.