Skip to content

Commit

Permalink
rename modifiedsdf shader to sdf, and allow registered shaders;
Browse files Browse the repository at this point in the history
remove old Jam3 shaders since they weren't being used

fix geometryComponent use before assignment from cleanup

update documentation

add unit tests for multiple and text autoscale

a little more on text geometry interaction
  • Loading branch information
machenmusik committed Jan 27, 2017
1 parent 4dc96e3 commit 1896ee0
Show file tree
Hide file tree
Showing 7 changed files with 266 additions and 143 deletions.
257 changes: 205 additions & 52 deletions docs/components/text.md

Large diffs are not rendered by default.

26 changes: 13 additions & 13 deletions examples/test/text/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,29 @@

<!-- Animations. -->
<a-entity id="opacity" position="-2.5 0.7 0"
text="color: white; align: center; value: Animate opacity; width: 1.5">
text="color: white; align: center; value: Animating opacity; width: 1.5">
</a-entity>
<a-entity mixin="marker" position="0 0.7 0.01"></a-entity>
<a-entity id="color" position="0 0.7 0"
text="color: white; align: center; value: Animate color; width: 1.5">
text="color: white; align: center; value: Animating color; width: 1.5">
</a-entity>
<a-entity mixin="marker" position="2.5 0.7 0.01"></a-entity>
<a-entity id="size" position="2.5 0.7 0"
text="color: white; align: center; value: Animate size; width: 1.5">
text="color: white; align: center; value: Animating size; width: 1.5">
</a-entity>

<!-- Anchors. -->
<a-entity mixin="marker" position="-2.5 1 0.01"></a-entity>
<a-entity position="-2.5 1 0"
text="font: kelsonsans; anchor: left; width: 1.5; color: white; value: (left anchor) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut enim ad minim veniam">
text="font: kelsonsans; anchor: left; width: 1.5; color: white; value: [LEFT ANCHOR] Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut enim ad minim veniam">
</a-entity>
<a-entity mixin="marker" position="0 1 0.01"></a-entity>
<a-entity position="0 1 0"
text="font: kelsonsans; anchor: center; width: 1.5; color: white; value: (center anchor) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut enim ad minim veniam">
text="font: kelsonsans; anchor: center; width: 1.5; color: white; value: [CENTER ANCHOR] Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut enim ad minim veniam">
</a-entity>
<a-entity mixin="marker" position="2.5 1 0.01"></a-entity>
<a-entity position="2.5 1 0"
text="font: kelsonsans; anchor: right; width: 1.5; color: white; value: (right anchor) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut enim ad minim veniam">
text="font: kelsonsans; anchor: right; width: 1.5; color: white; value: [RIGHT ANCHOR] Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut enim ad minim veniam">
</a-entity>

<!-- Spacing. -->
Expand All @@ -51,22 +51,22 @@

<a-entity mixin="marker" position="-1 2 0.01"></a-entity>
<a-entity position="-1 2 0"
text="width: 2; lineHeight: 50; letterSpacing: 5; color: white; value: (line and letter spacing) Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut enim ad minim veniam">
text="width: 2; lineHeight: 50; letterSpacing: 5; color: white; value: [LINE AND LETTER SPACING] Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut enim ad minim veniam">
</a-entity>

<!-- Alignments. -->
<a-entity position="2 2 0">
<a-entity mixin="marker" position="0 0 0.01"></a-entity>
<a-entity position="0 0 0" geometry="primitive: plane; width:auto; height:auto" material="color: #333"
text="color: yellow; align: left; value: left aligned; width: 2; ">
<a-entity position="0 0 0" geometry="primitive: plane; width: auto; height: auto" material="color: #333"
text="color: yellow; align: left; value: [LEFT ALIGNED]; width: 2; ">
</a-entity>
<a-entity mixin="marker" position="0 0.2 0.01"></a-entity>
<a-entity position="0 0.2 0" geometry="primitive: plane; width:auto; height:auto" material="color: #333"
text="color: red; align: right; value: right aligned; width: 2; ">
<a-entity position="0 0.2 0" geometry="primitive: plane; width: auto; height: auto" material="color: #333"
text="color: red; align: right; value: [RIGHT ALIGNED]; width: 2; ">
</a-entity>
<a-entity mixin="marker" position="0 0.4 0.01"></a-entity>
<a-entity position="0 0.4 0" geometry="primitive: plane; width:auto; height:auto" material="color: #eee"
text="color: blue; align: center; value: center aligned; width: 2; ">
<a-entity position="0 0.4 0" geometry="primitive: plane; width: auto; height: auto" material="color: #eee"
text="color: blue; align: center; value: [CENTER ALIGNED]; width: 2; ">
</a-entity>
</a-entity>

Expand Down
2 changes: 1 addition & 1 deletion examples/test/text/scenarios.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<a-mixin
id="marker"
geometry="primitive: box"
material="shader: flat; opacity: 0.5"
material="color: magenta; shader: flat; opacity: 0.5"
scale="0.01 0.01 0.01"
></a-mixin>
</a-assets>
Expand Down
49 changes: 14 additions & 35 deletions src/components/text.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
var createTextGeometry = require('three-bmfont-text');
var loadBMFont = require('load-bmfont');
var path = require('path');
var createBasic = require('three-bmfont-text/shaders/basic');
var createMSDF = require('three-bmfont-text/shaders/msdf');
var createSDF = require('three-bmfont-text/shaders/sdf');

