最近,我开始在C++中使用OpenGL进行一些3D渲染,但奇怪的是,它似乎只能在少数机器上工作。我使用的是OpenGL 3.0或更高版本(目前将其设置为3.0),并且使用了顶点数组对象(不确定如何调用它,但是删除了glBegin,glEnd等的API版本)。
在另一台机器上测试之前,我总是要求他们的GPU驱动程序,其中大多数都支持OpenGL 4.2,如果没有,请确保它们至少支持3.0。但是在某些机器上,我的应用程序只是崩溃了,或者什么都不渲染,OpenGL不会抛出任何错误(我每帧至少检查一次错误)。但是,它在我自己的计算机上可以正常工作,在某些情况下,我的计算机甚至比某些无法运行的计算机还要旧。
我开始只使用OpenGL本身和GLEW,但是为了易于使用和我喜欢的其他一些功能而切换到SFML和GLEW,但是OpenGL本身并没有改变其行为。我确实重写了我正在使用的引擎,以封装所有GL调用,并合并顶点数组对象和其他一些功能,实际上,我可以为您提供应用程序使用的所有API调用的列表。显然,它并没有在测试应用程序中使用所有这些,但是这些都是我在引擎中使用的所有调用(这是能够渲染的最低要求,因此,引擎甚至还没完成):
简而言之,Shader和ShaderProgram部分没什么特别的,我有一些方法可以创建/编译它们,预先设置一些属性位置,最后设置属性/制服。缓冲区对象也没有什么特别的,您可以编写,读取和映射缓冲区,目前我仅使用GL_ARRAY_BUFFER和GL_ELEMENT_ARRAY_BUFFER。最后,我使用顶点数组对象实际渲染对象,显然我设置了属性指针,并封装了绘制调用和程序用法,它始终使用索引绘制。
此外,我在google和堆栈溢出本身上进行了广泛的搜索,以寻求答案。但是所有问题都与OpenGL在任何地方都无法使用有关,例如有些API调用没有按顺序调用或根本没有调用。遗憾的是,这些答案都不对我有用,它一直在我自己的机器上和我可以直接访问的其他机器上工作,但是当我将应用程序发送给其他人在他们的机器上对其进行测试时,它从未起作用。
希望这足够具体XD
编辑,从下面的帖子向下复制
每个测试都在Windows Vista或Windows 7上完成。我已经对每个API调用进行了OpenGL错误检查,似乎没有一个错误。我无法在自己的机器上复制它,但是在其他机器上进行了更多跟踪之后,我发现直到渲染后它才崩溃。安装程序工作正常,它创建的所有缓冲区和对象都非常好,但是,一旦我尝试渲染网格(VAO),它就会崩溃而没有任何错误(除了.exe已停止工作以外)。我怀疑命令glUseProgram或glDrawElements
关于一个示例,除非您想搜索大约10个类别,否则我无法给您提供简短示例
编辑,一小段代码呈现对象
Mesh类将这些结构添加到对象中,因此它知道要绘制什么:
// Define Geometry (draw command)
struct Geometry
{
// Primitives
PrimitiveType primitiveType;
// Indices
IndexType indexType;
unsigned int count; // elements
unsigned int offset; // bytes
};
哦,顺便说一句,“几何标签”只是一个字符串,可以在其下多次输入多个绘制调用,定义如下:
// Define a list of primitives
typedef std::vector<Geometry> GeometryList;
// Define Geometry ordered by tag
typedef std::map<const std::string, GeometryList> GeometryMap;
对于每个“绘制”调用,它都会返回一个字符串,以便网格类可以绑定(bind)适当的 Material 。
//-----------------------------------------------------------------------
const std::string HardwareObject::nextGeometryTag()
{
// Loop back
GeometryMap::const_iterator end = _geometry.end();
if(_activeGeometry == end)
{
// Bind and go to begin
glBindVertexArray(_GL_VertexArray);
_activeGeometry = _geometry.begin();
}
// Check if new tag exists
else if(++_activeGeometry == end)
{
// Unbind and return empty tag
glBindVertexArray(0);
return "";
}
return _activeGeometry->first;
}
//-----------------------------------------------------------------------
bool HardwareObject::drawGeometryTag() const
{
// Validate current tag
if(_activeGeometry == _geometry.end()) return false;
// Draw each geometry call of tag
for(GeometryList::const_iterator it = _activeGeometry->second.begin(); it != _activeGeometry->second.end(); ++it)
glDrawElements(it->primitiveType, it->count, it->indexType, (void*)it->offset);
// GL Error
return !Console::GET().getError("HardwareObject Drawing");
}
//-----------------------------------------------------------------------
void HardwareObject::resetGeometryTag()
{
_activeGeometry = _geometry.end();
}
编辑,调用上述所有方法的网格实际渲染对象
lockVertexAttributes()仅确保所有属性指针都绑定(bind)到正确的顶点缓冲区。 HardwareProgram的bind方法无非是检查程序是否已编译并调用glUseProgram
//-----------------------------------------------------------------------
bool Mesh::render()
{
// Lock vertex attributes
if(!lockVertexAttributes()) return false;
// To avoid errors
_object.resetGeometryTag();
// Loop while there's a tag
for(std::string tag = _object.nextGeometryTag(); tag != ""; tag = _object.nextGeometryTag())
{
// Find material
MaterialMap::const_iterator it = _materials.find(tag);
if(it == _materials.end()) continue;
// Bind material (get program directly)
const HardwareProgram *prog = it->second->getProgram();
if(!prog) continue;
if(!prog->bind()) continue;
// Draw tag
_object.drawGeometryTag();
}
// Ok!
return true;
}
最佳答案
我敢打赌,您是通过VAO绑定(bind)GL_ELEMENT_ARRAY_BUFFER
。
过去(几年前),我在某些版本的NVidia驱动程序上遇到了问题(尽管我没有任何版本的记录),这纯粹使应用程序崩溃了。
我当时的解决方法是依靠VAO设置GL_ARRAY_BUFFER
绑定(bind)和顶点attrib指针,但是我明确地在GL_ELEMENT_ARRAY_BUFFER
之后重新定义了glBindVertexArray
绑定(bind)。
我认为问题已解决,但是周围的一些老司机可能会遇到问题。
您能看到有问题的平台的配置模式吗?