Opengl 透视投影中的像素完美文本绘制

Opengl 透视投影中的像素完美文本绘制,opengl,glsl,text-rendering,Opengl,Glsl,Text Rendering,我正在尝试在透视投影(不想使用正交投影)中将文本渲染为带纹理的四边形,我正在努力进行像素对齐 设置很简单,我有3D中带有对齐定位点的文本,我将其模型转换为公告牌转换,并计算比例(三角形相似性),使文本始终保持相同大小。由于文本四边形的几何体是用与像素相对应的世界单位构建的,因此无论摄影机方向或定位点偏移如何,生成的文本似乎都是相同的大小 Vector3d dist = camera.getPosition(); dist.sub(translation); double pxFov = cam

我正在尝试在透视投影(不想使用正交投影)中将文本渲染为带纹理的四边形,我正在努力进行像素对齐

设置很简单,我有3D中带有对齐定位点的文本,我将其模型转换为公告牌转换,并计算比例(三角形相似性),使文本始终保持相同大小。由于文本四边形的几何体是用与像素相对应的世界单位构建的,因此无论摄影机方向或定位点偏移如何,生成的文本似乎都是相同的大小

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);
}
文本在某些地方呈现为锐利,在某些地方呈现为模糊

对于简单的顶点着色器

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)),以及红色和绿色之间的角度是直角,我可以使用正弦定律来计算绿线的长度,这也是在当前投影中具有相同大小的一个texel的比例


无论相机/文本方向/位置如何(需要8个像素),文本的比例似乎都是正确的。可能是比例稍有错误,导致了模糊效果,但我看不出是如何产生的。

在我看来,由于数字问题,您正在遭受z缓冲区冲突。 也许您可以为文本z坐标添加一点值,将其与背景稍微分开一点。 另一种解决方案是避免文字比例非比例计算。

您可以通过在CPU端对每个文本进行透视数学计算来计算像素锚定。然后用正交投影显示。

我不知道
比例计算应该如何工作。透视分割不取决于点和相机之间的距离,而是取决于点和包含相机的平面之间的距离,并且平行于图像平面(或者,换句话说,距离在投影主轴上的正交投影)。您的比例因子对于任何不完全在主轴上的点都应该是错误的。@derhass为比例计算添加了更多细节您的解释没有解决我的问题。在图像中,您的文本可以位于任何高度,您可以计算
长度(pos-camPos)
,因此您使用的“相机-文本距离”不是您在图中绘制的水平距离。此外,现在您引入了
pxFOV
,将角度与屏幕大小关联,这根本没有任何意义。它很可能是零意义的,事实是只有亚像素误差是纯粹的机会。正确的解决方案是什么?z值/深度测试与问题中描述的问题有什么关系?我刚刚看了图片并描述了我所看到的。没有z战斗。字体的轮廓和正面在同一纹理中,纹理过滤在最近邻上,所有透明碎片都被丢弃。因为字母之间没有重叠,所以最后绘制的两个片段没有相同的坐标。