如何在OpenGL中实现世界坐标对齐的重复纹理映射?

时间:2011-08-25 23:41:45

标签: opengl textures texture-mapping

当您在3D地图编辑器(如Valve的Hammer Editor)中创建画笔时,默认情况下会重复对象的纹理并将其与世界坐标对齐。

如何使用OpenGL实现此功能?

可以用glTexGen实现这个目标吗?

或者我必须以某种方式使用纹理矩阵?

如果我创建3x3盒子,那么很容易: 将GL_TEXTURE_WRAP_T设置为GL_REPEAT 将纹理线设置为边缘处的3,3。

但是如果对象不是轴对齐的凸包,它会变得有点复杂。

基本上我想从Valve Hammer创建面部编辑表的功能:

Valve Hammer Face Edit tool

1 个答案:

答案 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.<> }。在顶点着色器中,您可以直接进行分支。