我有一个绘制球体的webGL代码,我在旁边添加了文本标签。 我正在做的是创建2D矩形,然后使用我的文本应用纹理。
function createCubeTexture(text) {
var canvas = document.createElement('canvas');
canvas.id = "hiddenCanvas";
canvas.width = 512;
canvas.height = 128;
canvas.style.display = "none";
var body = document.getElementsByTagName("body")[0];
body.appendChild(canvas);
var cubeImage = document.getElementById('hiddenCanvas');
var ctx = cubeImage.getContext('2d');
ctx.beginPath();
ctx.rect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.fillStyle = 'rgba(255,255,255,0)';
ctx.fill();
ctx.fillStyle = 'black';
ctx.font = "65px Arial";
ctx.textAlign = 'center';
ctx.fillText(text, ctx.canvas.width / 2, ctx.canvas.height / 2);
ctx.restore();
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_NEAREST);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
handleTextureLoaded(cubeImage, texture)
return texture;
}
但我正在寻找的是完全透明的纹理。我想要没有bgcolor的文本。 我可以使用alpha并获得“透明”颜色,但我的矩形永远不会透明(如果alpha = 0然后它是白色的),我从未设法通过矩形看到球体。
任何想法
由于
答案 0 :(得分:4)
为了使用alpha = 0进行绘制,您需要在画布2d中使用不同的globalCompositeOperation
。在rgba(255,255,255,0)
上方的代码中,globalCompositingOperation
的默认source-over
基本上就是这样做
dest = dest * (1 - alpha) + source * alpha
由于alpha为0表示它没有任何内容,因此您的第一个fill
调用什么都没有。
而是将alpha设置为1,但使用'ctx.globalCompositeOperation =“destination-out”for the fill, then set back to
source-over`作为文本。
看到这个问题 How do you draw with alpha = 0 in an html5 canvas to 'erase'
实际上,在您的情况下,只需删除填充。画布元素开始完全透明。要将画布清除回透明调用ctx.clearRect
。
以下是从另一个示例中复制的代码段:
var gl;
function initGL(canvas) {
try {
gl = canvas.getContext("webgl");
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
} catch (e) {
}
if (!gl) {
alert("Could not initialise WebGL, sorry :-(");
}
}
function getShader(gl, id) {
var shaderScript = document.getElementById(id);
if (!shaderScript) {
return null;
}
str = shaderScript.text;
var shader;
if (shaderScript.type == "x-shader/x-fragment") {
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
} else {
return null;
}
gl.shaderSource(shader, str);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
var shaderProgram;
function initShaders() {
var fragmentShader = getShader(gl, "shader-fs");
var vertexShader = getShader(gl, "shader-vs");
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}
gl.useProgram(shaderProgram);
// This is a bad code.
// If the context is lsot shaderProgram will be null
// and trying to assign a vertexPositionAttribute to null
// will throw an exception.
// better would be
// shaderProgram = {};
// shaderProgram.program = gl.createProgram();
// shaderProgram.vertexPositionAtrribute = ...
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
shaderProgram.textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord");
gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute);
shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");
shaderProgram.samplerUniform = gl.getUniformLocation(shaderProgram, "uSampler");
}
var texturen = new Array();
function initTexture(text,texturen)
{
var anz = texturen.length;
texturen[anz] = gl.createTexture();
// this is a bad code. on context lost gl.createTexture() will return null and
// an exception will be thrown when you try to attach .image to null
// Better would be
// texturen[anz] = {};
// texturen[anz].texture = gl.createTexture();
// texturen[anz].image = new Image();
var c = document.createElement("canvas");
c.width = 256;
c.height = 256;
var ctx = c.getContext("2d");
//ctx.fillStyle = "rgba(0, 0, 0, 1)";
//ctx.globalCompositeOperation = "destination-out";
//ctx.fillRect(0, 0, 64, 64);
//ctx.globalCompositeOperation = "source-over";
ctx.fillStyle = "rgb(255, 128, 64)";
ctx.font = "40px Arial";
ctx.fillText(text, 128 - 64, 128);
gl.bindTexture(gl.TEXTURE_2D, texturen[anz]);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, c);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
}
var mvMatrix = mat4.create();
var mvMatrixStack = [];
var pMatrix = mat4.create();
function mvPushMatrix() {
var copy = mat4.create();
mat4.set(mvMatrix, copy);
mvMatrixStack.push(copy);
}
function mvPopMatrix() {
if (mvMatrixStack.length == 0) {
throw "Invalid popMatrix!";
}
mvMatrix = mvMatrixStack.pop();
}
function setMatrixUniforms() {
gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, pMatrix);
gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, mvMatrix);
}
function degToRad(degrees) {
return degrees * Math.PI / 180;
}
function initBuffers() {
vertBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
var vertices = [
// Front face
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// Back face
-1.0, -1.0, -1.0,
-1.0, 1.0, -1.0,
1.0, 1.0, -1.0,
1.0, -1.0, -1.0,
// Top face
-1.0, 1.0, -1.0,
-1.0, 1.0, 1.0,
1.0, 1.0, 1.0,
1.0, 1.0, -1.0,
// Bottom face
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, -1.0, 1.0,
-1.0, -1.0, 1.0,
// Right face
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
1.0, 1.0, 1.0,
1.0, -1.0, 1.0,
// Left face
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0,
-1.0, 1.0, 1.0,
-1.0, 1.0, -1.0,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
// This is bad code. See the above examples of bad code.
// vertBuffer will be null on context lost and this code
// will throw an exception.
vertBuffer.itemSize = 3;
vertBuffer.numItems = 24;
CoordBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,CoordBuffer);
var textureCoords = [
// Front face
1.0, 0.0,
0.0, 0.0,
0.0, 1.0,
1.0, 1.0,
// Back face
0.0, 0.0,
0.0, 1.0,
1.0, 1.0,
1.0, 0.0,
// Top face
1.0, 1.0,
1.0, 0.0,
0.0, 0.0,
0.0, 1.0,
// Bottom face
0.0, 1.0,
1.0, 1.0,
1.0, 0.0,
0.0, 0.0,
// Right face
0.0, 0.0,
0.0, 1.0,
1.0, 1.0,
1.0, 0.0,
// Left face
1.0, 0.0,
0.0, 0.0,
0.0, 1.0,
1.0, 1.0,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
CoordBuffer.itemSize = 2;
CoordBuffer.numItems = 24;
IndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, IndexBuffer);
var Indices = [
0, 1, 2, 0, 2, 3, // Front face
4, 5, 6, 4, 6, 7, // Back face
8, 9, 10, 8, 10, 11, // Top face
12, 13, 14, 12, 14, 15, // Bottom face
16, 17, 18, 16, 18, 19, // Right face
20, 21, 22, 20, 22, 23 // Left face
];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(Indices), gl.STATIC_DRAW);
IndexBuffer.itemSize = 1;
IndexBuffer.numItems = 36;
}
var xRot = 0;
var yRot = 0;
var zRot = 0;
function drawScene() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
mat4.perspective(pMatrix, 45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0);
mat4.identity(mvMatrix);
mat4.translate(mvMatrix, mvMatrix, [0.0, 0.0, -5.0]);
mat4.rotate(mvMatrix, mvMatrix, degToRad(xRot), [1, 0, 0]);
mat4.rotate(mvMatrix, mvMatrix, degToRad(yRot), [0, 1, 0]);
mat4.rotate(mvMatrix, mvMatrix, degToRad(zRot), [0, 0, 0]);
setMatrixUniforms();
gl.bindBuffer(gl.ARRAY_BUFFER, vertBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,vertBuffer.itemSize,
gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, CoordBuffer);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute,CoordBuffer.itemSize,
gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, IndexBuffer);
// Draw face 0
gl.bindTexture(gl.TEXTURE_2D, texturen[0]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
// Draw face 1
gl.bindTexture(gl.TEXTURE_2D, texturen[1]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 12);
// Draw face 2
gl.bindTexture(gl.TEXTURE_2D, texturen[2]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 24);
// Draw face 3
gl.bindTexture(gl.TEXTURE_2D, texturen[3]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 36);
// Draw face 4
gl.bindTexture(gl.TEXTURE_2D, texturen[4]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 48);
// Draw face 5
gl.bindTexture(gl.TEXTURE_2D, texturen[5]);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 60);
}
var lastTime = 0;
function animate() {
var timeNow = new Date().getTime();
if (lastTime != 0) {
var elapsed = timeNow - lastTime;
xRot += (90 * elapsed) / 1000.0;
yRot += (90 * elapsed) / 1000.0;
zRot += (90 * elapsed) / 1000.0;
}
lastTime = timeNow;
}
function tick() {
requestAnimationFrame(tick);
drawScene();
animate();
}
function webGLStart() {
var canvas = document.getElementById("lesson05-canvas");
initGL(canvas);
initShaders();
initBuffers();
initTexture("face 0",texturen);
initTexture("face 1",texturen);
initTexture("face 2",texturen);
initTexture("face 3",texturen);
initTexture("face 4",texturen);
initTexture("face 5",texturen);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
tick();
}
webGLStart();
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.3.2/gl-matrix-min.js"></script>
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec2 vTextureCoord;
uniform sampler2D uSampler;
void main(void) {
gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
}
</script>
<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;
attribute vec2 aTextureCoord;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
varying vec2 vTextureCoord;
void main(void) {
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
vTextureCoord = aTextureCoord;
}
</script>
<canvas id="lesson05-canvas" style="border: none;" width="500" height="500"> </canvas>