Mus*_*sis 12 opengl objective-c ios
我有一个内存中的"位图",它只是一个Byte *包含简单RGB格式的像素数据的malloced 数组(所以字节数组的大小是3*像素数).
我的应用程序只是一个带有实例的视图控制器GLKView.我已经像这样实现了它的委托:
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
}
Run Code Online (Sandbox Code Playgroud)
并且正如预期的那样,它设置了GLKView的背景颜色.
我现在要做的是为此实现添加代码,glkView:drawInRect:以便将"bitmap"呈现到此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);
}
Run Code Online (Sandbox Code Playgroud)
...... 但它不起作用.该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];
Run Code Online (Sandbox Code Playgroud)
这是我写的代码。这不是生产代码:它缺乏对 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
Run Code Online (Sandbox Code Playgroud)
我不知道你想如何更新数据,也许你不必每次都 malloc/free 它,只需做一些小的更改并用glTexSubImage2D. 大部分时间都花在了填充数据上。
这段代码适用于我的 MacBook(模拟器中装有 Xcode 7)和 iPhone 6(装有 iOS 9.0.2)。