OpenGL VBO 访问冲突

发布于 2024-10-30 17:40:02 字数 7544 浏览 3 评论 0原文

过去几周我一直在学习 OpenGL,在阅读了 Swiftless tuts 和 Nehe 的 tuts 的一部分,以及其他有关法线、场景图、等等的文章之后,我决定创建某种“框架”,以让我更容易插入新学到的代码。因此,我决定创建一个场景图/渲染器组合,不是那么漂亮,也不是那么快(可能),但可以选择添加一个新的派生节点类来渲染我可能刚刚读过的新功能。因此,我在 interwebz 上查看有关如何实现一个基类并确定此基类的各种示例:

#pragma once

#ifndef NODE_H
#define NODE_H

#include <stdlib.h>
#include <stdio.h>      
#include <iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GL/glext.h>
#include <math.h>
#include <windows.h>
#include <list>
using namespace std;

class Node
{
public:
        Node(void);
        ~Node(void);

        //Node* parent;

        void addChild(Node* node);
        void removeChilds(Node* node);

        virtual void traverse();

        void kill();

protected:
        std::list<Node*> childs;
};

#endif

....我从中创建了该类:

#pragma once

#ifndef NODESPHERE_H
#define NODESPHERE_H

#include <stdlib.h>
#include <stdio.h>      
#include <iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GL/glext.h>
#include <math.h>
#include <windows.h>
#include "Various.h"
#include "Node.h"
class NodeSphere : public Node
{
public:
        NodeSphere(double R, double H, double K, double Z, const int space);
        ~NodeSphere(){delete this;}

        void traverse();

private:
        float out[3];
        int Radius;
        int vhVertexCount;
    Vert *vhVertices;
        Normal *vhNormals,*vhVNormals;
    TexCoord *vhTexCoords;
        unsigned int vhVBOVertices;
    unsigned int vhVBOTexCoords;
        unsigned int vhVBONormals;
    bool Init(void);
        bool Normals(const int nIndex);
        bool ReduceToUnit(void);
};

#endif

现在,我使用 freeglut 来处理窗口创建和循环:

    #include <windows.h>
#include <stdlib.h>
#include <stdio.h>      
#include <iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GL/glext.h>
#include <math.h>
#include "Scenegraph.h"
#include "View.h"
#include "Control.h"

#define WIDTH 800
#define HEIGHT 600


Scenegraph *bob;
View *myView;
Control *controler;

.................
.................

void main(int argc, char **argv)
{
        glewInit();
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
        glutInitWindowSize(WIDTH,HEIGHT);
        glutInitWindowPosition(0,0);
        glutCreateWindow("Mediensoftware - Finale Übung");
        bob = new Scenegraph();
        myView = new View(WIDTH, HEIGHT, bob);
        controler = new Control(myView);
        glutDisplayFunc(display);
        glutIdleFunc(idle);
        glutReshapeFunc(resize);
        glutKeyboardFunc(keyboard);
        glutSpecialFunc(keyboard_s);

        glutMainLoop();
}

场景图“ bob”像这样处理节点的创建:

Scenegraph::Scenegraph()
{
        this->root = new Node();

        this->sun = new NodeSphere(3,0,0,0,10);
        this->sun_transform = new NodeTransform();
        this->sun_tex = new NodeTexture("sunmap.bmp");
        this->sun_mat = new NodeMaterial(1.0,0,1.0,0.7,0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0);
        this->planet_earth = new NodeSphere(1,0,0,0,10);
        this->planet_earth_transform = new NodeTransform(6,0,0);
        this->planet_earth_tex = new NodeTexture("earthmap.bmp");
        this->planet_earth_mat = new NodeMaterial(1.0,0,1.0,0.7,0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0);
        this->moon = new NodeSphere(0.3,0,0,0,10);
        this->moon_tex = new NodeTexture("moonmap.bmp");
        this->moon_transform = new NodeTransform(1.5,0,0);
        this->moon_mat = new NodeMaterial(1.0,0,1.0,0.7,0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0);
        this->planet_venus = new NodeSphere(0.8,0,0,0,10);
        this->planet_venus_transform = new NodeTransform(3,0,0);
        this->planet_venus_tex = new NodeTexture("venusmap.bmp");
        this->planet_venus_mat = new NodeMaterial(1.0,0,1.0,0.7,0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0);
        this->planet_mars = new NodeSphere(0.6,0,0,0,10);
................................................................................................
        this->root->addChild(this->sun_transform);
        this->sun_transform->addChild(this->sun_mat);
        this->sun_mat->addChild(this->sun_tex);
        this->sun_tex->addChild(this->sun);
        this->sun->addChild(this->planet_venus_transform);
        this->planet_venus_transform->addChild(this->planet_venus_mat);
        this->planet_venus_mat->addChild(this->planet_venus_tex);
...................................................................................................
        }

