Opengl 3.3+ неправильные тени при использовании карты теней

Я пытаюсь реализовать отображение теней в своем ландшафтном редакторе с помощью OpenGL 3.3+. Используя несколько руководств, мне удалось скомпилировать и запустить мой код, но весь ландшафт находится в тени, за исключением заднего ряда моей ландшафтной сетки (наименьший z).

В настоящее время я использую те же матрицы проекции, вида и модели для моего света, что и камера (отрицательное значение z находится дальше всего от камеры).

Инициализация моих матриц проекций, представлений и моделей (из учебника по матрицам LWJGL):

modelPos = new Vector3f(0f, 0f, -20f);
modelAngle = new Vector3f(15f, 0f, 0f);
modelScale = new Vector3f(1f, 1f, 1f);
cameraPos = new Vector3f(-50f, 0f, -120f);

projectionMatrix = new Matrix4f();

float fieldOfView = 120f;
float aspectRatio = (float)width / (float)height;
float near_plane = 0.01f;
float far_plane = 100f;

float y_scale = DepthMatrixUtility.coTangent(DepthMatrixUtility.degreesToRadians(fieldOfView / 2f));
float x_scale = y_scale / aspectRatio;
float frustum_length = far_plane - near_plane;

projectionMatrix.m00 = x_scale;
projectionMatrix.m11 = y_scale;
projectionMatrix.m22 = -((far_plane + near_plane) / frustum_length);
projectionMatrix.m23 = -1;
projectionMatrix.m32 = -((2 * near_plane * far_plane) / frustum_length);

Привязка моих матриц при отображении сцены:

Matrix4f.translate(cameraPos, viewMatrix, viewMatrix);
Matrix4f.scale(modelScale, modelMatrix, modelMatrix);
Matrix4f.translate(modelPos, modelMatrix, modelMatrix);

Matrix4f.rotate(DepthMatrixUtility.degreesToRadians(modelAngle.z), new Vector3f(0, 0, 1), modelMatrix, modelMatrix);
Matrix4f.rotate(DepthMatrixUtility.degreesToRadians(modelAngle.y), new Vector3f(0, 1, 0), modelMatrix, modelMatrix);
Matrix4f.rotate(DepthMatrixUtility.degreesToRadians(modelAngle.x), new Vector3f(1, 0, 0), modelMatrix, modelMatrix);

matrix = new Matrix4f();
Matrix4f.mul(matrix, projectionMatrix, matrix);
Matrix4f.mul(matrix, viewMatrix, matrix);
Matrix4f.mul(matrix, modelMatrix, matrix);

matrix.store(matrix44Buffer);
matrix44Buffer.flip();

matrixLocation = GL20.glGetUniformLocation(pId, "matrix");
GL20.glUniformMatrix4(matrixLocation, false, matrix44Buffer);

Я протестировал свой FBO с сохранением цвета во фрагментном шейдере, карта высот отображается правильно (я нарисовал текстуру FBO в небольшом квадрате в углу экрана) и обновляется по мере изменения карты высот.

Затем я изменил свой FBO, чтобы сохранить глубину текстуры при первом проходе:

depthTexture = GL11.glGenTextures();

GL11.glBindTexture(GL11.GL_TEXTURE_2D, depthTexture);

GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_DEPTH_COMPONENT, Window.getScreenWidth(), Window.getScreenHeight(), 0, GL11.GL_DEPTH_COMPONENT, GL11.GL_UNSIGNED_BYTE, (ByteBuffer)null);

GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_NEAREST);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);

GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);

fboId = GL30.glGenFramebuffers();
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, fboId);

GL11.glDrawBuffer(GL11.GL_NONE);
GL11.glReadBuffer(GL11.GL_NONE);

GL32.glFramebufferTexture(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, depthTexture, 0);

verifyFBO();

Мой вершинный шейдер для первого прохода (создание карты теней):

#version 330 core

uniform mat4 matrix;

in vec4 in_Position;

void main(void)
{
gl_Position = matrix * in_Position;
}

Мой фрагментный шейдер для первого прохода:

#version 330 core

layout(location = 0) out float fragmentdepth;

void main(void)
{
fragmentdepth = gl_FragCoord.z;
}

Моя матрица смещения:

[0.5f, 0.0f, 0.0f, 0.0f]
[0.0f, 0.5f, 0.0f, 0.0f]
[0.0f, 0.0f, 0.5f, 0.0f]
[0.5f, 0.5f, 0.5f, 1.0f]

Мой вершинный шейдер для второго прохода (рендеринг сцены с помощью карты теней):

void main(void)
{
    gl_Position = matrix * in_Position;
    ShadowCoord = biasMatrix * lightMatrix * in_Position;
}

Мой фрагментный шейдер для второго прохода:

if (texture(shadowMap, ShadowCoord.xy).z  <  ShadowCoord.z)
{
    vec4 colour = 0.5 * out_Colour;
    out_Colour = new vec4(colour[0], colour[1], colour[2], 1.0f);
}

person graphicsProgrammer    schedule 02.07.2013    source источник
comment
GL_NEAREST никогда не был допустимым режимом для GL_TEXTURE_WRAP_[S|T].   -  person genpfault    schedule 03.07.2013
comment
Я также пытался использовать GL_CLAMP_TO_EDGE до GL_NEAREST.   -  person graphicsProgrammer    schedule 03.07.2013


Ответы (1)


После преобразования in_Position в lightMatrix результат еще не проецируется на экран.

Фактическая перспективная проекция применяется путем деления на w компонента.

Разделение перспективы даст вам координаты текстуры и глубину в диапазоне [-1,1]. На этом этапе вы используете biasMatrix, чтобы преобразовать их в диапазон [0,1].

Так что не стоит умножать на biasMatrix, тогда в вашем шейдере перед строкой

if (texture(shadowMap, ShadowCoord.xy).z  <  ShadowCoord.z)

Добавить

ShadowCoord.xyz /= ShadowCoord.w;
ShadowCoord = biasMatrix * ShadowCoord;

biasMatrix Контент, который вы показываете, должен храниться в памяти транспонированным. Если вы сомневаетесь, замените матричное произведение на

ShadowCoord.xyz = ShadowCoord.xyz * .5f + float3(.5f);
person a.lasram    schedule 03.07.2013