OpenGL - 渲染带纹理的茶壶 - .obj面孔和法线

时间:2015-05-17 21:46:48

标签: python opengl texturing

我的 .obj 文件只有 v f 参数。

我有一个任务,通过将它“封闭”在一个长方体(由每个轴上的最大和最小顶点定义),计算其中心,然后将茶壶顶点的空间坐标与中心坐标分开,以便将其纹理化。我得到的矢量在茶壶的中心有一个开头,在它的表面有一个末端,然后找到这些向量(光线)与外长方体表面相交的位置。长方体的每个面都必须模拟图像。之后,我必须计算每个顶点的纹理坐标 - 只需从3D交叉点获取2D参数,然后对结果进行标准化,使它们介于0和1之间(二维)。

所以,我用一些正确的代码行打开.obj文件,然后我进行所有描述的计算以找到vt参数,然后使用一个函数,允许我使用一个索引顶点列表来获取NORMALS三角形(面部属性)和顶点列表。

它看起来像(它实际上由两个不同的文件组成):

1)

def getNormals4Triangles(self):

    tind = np.resize(self.indx,(len(self.indx)/3,3))
    return VOB.getNormals(self.arrs[0],tind)

其中self.arrs [0]是从.obj获取的v属性列表,tind是3个构成面的顶点元素列表的列表。

2)

@staticmethod
def getNormals(verts,tinds):
    print("Shape verts: ",verts.shape)
    print("Shape tinds: ",tinds.shape)

    if len(verts[0])==3:
        xyz = verts
    elif len(verts[0])==4:
        xyz = verts[:,:3]/np.outer(1/verts[:,3],[1,1,1])
    else:
        raise Exception('No cross product defined')
    txyz = xyz[tinds,:]
    txy = txyz[:,2,:]-txyz[:,0,:]
    txz = txyz[:,1,:]-txyz[:,0,:]
    nrmls = np.cross(txy,txz)
    len_nrmls = norm(nrmls,axis=1)
    return nrmls/np.outer(len_nrmls,[1,1,1])

其中“norm”是线性代数NumPy集的函数。

之后我创建了一个VOB对象:

self.vob = VOB(arrs = [vert, point, normals],indx=self.obj.indx)

简而言之,我使用VOB对象将其发送到GPU。

vert - 从.obj获取的顶点列表 point - 以上述方式计算的纹理坐标列表 法线 - 使用上述函数计算的法线向量列表 self.obj.indx - 由.obj

的f属性组成的列表

我使用的纹理图像:texture

当我尝试使用经典的装饰来展示它时:

gl.glShadeModel( gl.GL_SMOOTH )
gl.glEnable( gl.GL_LIGHTING )
gl.glEnable( gl.GL_LIGHT0 )
gl.glLightModeli( gl.GL_LIGHT_MODEL_TWO_SIDE, 0 )
gl.glLightfv( gl.GL_LIGHT0, gl.GL_POSITION, [4, 4, 4, 1] )
lA = 0.8
gl.glLightfv( gl.GL_LIGHT0, gl.GL_AMBIENT, [lA, lA, lA, 1] )
lD = 1
gl.glLightfv( gl.GL_LIGHT0, gl.GL_DIFFUSE, [lD, lD, lD, 1] )
lS = 1
gl.glLightfv( gl.GL_LIGHT0, gl.GL_SPECULAR, [lS, lS, lS, 1] )
gl.glMaterialfv( gl.GL_FRONT_AND_BACK, gl.GL_AMBIENT, [0.9, 0.8, 0.7, 1] )
gl.glMaterialfv( gl.GL_FRONT_AND_BACK, gl.GL_DIFFUSE, [0.7, 0.8, 0.9, 1] )
gl.glMaterialfv( gl.GL_FRONT_AND_BACK, gl.GL_SPECULAR, [0.9, 0.9, 0.9, 1] )
gl.glMaterialf( gl.GL_FRONT_AND_BACK, gl.GL_SHININESS, 100 )

我可以看到这样的事情: normal lighting

但是当我使用Blinn和Phong着色模型时(我会避免将其全部粘贴,希望可能有人遇到过类似的问题)它是这样的:blinn i phong

为什么在这两种情况下都不能看到质地很好的茶壶? 在获得法线和vt坐标后,我是否必须准备要发送到VOB的新f属性?

1 个答案:

答案 0 :(得分:0)

您的面顶点的缠绕方向可能不一致,导致某些法线指向内部,弄乱了您的光照计算。理想情况下,模型文件中的数据具有正确定向的面,但您可以从播种面开始重新定向面并从那里开始工作。此问题已在此处介绍:How to unify normal orientation

快速解决方法是实现双面照明模式;实际上,如果基元面向… * !gl_FrontFacing ? -1 : 1,则在否定为正值之前,否定照明点积的结果。

关于纹理坐标生成:从技术上讲,您可以实现立方体贴图纹理坐标贴图,该贴图使用一个图片用于立方体的所有6个面,并使用顶点位置作为纹理坐标。或者您只需将相同的图像加载到立方体贴图的6个子图像中,并将position属性直接用作纹理查找的坐标。