编译器没有看到任何错误并执行代码,但它在这里收到访问冲突:

bool NodeSphere::Init(void){
        glGenBuffersARB(1, &vhVBOVertices); // DERP here
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vhVBOVertices);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, this->vhVertexCount * 3 * sizeof(float), this->vhVertices, GL_STATIC_DRAW_ARB);
        glGenBuffersARB(1, &vhVBONormals);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vhVBONormals);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, this->vhVertexCount * 3 * sizeof(float), this->vhVNormals, GL_STATIC_DRAW_ARB);
    glGenBuffersARB(1, &vhVBOTexCoords);
        glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vhVBOTexCoords);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, this->vhVertexCount * 2 * sizeof(float), this->vhTexCoords, GL_STATIC_DRAW_ARB);

        delete [] vhVertices;
    vhVertices = NULL;
    delete [] vhTexCoords;
    vhTexCoords = NULL;
        delete [] vhNormals;
        vhNormals = NULL;
        delete [] vhVNormals;
        vhVNormals = NULL;
        return true;
}

扩展在 View::initExtensions() 中调用,场景图的 init 是在窗口创建之后完成,所以......我很确定它与指针有关......

在以前的程序中,我使用完全相同的代码来创建VBO并且它有效。唯一的区别是这里使用的代码是在 Node* 中使用的,而之前的代码只是在 Node 中使用(没有指针)。但无论如何,我要检查一下 glew 是否启动良好。 至于我使用的显卡,在笔记本电脑上我有一个蹩脚的 Intel 集成卡,它应该支持 OpenGL 1.5,但甚至没有 GLSL,而在 PC 上,我有 6850。问题是,由于教师和其他方面的原因,我经常在笔记本电脑上工作。

但无论如何,创建 VBO 的代码可以工作,我的意思是,它可以用于以下用途:

#include <stdlib.h> 
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <GL/glew.h>
#include <GL/gl.h>                                                              // Header File For The OpenGL32 Library
#include <GL/glu.h>                                                             // Header File For The GLu32 Library
#include <GL/glext.h>
#include <math.h>

#define PI 3.14159265f


class Vert{
public:
        float x;
        float y;
    float z;
};

class Normal{
public:
        float x;
        float y;
    float z;
};

class TexCoord{
    public:
                float u;
                float v;
};

class Scenegraph {
private:
        float out[3];
        int Radius;
        GLuint tID[2];
        int vhVertexCount;
    Vert *vhVertices;
        Normal *vhNormals,*vhVNormals;
    TexCoord *vhTexCoords;
        unsigned int vhVBOVertices;
    unsigned int vhVBOTexCoords;
        unsigned int vhVBONormals;
    bool Init(void);
        bool Normals(const int nIndex);
        bool ReduceToUnit(void);


public:
        bool Create(double R, double H, double K, double Z, const int space);

        void Render();

};

它与 NodeSphere 相同,只是它是静态声明的。提前致谢。

I've been learning OpenGL the past few weeks and after reading the Swiftless tuts and part of Nehe's tuts, along side with other articles concerning normals, scene graphs, bla bla, i've decided to create some sort of "framework", to allow me to insert newly learned code easier. So I decided to create a scenegraph/renderer combo, not that pretty, not that fast (prolly), but with the option to add just a new derived node class to render a new whatever feature i might just have read. So i look on the interwebz to see various examples on how to implement one and settle on this base class:

