Страницы

Поиск по вопросам

Показаны сообщения с ярлыком opengles. Показать все сообщения
Показаны сообщения с ярлыком opengles. Показать все сообщения

среда, 4 марта 2020 г.

JNI DETECTED ERROR IN APPLICATION: jarray was NULL

#java #android #opengles


Всем привет, у меня возникла ошибка вот в этом куске кода :

GLES30.glGenVertexArrays(1, vao, 0);

GLES30.glBindVertexArray(vao[0]);

int[] vbo = new int[1];
int[] vbo_indices = new int[1];
GLES20.glGenBuffers(1, vbo, 0);
GLES20.glGenBuffers(1, vbo_indices, 0);

FloatBuffer posBuffer = BufferUtils.createFloatBuffer(positions.length);
posBuffer.put(positions);
posBuffer.position(0);

GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0]);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, positions.length * 4, posBuffer, GLES30.GL_STATIC_DRAW);
GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false, 0, 0);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0);

IntBuffer indicesBuf = BufferUtils.createIntBuffer(indices.length);
indicesBuf.put(indices);
indicesBuf.position(0);

GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, vbo_indices[0]);
GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER, indicesBuf.capacity() * 4, indicesBuf,
GLES30.GL_STATIC_DRAW);
GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0);

zGLES30.glBindVertexArray(0);


Если точнее, то в :

GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER, indicesBuf.capacity() * 4, indicesBuf,
GLES30.GL_STATIC_DRAW);GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER, indicesBuf.capacity()
* 4, indicesBuf, GLES30.GL_STATIC_DRAW);


Вот сама ошибка :

JNI DETECTED ERROR IN APPLICATION: jarray was NULL
in call to GetPrimitiveArrayCritical
from void android.opengl.GLES20.glBufferData(int, int, java.nio.Buffer, int)


Вот еще функция crateIntBuffer: 

public static IntBuffer createIntBuffer(int numInts) {
    ByteBuffer buffer = ByteBuffer.allocate(numInts * 4);
    buffer.order(ByteOrder.nativeOrder());
    return buffer.asIntBuffer();
}


Прошу тех кто знает в чем проблема помочь, заранее спасибою.
    


Ответы

Ответ 1



Используйте ByteBuffer.allocateDirect(...) в BufferUtils.createFloatBuffer(positions.length); Проблема в том, что glBufferData требует direct-буфер, который можно эффективно использовать совместно с нативным кодом. Если же используется ByteBuffer.allocate(...) или что-то вроде FloatBuffer.wrap(...), то это не будет direct-буфером. Поэтому надо использовать ByteBuffer.allocateDirect(...) для выделения буфера и ByteBuffer.put(...) для его инициализации.

четверг, 23 января 2020 г.

Проблема в OpenGL с неверными координатами вывода изображения

#java #android #opengl #opengles


Всем привет! Возникла проблема с glViewport в OpenGL ES 2.0 под Android.
Я реализовал следующий алгоритм. Изображение генерируется в текстуру с использованием
FBO. Шейдер, который генерирует изображение, также принимает на вход предыдущую отрисованную
текстуру того же размера. Шейдер использует ее для более быстрой генерации следующей
текстуры. 
Для всего этого у меня есть 2 фреймбуфера (+ экранный фреймбуфер), к каждому из которых
приаттачена 1 текстура. После каждого цикла отрисовки ссылки на фреймбуферы меняются
местами, чтобы каждый раз не копировать предыдущее изображение.
Размер текстуры степени 2, т.е. размеры текстуры и экрана не совпадают.

Итак, проблема в том, что на экран рендерится не вся текстура, а лишь ее часть.

Код отрисовки:

//Меняем местами ссылки на буферы
evenRender = !evenRender;
int srcFB = evenRender? 0:1;
int dstFB = evenRender? 1:0;

//Привязываем буфер, куда будет генерироваться изображение
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferID[dstFB]);
//Выбираем размеры окна вывода как размеры экрана устройства
**GLES20.glViewport(0, 0, mScreenWidth, mScreenHeight);**
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

//Выбираем предыдущую отрисованную текстуру
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + srcFB);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, frameTextureID[srcFB]);

//Устанавливаем шейдер для генерации изображения
GLES20.glUseProgram(sp_ImageGeneration);

int mPositionHandle = GLES20.glGetAttribLocation(sp_ImageGeneration, "vPosition");
GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, offscreen_vertexBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);

