gpt4 book ai didi

ios - OpenGL ES 代码在 Android 中工作,但 glAttachShader 不适用于 iOS

转载 作者:太空宇宙 更新时间:2023-11-04 02:21:40 24 4
gpt4 key购买 nike

我有一些在 Android 上运行良好的 OpenGL ES C 代码。代码质量很差(随机错误代码,使用全局变量等),因为我只是想在重构和清理之前启动并运行。但是,它适用于 Android 并正确显示红色三角形。

但相同的代码在 iOS 上不起作用。我在调用 glAttachShader 时得到 GL_INVALID_VALUE(我在下面评论了相关行),即使之前的每个调用都成功了。

代码如下:

#include "gl_render.h"
#include "gl_wrapper.h"
#include <math.h>

GLuint globalProgramObject;
int surfaceWidth;
int surfaceHeight;

GLuint LoadShader ( GLenum type, const char *shaderSrc )
{
GLuint shader;
GLint compiled;
GLenum error;

shader = glCreateShader ( type );

error = glGetError();
if (error != GL_NO_ERROR) {
return -50;
}

glShaderSource ( shader, 1, &shaderSrc, NULL );

error = glGetError();
if (error != GL_NO_ERROR) {
return -51;
}

glCompileShader ( shader );

error = glGetError();
if (error != GL_NO_ERROR) {
return -52;
}

glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );

error = glGetError();
if (error != GL_NO_ERROR) {
return -53;
}

if ( !compiled )
{
GLint infoLen = 0;

glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );

error = glGetError();
if (error != GL_NO_ERROR) {
return -54;
}

if ( infoLen > 1 )
{
char *infoLog = malloc ( sizeof ( char ) * infoLen );

glGetShaderInfoLog ( shader, infoLen, NULL, infoLog );

error = glGetError();
if (error != GL_NO_ERROR) {
return -55;
}

free ( infoLog );
}

glDeleteShader ( shader );

error = glGetError();
if (error != GL_NO_ERROR) {
return -56;
}

return -2;
}

return shader;

}

int on_surface_created(int width, int height) {
surfaceWidth = width;
surfaceHeight = height;

char vShaderStr[] =
"#version 300 es \n"
"layout(location = 0) in vec4 vPosition; \n"
"void main() \n"
"{ \n"
" gl_Position = vPosition; \n"
"} \n";

char fShaderStr[] =
"#version 300 es \n"
"precision mediump float; \n"
"out vec4 fragColor; \n"
"void main() \n"
"{ \n"
" fragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 ); \n"
"} \n";

GLuint vertexShader;
GLuint fragmentShader;
GLuint programObject;
GLint linked;
GLenum error;

vertexShader = LoadShader ( GL_VERTEX_SHADER, vShaderStr );

if (vertexShader <= 0) {
return -155;
}

fragmentShader = LoadShader ( GL_FRAGMENT_SHADER, fShaderStr );

if (fragmentShader <= 0) {
return -156;
}

programObject = glCreateProgram ( );

if (programObject == 0) {
return -157;
}

error = glGetError();
if (error != GL_NO_ERROR) {
return -57;
}

// this is failing with GL_INVALID_VALUE
glAttachShader ( programObject, vertexShader );

error = glGetError();
if (error != GL_NO_ERROR) {
return -58;
}

glAttachShader ( programObject, fragmentShader );

error = glGetError();
if (error != GL_NO_ERROR) {
return -59;
}

glLinkProgram ( programObject );

error = glGetError();
if (error != GL_NO_ERROR) {
return -60;
}

glGetProgramiv ( programObject, GL_LINK_STATUS, &linked );

error = glGetError();
if (error != GL_NO_ERROR) {
return -61;
}

if ( !linked )
{
GLint infoLen = 0;

glGetProgramiv ( programObject, GL_INFO_LOG_LENGTH, &infoLen );

error = glGetError();
if (error != GL_NO_ERROR) {
return -62;
}

if ( infoLen > 1 )
{
char *infoLog = malloc ( sizeof ( char ) * infoLen );

glGetProgramInfoLog ( programObject, infoLen, NULL, infoLog );

error = glGetError();
if (error != GL_NO_ERROR) {
return -63;
}

free ( infoLog );
}

glDeleteProgram ( programObject );

error = glGetError();
if (error != GL_NO_ERROR) {
return -64;
}

return -2;
}

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

error = glGetError();
if (error != GL_NO_ERROR) {
return -65;
}

globalProgramObject = programObject;

return 0;
}

int on_draw_frame() {
GLenum error;

GLfloat vVertices[] = { 0.0f, 0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f
};

glViewport ( 0, 0, surfaceWidth, surfaceHeight );

error = glGetError();
if (error != GL_NO_ERROR) {
return -66;
}

glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

error = glGetError();
if (error != GL_NO_ERROR) {
return -67;
}

glUseProgram ( globalProgramObject );

error = glGetError();
if (error != GL_NO_ERROR) {
return -68;
}

glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vVertices );

error = glGetError();
if (error != GL_NO_ERROR) {
return -69;
}

glEnableVertexAttribArray ( 0 );

error = glGetError();
if (error != GL_NO_ERROR) {
return -70;
}

