当前位置: 首页 > 知识库问答 >
问题:

OpenGL ES纹理质量下降

葛成济
2023-03-14

我试图绘制一个核心图形图像生成(在屏幕分辨率)到OpenGL。然而,图像呈现的别名比CG输出的更多(在CG中禁止抗锯齿)。文本是纹理(蓝色背景分别在核心图形中为第一幅图像绘制,在OpenGL中为第二幅图像绘制)。

OpenGL渲染(在模拟器中):

Framebuffer设置:

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);

共有1个答案

党博超
2023-03-14

GL呈现的输出看起来都是像素化的,因为它的像素较少。根据iOS的绘图和打印指南,CAEAGLLayer的默认比例因子为1.0,因此当您设置GL呈现缓冲区时,缓冲区中的每点有一个像素。(请记住,一个点是UI布局的一个单位,在带有视网膜显示器的现代设备上,它可以计算为几个硬件像素。)当你将缓冲区呈现为全屏时,所有内容都会被放大(在iPhone6(s)Plus上大约是2.61倍)。

要以本机屏幕分辨率呈现,需要增加视图的ContentScaleFactor。(最好是在设置renderbuffers之前尽早完成,这样它们就可以从视图的层中获得新的比例因子。)

但是要注意:您希望使用Uiscreen属性nativescale,而不是scalescale属性反映UI呈现,在iPhone6(s)Plus上,所有操作都以3倍的速度完成,然后稍微缩小到显示器的本机分辨率。nativescale属性反映每个点的实际设备像素数--如果您正在进行GPU渲染,您希望以该值为目标,这样就不会因为绘制超出需要的像素数而降低性能。(在除“Plus”iPhones以外的当前设备上,scalenativescale是相同的。但是使用后者可能是一个很好的保险策略。)

通过让glkview为您进行renderbuffer设置,您可以避免许多此类问题(以及其他问题)。即使您正在编写跨平台GL,这部分代码也必须是非常特定于平台和设备的,所以您最好减少您必须编写和维护的代码量。

(为了后代着想,解决前面的问题:这与多重采样或GL纹理数据的质量无关。多重采样与多边形边缘的光栅化有关--多边形内部的点每个像素得到一个片段,但边缘上的点得到多个片段,这些片段的颜色在解析阶段被混合。如果您将纹理绑定到FBO和GladPixels,您会发现图像与您输入的图像几乎相同。)

 类似资料:
  • 我正在尝试纹理球体。我的顶点着色器: 我的片段着色器: 我从二十面体构建球体,但使用6种相同的纹理对其进行纹理处理,并通过立方体映射原理将其连接起来。这是我如何将球坐标转换为UV的代码: 因此,我得到的只是可怕的纹理质量损失。这是原始纹理,也是我在球体上得到的(这里只有立方体贴图的一部分,其他面是红色的)。我猜这可能与建筑方法(二十面体)和纹理(立方体贴图)的不同有关。但它可以解释纹理不均匀的边缘

  • 在此之前,我们使用的材质都是单一颜色的,有时候,我们却希望使用图像作为材质。这时候,就需要导入图像作为纹理贴图,并添加到相应的材质中。下面,我们介绍具体的做法。 单张图像应用于长方体 例4.5.1 首先,我们选择一张长宽均为128像素的图像: 将其导入纹理中: var texture = THREE.ImageUtils.loadTexture('../img/0.png'); 然后,将材质的m

  • 创建和使用材质 通过主菜单 Assets->Create->Material 或项目视图的上下文菜单,可以创建一个新材质。 默认情况下,新建材质会分配标准着色器,并且所有属性都空着,就像这样: 一旦材质被创建,你就可以把它应用到一个对象,并且在 检视视图 中修改它的所有属性。想把材质应用到一个对象上,只需要把材质从 项目视图 拖动到 场景是图 或 层级视图 中的任意对象上。 设置材质属性 你可以为

  • 映射模式 THREE.UVMapping THREE.CubeReflectionMapping THREE.CubeRefractionMapping THREE.EquirectangularReflectionMapping THREE.EquirectangularRefractionMapping THREE.CubeUVReflectionMapping THREE.CubeUVRef

  • 🕒岗位/面试时间 质量运营 base上海 10.25 11:00 线上面试 约半小时 1.自我介绍 2.为什么保研到现在的学校? 3.哪里人?为什么要来上海?今年就业形式怎么样? 4.为什么选择这个岗位? 5.依次介绍一下项目 6.你项目中的质量运营该怎么做? 7.学术成果与项目有关吗? 8.你与研发有不同意见怎么办? 反问: 职业需求 要补充技术短板 🤔面试感受 面试官人很好,体验超级棒!就

  • 材质、着色器、纹理 在 Unity 中,渲染通过 材质、着色器 和 纹理 完成。 在 Unity 中,材质、着色器和纹理之间的关系非常紧密。 材质 定义了应该如何渲染表面,包含了对贴图的引用、拼接信息、颜色等等。材质的有效选项取决于所使用的的着色器。 着色器 是一些小脚本,包含了计算每个像素渲染颜色的数学计算和算法,基于光照输入和材质配置。 纹理 是一些位图图像。一个材质可以包含对多个纹理的引用,