int mTexCoordLoc = GLES20.glGetAttribLocation(sp_ImageGeneration, "a_texCoord");
GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT, false, 0, offscreen_uvBuffer);
GLES20.glEnableVertexAttribArray(mTexCoordLoc);

...

//Отправляем шейдеру предыдущую отрисованную текстуру
int mSamplerLoc = GLES20.glGetUniformLocation (sp_ImageGeneration, "prev_frame" );
GLES20.glUniform1i(mSamplerLoc, srcFB);

GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT,
drawListBuffer);

GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordLoc);

//Привязываем экранный буфер
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
GLES20.glViewport(0, 0, mScreenWidth, mScreenHeight);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

//Выбираем текстуру в том буфере, куда генерировалось изображение
GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + dstFB);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, frameTextureID[dstFB]);

// Устанавливаем простой шейдер
GLES20.glUseProgram(sp_Image);

mPositionHandle = GLES20.glGetAttribLocation(sp_Image, "vPosition");
GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
GLES20.glEnableVertexAttribArray(mPositionHandle);
mTexCoordLoc = GLES20.glGetAttribLocation(sp_Image, "a_texCoord" );
GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT, false, 0, uvBuffer);
GLES20.glEnableVertexAttribArray(mTexCoordLoc);

...

//Отправляем шейдеру текстуру, куда генерировалось изображение
mSamplerLoc = GLES20.glGetUniformLocation (sp_Image, "s_texture" );
GLES20.glUniform1i(mSamplerLoc, dstFB);

GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT,
drawListBuffer);

GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glDisableVertexAttribArray(mTexCoordLoc);
GLES20.glUseProgram(0);

GLES20.glActiveTexture(0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);


Координаты треугольников, на которые происходит отрисовка:

float koefWidth = (float)texSize / mScreenWidth;
float koefHeight = (float)texSize / mScreenHeight;

vertices = new float[] {
        0, 0, 0f,
        0, mScreenHeight * koefHeight, 0f,
        mScreenWidth * koefWidth, mScreenHeight * koefHeight, 0f,
        mScreenWidth * koefWidth, 0, 0f
};

offscreen_vertices = new float[] {
        0, 0, 0f,
        0, mScreenHeight * koefHeight* koefHeight, 0f,
        mScreenWidth * koefWidth * koefWidth , mScreenHeight * koefHeight* koefHeight, 0f,
        mScreenWidth * koefWidth * koefWidth, 0, 0f
};


texSize - размер текстуры. Например, mScreenWidth = 800, mScreenHeight = 600, texSize
= 1024.

Координаты текстур uvs и offscreen_uvs одинаковы:

uvs = new float[] {
            0, 0,
            0, 1,
            1, 1,
            1, 0,
    };


Фреймбуферы и текстуры для них были созданы так:

    frameBufferID = new int[2];
    frameTextureID = new int[2];

    GLES20.glGenFramebuffers(2, frameBufferID, 0);
    GLES20.glGenTextures(2, frameTextureID, 0);
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferID[0]);
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, frameTextureID[0]);

    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, texSize, texSize,
0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, null);
    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.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
GLES20.GL_TEXTURE_2D, frameTextureID[0], 0);

    //Next framebuffer
    GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferID[1]);
    GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + 1);
    GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, frameTextureID[1]);
    GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, texSize, texSize,
0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, null);
    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.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
    GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
    GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0,
GLES20.GL_TEXTURE_2D, frameTextureID[1], 0);


Я очень долго пробовал менять значения в glViewport, выделенном звездочками, а также
координаты треугольников. Но тогда либо возникали графические артефакты, либо сильно
падала производительность.
Заранее спасибо!
    


Ответы

Ответ 1



Вопрос решен. Оказалось, "графические артефакты" были связаны со спецификой работы моего шейдера. Он берет текстуры из фреймбуфера, но я не учитывал то, что эти текстуры были уменьшены glViewport'ом. Из-за этого данные текстур обрабатывались неправильно, что и выливалось в артефакты результирующего изображения. Решилось добавлением в шейдер соответствующих коэффициентов при обработке текстур. Эта проблема мучила меня на протяжении недели, и теперь я очень рад! :)

четверг, 2 января 2020 г.

Для чего нужны фреймбуферы?

#opengl #графика #webgl #opengles


Для чего нужны фреймбуферы в opengl? Я может не точно задаю вопрос, но я и не понимаю
как его задать. Я читаю книгу по opengl es 3. Там описано какие есть функции, но для
чего использовать или когда использовать я не пойму. Также есть что-то типа рендерить
фреймбуфер в текстуру.
    