glDrawArrays ( GL_TRIANGLES, 0, 3 );

error = glGetError();
if (error != GL_NO_ERROR) {
return -71;
}

glDisableVertexAttribArray ( 0 );

error = glGetError();
if (error != GL_NO_ERROR) {
return -72;
}

return 0;
}

对于额外的上下文,这里是我用来托管 OpenGL worker 的 Objective C 代码:

#import "OpenGLRender.h"
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>

@interface OpenGLRender()
@property (strong, nonatomic) EAGLContext *context;
@property (strong, nonatomic) id<OpenGLRenderWorker> worker;
@property (copy, nonatomic) void(^onNewFrame)(void);

@property (nonatomic) GLuint frameBuffer;
@property (nonatomic) GLuint depthBuffer;
@property (nonatomic) CVPixelBufferRef target;
@property (nonatomic) CVOpenGLESTextureCacheRef textureCache;
@property (nonatomic) CVOpenGLESTextureRef texture;
@property (nonatomic) CGSize renderSize;
@property (nonatomic) BOOL running;
@end

@implementation OpenGLRender

- (instancetype)initWithSize:(CGSize)renderSize
worker:(id<OpenGLRenderWorker>)worker
onNewFrame:(void(^)(void))onNewFrame {
self = [super init];
if (self){
self.renderSize = renderSize;
self.running = YES;
self.onNewFrame = onNewFrame;
self.worker = worker;

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
thread.name = @"OpenGLRender";
[thread start];
}
return self;
}

- (void)run {
[self initGL];
int result = [_worker onCreateWithWidth: self.renderSize.width andHeight: self.renderSize.height];

if (result != 0) {
NSLog(@"Failed to call onCreateWithWidth %f AndHeight %f: %d", self.renderSize.width, self.renderSize.height, result);
}

while (_running) {
CFTimeInterval loopStart = CACurrentMediaTime();
result = [_worker onDraw];

if (result != 0) {
NSLog(@"Failed to call onDraw: %d", result);
} else {
glFlush();
dispatch_async(dispatch_get_main_queue(), self.onNewFrame);
}

CFTimeInterval waitDelta = 0.016 - (CACurrentMediaTime() - loopStart);
if (waitDelta > 0) {
[NSThread sleepForTimeInterval:waitDelta];
}
}
[self deinitGL];
}

#pragma mark - Public

- (void)dispose {
_running = NO;
}

#pragma mark - FlutterTexture

- (CVPixelBufferRef _Nullable)copyPixelBuffer {
CVBufferRetain(_target);
return _target;
}

#pragma mark - Private

- (void)initGL {
_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

[EAGLContext setCurrentContext:_context];
[self createCVBufferWithSize:_renderSize withRenderTarget:&_target withTextureOut:&_texture];

glBindTexture(CVOpenGLESTextureGetTarget(_texture), CVOpenGLESTextureGetName(_texture));

glTexImage2D(GL_TEXTURE_2D,
0, GL_RGBA,
_renderSize.width, _renderSize.height,
0, GL_RGBA,
GL_UNSIGNED_BYTE, NULL);

glGenRenderbuffers(1, &_depthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, _depthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _renderSize.width, _renderSize.height);

glGenFramebuffers(1, &_frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, CVOpenGLESTextureGetName(_texture), 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _depthBuffer);

if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
} else {
NSLog(@"Successfully initialized GL");
}
}

- (void)createCVBufferWithSize:(CGSize)size
withRenderTarget:(CVPixelBufferRef *)target
withTextureOut:(CVOpenGLESTextureRef *)texture {

CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, _context, NULL, &_textureCache);

if (err) return;

CFDictionaryRef empty;
CFMutableDictionaryRef attrs;
empty = CFDictionaryCreate(kCFAllocatorDefault,
NULL,
NULL,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);

attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 1,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);

CFDictionarySetValue(attrs, kCVPixelBufferIOSurfacePropertiesKey, empty);
CVPixelBufferCreate(kCFAllocatorDefault, size.width, size.height,
kCVPixelFormatType_32BGRA, attrs, target);

CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
_textureCache,
*target,
NULL, // texture attributes
GL_TEXTURE_2D,
GL_RGBA, // opengl format
size.width,
size.height,
GL_BGRA, // native iOS format
GL_UNSIGNED_BYTE,
0,
texture);

CFRelease(empty);
CFRelease(attrs);
}

- (void)deinitGL {
glDeleteFramebuffers(1, &_frameBuffer);
glDeleteFramebuffers(1, &_depthBuffer);
CFRelease(_target);
CFRelease(_textureCache);
CFRelease(_texture);
}

@end

谁能告诉我为什么这在 iOS 上不起作用,尽管它在 Android 上运行良好?

最佳答案

您已经创建了 GLES2 上下文 (kEAGLRenderingAPIOpenGLES2),但您正在使用 GLES3 着色器 (#version 300 es)。

我有点惊讶 glCompileShader 没有捕获到错误,但我猜 iOS 驱动程序正在推迟实际编译,直到 glAttachShader 被调用。

关于ios - OpenGL ES 代码在 Android 中工作,但 glAttachShader 不适用于 iOS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57015669/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com