var registerComponent = require('../core/component').registerComponent;
var coreShader = require('../core/shader');
Expand Down Expand Up @@ -41,10 +38,7 @@ var fontWidthFactors = {};
* SDF-based text component.
* Based on https://github.com/Jam3/three-bmfont-text.
*
* Comes with several shaders:
* All the stock fonts are for `sdf` and `modifiedsdf`. We added `modifiedsdf` shader to
* improve jam3's original `sdf` shader. `msdf` and `basic` are available for the fonts that
* use those.
* All the stock fonts are for the `sdf` registered shader, an improved version of jam3's original `sdf` shader.
*/
module.exports.Component = registerComponent('text', {
multiple: true,
Expand All @@ -65,7 +59,7 @@ module.exports.Component = registerComponent('text', {
// `lineHeight` defaults to font's `lineHeight` value.
lineHeight: {type: 'number'},
opacity: {type: 'number', default: '1.0'},
shader: {default: 'modifiedsdf', oneOf: ['modifiedsdf', 'sdf', 'basic', 'msdf']},
shader: {default: 'sdf', oneOf: shaders},
side: {default: 'front', oneOf: ['front', 'back', 'double']},
tabSize: {default: 4},
transparent: {default: true},
Expand Down Expand Up @@ -141,7 +135,7 @@ module.exports.Component = registerComponent('text', {
createOrUpdateMaterial: function (oldShader) {
var data = this.data;
var hasChangedShader;
var ModifiedSDFShader;
var NewShader;
var material = this.material;
var shaderData;

Expand All @@ -157,33 +151,18 @@ module.exports.Component = registerComponent('text', {

// Shader has not changed, do an update.
if (!hasChangedShader) {
if (data.shader === 'modifiedsdf') {
// Update modifiedsdf shader material.
this.shaderObject.update(shaderData);
// Apparently, was not set on `init` nor `update`.
material.transparent = shaderData.transparent;
} else {
// Update other shader materials.
material.uniforms.opacity.value = data.opacity;
material.uniforms.color.value.set(data.color);
material.uniforms.map.value = this.texture;
}
// Update shader material.
this.shaderObject.update(shaderData);
// Apparently, was not set on `init` nor `update`.
material.transparent = shaderData.transparent;
updateBaseMaterial(material, shaderData);
return;
}

// Shader has changed. Create a shader material.
if (data.shader === 'modifiedsdf') {
ModifiedSDFShader = createModifiedSDFShader(this.el, shaderData);
this.material = ModifiedSDFShader.material;
this.shaderObject = ModifiedSDFShader.shader;
} else if (data.shader === 'sdf') {
this.material = new THREE.RawShaderMaterial(createSDF(shaderData));
} else if (data.shader === 'msdf') {
this.material = new THREE.RawShaderMaterial(createMSDF(shaderData));
} else {
this.material = new THREE.RawShaderMaterial(createBasic(shaderData));
}
NewShader = createShader(this.el, data.shader, shaderData);
this.material = NewShader.material;
this.shaderObject = NewShader.shader;

// Set new shader material.
updateBaseMaterial(this.material, shaderData);
Expand Down Expand Up @@ -255,7 +234,7 @@ module.exports.Component = registerComponent('text', {
var baseline;
var el = this.el;
var geometry = this.geometry;
var geometryComponent;
var geometryComponent = el.getAttribute('geometry');
var height;
var layout = geometry.layout;
var mesh = this.mesh;
Expand All @@ -266,6 +245,7 @@ module.exports.Component = registerComponent('text', {
var y;

// Determine width to use (defined width, geometry's width, or default width).
geometryComponent = el.getAttribute('geometry');
width = data.width || (geometryComponent && geometryComponent.width) || DEFAULT_WIDTH;

// Determine wrap pixel count. Either specified or by experimental fudge factor.
Expand All @@ -279,7 +259,6 @@ module.exports.Component = registerComponent('text', {

// Update geometry dimensions to match text layout if width and height are set to 0.
// For example, scales a plane to fit text.
geometryComponent = el.getAttribute('geometry');
if (geometryComponent) {
if (!geometryComponent.width) { el.setAttribute('geometry', 'width', width); }
if (!geometryComponent.height) { el.setAttribute('geometry', 'height', height); }
Expand Down Expand Up @@ -398,12 +377,12 @@ function loadTexture (src) {
});
}

function createModifiedSDFShader (el, data) {
function createShader (el, shaderName, data) {
var shader;
var shaderObject;

// Set up Shader.
shaderObject = new shaders.modifiedsdf.Shader();
shaderObject = new shaders[shaderName].Shader();
shaderObject.el = el;
shaderObject.init(data);
shaderObject.update(data);
Expand Down
2 changes: 1 addition & 1 deletion src/shaders/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
require('./flat');
require('./standard');
require('./modifiedsdf');
require('./sdf');
2 changes: 1 addition & 1 deletion src/shaders/modifiedsdf.js → src/shaders/sdf.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ var registerShader = require('../core/shader').registerShader;
/**
* Used by text component.
*/
module.exports.Shader = registerShader('modifiedsdf', {
module.exports.Shader = registerShader('sdf', {
schema: {
alphaTest: {type: 'number', is: 'uniform', default: 0.5},
color: {type: 'color', is: 'uniform', default: 'white'},
Expand Down
71 changes: 31 additions & 40 deletions tests/components/text.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ suite('text', function () {
});

el = entityFactory();
el.addEventListener('componentinitialized', function (evt) {

this.doneCalled = false;
el.addEventListener('componentinitialized', evt => {
if (this.doneCalled) { return; }
if (evt.detail.name !== 'text') { return; }
component = el.components.text;
this.doneCalled = true;
done();
});
el.setAttribute('text', '');
Expand All @@ -32,6 +36,18 @@ suite('text', function () {
});
});

suite('multiple', function () {
test('can have multiple instances', function () {
el.setAttribute('text__foo', {value: 'foo'});
el.setAttribute('text__bar', {value: 'bar'});
el.setAttribute('text__baz', {value: 'baz'});
assert.ok(el.getObject3D('text') instanceof THREE.Mesh);
assert.ok(el.getObject3D('text__foo') instanceof THREE.Mesh);
assert.ok(el.getObject3D('text__bar') instanceof THREE.Mesh);
assert.ok(el.getObject3D('text__baz') instanceof THREE.Mesh);
});
});

suite('update', function () {
test('updates geometry with value', function (done) {
// There are two paths by which geometry update can happen:
Expand Down Expand Up @@ -82,17 +98,17 @@ suite('text', function () {

test('calls createOrUpdateMaterial if shader changes', function () {
var updateMaterialSpy = this.sinon.spy(component, 'createOrUpdateMaterial');
el.setAttribute('text', 'shader', 'sdf');
el.setAttribute('text', 'shader', 'standard');
assert.shallowDeepEqual(updateMaterialSpy.getCalls()[0].args[0],
{shader: 'modifiedsdf'});
el.setAttribute('text', 'shader', 'msdf');
assert.shallowDeepEqual(updateMaterialSpy.getCalls()[1].args[0],
{shader: 'sdf'});
el.setAttribute('text', 'shader', 'sdf');
assert.shallowDeepEqual(updateMaterialSpy.getCalls()[1].args[0],
{shader: 'standard'});
});
});

suite('createOrUpdateMaterial', function () {
suite('modifiedsdf', function () {
suite('sdf', function () {
test('updates material color', function () {
var value;
value = el.getObject3D('text').material.uniforms.color.value;
Expand Down Expand Up @@ -120,39 +136,6 @@ suite('text', function () {
assert.equal(value, THREE.DoubleSide);
});
});

suite('msdf', function () {
setup(function () {
el.setAttribute('text', 'shader', 'msdf');
});

test('updates material color', function () {
var value;
value = el.getObject3D('text').material.uniforms.color.value;
assert.equal(new THREE.Color(value.r, value.g, value.b).getHexString(), 'ffffff');
el.setAttribute('text', 'color', '#123456');
value = el.getObject3D('text').material.uniforms.color.value;
assert.equal(new THREE.Color(value.r, value.g, value.b).getHexString(), '123456');
});

test('updates material opacity', function () {
var value;
value = el.getObject3D('text').material.uniforms.opacity.value;
assert.equal(value, 1);
el.setAttribute('text', 'opacity', '0.55');
value = el.getObject3D('text').material.uniforms.opacity.value;
assert.equal(value, 0.55);
});

test('updates material side', function () {
var value;
value = el.getObject3D('text').material.side;
assert.equal(value, THREE.FrontSide);
el.setAttribute('text', 'side', 'double');
value = el.getObject3D('text').material.side;
assert.equal(value, THREE.DoubleSide);
});
});
});

suite('updateFont', function () {
Expand Down Expand Up @@ -229,7 +212,7 @@ suite('text', function () {
assert.notEqual(el.getObject3D('text').scale.z, 1);
});

test('autoscales mesh', function () {
test('autoscales mesh to text', function () {
el.setAttribute('geometry', {primitive: 'plane', height: 0, width: 0});
assert.equal(el.getAttribute('geometry').width, 0);
assert.equal(el.getAttribute('geometry').height, 0);
Expand All @@ -238,6 +221,14 @@ suite('text', function () {
assert.equal(el.getAttribute('geometry').width, 10);
assert.ok(el.getAttribute('geometry').height);
});

test('autoscales text to mesh', function () {
el.setAttribute('geometry', {primitive: 'plane', height: 1, width: 50000});
el.setAttribute('text', {value: 'a', width: 0});
assert.ok(el.getObject3D('text').scale.x > 10);
assert.ok(el.getObject3D('text').scale.y < 10);
assert.ok(el.getObject3D('text').scale.z > 10);
});
});

suite('remove', function () {
Expand Down

0 comments on commit 1896ee0

Please sign in to comment.