阴影贴图在 Android 上的 OpenGL ES 3.0 中不起作用
Shadow mapping not working in OpenGL ES 3.0 on Android
我尝试在我的项目中实现阴影映射将近一个星期,none 的方法似乎有效。深度图纹理似乎是空的。
我一直在挖掘整个互联网,但没有任何帮助。也许我的代码中遗漏了一些东西。
在这里,我首先创建 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;
}
(注释没有改变,结果是一样的)。
在从阴影透视渲染场景之前,我使用这段代码更改视口,清除深度缓冲区,绑定 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();
然后我从光线角度传递所有制服 + View/Projection 矩阵,然后渲染场景。
我在顶点着色器中用这些线从光透视中找到片段位置:
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);
然后得到vFragPosLight
和depthMap
纹理
in vec4 vFragPosLight;
uniform sampler2DShadow depthMap;
...在片段着色器中使用此行计算阴影:
textureProj(depthMap, vFragPosLight);
...总是 returns 0!
着色器编译没有错误,没有纹理到帧缓冲区绑定错误,一切似乎都在工作,但深度图是空的。
非常感谢您的帮助,感谢您花时间阅读!
我仍然不知道确切的问题是什么,但我已经阅读并使用了 this book about OpenGL ES 3.0 中的阴影贴图部分,它起作用了。
可能我不得不禁用所有颜色渲染组件并将 glColorMask 设置为 False。
创建帧缓冲区时,需要检查帧缓冲区是否创建成功。
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 create failed,所以我将GL_DEPTH_COMPONENT修改为GL_DEPTH_COMPONENT16,framebuffer success和depth map OK!
我尝试在我的项目中实现阴影映射将近一个星期,none 的方法似乎有效。深度图纹理似乎是空的。
我一直在挖掘整个互联网,但没有任何帮助。也许我的代码中遗漏了一些东西。
在这里,我首先创建 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;
}
(注释没有改变,结果是一样的)。
在从阴影透视渲染场景之前,我使用这段代码更改视口,清除深度缓冲区,绑定 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();
然后我从光线角度传递所有制服 + View/Projection 矩阵,然后渲染场景。
我在顶点着色器中用这些线从光透视中找到片段位置:
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);
然后得到vFragPosLight
和depthMap
纹理
in vec4 vFragPosLight;
uniform sampler2DShadow depthMap;
...在片段着色器中使用此行计算阴影:
textureProj(depthMap, vFragPosLight);
...总是 returns 0!
着色器编译没有错误,没有纹理到帧缓冲区绑定错误,一切似乎都在工作,但深度图是空的。
非常感谢您的帮助,感谢您花时间阅读!
我仍然不知道确切的问题是什么,但我已经阅读并使用了 this book about OpenGL ES 3.0 中的阴影贴图部分,它起作用了。
可能我不得不禁用所有颜色渲染组件并将 glColorMask 设置为 False。
创建帧缓冲区时,需要检查帧缓冲区是否创建成功。
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 create failed,所以我将GL_DEPTH_COMPONENT修改为GL_DEPTH_COMPONENT16,framebuffer success和depth map OK!