为WebGL应用程序动态创建签名距离场图像

时间:2017-02-20 03:26:00

标签: javascript html5 html5-canvas webgl

我为这个长期问题提前道歉。

我正在研究HTML5中的“CAD”程序,需要在屏幕上绘制数千(700,000+)个图像。我认为,“幸运的是”许多图像被复制使用了一组独特的图像。独特的集合比它们的实例少许多个数量级。我正在使用的一个例子是拥有360,000个360独特图像的实例。这些图像实际上是在程序第一次加载时动态生成的,它们是矩形,图像的“名称”以矩形的中间为中心(矩形中没有颜色等,只是一个带有文本的矩形轮廓)中间,文字和矩形轮廓是黑色的)。该程序应该能够以许多放大级别显示图像,当然,还要足够快以使其有用。

第一个实现适用于加载的SVG图像。由于图像的矢量方面,它在所有放大倍率下都能很好地工作。但是在大约70,000左右的实例后,程序开始耗尽内存。我假设因为DOM无法跟上这么多实例。

经过大量的学习和实验,我能够使用WebGL实现该程序的工作版本。它工作得很好,速度很快。我知道我将不得不实现我从SVG免费获得的所有有趣的东西,比如CSS颜色,听众,DOM中的单个元素等等,但无论如何我都没有使用过很多东西。

到目前为止,我已经能够实现一个系统,该系统可以使用带有1个纹理的形状图集渲染矩形子集的许多不同实例,然后使用将纹理坐标传递给像素着色器的标准技术渲染。除了在地图集形状中心的琴弦在所有放大倍数下看起来都不太好之外,这个工作正常。为了使程序最有用,我需要能够清楚地显示字符串。生成矩形地图集形成一个画布2d,即使在高分辨率下,字符串作为地图集矩形的一部分,虽然非常简单,但在所有放大倍数下似乎都不能很好地渲染。我自己研究生成字符串地图集,这很好,但在我看来,我应该能够创建一个图像图集,它可以在包括文本在内的合理数量的放大率下很好地显示,并且可能保存一堆独特的绘制使用签名距离字段生成文本的调用。

这是我撞墙的地方。我找到了一些参考这篇论文的地方 - > Improved Alpha-Tested Magnification for Vector Textures and Special Effects。这似乎正是我要找的。我认为我独特的一组矩形文本对作为“贴花”,如上文所述。在我的情况下,我会让我所有的独特实例生成一个低分辨率SDF版本(64x64)的高分辨率版本(2048x2048)的实例,然后更改我的片段着色器,以便能够以此处概述的任何分辨率进行渲染 - &gt ; Drawing Text with Signed Distance Fields in Mapbox GL。但是,我没有找到任何显示如何从高分辨率图像生成较低分辨率版本SDF的地方。

我的问题如下:

  1. 如何使用画布和JavaScript生成动态生成的高分辨率图像(2048x2048)的低分辨率SDF版本(64x64),以便创建要在片段着色器中使用的纹理?理想情况下,只需在程序开始时生成一次。

  2. 我是否正确地思考他?文本注定必须使用SDF字体图集单独绘制吗?

1 个答案:

答案 0 :(得分:1)

您可以将高分辨率图像写入低分辨率渲染目标,并使用片段着色器处理图像,该片段着色器将高分辨率图像转换为距离场。我在LibGDX的文档中找到了一个距离场转换器,您可以尝试从Java转换为GLSL。

你需要记住你想要在距离场中渲染的内容之间的填充。

从那里你可以设置gl状态机来将距离场渲染到渲染目标。

// Bind the current Frame Buffer for this setup
gl.bindFrameBuffer(gl.FRAMEBUFFER, sdfFrameBuffer);

// Use the signedDistanceConversion program
gl.useProgram(signedDistanceConverter);

// Pass the texture as a uniform
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, largeFontTex);

// Generate a simple quad VBO/IBO

gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);

// Store that frame buffer and use it later.

然后你只需要生成一个顶点缓冲区,每个字符的UV位置映射到每个四边形,并使用片段着色器处理它,{1.}}是从该纹理读取的距离:

smoothstep

参考