我必须用投影机从计算机上显示的图像映射一个物理立方体。我立即意识到使用3D多维数据集和相机投影来尝试将虚拟图像拟合到真实对象上的问题,因此我决定简化该问题并使用多维数据集的2D表示并在2D空间中移动每个顶点直到它适合物体为止。该软件现已完成,除了一些细节:纹理。
我使用的是LWJGL,我的数据结构基于其文档中的一些示例。
我使用了7个顶点来表示2D空间中真实立方体的3个可见面,这将创建3个梯形(或不规则四边形)覆盖每个面,我将它们映射为您在此图像中看到的ST(或UV)坐标,请记住这一切都是二维的:
这是一个代码块,我在其中将顶点数据加载到缓冲区中,并将它们全部以XYZWRGBASTPQ的顺序保存到VBO中(请注意,Z始终为0,默认情况下PQ为0,1):
vertices = new VertexData[7];
vertices[0] = new VertexData().setXY(0, 0).setST(0.5f, 0.5f);
vertices[1] = new VertexData().setXY(0.5f, 1f/3).setST(0.5f, 0);
vertices[2] = new VertexData().setXY(0, 2f/3).setST(0, 0);
vertices[3] = new VertexData().setXY(-0.5f, 1f/3).setST(0, 0.5f);
vertices[4] = new VertexData().setXY(-0.5f, -1f/3).setST(0, 1);
vertices[5] = new VertexData().setXY(0, -2f/3).setST(0.5f, 1);
vertices[6] = new VertexData().setXY(0.5f, -1f/3).setST(1, 1);
0是六边形的中心,从右上角开始逆时针从1-6开始,绘制为三角形扇形。
当梯形仍为平行四边形时,一切都很好,这是另一个纹理测试:
但是问题是,当边不相等时,纹理投影在三角形上,因此当尝试投影纹理时,它看起来不像预期的那样:
我读了很多关于这个主题的文章,其中一些是:
到目前为止,没有什么让我接近解决问题的,我所知道的是与纹理的Q坐标有关。
我的顶点着色器是最低要求:
#version 150 core
in vec4 in_color;
in vec4 in_position;
in vec4 in_texture;
out vec4 pass_color;
out vec4 pass_texture;
void main(void) {
pass_color = in_color;
pass_texture = in_texture;
gl_Position = in_position;
}
而且我的片段着色器真的很简单,现在我正在使用textureProj,因为我试图摆弄Q坐标。
#version 330 core
in vec4 pass_color;
in vec4 pass_texture;
out vec4 color;
uniform sampler2D texture_diffuse;
void main(void) {
color = pass_color;
color = textureProj(texture_diffuse, pass_texture);
}
我愿意发布每段代码,以备您需要。我只需要向正确的方向推进即可。
因此,在潜入互联网后,我偶然发现了一个解决方案,不幸的是,我对三角形风扇进行UV绘制的方式与该风扇不兼容,因此我不得不将我的三角形风扇转换成由三个三角形组成的一组,每个三角形由两个三角形组成,我通过在面之间复制共享顶点来做到这一点:
VertexData[] vertices = new VertexData[12];
int i = 0;
for(VertexData vert : oldVertices){
vertices[i++] = new VertexData(vert);
}
vertices[7] = new VertexData(vertices[1]);
vertices[7].setST(1, 0.5f);
vertices[8] = new VertexData(vertices[0]);
vertices[9] = new VertexData(vertices[3]);
vertices[10] = new VertexData(vertices[0]);
vertices[11] = new VertexData(vertices[5]);
int[][] faces = {
{0, 1, 2, 3},
{4, 11, 10, 9},
{6, 7, 8, 5}
};
if(qMapping) TextureUtils.qMapFaces(vertices, faces);
有了这些信息,我现在可以使用BitLush的算法,该算法基本上根据每个面的对角线的差来计算Q坐标插值:
public static void qMapFaces(VertexData[] vertices, int[][] faces){
for(int[] face : faces){
VertexData[] verts = new VertexData[4];
int j = 0;
for(int i : face){
verts[j++] = vertices[i];
}
float ax = verts[2].getXYZ()[0] - verts[0].getXYZ()[0];
float ay = verts[2].getXYZ()[1] - verts[0].getXYZ()[1];
float bx = verts[3].getXYZ()[0] - verts[1].getXYZ()[0];
float by = verts[3].getXYZ()[1] - verts[1].getXYZ()[1];
float cross = ax * by - ay * bx;
if(cross != 0) {
float cx = verts[0].getXYZ()[0] - verts[1].getXYZ()[0];
float cy = verts[0].getXYZ()[1] - verts[1].getXYZ()[1];
float s = (ax * cy - ay * cx) / cross;
if(s > 0 && s < 1){
float t = (bx * cy - by * cx) / cross;
if(t > 0 && t < 1){
float[] qi = new float[4];
qi[0] = 1 / (1 - t);
qi[1] = 1 / (1 - s);
qi[2] = 1 / t;
qi[3] = 1 / s;
int q = 0;
for(VertexData vertex : verts){
float[] stpq = vertex.getSTPQ();
vertex.setSTPQ(stpq[0] * qi[q], stpq[1] * qi[q], 0, qi[q]);
q++;
}
}
}
}
}
}
在对Q坐标进行插值后,投影效果得到了很大改善,但是由于无法同时控制两个面的插值,因此纹理在边缘的对齐方式不太好。这对我的项目来说不是问题,但是如果有人找到解决方案,请与我联系!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句