Различия в загрузке текстуры iPad (32-разрядные и 64-разрядные)

Я работаю над графическим приложением, и я замечаю существенные различия в текстурах, загружаемых в 32-разрядный iPad против 64-битного iPad.

Вот текстура, нарисованная на 32-битном iPad:

enter image description here

Вот текстура, нарисованная на 64-битном iPad:

enter image description here

64-битный - это то, что я хочу, но похоже, что он теряет некоторые данные?

Я создаю текстуру кисти по умолчанию с помощью этого кода:

UIGraphicsBeginImageContext(CGSizeMake(64, 64));
CGContextRef defBrushTextureContext = UIGraphicsGetCurrentContext();
UIGraphicsPushContext(defBrushTextureContext);

size_t num_locations = 3;
CGFloat locations[3] = { 0.0, 0.8, 1.0 };
CGFloat components[12] = { 1.0,1.0,1.0, 1.0,
    1.0,1.0,1.0, 1.0,
    1.0,1.0,1.0, 0.0 };
CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
CGGradientRef myGradient = CGGradientCreateWithColorComponents (myColorspace, components, locations, num_locations);

CGPoint myCentrePoint = CGPointMake(32, 32);
float myRadius = 20;

CGGradientDrawingOptions options = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation;
CGContextDrawRadialGradient (UIGraphicsGetCurrentContext(), myGradient, myCentrePoint,
                             0, myCentrePoint, myRadius,
                             options);

CFRelease(myGradient);
CFRelease(myColorspace);
UIGraphicsPopContext();

[self setBrushTexture:UIGraphicsGetImageFromCurrentImageContext()];

UIGraphicsEndImageContext();

И тогда на самом деле установите текстуру кисти следующим образом:

-(void) setBrushTexture:(UIImage*)brushImage{
// save our current texture.
currentTexture = brushImage;

// first, delete the old texture if needed
if (brushTexture){
    glDeleteTextures(1, &brushTexture);
    brushTexture = 0;
}

// fetch the cgimage for us to draw into a texture
CGImageRef brushCGImage = brushImage.CGImage;

// Make sure the image exists
if(brushCGImage) {
    // Get the width and height of the image
    GLint width = CGImageGetWidth(brushCGImage);
    GLint height = CGImageGetHeight(brushCGImage);

    // Texture dimensions must be a power of 2. If you write an application that allows users to supply an image,
    // you'll want to add code that checks the dimensions and takes appropriate action if they are not a power of 2.

    // Allocate  memory needed for the bitmap context
    GLubyte* brushData = (GLubyte *) calloc(width * height * 4, sizeof(GLubyte));
    // Use  the bitmatp creation function provided by the Core Graphics framework.
    CGContextRef brushContext = CGBitmapContextCreate(brushData, width, height, 8, width * 4, CGImageGetColorSpace(brushCGImage), kCGImageAlphaPremultipliedLast);
    // After you create the context, you can draw the  image to the context.
    CGContextDrawImage(brushContext, CGRectMake(0.0, 0.0, (CGFloat)width, (CGFloat)height), brushCGImage);
    // You don't need the context at this point, so you need to release it to avoid memory leaks.
    CGContextRelease(brushContext);

    // Use OpenGL ES to generate a name for the texture.
    glGenTextures(1, &brushTexture);
    // Bind the texture name.
    glBindTexture(GL_TEXTURE_2D, brushTexture);
    // Set the texture parameters to use a minifying filter and a linear filer (weighted average)
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    // Specify a 2D texture image, providing the a pointer to the image data in memory
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, brushData);
    // Release  the image data; it no longer needed
    free(brushData);
}
}

Update:

Я обновил CGFloats, чтобы быть GLfloats без успеха. Может быть, есть проблема с этим кодом рендеринга?

if(frameBuffer){
    // draw the stroke element
    [self prepOpenGLStateForFBO:frameBuffer];
    [self prepOpenGLBlendModeForColor:element.color];
    CheckGLError();
}

// find our screen scale so that we can convert from
// points to pixels
GLfloat scale = self.contentScaleFactor;

// fetch the vertex data from the element
struct Vertex* vertexBuffer = [element generatedVertexArrayWithPreviousElement:previousElement forScale:scale];

glLineWidth(2);

// if the element has any data, then draw it
if(vertexBuffer){
    glVertexPointer(2, GL_FLOAT, sizeof(struct Vertex), &vertexBuffer[0].Position[0]);
    glColorPointer(4, GL_FLOAT, sizeof(struct Vertex), &vertexBuffer[0].Color[0]);
    glTexCoordPointer(2, GL_FLOAT, sizeof(struct Vertex), &vertexBuffer[0].Texture[0]);
    glDrawArrays(GL_TRIANGLES, 0, (GLint)[element numberOfSteps] * (GLint)[element numberOfVerticesPerStep]);
    CheckGLError();
}

if(frameBuffer){
    [self unprepOpenGLState];
}

Структура вершин следующая:

struct Vertex{
    GLfloat Position[2];    // x,y position
    GLfloat Color [4];      // rgba color
    GLfloat Texture[2];    // x,y texture coord
};

Update:

Проблема на самом деле не является 32-разрядной, основанной на 64-разрядных версиях, а скорее чем-то отличной от драйверов A7 GPU и GL. Я нашел это, запустив 32-битную сборку и 64-битную сборку на 64-битном iPad. Текстуры оказались одинаково похожими на обеих сборках приложения.

Ответ 1

Я бы хотел, чтобы вы проверили две вещи.

  • Проверьте логику альфа-смешивания (или опцию) в OpenGL.

  • Проверьте свою логику интерполяции, которая пропорциональна скорости перетаскивания.

Кажется, у вас нет второго или неэффективного, который требуется для рисования приложения

Ответ 2

Я не думаю, что проблема заключается в текстуре, но в буфере кадров, к которому вы добавляете элементы строки.

Ваши фрагменты кода выглядят так, как будто вы рисуете сегменты по сегментам, поэтому есть несколько перекрывающихся сегментов, нарисованных друг над другом. Если глубина буфера кадра низкая, то будут артефакты, особенно в более светлых областях смешанных областей.

Вы можете проверить буфер кадра с помощью отладчика Xcode OpenGL. Активируйте его, запустив код на устройстве и нажмите маленькую кнопку "Capture OpenGL ES Frame": Capture OpenGL ES Frame.

Выберите команду "glBindFramebuffer" в "Debug Navigator" и посмотрите описание буфера фрейма в области консоли:

frame buffer description

Интересной частью является GL_FRAMEBUFFER_INTERNAL_FORMAT.

Ответ 3

На мой взгляд, проблема заключается в режиме смешивания, который вы используете при составлении разных проходов изображения. Я предполагаю, что вы загружаете текстуру только для отображения и сохраняете изображение в памяти, где вы комбинируете различные операции рисования, или читаете содержимое изображения с помощью glReadPixels? В основном ваши два изображения выглядят как прямое альфа-изображение, нарисованное как предварительно умноженное альфа-изображение. Чтобы убедиться, что это не проблема текстуры, сохраните файл NSImage перед загрузкой в ​​текстуру и убедитесь, что изображение действительно правильно.