当您在3D地图编辑器(如Valve的Hammer Editor)中创建画笔时,默认情况下会重复对象的纹理并将其与世界坐标对齐。
如何使用OpenGL实现此功能?
可以用glTexGen实现这个目标吗?
或者我必须以某种方式使用纹理矩阵?
如果我创建3x3盒子,那么很容易: 将GL_TEXTURE_WRAP_T设置为GL_REPEAT 将纹理线设置为边缘处的3,3。
但是如果对象不是轴对齐的凸包,它会变得有点复杂。
基本上我想从Valve Hammer创建面部编辑表的功能:
答案 0 :(得分:2)
从技术上讲,您可以使用纹理坐标生成。但我建议使用顶点着色器,从变换后的顶点坐标生成纹理坐标。更具体一点(我不太了解Hammer)。
看完视频后,我理解你的困惑。我想你应该知道,Hammer / Source可能没有绘图API生成纹理坐标,但是在内部生成它们。
所以你可以看到有些纹理投射在X,Y或Z平面上,这取决于面指向的主要方向。然后它使用局部顶点坐标作为纹理坐标。
您可以在将模型加载到顶点缓冲区对象的代码中实现此功能(更高效,因为计算只进行一次),或者在GLSL顶点着色器中实现。我会给你伪代码:
cross(v1, v2):
return { x = v1.y * v2.z - v1.z * v2.y,
y = v2.x * v1.z - v2.z * v1.x, // <- "swapped" order!
z = v1.x * v2.y - v1.y * v2.x }
normal(face):
return cross(face.position[1] - face.position[0], face.position[2] - face.position[0])
foreach face in geometry:
n = normal(face) // you'd normally precompute the normals and store them
if abs(n.x) > max(abs(n.y), abs(n.z)): // X major axis, project to YZ plane
foreach (i, pos) in enumerate(face.position):
face.texcoord[i] = { s = pos.y, t = pos.z }
if abs(n.y) > max(abs(n.x), abs(n.z)): // Y major axis, project to XZ plane
foreach (i, pos) in enumerate(face.position):
face.texcoord[i] = { s = pos.x, t = pos.z }
if abs(n.z) > max(abs(n.y), abs(n.x)): // Z major axis, project to XY plane
foreach (i, pos) in enumerate(face.position):
face.texcoord[i] = { s = pos.x, t = pos.y }
要使用glTexGen纹理坐标生成来完成此工作,您必须将模型拆分为每个主轴的部分。 glTexGen所做的只是映射步骤face.texcoord[i] = { s = pos.<>, t = pos.<> }
。在顶点着色器中,您可以直接进行分支。