class WebGLSprite {
constructor(text) {
let config = {
uv1: {
us: [0, 5/256, 250/256, 1.0],
vs: [0, 78/128, 126/128, 1.0]
},
uv2: {
us: [0, 0, 1.0, 1.0],
vs: [0, 0, 1.0, 1.0]
},
text:text
};
this.sprite = this.createSprite(config);
}
getUv(uvs) {
let uv = [];
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
uv.push({ u: uvs.us[i], v: uvs.vs[j] });
}
}
let uvs_data = [];
for (let m = 0; m < 3; m++) {
for (let n = 0; n < 3; n++) {
uvs_data.push(uv[4 * m + n].u, uv[4 * m + n].v);
uvs_data.push(uv[4 * (m + 1) + n + 1].u, uv[4 * (m + 1) + n + 1].v);
uvs_data.push(uv[4 * m + n + 1].u, uv[4 * m + n + 1].v);
uvs_data.push(uv[4 * m + n].u, uv[4 * m + n].v);
uvs_data.push(uv[4 * (m + 1) + n].u, uv[4 * (m + 1) + n].v);
uvs_data.push(uv[4 * (m + 1) + n + 1].u, uv[4 * (m + 1) + n + 1].v);
}
}
return uvs_data;
}
getPoints(mesh) {
let vv = [];
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
vv.push({ x: mesh.pointXs[i], y: mesh.pointYs[j], z: 0 });
}
}
let vertices_data = [];
for (let m = 0; m < 3; m++) {
for (let n = 0; n < 3; n++) {
vertices_data.push(vv[4 * m + n].x, vv[4 * m + n].y, vv[4 * m + n].z);
vertices_data.push(vv[4 * (m + 1) + n + 1].x, vv[4 * (m + 1) + n + 1].y, vv[4 * (m + 1) + n + 1].z);
vertices_data.push(vv[4 * m + n + 1].x, vv[4 * m + n + 1].y, vv[4 * m + n + 1].z);
vertices_data.push(vv[4 * m + n].x, vv[4 * m + n].y, vv[4 * m + n].z);
vertices_data.push(vv[4 * (m + 1) + n].x, vv[4 * (m + 1) + n].y, vv[4 * (m + 1) + n].z);
vertices_data.push(vv[4 * (m + 1) + n + 1].x, vv[4 * (m + 1) + n + 1].y, vv[4 * (m + 1) + n + 1].z);
}
}
return vertices_data;
}
createSprite(config) {
let textInfo = this.createText(config.text);
//计算出2^n像素图片
config.mesh = {
pointXs: [-textInfo.width * 0.5 - 10, -textInfo.width * 0.5, textInfo.width * 0.5, textInfo.width * 0.5 + 10],
pointYs: [0, 100, textInfo.height + 100, textInfo.height + 110]
};
let vertices_data = this.getPoints(config.mesh);
let uv1s_data = this.getUv(config.uv1);
let uv2s_data = this.getUv(config.uv2);
var geometry = new THREE.BufferGeometry();
var uv1s = new Float32Array(uv1s_data);
var uv2s = new Float32Array(uv2s_data);
var vertices = new Float32Array(vertices_data);
geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3));
geometry.addAttribute('uv', new THREE.BufferAttribute(uv1s, 2));
geometry.addAttribute('uvtext', new THREE.BufferAttribute(uv2s, 2));
var textureLoader = new THREE.TextureLoader();
this.background = textureLoader.load('../content/terrain/label/test5.png');
let sprite = new THREE.Mesh(geometry, new THREE.ShaderMaterial({
uniforms: {
uPos: { value: new THREE.Vector3(0) },
uSize: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },
uSizeAttenuation: { value: 0 },
uColor: { value: new THREE.Vector4(0.2, 0.8, 0.2, 1) },
uMap: { value: this.background },
uText: { value: textInfo.texture },
//transparent: true,
alphaTest: 0.5,
},
vertexShader: `
in vec2 uvtext;
uniform vec3 uPos;
uniform vec2 uSize;
uniform int uSizeAttenuation;
varying vec2 vUv;
varying vec2 vUv2;
void main() {
vUv = uv;
vUv2 = uvtext;
vec4 mvPosition = modelViewMatrix * vec4( uPos, 1.0 );
vec4 screenpos = projectionMatrix * mvPosition;
if(uSizeAttenuation == 1){
vec3 v = vec3(position.x, position.y, 0);
screenpos += vec4(v, 0);
} else {
vec3 v = vec3(position.x / uSize.x, position.y / uSize.y, 0);
screenpos += vec4(v * screenpos.w, 0);
}
gl_Position = screenpos;
}`,
fragmentShader: `
uniform vec4 uColor;
uniform sampler2D uMap;
uniform sampler2D uText;
varying vec2 vUv;
varying vec2 vUv2;
void main() {
vec4 color = texture2D( uMap, vUv);// * uColor;
vec4 color2 = texture2D( uText, vUv2);// * uColor;
if(color.a < 0.2)
discard;
else
gl_FragColor = vec4(color.rgb, 1.0 - color2.a) + color2;
}`
}));
sprite.onBeforeRender = function (renderer) {
var size = renderer.getDrawingBufferSize(new THREE.Vector2());
this.material.uniforms.uSize.value = size;
};
//mesh.receiveShadow = false;
//mesh.castShadow = false;
return sprite;
}
createText(text) {
var canvas = document.createElement('canvas');
canvas.style.background = 'rgba(255, 255, 255, 0)';
var context = canvas.getContext('2d');
let fontsize = 32;
let fontface = 'Arial';
let width = 0;
let height = 0;
context.font = fontsize + "px " + fontface;
text.forEach(item => {
var metrics = context.measureText(item);
if (width < metrics.width)
width = metrics.width;
height += fontsize;
});
canvas.width = width + 8;
canvas.height = height + 8;
// text color
context.fillStyle = "rgba(0, 255, 0, 1.0)";
context.font = fontsize + "px " + fontface;
for (let i = 0; i < text.length; i++) {
context.fillText(text[i], 2, fontsize * (i + 1));
}
let texture = new THREE.Texture(canvas);
texture.needsUpdate = true;
return {
texture: texture,
width: canvas.width,
height: canvas.height
}
}
get() {
return this.sprite;
}
update(position) {
}
}