Впервые пытаюсь реализовать карту теней, используя язык шейдеров openGL и glsl.
Я думаю, что первый проход, где я рендеринг текстуры, является правильным, но когда я сравниваю значения глубины, кажется, что все затеняет.
https://www.dropbox.com/s/myxenx9y41yz2fc/Screenshot%202014-12-09%2012.18.53.png?dl=0
Моя матрица перспективной проекции выглядит так:
FOV = 90
Aspect = According to the programs window size. (I also tried to put different values here)
Near = 2;
Far= 10000;
Функция для инициализации кадрового буфера
void OpenGLWin::initDepthMap()
{
//Framebuffer
m_glFunctions->glGenFramebuffers(1, &m_frameBuffer);
m_glFunctions->glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer);
//////////////////////////////////////////////////////////////////////////
//Texture to render scene to
m_glFunctions->glGenTextures(1, &m_renderToTexture);
//Bind created texture to make it current
m_glFunctions->glBindTexture(GL_TEXTURE_2D, m_renderToTexture);
//Creates an empty texture of specified size.
//m_glFunctions->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1024, 768, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
m_glFunctions->glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, 1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
m_glFunctions->glDrawBuffer(GL_NONE);
m_glFunctions->glReadBuffer(GL_NONE);
// Always check that our framebuffer is ok
if (m_glFunctions->glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
qDebug() << "FrameBuffer not OK";
return;
}
m_glFunctions->glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
Функция Draw для каждой сетки. Модельная матрица передается как аргумент из функции рисования класса Transform
void Mesh::draw(const Matrix4x4& projection, const Matrix4x4& view, const Matrix4x4& model)
{
//Shadow map pass 1
if (m_shadowMapFirstpass){
//Pass 1 Shaders
m_glFunctions->glUseProgram(m_depthRTTShaderProgram);
//Light view matrix
m_depthMVP = projection*view*model;
//Get the location of the uniform name mvp
GLuint depthMVPLocation = m_glFunctions->glGetUniformLocation(m_depthRTTShaderProgram, "depthMVP");
m_glFunctions->glUniformMatrix4fv(depthMVPLocation, 1, GL_TRUE, &m_depthMVP[0][0]);
m_shadowMapFirstpass = false;
}
//Shadow map pass 2
else if(m_shadowMapFirstpass == false){
//Pass 2 Shader
m_glFunctions->glUseProgram(m_shaderProgram);
//Gets the model matrix which is then multiplied with view and projection to form the mvp matrix
Matrix4x4 mvp = projection * view * model;
//Get the location of the uniform name mvp
GLuint mvpLocation = m_glFunctions->glGetUniformLocation(m_shaderProgram, "mvp");
//Send the mvp matrix to the vertex shader
m_glFunctions->glUniformMatrix4fv(mvpLocation, 1, GL_TRUE, &mvp[0][0]);
Matrix4x4 depthBiasMVP = m_depthMVP;// biasMatrix*m_depthMVP;
GLuint depthBiasMVPLocation = m_glFunctions->glGetUniformLocation(m_shaderProgram, "depthBiasMVP");
m_glFunctions->glUniformMatrix4fv(depthBiasMVPLocation, 1, GL_TRUE, &depthBiasMVP[0][0]);
m_shadowMapFirstpass = true;
}
//Bind this mesh VAO
m_glFunctions->glBindVertexArray(m_vao);
//Draw the triangles using the index buffer(EBO)
glDrawElements(GL_TRIANGLES, m_indices.size(), GL_UNSIGNED_INT, 0);
//Unbind the VAO
m_glFunctions->glBindVertexArray(0);
/////////////////////////////////////////////////////////////////////////////////////////////////////
//Calls the childrens' update
if (!m_children.empty())
{
for (int i = 0; i < m_children.size(); i++)
{
if (m_children[i] != NULL)
{
m_children[i]->draw(frustumCheck, projection, view, bvScaleFactor, model);
}
}
}
}
Мой цикл рендеринга
void OpenGLWin::paintGL()
{
// m_glFunctions->glBindFramebuffer(GL_FRAMEBUFFER, m_frameBuffer);
m_glFunctions->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_frameBuffer);
glViewport(0, 0, 1024, 1024);
// Clear the buffer with the current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Light View Matrix
Matrix4x4 lightView;
lightView.lookAt(Vector3(0, 0, 0), Vector3(0, 0, -1), Vector3(0, 1, 0));
//Draw scene to Texture
m_root->draw(m_projection, lightView);///////////////////////////////////////////////////////////////////
//Draw to real scene
m_glFunctions->glBindFramebuffer(GL_FRAMEBUFFER, 0);
// m_glFunctions->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Bind Pass 2 shader
m_glFunctions->glUseProgram(m_shadowMapShaderProgram->getShaderProgramID());
GLuint shadowMapLocation = m_glFunctions->glGetUniformLocation(m_shadowMapShaderProgram->getShaderProgramID(), "shadowMap");
//Shadow Texture
m_glFunctions->glActiveTexture(GL_TEXTURE0);
m_glFunctions->glBindTexture(GL_TEXTURE_2D, m_renderToTexture);
m_glFunctions->glUniform1i(shadowMapLocation, 0);
//Updates matrices and view matrix for player camera
m_root->update(m_view);
//Render scene to main frame buffer
m_root->draw(m_projection, m_view);
}
Pass 1 вершинный шейдер
#version 330 core
//Passthrough vertex shader
uniform mat4 depthMVP;
//Vertex received from the program
layout(location = 0) in vec3 vertexPosition_modelspace;
void main(void)
{
//Output position of vertex in clip space
gl_Position = depthMVP * vec4(vertexPosition_modelspace, 1);
}
Pass 1 Fragment Shader
#version 330 core
//Render to texture
// Ouput data
layout(location = 0) out float depthValue;
void main(void)
{
depthValue = gl_FragCoord.z;
}
Pass 2 Vertex Shader
#version 330 core
layout(location = 0) in vec3 vertexPosition_modelspace;
out vec4 ShadowCoord;
// Values that stay constant for the whole mesh.
uniform mat4 mvp;
uniform mat4 depthBiasMVP;void main(){
// Output position of the vertex, in clip space : MVP * position
gl_Position = mvp * vec4(vertexPosition_modelspace,1);
ShadowCoord = depthBiasMVP * vec4(vertexPosition_modelspace,1);
}
Pass 2 Fragment Shader
#version 330 core
in vec4 ShadowCoord;
// Ouput data
layout(location = 0) out vec3 color;
// Values that stay constant for the whole mesh.
uniform sampler2D shadowMap;void main(){
float visibility=1.0;vec3 ProjCoords = ShadowCoord.xyz / ShadowCoord.w;
vec2 UVCoords;
UVCoords.x = 0.5 * ProjCoords.x + 0.5;
UVCoords.y = 0.5 * ProjCoords.y + 0.5;
float z = 0.5 * ProjCoords.z + 0.5;
float Depth = texture(shadowMap, UVCoords).z;//or x
if (Depth < (z + 0.00001)){
visibility = 0.1;
}color = visibility*vec3(1,0,0);
}
Отключить сравнение текстур для одной вещи. Это действительно только при использовании с sampler2DShadow
и вы явно не используете это в своем коде, потому что ваши координаты текстуры 2D.
m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
m_glFunctions->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
Аналогично, используя GL_LINEAR
фильтрация на неsampler2DShadow
текстура это плохая идея. Это позволит усреднить 4 ближайших значения глубины и вернуть вам одну глубину. Но это не правильный способ сглаживания теней; вы на самом деле хотите усреднить результат 4-х тестов глубины вместо того, чтобы делать один тест в среднем за 4 глубины.