1

尝试从我的数据中的地形图生成阴影贴图时遇到问题。我已经成功地使用了如下图所示的照明程序(定向照明,方位角: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 来规范化纹理。

下图是我现在实现的截图。仍然没有阴影,但上部有黑色伪影(如果我移动灯光位置,它会移动)

在此处输入图像描述

这是我想要实现的图像的示例。 在此处输入图像描述

另外,我需要应用几何变换精度来处理我几何中的高数字(x 和 y 轴)

我不确定我在哪里犯了错误。我怀疑它在矩阵转换中,但不知道要解决这个问题。无论如何,提前感谢您的帮助。

4

0 回答 0