#pragma once

#ifndef NODE_H
#define NODE_H

#include <stdlib.h>
#include <stdio.h>      
#include <iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GL/glext.h>
#include <math.h>
#include <windows.h>
#include <list>
using namespace std;

class Node
{
public:
        Node(void);
        ~Node(void);

        //Node* parent;

        void addChild(Node* node);
        void removeChilds(Node* node);

        virtual void traverse();

        void kill();

protected:
        std::list<Node*> childs;
};

#endif

.... from which i made this class:

#pragma once

#ifndef NODESPHERE_H
#define NODESPHERE_H

#include <stdlib.h>
#include <stdio.h>      
#include <iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GL/glext.h>
#include <math.h>
#include <windows.h>
#include "Various.h"
#include "Node.h"
class NodeSphere : public Node
{
public:
        NodeSphere(double R, double H, double K, double Z, const int space);
        ~NodeSphere(){delete this;}

        void traverse();

private:
        float out[3];
        int Radius;
        int vhVertexCount;
    Vert *vhVertices;
        Normal *vhNormals,*vhVNormals;
    TexCoord *vhTexCoords;
        unsigned int vhVBOVertices;
    unsigned int vhVBOTexCoords;
        unsigned int vhVBONormals;
    bool Init(void);
        bool Normals(const int nIndex);
        bool ReduceToUnit(void);
};

#endif

Now, i use freeglut to handle the window creation and the loop:

    #include <windows.h>
#include <stdlib.h>
#include <stdio.h>      
#include <iostream>
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <GL/glext.h>
#include <math.h>
#include "Scenegraph.h"
#include "View.h"
#include "Control.h"

#define WIDTH 800
#define HEIGHT 600


Scenegraph *bob;
View *myView;
Control *controler;

.................
.................

void main(int argc, char **argv)
{
        glewInit();
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
        glutInitWindowSize(WIDTH,HEIGHT);
        glutInitWindowPosition(0,0);
        glutCreateWindow("Mediensoftware - Finale Übung");
        bob = new Scenegraph();
        myView = new View(WIDTH, HEIGHT, bob);
        controler = new Control(myView);
        glutDisplayFunc(display);
        glutIdleFunc(idle);
        glutReshapeFunc(resize);
        glutKeyboardFunc(keyboard);
        glutSpecialFunc(keyboard_s);

        glutMainLoop();
}

The Scenegraph "bob" handles the creation of nodes like this:

Scenegraph::Scenegraph()
{
        this->root = new Node();

        this->sun = new NodeSphere(3,0,0,0,10);
        this->sun_transform = new NodeTransform();
        this->sun_tex = new NodeTexture("sunmap.bmp");
        this->sun_mat = new NodeMaterial(1.0,0,1.0,0.7,0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0);
        this->planet_earth = new NodeSphere(1,0,0,0,10);
        this->planet_earth_transform = new NodeTransform(6,0,0);
        this->planet_earth_tex = new NodeTexture("earthmap.bmp");
        this->planet_earth_mat = new NodeMaterial(1.0,0,1.0,0.7,0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0);
        this->moon = new NodeSphere(0.3,0,0,0,10);
        this->moon_tex = new NodeTexture("moonmap.bmp");
        this->moon_transform = new NodeTransform(1.5,0,0);
        this->moon_mat = new NodeMaterial(1.0,0,1.0,0.7,0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0);
        this->planet_venus = new NodeSphere(0.8,0,0,0,10);
        this->planet_venus_transform = new NodeTransform(3,0,0);
        this->planet_venus_tex = new NodeTexture("venusmap.bmp");
        this->planet_venus_mat = new NodeMaterial(1.0,0,1.0,0.7,0,1.0,1.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0);
        this->planet_mars = new NodeSphere(0.6,0,0,0,10);
................................................................................................
        this->root->addChild(this->sun_transform);
        this->sun_transform->addChild(this->sun_mat);
        this->sun_mat->addChild(this->sun_tex);
        this->sun_tex->addChild(this->sun);
        this->sun->addChild(this->planet_venus_transform);
        this->planet_venus_transform->addChild(this->planet_venus_mat);
        this->planet_venus_mat->addChild(this->planet_venus_tex);
...................................................................................................
        }

