尝试从我的数据生成地形图中的阴影贴图时出现问题。我已成功使用照明程序,如下图所示(定向照明,方位角:180',海拔:90')。
最终我需要在那里应用更多阴影,所以我尝试创建了shadowMap
这是我初始化着色器时的代码
bool BFB_Patch::initialise(QString filePath_ = "")
{
initializeOpenGLFunctions();
if(initialised_) return true;
openFile(filePath_);
program = new QOpenGLShaderProgram();
program->addShaderFromSourceCode(QOpenGLShader::Vertex, vtxshdr_source);
program->addShaderFromSourceCode(QOpenGLShader::Fragment, frgshdr_source);
program->link();
program->bind();
if(!vao.create() || !vbo.create() || !ibo.create()) {
qDebug() << "Error creating VAO or VBO or IBO";
return false;
}
// Bind all
vao.bind(); vbo.bind(); ibo.bind();
vbo.setUsagePattern(QOpenGLBuffer::DynamicDraw);
ibo.setUsagePattern(QOpenGLBuffer::DynamicDraw);
// Release (unbind) all
vao.release(); vbo.release(); ibo.release(); program->release();
// Bind all
//vao.bind(); vbo.bind(); ibo.bind();
programShadow = new QOpenGLShaderProgram();
programShadow->addShaderFromSourceCode(QOpenGLShader::Vertex, svtxshdr_source);
programShadow->addShaderFromSourceCode(QOpenGLShader::Fragment, sfrgshdr_source);
programShadow->link();
programShadow->bind();
if(m_shadowMapFBO != 0)
return false;
// Create a frame-buffer and associate the texture with it.
glGenFramebuffers(1, &m_shadowMapFBO);
// Create a texture for storing the depth map
glGenTextures(1, &m_shadowMapTex);
glBindTexture(GL_TEXTURE_2D, m_shadowMapTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
1024, 1024, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glBindFramebuffer(GL_FRAMEBUFFER, m_shadowMapFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_shadowMapTex, 0);
// Let OpenGL know that we are not interested in colors for this buffer
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
// Cleanup for now.
glBindFramebuffer(GL_FRAMEBUFFER, 0);
programShadow->release();
initialised_ = true;
return false;
}
这是我绘制场景的代码
void BFB_Patch::draw(mat4 mvpMatrix, vec2 range)
{
if(!initialised_) return;
int viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
glEnable(GL_DEPTH_TEST);
glViewport(0, 0, 1024, 1024);
glBindFramebuffer(GL_FRAMEBUFFER, m_shadowMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
programShadow->bind();
vbo.bind(); ibo.bind();
programShadow->enableAttributeArray("posAttrH");
programShadow->setAttributeBuffer("posAttrH", GL_FLOAT, 0, 3, 3*sizeof(vec3));
programShadow->enableAttributeArray("posAttrL");
programShadow->setAttributeBuffer("posAttrL", GL_FLOAT, sizeof(vec3), 3, 3*sizeof(vec3));
vec3 lightPos = vec3(-lightDir[0]*range[1]/2, -lightDir[1]*range[1]/2, lightDir[2]);
mat4 lightMatrix;
lightMatrix.setToIdentity();
lightMatrix.lookAt(lightPos, vec3(0.0f, 0.0f, 0.0f), vec3(0.0f, 1.0f, 0.0f));
m_projection.setToIdentity();
m_projection.ortho(-range[0]/2, range[0]/2,
-range[1]/2, range[1]/2,
10.0f, 0.0f);
programShadow->setUniformValue("mvpMatrix", m_projection*lightMatrix);
programShadow->setUniformValue("centerEyeH", centerEyeH);
programShadow->setUniformValue("centerEyeL", centerEyeL);
glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0);
vbo.release(); ibo.release();
programShadow->release();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Rendering
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(m_shadowMapTex > 0) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_shadowMapTex);
}
program->bind();
vao.bind(); vbo.bind(); ibo.bind(); //
program->enableAttributeArray("posAttrH");
program->setAttributeBuffer("posAttrH", GL_FLOAT, 0, 3, 3*sizeof(vec3));
program->enableAttributeArray("posAttrL");
program->setAttributeBuffer("posAttrL", GL_FLOAT, sizeof(vec3), 3, 3*sizeof(vec3));
program->enableAttributeArray("normalAttr");
program->setAttributeBuffer("normalAttr", GL_FLOAT, 2*sizeof(vec3), 3, 3*sizeof(vec3));
program->setUniformValueArray("colorTable", rainbowTable.data(), rainbowTable.size());
program->setUniformValue("mvpMatrix", mvpMatrix);
program->setUniformValue("pMat", m_projection*lightMatrix);
program->setUniformValue("centerEyeH", centerEyeH);
program->setUniformValue("centerEyeL", centerEyeL);
program->setUniformValue("colorSize", float(rainbowTable.size()) - 1.0f);
program->setUniformValue("heightSize", float(maxZ - minZ));
program->setUniformValue("heightMin", float(minZ));
program->setUniformValue("lightDir", lightDir);
program->setUniformValue("qt_ShadowMap", m_shadowMapTex);
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glLineWidth(2.0f);
glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
// glEnable(GL_DEPTH_TEST);
glDrawElements(GL_TRIANGLE_STRIP, indices.size(), GL_UNSIGNED_INT, 0);
glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
vao.release(); vbo.release(); ibo.release();
program->release();
if(m_shadowMapTex > 0) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
}
glDisable(GL_DEPTH_TEST);
}
这是阴影的代码顶点和片段着色器代码,分别是
const char* const svtxshdr_source =
"attribute highp vec3 posAttrH;\n"
"attribute highp vec3 posAttrL;\n"
"uniform mat4 mvpMatrix;\n"
"uniform vec3 centerEyeH;\n"
"uniform vec3 centerEyeL;\n"
"void main() {\n"
" vec3 t1 = posAttrL - centerEyeL;\n"
" vec3 e = t1 - posAttrL;\n"
" vec3 t2 = ((-centerEyeL - e) + (posAttrL - (t1 - e))) + posAttrH - centerEyeH;\n"
" vec3 highDiff = t1 + t2;\n"
" vec3 lowDiff = t2 - (highDiff - t1);\n"
" gl_Position = mvpMatrix*vec4(highDiff + lowDiff, 1.0f);\n"
"}\n";
const char* const sfrgshdr_source =
"void main() {\n"
" gl_FragDepth = gl_FragCoord.z;\n"
"}\n";
最后一个代码是我的顶点和片段着色器显示场景+阴影。
const char* const vtxshdr_source =
"attribute highp vec3 posAttrH;\n"
"attribute highp vec3 posAttrL;\n"
"attribute highp vec3 normalAttr;\n"
"uniform mat4 mvpMatrix;\n"
"uniform mat4 pMat;\n"
"uniform vec3 centerEyeH;\n"
"uniform vec3 centerEyeL;\n"
"varying float height;\n"
"varying vec3 normal;\n"
"varying vec4 posShadow;\n"
"void main() {\n"
" vec3 t1 = posAttrL - centerEyeL;\n"
" vec3 e = t1 - posAttrL;\n"
" vec3 t2 = ((-centerEyeL - e) + (posAttrL - (t1 - e))) + posAttrH - centerEyeH;\n"
" vec3 highDiff = t1 + t2;\n"
" vec3 lowDiff = t2 - (highDiff - t1);\n"
" normal = normalAttr;\n"
" height = highDiff.z + lowDiff.z;\n"
" posShadow = pMat*vec4(highDiff + lowDiff, 1.0f);\n"
" gl_Position = mvpMatrix*vec4(highDiff + lowDiff, 1.0f);\n"
"}\n";
const char* const frgshdr_source =
"uniform const float colorSize;\n"
"uniform vec3 colorTable[512];"
"uniform vec3 lightDir;"
"varying float height;\n"
"varying vec3 normal;\n"
"varying vec3 fragPos;\n"
"varying vec4 posShadow;\n"
"uniform float heightSize;\n"
"uniform float heightMin;\n"
"uniform sampler2D qt_ShadowMap;\n"
"\n"
"float evaluateShadow(vec4 shadowPos) {\n"
" vec3 shadowCoords = shadowPos.xyz/shadowPos.w;\n"
" shadowCoords = shadowCoords*0.5f + 0.5f;\n"
" float closestDepth = texture2D(qt_ShadowMap, shadowCoords.xy).r;\n"
" float currentDepth = shadowCoords.z;\n"
" float shadow = (currentDepth > closestDepth) ? 1.0 : 0.0;\n"
" return shadow;\n"
"}\n"
"void main() {\n"
" vec3 ambient = vec3(0.0f, 0.0f, 0.0f);\n"
" float diff = max(dot(normal, lightDir), 0.0f);\n"
" vec3 diffuse = vec3(1.0f, 1.0f, 1.0f) * diff;\n"
" float h = (height - heightMin)/heightSize;\n"
" int i = 0;\n"
" while (h >= float(i + 1)/colorSize) {\n"
" i += 1;}\n"
" vec3 base = mix(colorTable[i], colorTable[i+1], colorSize*(h - (float(i)/colorSize)));\n"
" float shadow = evaluateShadow(posShadow);\n"
" vec3 lighting = (ambient + (1.0 - shadow)*diffuse)*base;\n"
" gl_FragColor = vec4(lighting, 1.0f);\n"
"}\n";
我相信通过使用上面的代码,我不需要使用biasMatrix来标准化纹理。
下图是我现在所取得的截图。仍然没有阴影,但上部有黑色人工制品(如果我移动光线位置,它会移动)
另外,我需要应用Geometry Transform Precision来处理几何体中的高数字(x和y轴)
我不确定我在哪里犯错误。我怀疑它在矩阵变换中但不知道要解决这个问题。无论如何,请提前感谢您的帮助。