Ответы

Ответ 1



Что такое фреймбуфер (OpenGL FrameBuffer, WebGL FrameBuffer)? Когда Вы вызываете методы отрисовки, в соответствии с текущими настройками графического конвейера заполняется несколько буферов размером с область отрисовки (буфер цвета, опционально буфер глубины, буфер трафарета). Такая группа буферов и называется фреймбуфером. Базовый фреймбуфер создается и настраивается в момент создания окна приложения. Базовый фреймбуфер привязывается по умолчанию. У Вас есть возможность создавать и привязывать дополнительные фреймбуферы. Создавая собственный фреймбуфер Вы получаете дополнительное пространство куда можно направить ортрисовку. Привязывая не базовый фреймбуфер Вы говорите таким образом конвейеру, что хотите чтобы все последующие вызовы отрисовки происходили в него. Фреймбуфер, сам по себе это только точка привязки, к нему привязываются так называемые рендер-тектуры. Рендер текстуры уже будут хранить непосредственно цветовую информацию. После наполнения фрейм буфера(ов) Вы привязываете базовй фреймбуфер и рисуете уже на экране, используя при отрисовке информацию из фреймбуфера(ов). Для чего это можно и нужно использовать? Самое очевидное - программная генерация текстур. Deferred Shading - Отложенное освещение и затенение. Это такая техника, при которой финальный цвет фрагмента определяется при отрисовке одного прямоугольника, закрывающего всю область экрана. При этом во фрагментном шейдере берутся значения из рендер текстур и из этих значений вычисляется финальный цвет. Тут есть важный момент что в этом случае скорость выполнения второго этапа не зависит от сложности сцены, а зависит от размера кадра. G-Buffer (Geometry Buffer) - специальное название для группы текстур при отложенном рендеринге: Результат (много источников света): Depth of Field или DoF - глубина резкости, пожалуй самый простой для понимания эффект - он применяет blur помноженный на значение из текстуры глубины. High Dynamic Range Compression или HDR - технология расширения диапазона яркости кадра подробнее тут (тут) Bloom - своеобразный эффект свечения, заключается в размытии границ ярких объектов. Screen Space Ambient Occlusion (SSAO), обманка с самозатенением - про я недавно писал ответ на вопрос тут. Screen Space Reflections (SSR) - Алгоритм который позволяет получить отражения для плоских поверхностей. При этом отразится может лишь то, что попало в кадр - подходит для горизонтальных поверхностей вроде луж на земле. Screen Space Subsurface Scattering (SSSS) - Подповерхностное рассеивание описывает механизм распространения света, при котором свет, проникая внутрь полупрозрачного тела через его поверхность, рассеивается внутри самого тела, многократно отражаясь от частиц тела в случайном направлении и на нерегулярные углы. В итоге свет выходит из объекта в выходной точке, отличной от точки вхождения в объект Screen-Space Percentage-Closer Soft Shadows

пятница, 27 декабря 2019 г.

Проблема с освещением в шейдере opengl es 2.0

#android #shader #opengles


Имеется ландшафт который я хочу осветить. Собственно везде освещение нормальное,
а ближе к центру огромное белое пятно! Я пока не пойму из за чего это пятно, и как
это исправить. Нужна помощь. Мне нужно понять из за чего это белое пятно выходит, и
понять как его исправить?

Вот скриншет со смартфона samsung galaxy S4



Теперь покажу как на эмуляторе andy



Теперь покажу как распологаются нормали



Вот код фрагментного шейдера:

precision mediump float;
varying vec3 vPosition;
uniform sampler2D uTexture;
uniform sampler2D uTexture2;
uniform vec3 u_camera;
varying vec2 vTexcoord;
varying vec3 v_normal;

float getLight(vec3 lightPos,vec3 camPos,vec3 vertexPos, vec3 normal,
               float ambient, float k_diffuse, float k_specular)
{
    vec3 n_normal=normalize(normal);
    vec3 lightvector = normalize(lightPos - vertexPos);
    vec3 lookvector = normalize(camPos - vertexPos);
    float diffuse = k_diffuse * max(dot(n_normal, lightvector), 0.0);
    vec3 reflectvector = reflect(-lightvector, n_normal);
    float specular = k_specular * pow( max(dot(lookvector,reflectvector),0.0), 60.0
);      
    return ambient+diffuse+specular;
}


