texture对象,其实指针就是texture的id。对象的属性,大多数情况,是隐式的随着它texture被激活而显现的。
opentk修改texture属性参数的方法,有两个,GL.TexParameter和GL.TextureParameter。前者是通过texture绑定的target来定位texture,类似这样:
先绑定,后修改参数:
GL.BindTexture(TextureTarget.Texture2D, textureId);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
而后者比较简单:
GL.TexParameter(textureId,TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
读出参数的方法,是把方法名改成带Get的,GL.GetTexParameter和GL.GetTextureParameter ,使用方法类似。
但是这个函数,opengl 4.5以后才有。
一个texture对象,是什么时候才能设置参数呢?或者说,改变参数之后,能够原样取出来。
int textureId=GL.GenTexture();//此时设置参数,是无效的,不会报错,但永远是默认值
GL.BindTexture(TextureTarget.Texture2D, terxtureId); //这个时候,属性就可以设置了,设置多少,取出来就是多少
由此可见,GL.BindTexture之后,opengl实现内部,texture对象才真正被创建。
显然,GL.TexParameter函数,只能对当前激活的texture对象进行操作,很不方便,而GL.TextureParameter,根据textureId选择对象进行操作,逻辑上更加自然合理。但可惜,只有opengl 4.5之后才有。opengl es 2.x,3.x都没有。
这也是opengl设计的缺陷。oo意识并不强。上下文相关的设计,其实用起来是很不方便的,老是切换上下文,也不高效。你想改变一个texture的对象,还得先把它设置为当前激活的texture。
然后,这种上下文相关的设计,是如何定位texture的呢 ?
经检测,是通过两个参数来定位,ActiveTexture和TextureTarget。
如何证明呢,也可以写代码探索。
先用最简单的代码,来创建一个texture,就是省去数据传送这些没用的操作。
int tex = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, tex);
SetTextureAttribute();//对参数进行设置,注意设置的参数值
secondTex = GL.GenTexture();//创建第二个texture,注意,此时默认绑定了TextureUnit.Texture0
GL.BindTexture(TextureTarget.Texture2D, secondTex);//如果此时运行GetTexture的参数观察,会发现参数全部都是默认值了,证明texture对象已经切换到secondTexture了。
GL.BindTexture(TextureTarget.Texture2D, tex);//如果此时运行GetTexture的参数观察,会发现之前设置的参数,又全部恢复了,对象又切换到第一个纹理对象tex了。
GL.BindTexture(TextureTarget.Texture1D, tex);//改变Target,运行GetTexture的参数,没有变化,证明Texture的对象定位,是由texture的id决定的,跟target无关。
GL.ActiveTexture(TextureUnit.Texture7);//此时运行GetTexture的参数观察,又是默认值了。
GL.ActiveTexture(TextureUnit.Texture0);//此时运行GetTexture,发现参数又回到了设置的值
说明opengl的内部逻辑,是用ActiveTexture和纹理对象的id来定位当前的texture的。每一个ActiveTexture都可以绑定一个textureId。
而texture对象的存储,只跟texture的id相关,textureId,就是它的对象指针。opengl的其他对象,其实逻辑也是类似的。所有对象的存储数据,其实都挂在对象的Id下面。