OpenGL是非常特定于机器的
OpenGL being very machine specific
最近我开始在C++中使用OpenGL进行一些3D渲染,但奇怪的是,它似乎只适用于少数机器。我使用的是OpenGL 3.0或更高版本(目前设置为3.0),使用的是顶点数组对象(不确定其调用方式,但API版本删除了glBegin、glEnd等)。
在另一台机器上测试之前,我总是询问他们的GPU驱动程序,他们中的大多数都支持OpenGL 4.2,如果不支持,我会确保他们至少支持3.0。然而,在一些机器上,我的应用程序只是崩溃,或者什么都不渲染,OpenGL不会抛出任何错误(我每帧至少检查一次错误)。不过,它在我自己的机器上运行得很好,在某些情况下,我的机器甚至比一些不工作的机器还要旧。
我开始只使用OpenGL本身和GLEW,但为了易于使用和其他一些我喜欢的功能,我改用了SFML和GLEW,OpenGL本身并没有改变它的行为。我在某个时候重写了我正在使用的引擎,以封装所有GL调用并合并顶点数组对象和其他一些功能,事实上,我可以为您提供应用程序使用的所有API调用的列表。显然,它并没有在测试应用程序中使用所有这些,但这些都是我在引擎中使用的所有调用(这是能够渲染的最低限度,所以是的,引擎甚至还没有完成):
- glAttachShader
- glBindAttribLocation
- glBindBuffer
- glBindVertexArray
- glBufferData
- glBufferSubData
- glClear
- glClearColor
- glClearDepth
- glCompileShader
- glCreateProgram
- glCreateShader
- glCullFace
- glDeleteBuffers
- glDeleteProgram
- glDeleteShader
- glDeleteVertexArrays
- glDepthFunc
- glDepthMask
- glDepthRange
- glDisableVertexAttribArray
- glDrawElements
- glEnable
- glEnableVertexAttribArray
- gl正面
- glGenBuffers
- glGenVertexArrays
- glGetAttribLocation
- glGetBufferParameteriv
- glGetBufferSubData
- glGetError
- glGetIntegev
- glGetProgramInfoLog
- glGetProgramiv
- glGetShaderInfoLog
- glGetShaderiv
- glGetShaderSource
- glGetUniformLocation
- glIs程序
- glIsShader
- glLink程序
- glMapBufferRange
- glPixelStorei
- glShaderSource
- glUniform(1i、1ui、1f、2f、3f、4f、Matrix3fv、Matrix4fv)
- glUnmapBuffer
- glUseProgram
- glVertexAttrib(1i,1ui,1f,2f,3f,4f)
- glVertexAttribPointer
简而言之,着色器和着色器程序部分没有什么特别的,我有一些方法来创建/编译它们,预先设置一些属性位置,最后设置属性/统一。缓冲区对象也没有什么特别的,你可以写、读和映射缓冲区,目前我只使用GL_ARRAY_buffer和GL_ELEMENT_ARRAY.buffer。最后,我使用顶点数组对象来实际渲染对象,显然我设置了属性指针,并封装了绘图调用和程序使用,它总是使用索引绘图。
此外,我在谷歌和堆栈溢出本身上进行了广泛的搜索,以寻找答案。但所有的问题都与OpenGL无法在任何地方工作有关,例如,一些API调用没有按顺序调用或根本没有调用。遗憾的是,这些答案都不适用于我,它一直在我自己的机器和我可以直接访问的其他机器上运行,但当我将应用程序发送给其他人在他们的机器上测试时,它从未运行过。
希望这是足够具体的XD
编辑,从下方的帖子复制
每个测试都在windowsvista或7上完成。我对每个API调用都进行了OpenGL错误检查,似乎没有发现任何错误。我无法在自己的机器上复制它,但在其他机器上进行了更多的跟踪后,我发现它在渲染之前不会崩溃。该设置运行良好,它创建的所有缓冲区和对象都非常好,但一旦我尝试渲染网格(VAO),它就会崩溃,没有任何错误(除了.exe已经停止工作)。我怀疑命令glUseProgram或glDrawElements
关于一个例子,除非你想搜索大约10个类,否则我不能给你一个简短的例子
EDIT,渲染对象的微小代码
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;
对于每个"draw"调用,它都会返回一个字符串,以便网格类可以绑定相应的材质。
//-----------------------------------------------------------------------
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();
}
EDIT,网格调用所有上述方法来实际渲染对象
lockVertexAttributes()只是确保所有属性指针都绑定到正确的顶点缓冲区。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绑定GL_ELEMENT_ARRAY_BUFFER
。
过去(几年前),我在某些版本的NVidia驱动程序上遇到过这样的问题(但我没有任何版本的记录),这纯粹是导致应用程序崩溃。
我当时的解决方法是依靠VAO来设置GL_ARRAY_BUFFER
绑定和顶点属性指针,但我明确地在glBindVertexArray
之后重新定义了GL_ELEMENT_ARRAY_BUFFER
绑定。
我认为问题现在已经解决了,但周围的一些老司机可能会表现出这个问题。
你能看到有问题的平台的配置模式吗?
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 如何在本地机器上运行c++和javascript客户端代码(hackerbank风格)
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 64位机器上的C++内存对齐
- 使用不同的链接器会产生不同的机器代码吗
- 我写了一个C++程序来模拟Enigma机器.我没有得到输出
- 如何将经过训练的机器学习模型保存在python中并将其加载到C++中进行预测?
- C++ 两台不同机器之间通过wifi进行套接字通信
- 使用 ssh 重新连接到远程 Ubuntu 机器后,如何继续使用 gdb 调试 c++ 代码?
- 代码厨师 2019 年 12 月午餐时间愚蠢的机器
- CMake:尝试在 Jenkins 构建机器上运行时出现"Linked Library"错误 (0xc0000135)
- objdump 不显示机器代码,但显示 ASM
- 不同机器之间的标准时钟性能差异显著
- 如何使用Messenger示例连接两台机器
- 如何在拆分为多个文件的分层 SM 中退出子机器?(使用boost::MSM)
- 如果C++依赖于机器,那么用C++编写的软件如何在不同的计算机上工作
- OpenGL是非常特定于机器的
- 依赖于机器架构意味着什么
- 为Mac生成特定于机器的密钥
- 如何知道TCP连接是否存在于同一机器上的两个进程之间