Shadow Mapping не работает в OpenGL ES 3.0 на Android - PullRequest
0 голосов
/ 17 января 2019

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

Я копал весь интернет, и ничто не помогло мне.Возможно, я что-то упустил в своем коде.

Здесь я начинаю с создания текстуры FBO и карты глубины:

//  create depthMap
int[] depthMapPtr = new int[1];
GLES30.glGenTextures(1, depthMapPtr, 0);
depthMap = depthMapPtr[0];

//  use depthMap
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, depthMap);

GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_DEPTH_COMPONENT16, size, size, 
    0, GLES30.GL_DEPTH_COMPONENT, GLES30.GL_UNSIGNED_SHORT, null);

GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_REPEAT);
GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_REPEAT);

//  create fbo
int[] fboPtr = new int[1];
GLES30.glGenFramebuffers(1, fboPtr, 0);
fbo = fboPtr[0];

//  use fbo
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, fbo);
GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, 
    GLES30.GL_DEPTH_ATTACHMENT, GLES30.GL_TEXTURE_2D, depthMap, 0);

//  draw/read buffers
int[] buffer = {GLES30.GL_NONE};
GLES30.glDrawBuffers(1, buffer, 0);
GLES30.glReadBuffer(GLES30.GL_NONE);

Затем я определяю шейдеры глубины для рендеринга моей сцены:

ВЕРТЕКС ШЕЙДЕР ДЛЯ ГЛУБИНЫ:

#version 300 es

layout (location = 0) in vec3 vPos;

uniform mat4 mLightSpace;
uniform mat4 mModel;

void main()
{
    gl_Position = mLightSpace * mModel * vec4(vPos, 1.0);
}

ФРАГМЕНТ ШЕЙДЕР ДЛЯ ГЛУБИНЫ:

#version 300 es


//out float fragDepth;

void main()
{
    //fragDepth = gl_FragCoord.z;
}

(комментарии ничего не меняют, результат тот же).

Перед рендерингом сцены с теневой перспективы, я использую этот фрагмент кода, чтобы изменить viewPort, очистить буфер глубины, связать FBO:

GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, 0);

//  clear the depth
GLES30.glClear(GLES30.GL_DEPTH_BUFFER_BIT);

GLES30.glViewport(0, 0, size, size);
GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, fbo);


//  use the shader program for the shadows
useProgramShadow();

После того, как я закончу рендеринг глубины, я готовлю вседля рендеринга сцены обычным способом:

GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);

GLES30.glViewport(0, 0, GLWindow.width, GLWindow.height);
GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);

GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, depthMap);


useProgram();

Затем я пропускаю все униформы + матрицу вида / проекции с точки зрения света и отрисовываю сцену.

Я нахожу фрагментПоложение с точки зрения света в вершинном шейдере с такими линиями:

const mat4 tMat = mat4(
    0.5, 0.0, 0.0, 0.0,
    0.0, 0.5, 0.0, 0.0,
    0.0, 0.0, 0.5, 0.0,
    0.5, 0.5, 0.5, 1.0
);

/* ... */

vFragPosLight = tMat * mLightSpace * mModel * vec4(vPosition, 1.0);

Чтобы затем получить текстуру vFragPosLight и depthMap

in vec4 vFragPosLight;
uniform sampler2DShadow depthMap;

... во фрагментешейдер и рассчитать тень с помощью этой линии:

textureProj(depthMap, vFragPosLight);

... который всегда возвращает 0!

При компиляции шейдера нет ошибок, нет ошибки привязки текстуры к фреймбуферу, похоже, все работает, find, но карта глубины пуста.

Я очень ценю вашу помощь и благодарю вас за то, что вы нашли время прочитать!

1 Ответ

0 голосов
/ 21 января 2019

Я до сих пор не знаю, в чем именно заключалась проблема, но я прочитал и использовал часть Shadow Mapping в этой книге об OpenGL ES 3.0 , которая работала.

Возможно, мне пришлось отключить все компоненты цветопередачи, если для glColorMask установлено значение False.

...