The compiler doesn't see any errors and executes the code, but it receives an access violation here:

bool NodeSphere::Init(void){
        glGenBuffersARB(1, &vhVBOVertices); // DERP here
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vhVBOVertices);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, this->vhVertexCount * 3 * sizeof(float), this->vhVertices, GL_STATIC_DRAW_ARB);
        glGenBuffersARB(1, &vhVBONormals);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vhVBONormals);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, this->vhVertexCount * 3 * sizeof(float), this->vhVNormals, GL_STATIC_DRAW_ARB);
    glGenBuffersARB(1, &vhVBOTexCoords);
        glBindBufferARB(GL_ARRAY_BUFFER_ARB, this->vhVBOTexCoords);
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, this->vhVertexCount * 2 * sizeof(float), this->vhTexCoords, GL_STATIC_DRAW_ARB);

        delete [] vhVertices;
    vhVertices = NULL;
    delete [] vhTexCoords;
    vhTexCoords = NULL;
        delete [] vhNormals;
        vhNormals = NULL;
        delete [] vhVNormals;
        vhVNormals = NULL;
        return true;
}

The extensions are called in the View::initExtensions(), the init of the Scenegraph is done after the window creation, so.... i'm pretty sure it has something to do with pointers...

on previous programs i used the exact same code for VBO creation and it worked. The only difference is that the code used here is used in a Node*, while the previous ones were used in just Node (no pointer). But in any case, i'm gonna check if glew starts up well.
As for what video card i am using, on the laptop i have a crappy Intel integrated card, which should support OpenGL 1.5, but doesn't even have GLSL, and on the PC, a 6850. The thing is that i work a lot on the laptop, because of faculty and other stuff as well.

But anyway, the code for creating VBO's works, i mean, it has worked for the following:

#include <stdlib.h> 
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <GL/glew.h>
#include <GL/gl.h>                                                              // Header File For The OpenGL32 Library
#include <GL/glu.h>                                                             // Header File For The GLu32 Library
#include <GL/glext.h>
#include <math.h>

#define PI 3.14159265f


class Vert{
public:
        float x;
        float y;
    float z;
};

class Normal{
public:
        float x;
        float y;
    float z;
};

class TexCoord{
    public:
                float u;
                float v;
};

class Scenegraph {
private:
        float out[3];
        int Radius;
        GLuint tID[2];
        int vhVertexCount;
    Vert *vhVertices;
        Normal *vhNormals,*vhVNormals;
    TexCoord *vhTexCoords;
        unsigned int vhVBOVertices;
    unsigned int vhVBOTexCoords;
        unsigned int vhVBONormals;
    bool Init(void);
        bool Normals(const int nIndex);
        bool ReduceToUnit(void);


public:
        bool Create(double R, double H, double K, double Z, const int space);

        void Render();

};

which is identical to NodeSphere, except it was statically declared. Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

微凉 2024-11-06 17:40:02

最有可能的是,发生错误的原因是当您尝试调用 init() 时,NodeSphere 不存在(或不再有效)。

您可能应该将资源初始化代码移至构造函数中(这通常是它们的用途),除非您稍后需要它发生。 VBO 与对象具有相似的生命周期是有意义的,因此在 ctor/dtor 中创建和销毁它们应该可以工作,并节省显式初始化的复杂性。

Most likely, the error is occurring because the NodeSphere doesn't exist (or is no longer valid) when you try to call init().

You should probably move the resource initialization code into the constructor (that's generally what they're for) unless you need it to occur later on. It makes sense for the VBO to have a similar lifespan to the object, so creating and destroying them in the ctor/dtor should work and saves you the complexity of explicitly initializing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文