我正在试图以透视投影的方式将文本渲染为纹理四边形(不想使用正交投影),但在像素对齐方面遇到了困难。
设置很简单,我有一个带有三维对齐锚点的文本,我将其模型变换转换为广告牌变换,并计算比例(三角相似性),使得文本始终保持相同的大小。由于文本四边形的几何结构是使用与像素对应的世界单位构建的,所以无论相机方向或锚点偏移如何,最终的文本看起来确实是相同的大小。
Vector3d dist = camera.getPosition();
dist.sub(translation);
double pxFov = camera.getFOV() / camera.getScreenWidth();
double scale = Math.sin(pxFov) / Math.sin((Math.PI / 2) - pxFov)
* dist.length() * camera.getAspectRatio();
V.getRotationScale(R);
R.transpose();
M.setIdentity();
M.setRotation(R);
M.setScale(scale);
M.setTranslation(translation);
其中V是4x4相机视图矩阵,R是临时的3x3矩阵,M是用于MVP计算的4x4模型变换矩阵。
我找到了所谓的解决方案,但它只是稍微改变了渲染文本的行为,而没有解决问题。
当使用顶点着色器时
void main () {
vec2 view = vec2(1280, 720);
vec4 cpos = MVP * vec4 (position, 1.0f);
vec2 p = floor(cpos.xy * view*0.5/cpos.w);
p += 0.5; // does not influence result
cpos.xy = p * (2.0/view*cpos.w);
gl_Position = cpos;
}
有些地方文本呈现清晰,而有些地方模糊不清
在简单的顶点着色器情况下
void main () {
gl_Position = MVP * vec4 (position, 1.0f);
}
文本是完全模糊还是完全清晰的?
将顶点位置转换为视口空间,进行四舍五入并移回原位似乎是合乎逻辑的,但似乎还缺少一些东西。
编辑:我如何计算比例因子的解释。
在这里,您可以看到我正在以红、绿和蓝线的形式得到直角三角形。通过知道红线(相机-文本锚点距离)的长度、红线和蓝线之间的角度((fov/2)/(屏幕宽度/2)),以及红线和绿线之间的角度为直角,我可以使用正弦定理来计算绿线的长度,这也是一个像素在当前投影中具有相同大小的比例尺。
文本的比例似乎无论相机/文本方向/位置如何都是正确的(期望为8个像素)。可能比例只是稍微偏差了一点,导致了模糊效果,但我不知道原因。
scale
计算应该如何工作。透视除法并不取决于点与相机之间的距离,而是取决于点与包含相机且平行于图像平面(或者换句话说,是在投影的主轴上正交投影距离)的平面之间的距离。对于任何不恰好在该主轴上的点,您的比例因子都应该是错误的。 - derhasslength(pos - camPos)
,因此您用作“相机-文本距离”的内容并不是您在图中绘制的水平距离。此外,您现在引入了一个pxFOV
,将角度与屏幕大小相关联,这根本毫无意义。 - derhass