【问题标题】:Progmatically generating and applying an OpenGL texture to a OpenGL View以编程方式生成 OpenGL 纹理并将其应用于 OpenGL 视图
【发布时间】:2014-10-07 20:11:59
【问题描述】:

好的,所以我一直在努力解决这个问题,我已经设法在 OpenGLView 上进行子类化并绘制一些形状(正方形、三角形),并让它们在那里改变颜色等

现在我正在研究如何加载纹理数据并进行渲染,但我有点迷茫。

这是我尝试使用的代码,它似乎没有加载任何类型的纹理,我只是得到一个白框。我应该相信它会创建一个黑白复选框效果,但我似乎无法让它工作。

这是代码,非常感谢!

#import "MyOpenGLView.h"
#import <OpenGL/gl.h>

@implementation MyOpenGLView

static void drawAnObject ()


{
    glEnable(GL_TEXTURE_2D);

    GLuint tex;

    glGenTextures(1, &tex);

    glBindTexture(GL_TEXTURE_2D, tex);

    glPixelStorei(GL_UNPACK_ALIGNMENT, tex);


    // Black/white checkerboard
    float pixels[] = {
        0.0f, 0.0f, 0.0f,   1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 1.0f,   0.0f, 0.0f, 0.0f
    };

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    float color[] = { 1.0f, 0.0f, 0.0f, 1.0f };

    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);

    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0.1, 0.1, 0, GL_RGB, GL_FLOAT, pixels);


    glBindTexture (GL_TEXTURE_2D, tex);

    glBegin (GL_QUADS);
    glTexCoord2f (0.0, 0.0);
    glVertex3f (0.0, 0.0, 0.0);
    glTexCoord2f (1.0, 0.0);
    glVertex3f (10.0, 0.0, 0.0);
    glTexCoord2f (1.0, 1.0);
    glVertex3f (10.0, 10.0, 0.0);
    glTexCoord2f (0.0, 1.0);
    glVertex3f (0.0, 10.0, 0.0);
    glEnd ();



}

-(void)awakeFromNib
{
    renderTimer = [NSTimer timerWithTimeInterval:0.001   //a 1ms time interval
                                      target:self
                                    selector:@selector(timerFired:)
                                    userInfo:nil
                                     repeats:YES];

    [[NSRunLoop currentRunLoop] addTimer:renderTimer
                             forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] addTimer:renderTimer
                             forMode:NSEventTrackingRunLoopMode]; //Ensure timer fires during resize
}

// Timer callback method
- (void)timerFired:(id)sender
{

     [self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)dirtyRect {
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT);
    drawAnObject();
    glFlush();
    GLint swapInterval = 1;
    [[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];


    CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
}

原创

我正在为 OS X 开发一个 Cocoa 应用程序,其中我有一个大约 500px x 500px 的矩形,我需要以大约 25fps 的速度更改每个像素的颜色。

每个像素的颜色值将存储在一个 NSDictionary 中,可以在渲染每个像素时从中读取。

在最基本的意义上,我可以继承我正在绘制的 View 并覆盖 drawRect 方法。但是,我需要每秒调用 25 次,我怀疑这要求太多,而且它会陷入困境,它也不能保证渲染会在正确的时间发生。

所以我认为我需要使用 Core Graphics 或 OpenGL 在较低级别上执行此操作,但这些都是我之前没有花太多时间研究的大型主题。所以在我深入研究其中一个之前,有什么正确方向的指针吗?

【问题讨论】:

  • 创建一个 OpenGL 纹理并用glTexSubImage2Dopengl.org/sdk/docs/man/html/glTexSubImage2D.xhtml 在每一帧中写入数据。如果您的数据仅在 CPU 上可用,我没有看到更简单的解决方案。
  • 是的,我担心它必须是那样的,好吧,我进入 OpenGL 的世界,祝我好运。 . .
  • 好吧,已经很困惑了。据我所知,我需要将 RGB 数据加载到数组中并将其馈送到渲染的纹理中,但我没有概述将所有内容放在一起的一般构建块。我需要导入哪些库,如何创建渲染纹理的 OpenGL 视图以及如何告诉它更新。任何指向一些教程让我继续前进的指针将不胜感激?

标签: objective-c cocoa opengl core-graphics


【解决方案1】:

线

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0.1, 0.1, 0, GL_RGB, GL_FLOAT, pixels);

没有做你认为的那样。 width 和height 参数的类型为GLsizei,它是一个整数 类型——您应该在此处设置纹理的像素尺寸。您将其设置为 0.1,它将被隐式转换为整数并最终为 0。显然,您应该在此处使用 2 和 2 作为 2×2 纹理。

调用glPixelStorei(GL_UNPACK_ALIGNMENT, tex); 现在完全没有意义了,因为tex 只是GL 实现随机分配的某个数字(或多或少),而您不希望将解包对齐设置为任何值。由于您使用 float 作为基本数据类型(从性能的角度来看,您可能不应该这样做 - 但这是另一回事),4 字节的默认对齐方式可以正常工作。

即使您修复了该问题,纹理也不会显示,因为它不是 _mipmap 完整的。默认的缩小过滤器是GL_NEAREST_MIPMAP_LINEAR。如果您不打算使用 mipmapping,则必须相应地设置过滤器模式:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // or GL_LINEAR

我看到的第三个问题是,您每次调用 drawAnObject() 时都会创建一个新的纹理对象,您永远不会删除它 - 这会随着时间的推移而泄漏内存。

您应该考虑何时要创建纹理以及它应该具有什么样的生命周期。无需重新创建对象即可更改图像数据。

UPDATE回答UPTATE2的问题:

你用glTexSubImage2D错了,参数是:

target、level、xoffset、yoffset、width、height。

您基本上跳过了level 并在height 的位置插入了另一个0,因此您正在尝试更新4 x 0 子区域。正确的调用当然是

glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_RGB, GL_FLOAT, cpixelArray);

【讨论】:

  • 嗨 Derhass,非常感谢您的帮助,现在一切都开始变得有意义了,我让它按照我的意愿渲染棋盘,并在两种不同的模式之间交替。但是,我确实按照您的建议泄漏了内存,以解决我试图更新现有纹理的问题,但由于某种原因它不起作用。
  • @GarethJeanne:嗯,不知为何,我的千里眼技能消失了……;)
  • 对不起,我试图发布一个后续消息,说我更新了帖子,但它把我锁定了一分钟。因此,上面发布的更新成本。谢谢!
  • 恐怕还是不行,glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_RGB, GL_FLOAT, cpixelArray);工作,glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_RGB, GL_FLOAT, cpixelArray);方法不同:(
  • 我已更新问题以显示(大部分)我正在使用的完整代码。想知道我是否以某种方式丢失了指向纹理对象的指针?
猜你喜欢
  • 2018-08-15
  • 1970-01-01
  • 2015-05-21
  • 1970-01-01
  • 2018-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多