我正在为一个名为 Autodesk MotionBuilder 的应用程序编写一个插件,该应用程序有一个 OpenGL 渲染器,并且我正在尝试将纹理几何体渲染到场景中。我有一个嵌入了 3D 视图的窗口,每次渲染我的窗口时,这就是(简而言之)发生的情况:
- 我告诉渲染器我将要绘制到一个给定大小的区域
- 我告诉渲染器在该区域绘制 MotionBuilder 场景
- 我在场景中和/或顶部画了一些额外的东西
这里的挑战是我从 MotionBuilder 的渲染器继承了一些任意的 OpenGL 状态,这取决于它正在绘制什么以及场景中存在什么。到目前为止,我一直在处理这个问题,但有一件事我无法弄清楚。OpenGL 解释我的 UV 坐标的方式似乎会根据 MotionBuilder 在我背后所做的事情而改变。
这是我的渲染代码。如果场景中没有纹理几何体,这意味着 MotionBuilder 尚未处理任何与纹理相关的属性,它会按预期工作。
// Tell MotionBuilder's renderer to draw the scene
RenderScene();
// Clear whatever arbitrary state MotionBuilder left for us
InitializeAttributes(); // includes glPushAttrib(GL_ALL_ATTRIB_BITS)
InitializePerspective(); // projects into the scene / loads matrices
// Enable texturing, bind to our texture, and draw a triangle into the scene
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, mTexture);
glBegin(GL_TRIANGLES);
glColor4f(1.0, 1.0, 1.0, 0.5f);
glTexCoord2f(1.0, 0.0); glVertex3f(128.0, 0.0, 0.0);
glTexCoord2f(0.0, 1.0); glVertex3f( 0.0, 128.0, 0.0);
glTexCoord2f(0.0, 0.0); glVertex3f( 0.0, 0.0, 0.0);
glEnd();
// Clean up so we don't confound MotionBuilder's initial expectations
RestoreState(); // includes glPopAttrib()
现在,如果我引入一些带有纹理的网格,就会发生一些奇怪的事情。我的纹理坐标被放大了。这是之前和之后:
(来源:awforsythe.com)
从右侧的特写可以看出,当 MotionBuilder 被要求渲染其文件找不到的纹理时,它会加载这个小问号纹理并将其平铺在几何体上。我唯一的假设是 MotionBuilder 正在更改一些全局纹理坐标标量,例如,glTexCoord2f(0.5, 1.0) 将被解释为 (50.0, 100.0)。OpenGL中有这样的功能吗?知道我需要修改什么以保留我输入的纹理坐标吗?
自从输入上述内容并进行了一些研究后,我发现有一个用于此效果的 GL_TEXTURE 矩阵。整洁的!事实上,当我最初得到这个矩阵的值时,它是好的 ol' 单位矩阵:
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1
当我在 MotionBuilder 捏造我的纹理坐标后再次检查它时:
16 0 0 0
0 16 0 0
0 0 1 0
0 0 0 1
多有话说!但这里有一个小问题:如果我在自己绘制之前尝试显式设置纹理矩阵,无论 MotionBuilder 在做什么,似乎我的纹理坐标都没有效果,它只是对纹理的左下角进行采样( 0.0, 0.0) 对于每个顶点。
这是尝试的修复,位于RenderScene
上面发布的代码之后:
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
我可以验证 GL_TEXTURE_MATRIX 的值现在是单位矩阵,但无论我在 glTexCoord2f 中指定什么坐标,它总是像每个顶点的坐标是 (0.0, 0.0) 一样绘制:
(来源:awforsythe.com)
知道还有什么会影响 OpenGL 如何解释我的纹理坐标吗?