void main() {
    vec3 lightPos = vec3(60.0,100.0,-415.0);
    float light = getLight(lightPos,u_camera,vPosition,v_normal,
                           0.5,  0.9,   0.3);

    vec4 pixsel;
    vec3 pos = normalize(vPosition);
    if (pos.y > 0.01) 
        pixsel = texture2D(uTexture2,vTexcoord); 
    else 
        pixsel = texture2D(uTexture,vTexcoord);

    gl_FragColor = light * pixsel;
}

    


Ответы

Ответ 1



Проблема решена, на самом деле не верно передавались координаты камеры.

Вывести буфер пикселей на экран при помощи OpenGL ES

#cpp #c #opengl #android_ndk #opengles


Имеется сгенерированный буфер пикселей. Вывожу их на экран при помощи ANativeWindow_lock
и ANativeWindow_unlockAndPost. Такой метод работает очень медленно. Хочу ускорить вывод
графики. Подскажите как при помощи OpenGL ES вывести буфер пикселей на экран. Или может
возможно как то ускорить вывод через ANativeWindow_lock?
    


Ответы

Ответ 1



Через OpenGL, самое простое и быстрое - создать текстуру и вывести ее на экран (используя квад и шейдеры, раз уж вопрос про OpenGL ES).

пятница, 15 марта 2019 г.

Проблема в OpenGL с неверными координатами вывода изображения

Всем привет! Возникла проблема с glViewport в OpenGL ES 2.0 под Android. Я реализовал следующий алгоритм. Изображение генерируется в текстуру с использованием FBO. Шейдер, который генерирует изображение, также принимает на вход предыдущую отрисованную текстуру того же размера. Шейдер использует ее для более быстрой генерации следующей текстуры. Для всего этого у меня есть 2 фреймбуфера (+ экранный фреймбуфер), к каждому из которых приаттачена 1 текстура. После каждого цикла отрисовки ссылки на фреймбуферы меняются местами, чтобы каждый раз не копировать предыдущее изображение. Размер текстуры степени 2, т.е. размеры текстуры и экрана не совпадают.
Итак, проблема в том, что на экран рендерится не вся текстура, а лишь ее часть.
Код отрисовки:
//Меняем местами ссылки на буферы evenRender = !evenRender; int srcFB = evenRender? 0:1; int dstFB = evenRender? 1:0;
//Привязываем буфер, куда будет генерироваться изображение GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferID[dstFB]); //Выбираем размеры окна вывода как размеры экрана устройства **GLES20.glViewport(0, 0, mScreenWidth, mScreenHeight);** GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
//Выбираем предыдущую отрисованную текстуру GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + srcFB); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, frameTextureID[srcFB]);
//Устанавливаем шейдер для генерации изображения GLES20.glUseProgram(sp_ImageGeneration);
int mPositionHandle = GLES20.glGetAttribLocation(sp_ImageGeneration, "vPosition"); GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, offscreen_vertexBuffer); GLES20.glEnableVertexAttribArray(mPositionHandle);
int mTexCoordLoc = GLES20.glGetAttribLocation(sp_ImageGeneration, "a_texCoord"); GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT, false, 0, offscreen_uvBuffer); GLES20.glEnableVertexAttribArray(mTexCoordLoc);
...
//Отправляем шейдеру предыдущую отрисованную текстуру int mSamplerLoc = GLES20.glGetUniformLocation (sp_ImageGeneration, "prev_frame" ); GLES20.glUniform1i(mSamplerLoc, srcFB);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle); GLES20.glDisableVertexAttribArray(mTexCoordLoc);
//Привязываем экранный буфер GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); GLES20.glViewport(0, 0, mScreenWidth, mScreenHeight); GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
//Выбираем текстуру в том буфере, куда генерировалось изображение GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + dstFB); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, frameTextureID[dstFB]);
// Устанавливаем простой шейдер GLES20.glUseProgram(sp_Image);
mPositionHandle = GLES20.glGetAttribLocation(sp_Image, "vPosition"); GLES20.glVertexAttribPointer(mPositionHandle, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer); GLES20.glEnableVertexAttribArray(mPositionHandle); mTexCoordLoc = GLES20.glGetAttribLocation(sp_Image, "a_texCoord" ); GLES20.glVertexAttribPointer ( mTexCoordLoc, 2, GLES20.GL_FLOAT, false, 0, uvBuffer); GLES20.glEnableVertexAttribArray(mTexCoordLoc);
...
//Отправляем шейдеру текстуру, куда генерировалось изображение mSamplerLoc = GLES20.glGetUniformLocation (sp_Image, "s_texture" ); GLES20.glUniform1i(mSamplerLoc, dstFB);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length, GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle); GLES20.glDisableVertexAttribArray(mTexCoordLoc); GLES20.glUseProgram(0);
GLES20.glActiveTexture(0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
Координаты треугольников, на которые происходит отрисовка:
float koefWidth = (float)texSize / mScreenWidth; float koefHeight = (float)texSize / mScreenHeight;
vertices = new float[] { 0, 0, 0f, 0, mScreenHeight * koefHeight, 0f, mScreenWidth * koefWidth, mScreenHeight * koefHeight, 0f, mScreenWidth * koefWidth, 0, 0f };
offscreen_vertices = new float[] { 0, 0, 0f, 0, mScreenHeight * koefHeight* koefHeight, 0f, mScreenWidth * koefWidth * koefWidth , mScreenHeight * koefHeight* koefHeight, 0f, mScreenWidth * koefWidth * koefWidth, 0, 0f };
texSize - размер текстуры. Например, mScreenWidth = 800, mScreenHeight = 600, texSize = 1024.
Координаты текстур uvs и offscreen_uvs одинаковы:
uvs = new float[] { 0, 0, 0, 1, 1, 1, 1, 0, };
Фреймбуферы и текстуры для них были созданы так:
frameBufferID = new int[2]; frameTextureID = new int[2];
GLES20.glGenFramebuffers(2, frameBufferID, 0); GLES20.glGenTextures(2, frameTextureID, 0); GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferID[0]); GLES20.glActiveTexture(GLES20.GL_TEXTURE0); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, frameTextureID[0]);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, texSize, texSize, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, null); 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.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, frameTextureID[0], 0);
//Next framebuffer GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, frameBufferID[1]); GLES20.glActiveTexture(GLES20.GL_TEXTURE0 + 1); GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, frameTextureID[1]); GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, texSize, texSize, 0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_BYTE, null); 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.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, frameTextureID[1], 0);
Я очень долго пробовал менять значения в glViewport, выделенном звездочками, а также координаты треугольников. Но тогда либо возникали графические артефакты, либо сильно падала производительность. Заранее спасибо!


