2011-08-25 100 views
1

当您在三维地图编辑器(例如Valve的Hammer Editor)中创建画笔时,对象的纹理默认重复并与世界坐标对齐。如何在OpenGL中实现世界坐标对齐的重复纹理映射?

如何使用OpenGL实现此功能?

glTexGen可以用来实现这个吗?

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

如果我创建3×3盒,那么它很简单: 设置GL_TEXTURE_WRAP_T在边缘GL_REPEAT 设置texturecoords到3,3。

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

基本上我想从阀门锤面对创建编辑页面的功能:

Valve Hammer Face Edit tool

回答

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

+0

问题是:如何在openGL中实现世界坐标对齐的重复纹理映射? Valve Hammer只是一个例子(见:http://www.youtube.com/watch?v = 8R4aWvRQP-E) – JBeurer

+0

这可以工作,我会试试这个。我尝试寻找脸部平面的正交基向量,然后在脸部上投影脸部顶点。 s = Vector.Dot(basis1,vertex); t = Vector.Dot(basis2,vertex);这种方法中的问题是该平面可以具有围绕平面法线旋转的多个正交基矢量。而且我不知道如何获得飞机基础矢量与原点有什么不同。 – JBeurer