【问题标题】:OpenGL ES texture degrades in qualityOpenGL ES 纹理质量下降
【发布时间】:2016-01-14 07:02:35
【问题描述】:

我正在尝试将生成的核心图形图像(以屏幕分辨率) 绘制到 OpenGL 中。但是,图像渲染的锯齿比 CG 输出更多(在 CG 中禁用了抗锯齿)。 文字是纹理(蓝色背景分别在Core Graphics中绘制第一张图片和OpenGL绘制第二张)。

CG 输出:

OpenGL 渲染(在模拟器中):

帧缓冲设置:

context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
[EAGLContext setCurrentContext:context];

glGenRenderbuffers(1, &onscrRenderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, onscrRenderBuffer);
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:self.layer];

glGenFramebuffers(1, &onscrFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, onscrFramebuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, onscrRenderBuffer);

纹理加载代码:

-(GLuint) loadTextureFromImage:(UIImage*)image {

    CGImageRef textureImage = image.CGImage;

    size_t width = CGImageGetWidth(textureImage);
    size_t height = CGImageGetHeight(textureImage);

    GLubyte* spriteData = (GLubyte*) malloc(width*height*4);

    CGColorSpaceRef cs = CGImageGetColorSpace(textureImage);
    CGContextRef c = CGBitmapContextCreate(spriteData, width, height, 8, width*4, cs, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(cs);

    CGContextScaleCTM(c, 1, -1);
    CGContextTranslateCTM(c, 0, -CGContextGetClipBoundingBox(c).size.height);

    CGContextDrawImage(c, (CGRect){CGPointZero, {width, height}}, textureImage);
    CGContextRelease(c);

    GLuint glTex;
    glGenTextures(1, &glTex);
    glBindTexture(GL_TEXTURE_2D, glTex);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);

    glBindTexture(GL_TEXTURE_2D, 0);

    free(spriteData);

    return glTex;
}

顶点:

struct vertex {
    float position[3];
    float color[4];
    float texCoord[2];
};

typedef struct vertex vertex;

const vertex bgVertices[] = {
    {{1, -1, 0}, {0, 167.0/255.0, 253.0/255.0, 1}, {1, 0}}, // BR (0)
    {{1, 1, 0}, {0, 222.0/255.0, 1.0, 1}, {1, 1}}, // TR (1)
    {{-1, 1, 0}, {0, 222.0/255.0, 1.0, 1}, {0, 1}}, // TL (2)
    {{-1, -1, 0}, {0, 167.0/255.0, 253.0/255.0, 1}, {0, 0}} // BL (3)
};

const vertex textureVertices[] = {
    {{1, -1, 0}, {0, 0, 0, 0}, {1, 0}}, // BR (0)
    {{1, 1, 0}, {0, 0, 0, 0}, {1, 1}}, // TR (1)
    {{-1, 1, 0}, {0, 0, 0, 0}, {0, 1}}, // TL (2)
    {{-1, -1, 0}, {0, 0, 0, 0}, {0, 0}} // BL (3)
};

const GLubyte indicies[] = {
    3, 2, 0, 1
};

渲染代码:

glClear(GL_COLOR_BUFFER_BIT);

GLsizei width, height;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);

glViewport(0, 0, width, height);

glBindBuffer(GL_ARRAY_BUFFER, bgVertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);

glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)(sizeof(float)*3));
glVertexAttribPointer(textureCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)(sizeof(float)*7));

glDrawElements(GL_TRIANGLE_STRIP, sizeof(indicies)/sizeof(indicies[0]), GL_UNSIGNED_BYTE, 0);


glBindBuffer(GL_ARRAY_BUFFER, textureVertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(textureUniform, 0);

glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
glVertexAttribPointer(colorSlot, 4, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)(sizeof(float)*3));
glVertexAttribPointer(textureCoordSlot, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (GLvoid*)(sizeof(float)*7));

glDrawElements(GL_TRIANGLE_STRIP, sizeof(indicies)/sizeof(indicies[0]), GL_UNSIGNED_BYTE, 0);

glBindTexture(GL_TEXTURE_2D, 0);

我正在使用混合功能 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) 以防万一。

有什么想法吗?

【问题讨论】:

  • 您说您首先使用 CoreGraphics 将文本绘制到 CGImage 中。在您将其用作 GL 纹理之前, 的输出是什么样的?
  • 在 OP 中添加了 CG 输出
  • 对于您的问题,恐怕我仍然没有答案,但我可以告诉您它不是 .多重采样仅影响多边形边缘的光栅化,并且您正在查看纹理内容。这可能与您的纹理过滤模式和/或视口的大小和比例因子有关。
  • 同意...我已编辑 OP 以将问题集中在纹理导入和渲染上
  • 您基于self.frame 设置视口是一个警告信号。您在哪里设置渲染缓冲区?请记住,视图大小是按in points 测量的,根据屏幕的原生比例因子,每个点可能有 2 倍或更多像素。

标签: ios c opengl-es textures opengl-es-2.0


【解决方案1】:

您的 GL 渲染输出看起来都是像素化的,因为它的像素较少。根据Drawing and Printing Guide for iOSCAEAGLLayer 的默认比例因子为 1.0,因此当您设置 GL 渲染缓冲区时,缓冲区中的每个点都会得到一个像素。 (请记住,一个点是 UI 布局的一个单位,在配备 Retina 显示器的现代设备上,它可以处理几个硬件像素。)当您全屏渲染该缓冲区时,所有内容都会按比例放大(大约 2.61x on an iPhone 6(s) Plus)。

要以原生屏幕分辨率进行渲染,您需要增加视图的contentScaleFactor。 (最好在设置渲染缓冲区之前尽早执行此操作,以便它们从视图层获得新的比例因子。)

但请注意:您想使用the UIScreen property nativeScale,而不是scalescale 属性反映了 UI 渲染,在 iPhone 6(s) Plus 上,一切都以 3 倍完成,然后稍微缩小到显示器的原始分辨率。 nativeScale 属性反映了每个点的实际设备像素数 — 如果您正在执行 GPU 渲染,您希望将其作为目标,这样您就不会因为绘制比您需要的更多的像素而降低性能. (在“Plus” iPhone 之外的当前设备上,scalenativeScale 是相同的。但使用后者可能是一个很好的保险政策。)

通过让GLKView 为您设置渲染缓冲区,您可以避免很多此类问题(以及其他问题)。即使您正在编写跨平台的 GL,您的代码的这一部分也必须是非常特定于平台和设备的,因此您最好减少必须编写和维护的代码量。

(为了后代的缘故,解决问题的先前编辑:这与多重采样或 GL 纹理数据的质量无关。多重采样与多边形边缘的光栅化有关 - 内部的点多边形每个像素得到一个片段,但边缘上的点得到多个片段,它们的颜色在解析阶段混合。如果你将纹理绑定到 FBO 并从中glReadPixels,你会发现图像几乎是与您放入的相同。)

【讨论】:

  • 非常感谢您的帮助,信息量很大。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-08
  • 2012-07-28
相关资源
最近更新 更多