OpenGL对象创建 [英] OpenGL object creation

查看:121
本文介绍了OpenGL对象创建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

现在,我正在建模一些小的OpenGL库来愚弄图形编程等。因此,我使用类来包围特定的OpenGL函数调用像纹理创建,着色器创建等等,到目前为止,所以很好。



我的问题:



由拥有创建的OpenGL上下文的线程(至少在Windows下,每个其他线程将不做任何事情,并创建一个OpenGL错误)。所以,为了得到一个OpenGL上下文,我首先创建一个窗口类的实例(只是Win API调用的另一个包装器),最后为该窗口创建一个OpenGL上下文。对我来说听起来很安静。 (如果我的设计中已经有一个缺陷让你尖叫,让我知道...)



如果我想创建一个纹理或任何其他需要OpenGL调用创建,我基本上这样做(一个OpenGL对象的调用构造函数,例子):

  opengl_object $ b {
//为对象初始化做必要的操作
//将对象传递给OpenGL线程以进行最终调用
//等待对象被OpenGL线程构造
}

所以,就像任何其他对象一样,使用

  opengl_object obj; 

然后,在其结构中,将自己放入OpenGL对象的队列上下文线程。 OpenGL上下文线程然后调用一个虚拟函数,它在所有OpenGL对象中实现,并包含必要的OpenGL调用,最终创建对象。



我真的想,处理这个问题,会很好。但是,现在,我想我真的错了。



这种情况是,即使上面的方式工作得很好,到目前为止,我有麻烦了因为类层次结构越深入。例如(这不完美,但它显示我的问题):



让我们说,我有一个名为sprite的类,代表一个Sprite。它有自己的OpenGL线程的创建函数,其中顶点和纹理坐标被加载到显卡内存等等。这到目前为止没有问题。
让我们进一步说,我想有2种方式渲染精灵。一个实例和一个到另一个方式。所以,我最终会有2个类,sprite_instanced和sprite_not_instanced。两者都派生自sprite类,因为它们都是精灵,只有不同的渲染。但是,sprite_instanced和sprite_not_instanced在创建函数中需要进一步的OpenGL调用。



我的解决方案到目前为止(我感觉真的很糟糕。)



我有一些了解如何在c ++中的对象生成工作以及它如何影响虚拟函数。所以我决定使用类sprite的虚拟创建函数来加载顶点数据等等到图形内存中。然后,sprite_instanced的虚拟create方法将准备渲染该sprite实例化。
所以,如果我想写

  sprite_instanced s; 

首先,sprite构造函数被调用,在初始化之后,构造线程将对象传递给OpenGL线。在这一点上,传递的对象只是一个普通的精灵,所以sprite :: create将被调用,OpenGL线程将创建一个普通的精灵。之后,构造线程将调用sprite_instanced的构造函数,再次做一些初始化并将对象传递给OpenGL线程。这个时候,它是一个sprite_instanced,因此sprite_instanced :: create将被调用。



所以,如果我是对上述假设,一切都发生正确的,在我的情况下,至少。我花了最后一个小时阅读关于从构造函数调用虚函数以及如何构建v表。我运行一些测试来检查我的假设,但这可能是编译器特定的,所以我不依赖他们100% 。



p>另一种可能性是在OpenGL线程类中实现工厂方法来处理。所以我可以做那些对象的构造函数内的所有OpenGL调用。但是,在这种情况下,我需要许多函数(或一个基于模板的方法),当OpenGL线程需要做更多的事情时,感觉像是潜在的渲染时间可能会丢失...



我的问题



是否可以按照上述方式处理?

解决方案


  1. 这是总是坏的形式调用任何虚拟函数在构造函数。虚拟调用不会照常完成。


  2. 您的数据结构非常混乱。您应该调查Factory对象的概念。这些是用于构造其他对象的对象。你应该有一个SpriteFactory,它被推入某种队列或任何。 SpriteFactory应该是什么创建Sprite对象本身。这样,你没有一个部分构造的对象的概念,其中创建它自己进入队列等等。



    确实,任何时候你开始写,Objectname :: Create,停下来思考,我真的应该使用Factory对象。