Ответ

Вопрос решен. Оказалось, "графические артефакты" были связаны со спецификой работы моего шейдера. Он берет текстуры из фреймбуфера, но я не учитывал то, что эти текстуры были уменьшены glViewport'ом. Из-за этого данные текстур обрабатывались неправильно, что и выливалось в артефакты результирующего изображения. Решилось добавлением в шейдер соответствующих коэффициентов при обработке текстур. Эта проблема мучила меня на протяжении недели, и теперь я очень рад! :)

среда, 5 декабря 2018 г.

Проблема с освещением в шейдере opengl es 2.0

Имеется ландшафт который я хочу осветить. Собственно везде освещение нормальное, а ближе к центру огромное белое пятно! Я пока не пойму из за чего это пятно, и как это исправить. Нужна помощь. Мне нужно понять из за чего это белое пятно выходит, и понять как его исправить?
Вот скриншет со смартфона samsung galaxy S4

Теперь покажу как на эмуляторе andy

Теперь покажу как распологаются нормали

Вот код фрагментного шейдера:
precision mediump float; varying vec3 vPosition; uniform sampler2D uTexture; uniform sampler2D uTexture2; uniform vec3 u_camera; varying vec2 vTexcoord; varying vec3 v_normal;
float getLight(vec3 lightPos,vec3 camPos,vec3 vertexPos, vec3 normal, float ambient, float k_diffuse, float k_specular) { vec3 n_normal=normalize(normal); vec3 lightvector = normalize(lightPos - vertexPos); vec3 lookvector = normalize(camPos - vertexPos); float diffuse = k_diffuse * max(dot(n_normal, lightvector), 0.0); vec3 reflectvector = reflect(-lightvector, n_normal); float specular = k_specular * pow( max(dot(lookvector,reflectvector),0.0), 60.0 ); return ambient+diffuse+specular; }
void main() { vec3 lightPos = vec3(60.0,100.0,-415.0); float light = getLight(lightPos,u_camera,vPosition,v_normal, 0.5, 0.9, 0.3);
vec4 pixsel; vec3 pos = normalize(vPosition); if (pos.y > 0.01) pixsel = texture2D(uTexture2,vTexcoord); else pixsel = texture2D(uTexture,vTexcoord);
gl_FragColor = light * pixsel; }


Ответ

Проблема решена, на самом деле не верно передавались координаты камеры.