Почему цвета пикселей не соответствуют в OpenGL ES 2.0 на Android? - PullRequest
6 голосов
/ 15 февраля 2012

(Edit: я попробовал образец, который просто нарисовал треугольник без какой-либо текстуры или шейдеров и только OpenGL-ES 1.1 на моем устройстве и мог видеть те же самые артефакты. Я попробовал тот же самый образец в эмуляторе, и там не было никаких артефактовМожет ли это быть проблемой Tegra 2, или мне нужно установить определенное состояние или что-то, что не нужно в эмуляторе?)

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

Вот увеличенный скриншот проблемы.Вокруг белой линии темные значения немного ярче, чем они должны быть:

enter image description here

Я уже пробовал:

GLES20.glDisable(GLES20.GL_DITHER);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST );
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST );
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE );
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE );

, но это не имело никакого эффекта.Пиксели просто немного отключены.Его легко увидеть между темным и белым пикселем, потому что темный пиксель рядом с ним немного ярче, и проверка значений r, g, b с помощью программы рисования показывает мне это тоже.

Может кто-нибудь помочь мне с этим?

Дополнительная информация:

ЦП моего устройства - Tegra 2.0.Я рендерил квадрат 256x256 точно в 256x256 пикселей (я проверил это, взяв снимок экрана с затмением DDMS).Прозрачность отключена, и растровое изображение имеет альфа-значение 255 для каждого пикселя.Я создал поверхность как 32-битную поверхность с альфа-формулой:

    glSurface.setEGLConfigChooser(8, 8, 8, 8, 0, 0);

Я упростил код, но все еще вижу проблему при рендеринге с использованием следующих шейдеров:

    String vshaderquad =    "attribute vec4 a_pos;              \n" +   //  in      position
                            "attribute vec2 a_tex;              \n" +   //  in      Texture coordinates
                            "varying vec2 vtex;                 \n" +   //  out     Texture coordinates
                            "void main(void) {                  \n" +
                            "   gl_Position = vec4(a_pos);      \n" +
                            "   vtex = a_tex;                   \n" +
                            "}";

    String fshaderquad =    "precision mediump  float;                      \n" +
                            "varying vec2       vtex;                       \n" +
                            "uniform sampler2D  samp0;                      \n" +
                            "void main() {                                  \n" +
                            "   gl_FragColor = texture2D(samp0, vtex);      \n" +
                            "}";

и команд:

GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mapid[0]);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST );
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST );
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE );
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE );
GLES20.glUniform1i(handlesampler0, 0);
GLES20.glDisable(GLES20.GL_DITHER);



GLES20.glViewport(0, 0, screenx, screeny);

float screenx = (float)ddimx;
float screeny = (float)ddimy;
//
vdata.put(0*4+0,     0.0f * (2.0f/screenx));
vdata.put(0*4+1,   256.0f * (2.0f/screeny));
vdata.put(0*4+2,     0.0f * (1.0f/256f));
vdata.put(0*4+3,   256.0f * (1.0f/256f));
//  
vdata.put(1*4+0,     0.0f * (2.0f/screenx));
vdata.put(1*4+1,     0.0f * (2.0f/screeny));
vdata.put(1*4+2,     0.0f * (1.0f/256f));
vdata.put(1*4+3,     0.0f * (1.0f/256f));
//  
vdata.put(2*4+0,   256.0f * (2.0f/screenx));
vdata.put(2*4+1,   256.0f * (2.0f/screeny));
vdata.put(2*4+2,   256.0f * (1.0f/256f));
vdata.put(2*4+3,   256.0f * (1.0f/256f));
//  
vdata.put(3*4+0,   256.0f * (2.0f/screenx));
vdata.put(3*4+1,     0.0f * (2.0f/screeny));
vdata.put(3*4+2,   256.0f * (1.0f/256f));
vdata.put(3*4+3,     0.0f * (1.0f/256f));

GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

PS: Небольшое изменение цвета на самом деле не заметно без чрезмерного увеличения, но я хочу сделать вычисления со значениями, и это означает, что они просто должны быть точными.

Редактировать:Я добавил изображение в полном разрешении.Цвета на линиях должны быть от (0,0,0) до (255,255,255) и обратны градиенту фона.Я сделал это изображение только для проверки точности текстуры, и там я обнаружил проблему, которая не очень точна.Вы должны увеличить, хотя, чтобы различить, поэтому я также разместил увеличенное изображение.Примечание: координаты отличаются от приведенного выше кода, но проблема та же (я пробовал разные экранные координаты, и проблема сохраняется).

enter image description here

1 Ответ

3 голосов
/ 18 февраля 2012

Хорошо, я думаю, что нашел решение.

Как я уже писал, я сделал скриншот с затмением DDMS, и это, кажется, вызывает проблему. Этот скриншот не является точным кадровым буфером, но там происходит какое-то сглаживание / сглаживание.

Похоже, что это не результат самой DDMS, а только при использовании на моем реальном устройстве. Когда я попробовал его с эмулятором, эта проблема не появилась, поэтому могло случиться так, что у моего устройства был экран с экраном "пентиль" (пока он был выпущен только в Японии, и я не нашел никакого информационного материала, подтверждающего или опровергающего его, но его sony и sony сделали использовать дисплеи Pentile в устройствах) или, возможно, это связано с чипом Tegra 2, или, может быть, это своего рода сжатие, которое происходит во время передачи изображения, или, может быть, по какой-то другой причине.

В любом случае, когда я использую следующую функцию, я могу сохранить абсолютно идеальные снимки экрана, так как он использует кадровый буфер OpenGL-ES 2.0 и сохраняет его в png-файле, который затем можно легко перенести с помощью пакетного файла («adb pull»). /mnt/sdcard/info/Testfile.txt ") и просмотр на моем компьютере:

public boolean SaveFrameBuffer(int x, int y)
{   try
    {   IntBuffer   pinbuffer   = IntBuffer.allocate(x*y*4);
        IntBuffer   poutbuffer  = IntBuffer.allocate(x*y*4);
        int         i,j,z;
        int []      pin         = pinbuffer.array();
        int []      pout        = poutbuffer.array();
        //
        GLES20.glReadPixels(0, 0, x, y, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, pinbuffer);            
        for(i=0;i<y;i++)
        {   for(j=0;j<x;j++)
            {   z = pin[(y-1-i)*x+j];
                pout[i*x+j] = (z & 0xff000000) | ((z >> 16) & 0x000000ff) | ((z << 16) & 0x00ff0000) | (z  & 0x0000ff00); 
            }
        }
        Bitmap map = Bitmap.createBitmap(x, y, Bitmap.Config.ARGB_8888);
        map.setPixels(pout, 0, x, 0,0, x, y);
        OutputStream stream = new FileOutputStream("/sdcard/info/test.png");
        map.compress(CompressFormat.PNG, 100, stream);
        stream.close();
        return true;
    } catch (Exception e)
    {   e.printStackTrace();
        return false;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...