c – 如何使可移植和编译器无关的glBufferData?
This question询问是否可以依赖编译器来处理结构值的顺序和填充.
根据这个问题的答案,
那可能但不总是存在填充可能真的搞砸了,最糟糕的部分 – 它取决于编译器. 为了避免错误和恶梦,使用编译器无关的方法不是更好吗? 例如: class BufferData { private: GLfloat data[12]; public: GLfloat* getCameraPosition() { return (GLfloat*) &data[0]; } GLfloat* getLightPosition() { return (GLfloat*) &data[4]; } GLfloat* getLightDiffuse() { return (GLfloat*) &data[8]; } GLfloat* getData() { return data; } }; 与天真相反: struct BufferData { GLfloat camera_position[4]; GLfloat light_position[4]; GLfloat light_diffuse[4]; }; 或者天真的方法是否足够好? (假设类/结构不仅仅是那个,而且可能会改变) 解决方法
“编译器无关”?没有这样的动物.你试图写一个证明了它.考虑您的struct成员定义:
GLfloat data[12]; 这需要存在GLfloat类型.但问题是,C没有定义那种类型. OpenGL呢. OpenGL非常清楚地定义了这种类型:它是一个IEEE-754 floating-point type,using the BINARY32 format. 问题是,C不要求浮点符合那个.实际上,C并不要求任何类型符合这一点.如果编译器希望浮点数使用IEEE-754之外的其他东西,那就没问题了. 现在,您可以说OpenGL头可以将GLfloat定义为类型,大小为32位,将从编译器的float类型转换为IEEE-754.当然,这可能发生……除非没有办法获得32位值. 有些系统有9位字节.或18位字节.这些系统有C编译器.此类系统不能声明大小仅为32位的类型. 但能够传递32位值(更不用说16位和8位)是OpenGL的一项硬性要求.没有它,您将无法在缓冲区对象中传递任何数据.然而,C并不需要它. 说到顶点数据,半现代OpenGL中最基本的功能之一是glVertexAttribPointer.它依赖于你将一个字节偏移量转换为void *,然后它将被转换回来. C不保证这是有效的.在C标准中没有任何地方要求如果你将一个整数转换为指针,然后将该指针强制转换为整数,你将得到相同的整数(它确实说ptr-> int-> ptr工作,但这并不意味着相反). 然而OpenGL需要它.除非您使用单独的属性缓冲区(和I strongly suggest you do if it’s available),否则您的代码和您调用的OpenGL代码将依赖于此未定义的行为. OpenGL将GLint定义为带符号,二进制补码,32位整数.但是C不需要任何整数类型作为二进制补码. 但OpenGL确实如此. OpenGL flat out无法在类型不同的系统上运行.它不能在具有9位字节的系统上运行.它不能在使用有符号整数数学补码的系统上运行.我可以坚持下去,但我认为我的观点很明确. 通过选择使用OpenGL(Vulkan,如果你想知道),你已经依赖于实现定义的行为.那么,当您已经依赖于大量其他实现定义的行为时,为什么还要让您的生活更难以避免这些特定的实现定义行为? 这匹马离开了谷仓;现在关门没有帮助. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |