我理解如何将纹理贴图应用于多边形。
但是,是否可以在运行时创建字符串的纹理(如每秒显示的当前帧数)并将其映射到多边形?
更新
这可能会奏效。我必须为自己测试一下。 Drawing text as textures on squares does not show anything
答案 0 :(得分:2)
使用2D画布API
可以轻松地在运行时创建纹理var gl = someCavnasInThePage.getContext("webgl");
// create an offscreen canvas with a 2D canvas context
var ctx = document.createElement("canvas").getContext("2d");
// make it a desired size
ctx.canvas.width = 128;
ctx.canvas.height = 64;
// fill it a certain color
ctx.fillStyle = "rgb(255,0,0)"; // red
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
// draw some text into it.
ctx.fillStyle = "rgb(255,255,0)"; // yellow
ctx.font = "20px sans-serif";
ctx.fillText("Hello World", 5, 40);
// Now make a texture from it
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, ctx.canvas);
// generate mipmaps or set filtering
gl.generateMipmap(gl.TEXTURE_2D);
这是一个有效的例子
var m4 = twgl.m4;
var gl = twgl.getWebGLContext(document.getElementById("c"));
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);
var arrays = {
position: [1, 1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1],
normal: [1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1],
texcoord: [1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1],
indices: [0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23],
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);
var tex = createTextTexture(gl, "Hello World", 256, 128);
gl.bindTexture(gl.TEXTURE_2D, tex);
function render(time) {
time *= 0.001;
twgl.resizeCanvasToDisplaySize(gl.canvas);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.enable(gl.DEPTH_TEST);
var fieldOfView = Math.PI * 0.25;
var aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
var projection = m4.perspective(fieldOfView, aspect, 0.0001, 500);
var radius = 5;
var eye = [
Math.sin(time) * radius,
2,
Math.cos(time) * radius];
var target = [0, 0, 0];
var up = [0, 1, 0];
var camera = m4.lookAt(eye, target, up);
var view = m4.inverse(camera);
var worldViewProjection = m4.multiply(view, projection);
var uniforms = {
u_worldViewProjection: worldViewProjection,
};
gl.useProgram(programInfo.program);
twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
twgl.setUniforms(programInfo, uniforms);
gl.drawElements(gl.TRIANGLES, bufferInfo.numElements, gl.UNSIGNED_SHORT, 0);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
var ctxForMakingTextures;
function createTextTexture(gl, str, width, height) {
// create an offscreen canvas with a 2D canvas context
if (!ctxForMakingTextures) {
ctxForMakingTextures = document.createElement("canvas").getContext("2d");
}
var ctx = ctxForMakingTextures;
// make it a desired size
ctx.canvas.width = width;
ctx.canvas.height = height;
// fill it a certain color
ctx.fillStyle = "rgb(255,0,0)"; // red
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
// draw some text into it.
ctx.fillStyle = "rgb(255,255,0)"; // yellow
ctx.font = "40px sans-serif";
ctx.fillText("Hello World", 5, 40);
// Now make a texture from it
var tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, ctx.canvas);
// generate mipmaps or set filtering
gl.generateMipmap(gl.TEXTURE_2D);
return tex;
};

html, body, canvas {
width: 100%;
height: 100%;
margin: 0;
}

<script src="https://twgljs.org/dist/twgl-full.min.js"></script>
<script id="vs" type="not-js">
attribute vec4 position;
attribute vec2 texcoord;
varying vec2 v_texcoord;
uniform mat4 u_worldViewProjection;
void main() {
gl_Position = u_worldViewProjection * position;
v_texcoord = texcoord;
}
</script>
<!-- fragment shader -->
<script id="fs" type="not-js">
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D u_texture;
void main() {
gl_FragColor = texture2D(u_texture, v_texcoord);
}
</script>
<canvas id="c"></canvas>
&#13;
答案 1 :(得分:0)
如果我理解正确,您正尝试使用OpenGL在3D中显示文本。以下是您应该考虑的几个选项:
使用要显示的文本创建常规矩形纹理,并在简单的4顶点矩形上进行渲染。这是最简单的实现,但它需要为要显示的每个字符串生成不同的纹理。
如上所述,创建一个矩形纹理,但这一次,为您希望能够支持的每个字母/字符创建一个。然后,构建一个工厂,为某个字符串中的每个字母生成4个顶点矩形,为每个形状选择合适的字母。你需要做一些好的定位,但这会给你一个相当灵活的解决方案。
与#2类似,但这一次,使用一些无缝纹理,但为您希望支持的每个字母/字符生成形状。每个形状将包含多个顶点,除非您使用外部图形资源,否则可能需要一些时间才能完成。但是,这个实现将为您提供最令人印象深刻的显示文本的方法,因为每个字母在空间中显示为三维对象。