Right now, I'm modelling some sort of little OpenGL library to fool around with graphic programming etc. Therefore, I'm using classes to wrap around specific OpenGL function calls like texture creation, shader creation and so on, so far, so good.

My Problem:

All OpenGL calls must be done by the thread which owns the created OpenGL Context (at least under Windows, every other thread will do nothing and create an OpenGL error). So, in order to get an OpenGL context, I firstly create an instance of a window class (just another wrapper around the Win API calls) and finally create an OpenGL context for that window. That sounded quiet logical to me. (If there's already a flaw in my design that makes you scream, let me know...)

If I want to create a texture, or any other object that needs OpenGL calls for creation, I basically do this (the called constructor of an OpenGL object, example):

opengl_object()
{
    //do necessary stuff for object initialisation
    //pass object to the OpenGL thread for final contruction
    //wait until object is constructed by the OpenGL thread 
}

So, in words, I create an object like any other object using

 opengl_object obj;

Which then, in its contructor, puts itself into a queue of OpenGL objects to be created by the OpenGL context thread. The OpenGL context thread then calls a virtual function which is implemented in all OpenGL objects and contains the necessary OpenGL calls to finally create the object.

I really thought, this way of handling that problem, would be nice. However, right now, I think I'm awfully wrong.

The case is, even though the above way works perfectly fine so far, I'm having troubles as soon as the class hierarchy goes deeper. For example (which is not perfectly, but it shows my problem):

Let's say, I have a class called sprite, representing a Sprite, obviously. It has its own create function for the OpenGL thread in which the vertices and texture coordinates are loaded into the graphic cards memory and so on. That's no problem so far. Let's further say, I want to have 2 ways of rendering sprites. One Instanced and one through another way. So, I would end up with 2 classes, sprite_instanced and sprite_not_instanced. Both are derived from the sprite class, as they both are sprite which are only rendered differently. However, sprite_instanced and sprite_not_instanced need further OpenGL calls in their create function.

My Solution so far (and I feel really awful about it!)

I have some kind of understanding how object generation in c++ works and how it affects virtual functions. So I decided to use the virtual create function of the class sprite only to load the vertex data and so on into the the graphics memory. The virtual create method of sprite_instanced will then do the preparation to render that sprite instanced. So, if I want write

sprite_instanced s;

Firstly, the sprite constructor is called and after some initialisation, the constructing thread passes the object to the OpenGL thread. At this point, the passed object is merely a normal sprite, so sprite::create will be called and the OpenGL thread will create a normal sprite. After that, the constructing thread will call the constructor of sprite_instanced, again do some initialisation and pass the object to the OpenGL thread. This time however, it's a sprite_instanced and therefore sprite_instanced::create will be called.

So, if I'm right with the above assumption, everything happens exactly as it should, in my case at least. I spend the last hour reading about calling virtual functions from constructors and how the v-table is build etc. I've ran some test to check my assumption, but that might be compiler-specific so I don't rely on them 100%. In addition, it just feels awful and like a terrible hack.

Another Solution

Another possibility would be implementing factory method in the OpenGL thread class to take care of that. So I can do all the OpenGL calls inside the constructor of those objects. However, in that case, I would need a lot of functions (or one template-based approach) and it feels like a possible loss of potential rendering time when the OpenGL thread has more to do than it needs to...

My Question

Is it ok to handle it the way I described it above? Or should I rather throw that stuff away and do something else?

解决方案

  1. It is always bad form to call any virtual function in a constructor. The virtual call will not be completed as normal.

  2. Your data structures are very confused. You should investigate the concept of Factory objects. These are objects that you use to construct other objects. You should have a SpriteFactory, which gets pushed into some kind of queue or whatever. That SpriteFactory should be what creates the Sprite object itself. That way, you don't have this notion of a partially constructed object, where creating it pushes itself into a queue and so forth.

    Indeed, anytime you start to write, "Objectname::Create", stop and think, "I really should be using a Factory object."

这篇关于OpenGL对象创建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