阴影映射在Android的OpenGL ES 3.0中不起作用

时间:2019-01-16 22:28:07

标签: android opengl-es glsl opengl-es-3.0

我试图在我的项目中实施阴影映射将近一个星期,而且似乎没有一种方法可行。深度图纹理似乎是空的。

我一直在研究整个互联网,没有任何帮助。也许我的代码中缺少某些内容。

在这里,我首先创建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);

然后获得vFragPosLightdepthMap纹理

in vec4 vFragPosLight;
uniform sampler2DShadow depthMap;

...在片段着色器中,并使用此行计算阴影:

textureProj(depthMap, vFragPosLight);

...总是返回0!

着色器编译没有错误,没有纹理到帧缓冲区的绑定错误,似乎一切正常,但是depthMap为空。

非常感谢您的帮助,并感谢您抽出宝贵的时间阅读!

2 个答案:

答案 0 :(得分:0)

我仍然不知道确切的问题是什么,但是我已经阅读并使用了this book about OpenGL ES 3.0中有效的阴影映射部分。

有可能不得不在glColorMask设置为False的情况下禁用所有颜色呈现组件。

答案 1 :(得分:0)

创建帧缓冲区时,需要检查帧缓冲区是否创建成功。

glGenTextures(1, &depthTexture);
glBindTexture(GL_TEXTURE_2D, depthTexture);
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_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// set up hardware comparison
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE,
                GL_COMPARE_REF_TO_TEXTURE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC,
                GL_LEQUAL);
//android use GL_DEPTH_COMPONENT16
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT,
             GL_UNSIGNED_SHORT,
             NULL);
glBindTexture(GL_TEXTURE_2D, 0);

glGenFramebuffers(1, &mDepthFbo);
glBindFramebuffer(GL_FRAMEBUFFER, mDepthFbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
glDrawBuffers(1, GL_NONE);
glReadBuffer(GL_NONE);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, depthTexture);

if (GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER)) {
    LOGI("frame buffer success");
} else {
    LOGI("frame buffer fail");
}

我也遇到了和你一样的问题,终于找到原因是framebuffer创建失败,所以我把GL_DEPTH_COMPONENT固定为GL_DEPTH_COMPONENT16,framebuffer成功,深度图就OK了!