- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一些在 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/
我在Windows 10中使用一些简单的Powershell代码遇到了这个奇怪的问题,我认为这可能是我做错了,但我不是Powershell的天才。 我有这个: $ix = [System.Net.Dn
var urlsearch = "http://192.168.10.113:8080/collective-intellegence/StoreClicks?userid=" + userId +
我有一个非常奇怪的问题,过去两天一直让我抓狂。 我有一个我试图控制的串行设备(LS 100 光度计)。使用设置了正确参数的终端(白蚁),我可以发送命令(“MES”),然后是定界符(CR LF),然后我
我目前正试图让无需注册的 COM 使用 Excel 作为客户端,使用 .NET dll 作为服务器。目前,我只是试图让概念验证工作,但遇到了麻烦。 显然,当我使用 Excel 时,我不能简单地使用与可
我开发了简单的 REST API - https://github.com/pavelpetrcz/MandaysFigu - 我的问题是在本地主机上,WildFly 16 服务器的应用程序运行正常。
我遇到了奇怪的情况 - 从 Django shell 创建一些 Mongoengine 对象是成功的,但是从 Django View 创建相同的对象看起来成功,但 MongoDB 中没有出现任何数据。
我是 flask 的新手,只编写了一个相当简单的网络应用程序——没有数据库,只是一个航类搜索 API 的前端。一切正常,但为了提高我的技能,我正在尝试使用应用程序工厂和蓝图重构我的代码。让它与 pus
我的谷歌分析 JavaScript 事件在开发者控制台中运行得很好。 但是当从外部 js 文件包含在页面上时,它们根本不起作用。由于某种原因。 例如; 下面的内容将在包含在控制台中时运行。但当包含在单
这是一本名为“Node.js 8 the Right Way”的书中的任务。你可以在下面看到它: 这是我的解决方案: 'use strict'; const zmq = require('zeromq
我正在阅读文本行,并创建其独特单词的列表(在将它们小写之后)。我可以使它与 flatMap 一起工作,但不能使它与 map 的“子”流一起工作。 flatMap 看起来更简洁和“更好”,但为什么 di
我正在编写一些 PowerShell 脚本来进行一些构建自动化。我发现 here echo $? 根据前面的语句返回真或假。我刚刚发现 echo 是 Write-Output 的别名。 写主机 $?
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 4年前关闭。 Improve thi
我将一个工作 View Controller 类从另一个项目复制到一个新项目中。我无法在新项目中加载 View 。在旧项目中我使用了presentModalViewController。在新版本中,我
我对 javascript 很陌生,所以很难看出我哪里出错了。由于某种原因,我的功能无法正常工作。任何帮助,将不胜感激。我尝试在外部 js 文件、头部/主体中使用它们,但似乎没有任何效果。错误要么出在
我正在尝试学习Flutter中的复选框。 问题是,当我想在Scaffold(body :)中使用复选框时,它正在工作。但我想在不同的地方使用它,例如ListView中的项目。 return Cente
我们当前使用的是 sleuth 2.2.3.RELEASE,我们看不到在 http header 中传递的 userId 字段没有传播。下面是我们的代码。 BaggageField REQUEST_I
我有一个组合框,其中包含一个项目,比如“a”。我想调用该组合框的 Action 监听器,仅在手动选择项目“a”完成时才调用。我也尝试过 ItemStateChanged,但它的工作原理与 Action
你能看一下照片吗?现在,一步前我执行了 this.interrupt()。您可以看到 this.isInterrupted() 为 false。我仔细观察——“这个”没有改变。它具有相同的 ID (1
我们当前使用的是 sleuth 2.2.3.RELEASE,我们看不到在 http header 中传递的 userId 字段没有传播。下面是我们的代码。 BaggageField REQUEST_I
我正在尝试在我的网站上设置一个联系表单,当有人点击发送时,就会运行一个作业,并在该作业中向所有管理员用户发送通知。不过,我在失败的工作表中不断收到此错误: Illuminate\Database\El
我是一名优秀的程序员,十分优秀!