簡體   English   中英

如何使用2D紋理將RGB位圖渲染到GLKView中?

[英]How can I render an RGB bitmap into a GLKView using 2D textures?

我有一個內存中的“位圖”,它只是一個malloced Byte *數組,它包含一個簡單RGB格式的像素數據(所以字節數組的大小是3 *像素數)。

我的應用程序只是一個帶有GLKView實例的視圖控制器。 我已經像這樣實現了它的委托:

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
}

並且正如預期的那樣,它設置了GLKView的背景顏色。

我現在要做的是為glkView:drawInRect:這個實現添加代碼glkView:drawInRect:這樣我的“位圖”就會呈現在這個GLKView中。 但我似乎無法找到任何簡單的方法; 我對OpenGL可以做的所有不同事情感到不知所措,所有這些都比我在這里嘗試的要復雜得多。

glReadPixels似乎有點像我在這里,因為它似乎提供了一個指向緩沖區數據的指針。

編輯:顯然這只能通過使用紋理來完成。 我試圖用這個示例代碼實現這一點(請注意,我的“位圖”是每個樣本4個字節,與格式參數匹配):

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {

    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    // raw data
    int width = 30;
    int height = 30;
    int pixelCount = width * height;
    int byteSize = pixelCount * 4;
    GLubyte *textureData = (GLubyte *)malloc(byteSize);

    for (int i = 0; i < byteSize; i++) {
        textureData[i] = 255; // white
    }

    glEnable(GL_TEXTURE_2D);

    GLuint textureID;
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, 
        GL_RGBA, GL_UNSIGNED_BYTE, textureData);

    free(textureData);

}

...... 但它不起作用 glClear()調用按預期工作,並將整個背景設置為紅色; 但如果我正確理解紋理樣本,下面的代碼應該在角落里繪制一個30x30的白色方塊,但我得到的只是純紅色背景。

誰能發現我在這里做錯了什么?

抱歉推進OpenGL :)

我會創建CGImage然后創建UIImage

void *baseAddress = & textureData;
size_t bytesPerRow = width * 4;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
CGImageRef cgImage = CGBitmapContextCreateImage(context);
CGContextRelease(context);
CGColorSpaceRelease(colorSpace);
UIImage *image = [UIImage imageWithCGImage:cgImage];

然后使用drawInRect繪制它

編輯:

這是我寫的代碼。 這不是生產代碼:它缺乏對openGL錯誤的檢查,一些小的泄漏以及全局變量,但它是增強它的好地方。

#import "ViewController.h"
#include <OpenGLES/ES2/gl.h>
#include <OpenGLES/ES2/glext.h>

@interface ViewController ()

@end

@implementation ViewController

GLuint tex;
float vertices[] = {
    //  Position    Texcoords
    -1.0f,  1.0f, 0.0f, 0.0f, // Top-left
    1.0f,  1.0f, 1.0f, 0.0f, // Top-right
    1.0f, -1.0f, 1.0f, 1.0f, // Bottom-right
    -1.0, -1.0f, 0.0f, 1.0f  // Bottom-left
};

const char * vertexShader = "attribute vec2 position;\n"
                            "attribute vec2 TexCoordIn;\n"
                            "varying vec2 TexCoordOut;\n"
                            "void main() {\n"
                                "gl_Position = vec4(position, 0.0, 1.0);\n"
                                "TexCoordOut = TexCoordIn;\n"
                            "}\n";

const char * fragmentShader =   "precision mediump float;\n"
                                "varying lowp vec2 TexCoordOut;\n"
                                "uniform sampler2D Texture;\n"
                                "void main() {\n"
                                    "gl_FragColor = texture2D(Texture, TexCoordOut);\n"
                                "}\n";

GLuint shaderProgram;
GLuint vao;
GLuint vbo;

-(void) initOpenGLObjects {
    glGenVertexArraysOES(1, &vao);
    glBindVertexArrayOES(vao);

    glGenTextures(1, &tex);
    glBindTexture(GL_TEXTURE_2D, tex);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glGenerateMipmap(GL_TEXTURE_2D);

    GLuint vs = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vs, 1, &vertexShader, NULL);
    glCompileShader(vs);

    GLint status;
    glGetShaderiv(vs, GL_COMPILE_STATUS, &status);

    char buffer[512];
    glGetShaderInfoLog(vs, 512, NULL, buffer);

    GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fs, 1, &fragmentShader, NULL);
    glCompileShader(fs);

    glGetShaderiv(fs, GL_COMPILE_STATUS, &status);

    glGetShaderInfoLog(fs, 512, NULL, buffer);

    shaderProgram = glCreateProgram();
    glAttachShader(shaderProgram, vs);
    glAttachShader(shaderProgram, fs);
    glLinkProgram(shaderProgram);

    GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
    GLint texAttrib = glGetAttribLocation(shaderProgram, "TexCoordIn");

    glGenBuffers(1, &vbo); // Generate 1 buffer
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), 0);
    glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE, 4*sizeof(float), (void*)(2*sizeof(float)));

    glEnableVertexAttribArray(posAttrib);
    glEnableVertexAttribArray(texAttrib);
}


-(void) viewDidLoad{
    [super viewDidLoad];

    self.glkView.context = [[EAGLContext alloc] initWithAPI:
                           kEAGLRenderingAPIOpenGLES2];

    [EAGLContext setCurrentContext:self.glkView.context];

    CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)];
    [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

    self.glkView.delegate = self;
    [self initOpenGLObjects];
}

- (void)update
{
    [self.glkView setNeedsDisplay];
}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {

    glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    int width = 300;
    int height = 300;
    int pixelCount = width * height;
    int byteSize = pixelCount * 4;
    GLubyte *textureData = (GLubyte *)malloc(byteSize);
    static int time = 0;
    time = (time+1)%256;

    for (int i = 0; i < byteSize; i+=4) {
        textureData[i] = 255;
        textureData[i+1] = time;
        textureData[i+2] = 255;
        textureData[i+3] = 255;
    }

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
                 GL_RGBA, GL_UNSIGNED_BYTE, textureData);

    glUseProgram(shaderProgram);
    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);

    free(textureData);
}

@end

我不知道你想如何更新數據,也許你不必每次都使用malloc / free,只需做一些小改動並用glTexSubImage2D更新它。 大部分時間都花在填充數據上。

這段代碼在我的MacBook上運行,Xcode 7采用模擬器,iPhone 6采用iOS 9.0.2。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM