OpenGL-加载顶点数据时glBufferData()上的SegFault
OpenGL - SegFault on glBufferData() while loading vertex data
问题:glBufferData上的分段错误。
关于libs&输入数据:
3ds file contains a few models.
GLEW - 1.11.0
GLFW - 3.0.4
GLM - 0.9.5.4
ASSIMP - 3.1.1
OS - Windows 7 x64 lastest PS
GPU: nvidia 770
输出:
Wersja OpenGL: 4.4.0
Kompilacja shadera...
Compiling shader : vert.vs
- Success
Compiling shader : frag.fs
- Success
Ustawianie Model - Widok - Projekcja...
Wczytywanie wczeťniej wygenerowanych obiektˇw...
Ladowanie Mesha nr.0...
Rozmiary - 2 | 108 | 108
a
b
c
这是代码:
网格加载器.cpp
GLfloat **vertexData, **normalData, **colorsData_buffer;
GLushort** indexData;
/** Bufory */
GLuint* vertexBuffer, *colorBuffer, *indexBuffer;
int mesh_size = 0;
unsigned int* count_of_vertex; //Licznik ile vertex-ów na danym meshie jest
int* count_of_index; //Licznik indeksów
unsigned int suma_vertexow = 0; //Suma wszystkich vertexow... normalnie się powinno to inaczej obejść. Ale kij.
const struct aiFace* tmp_face;
int tmp_index = 0;
//[...]
bool mesh_load(const std::string& Filename)
{
Assimp::Importer Importer;
const aiScene* pScene = Importer.ReadFile(Filename.c_str(), aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_FlipUVs);
/** Sprawdzenie czy wczytał scene */
if (pScene) {
init_from_scene(pScene);
return true;
}
else
{
std::cout << "Wystąpił błąd podczas wczytywania: " << Importer.GetErrorString() << std::endl;
return false;
}
}
void pre_reserve_memory(const aiMesh* paiMesh, int cur_poz)
{
count_of_index[cur_poz] = 0;
for (unsigned int i = 0; i < paiMesh->mNumFaces; i++) {
tmp_face = &paiMesh->mFaces[i];
count_of_index[cur_poz] += tmp_face->mNumIndices;
}
indexData[cur_poz] = new GLushort[count_of_index[cur_poz]];
}
void init_from_scene(const aiScene* pScene)
{
mesh_size = pScene->mNumMeshes;
//Pre Rezerwacja miejsca
vertexData = new GLfloat*[mesh_size];
colorsData_buffer = new GLfloat*[mesh_size];
normalData = new GLfloat*[mesh_size];
indexData = new GLushort*[mesh_size];
//Buffory
vertexBuffer = new GLuint[mesh_size];
colorBuffer = new GLuint[mesh_size];
indexBuffer = new GLuint[mesh_size];
count_of_vertex = new unsigned int[mesh_size];
count_of_index = new int[mesh_size];
for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
{
pre_reserve_memory(pScene->mMeshes[i], i);
// [...]
przepare_mesh(pScene->mMeshes[i], vertexData[i], colorsData_buffer[i], normalData[i], indexData[i], &count_of_vertex[i]);
}
}
void przepare_mesh(const aiMesh* paiMesh, GLfloat* vertexData, GLfloat* colorsData_buffer, GLfloat* normalData, GLushort* indexData, unsigned int* count_of_vertex)
{
int counter;
vertexData = (GLfloat *)&paiMesh->mVertices;
colorsData_buffer = (GLfloat *)&paiMesh->mColors;
normalData = (GLfloat *)&paiMesh->mNormals;
*count_of_vertex = paiMesh->mNumVertices;
for (unsigned int i = 0; i < paiMesh->mNumFaces; i++) {
tmp_face = &paiMesh->mFaces[i];
for (unsigned int j = 0; j < tmp_face->mNumIndices; j++)
{
counter = i + j;
indexData[counter] = tmp_face->mIndices[j];
}
}
}
/** TODO: RE-LIGHTING, MOUSE */
void render_scene()
{
glLinkProgram(program); // jak skompilowalem kod to moge go polaczyc z bibliotekami - linkowanie
glUseProgram(program); // od tego momentu wszystko co zrobie bedzie uzywac tego programu (tej kombinacji shaderow)
glClearColor(0.0f, 0.0f, 0.4f, 0.0f); // ustala kolor wyczyszczonego okna
glEnable(GL_CULL_FACE); // wewnetrzne flagi opengl
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/** Model - View - Projection */
glm::mat4 Model = glm::mat4(1.0f); // tworzenie macierzy obiektu
glm::mat4 View = glm::lookAt(glm::vec3(0.0f, 2.0f, -5.0f), glm::vec3(), glm::vec3(0.0f, 1.0f, 0.0f)); // widoku
glm::mat4 Projection = glm::perspective(60.0f, 16.0f / 9.0f, 0.1f, 1000.0f); // projekcji
glm::mat4 MVP; // zmienna na pozniej
GLuint MVPUniformLoc = glGetUniformLocation(program, "MVP"); // daje wskaznik gdzie MVP znajduje sie w pamieci
/** Addresy Pamięci */
GLuint positionAttribLoc = glGetAttribLocation(program, "position"); // wytlumaczenie cpu jak sie dostac do adresu pamieci gpu
GLuint colorAttribLoc = glGetAttribLocation(program, "color");
/** tworzenie tablicy przechowujacej vertexy */
GLuint vertexArrayObject;
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
for (int i = 0; i < mesh_size; i++)
{
suma_vertexow += count_of_vertex[i];
glGenBuffers(1, &vertexBuffer[i]);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[i]);
glBufferData(GL_ARRAY_BUFFER, (sizeof(GLfloat)* count_of_vertex[i]), vertexData[i], GL_STATIC_DRAW); //Problem Area
if (colorsData_buffer[i] != NULL)
{
glGenBuffers(1, &colorBuffer[i]);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer[i]);
glBufferData(GL_ARRAY_BUFFER, (sizeof(GLfloat) * count_of_vertex[i]), colorsData_buffer[i], GL_DYNAMIC_DRAW);
}
glGenBuffers(1, &indexBuffer[i]);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer[i]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (sizeof(GLushort)* count_of_index[i]), indexData[i], GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, NULL);
glEnableVertexAttribArray(positionAttribLoc); // atrybuty wskazinikow (bufory)
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer[i]);
glVertexAttribPointer(
positionAttribLoc, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
NORMALIZED, // normalized?
0, // stride - wierzcholki oznaczajace pozycje sa w tym buforze jeden za drugim (odstep miedzy kolejnymi wierzcholkami)
(GLvoid*)0 // array buffer offset - w ktorym miejscu bufora zaczyna sie inf o wierzcholkach
);
glBindBuffer(GL_ARRAY_BUFFER, NULL);
if (colorsData_buffer[i] != NULL)
{
glEnableVertexAttribArray(colorAttribLoc);
glBindBuffer(GL_ARRAY_BUFFER, colorBuffer[i]);
glVertexAttribPointer(
colorAttribLoc, // attribute. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
NORMALIZED, // normalized?
0, // stride
(GLvoid*)0 // array buffer offset
);
}
glBindBuffer(GL_ARRAY_BUFFER, NULL);
}
//[...]
}
Mesh_Loader->通过assimp.importer从3DS文件加载数据并提取每个网格的索引、颜色、顶点、法线的数据
函数渲染->加载数据关于:数据关于索引,颜色,顶点,法线
但是当它将数据加载到缓冲区"glBufferData"时会引起一些问题SegFault
附加功能.cpp加载着色器的额外功能&鼠标回调
哪里有问题?
我不认为这是OpenGL的问题。代码只是使用未初始化的指针。如果它们被用于任何用途,这可能会导致崩溃。它们恰好被传递给glBufferData()
。
遍历vertexData
的用法,它被声明为指向GLfloat
:的指针
GLfloat **vertexData;
然后它被分配:
vertexData = new GLfloat*[mesh_size];
CCD_ 4现在指向指向CCD_ 6的CCD_。请注意,这些指针未初始化。
然后,这些指针作为参数传递给一个函数:
przepare_mesh(..., vertexData[i], ...);
在函数内部,然后将一个值分配给函数参数(我将从原始代码中重命名参数,以避免在解释中混淆名称):
void przepare_mesh(..., GLfloat* vertices, ...)
{
...
vertices = (GLfloat *)&paiMesh->mVertices;
由于指针是按值传递给函数的,因此此赋值只更改参数的本地值,而不会为最初传入的指针设置值。因此,当此函数返回时,vertexData[i]
仍将未初始化。
稍后,vertexData[i]
被用作glBufferData()
的参数,并由于未初始化而导致崩溃。
解决此问题的最简单方法是将函数参数的声明更改为引用:
void przepare_mesh(..., GLfloat*& vertices, ...)
一旦参数是引用,在函数内部为其赋值将更改调用方传入的指针的值。
代码中还有其他相同问题的情况,我只是用第一个来说明这个问题。
相关文章:
- Linux的Cpp上的计时器
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 物理键盘上的触发器按键
- 如何加载(或映射)文件部分的最大大小,但适合在Windows上的RAM
- SSL上的`curl_easy_send`和`curl_asy_recv`:如何处理`CURLE_AGAIN`
- PowerPC ppc64le上的Gcc Woverloaded虚拟错误
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 集合上的输出迭代器:assign和increment迭代器
- Cuda C++:设备上的Malloc类,并用来自主机的数据填充它
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 对于set上的循环-获取next元素迭代器
- 组合OpenGL和QML时,gldrawarrays上的segfault
- 如何使用Cuda避免segfault上的内存泄漏
- 在嵌入式Linux上使用C++Std Lib时出现异常的segfault
- OpenGL-加载顶点数据时glBufferData()上的SegFault
- cl::nVidia TITAN黑色但不是Intel openCL设备上的Image3D segfault
- 析构函数上的Segfault
- v8在Windows上的HandleScope构造函数中的SegFault
- 互斥对象上的C++并发segfault
- 在c++地图访问上的segfault