我正在尝试在 openGL 3.3 版中创建全向/点照明。我在互联网和这个网站上四处搜索,但到目前为止我还没有能够做到这一点。根据我的理解,我应该
使用深度组件生成帧缓冲区
生成一个立方体贴图并将其绑定到所述帧缓冲区
绘制到由枚举 GL_TEXTURE_CUBE_MAP_* 引用的立方体贴图的各个部分
正常绘制场景,并将片段的深度值与立方体贴图中的深度值进行比较
现在,我读到最好使用从光到片段的距离,而不是存储片段深度,因为它可以更轻松地查找立方体贴图(不需要检查每个单独的纹理?)
我目前的问题是发出的光实际上是在一个球体中,并且不会产生阴影。另一个问题是帧缓冲区抱怨不完整,尽管我的印象是帧缓冲区在渲染到纹理时不需要渲染缓冲区。
这是我的帧缓冲区和立方体贴图初始化:
framebuffer = 0;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glGenTextures(1, &shadowTexture);
glBindTexture(GL_TEXTURE_CUBE_MAP, shadowTexture);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);GL_COMPARE_R_TO_TEXTURE);
for(int i = 0; i < 6; i++){
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i , 0,GL_DEPTH_COMPONENT16, 800, 800, 0,GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
}
glDrawBuffer(GL_NONE);
阴影顶点着色器
void main(){
gl_Position = depthMVP * M* vec4(position,1);
pos =(M * vec4(position,1)).xyz;
}
阴影片段着色器
void main(){
fragmentDepth = distance(lightPos, pos);
}
顶点着色器(不相关的位被剪掉)
uniform mat4 depthMVP;
void main() {
PositionWorldSpace = (M * vec4(position,1.0)).xyz;
gl_Position = MVP * vec4(position, 1.0 );
ShadowCoord = depthMVP * M* vec4(position, 1.0);
}
片段着色器(无关代码剪切)
uniform samplerCube shadowMap;
void main(){
float bias = 0.005;
float visibility = 1;
if(texture(shadowMap, ShadowCoord.xyz).x < distance(lightPos, PositionWorldSpace)-bias)
visibility = 0.1
}
现在您可能在想,depthMVP 是什么?深度投影矩阵目前是正交投影,每个方向的范围为 [-10, 10] 好吧,它们的定义如下:
glm::mat4 depthMVP = depthProjectionMatrix* ??? *i->getModelMatrix();
这里的问题是我不知道是什么???价值应该是。它曾经是相机矩阵,但我不确定这是否应该是它。然后为立方体贴图的侧面完成绘制代码,如下所示:
for(int loop = 0; loop < 6; loop++){
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X+loop, shadowTexture,0);
glClear( GL_DEPTH_BUFFER_BIT);
for(auto i: models){
glUniformMatrix4fv(modelPos, 1, GL_FALSE, glm::value_ptr(i->getModelMatrix()));
glm::mat4 depthMVP = depthProjectionMatrix*???*i->getModelMatrix();
glUniformMatrix4fv(glGetUniformLocation(shadowProgram, "depthMVP"),1, GL_FALSE, glm::value_ptr(depthMVP));
glBindVertexArray(i->vao);
glDrawElements(GL_TRIANGLES, i->triangles, GL_UNSIGNED_INT,0);
}
}
最后场景被正常绘制(我会省略你的细节)。在调用绘制到立方体贴图之前,我将帧缓冲区设置为我之前生成的帧缓冲区,并将视口更改为 800 x 800。我将帧缓冲区更改回 0 并将视口重置为 800 x 600,然后再进行正常绘图。对此主题的任何帮助将不胜感激。
更新 1
经过一些调整和错误修复,这是我得到的结果。我修复了深度MVP不起作用的错误,我在这里绘制的是存储在立方体贴图中的距离。 http://imgur.com/JekOMvf
基本上发生的是它在每一侧绘制相同的单侧投影。这是有道理的,因为我们为每一侧使用相同的视图矩阵,但是我不确定我应该使用哪种视图矩阵。我认为它们应该是位于中心的lookAt() 矩阵,并朝立方体贴图一侧的方向看。但是,出现的问题是我应该如何在我的主要绘图调用中使用这些多个投影。
更新 2
我已经创建了这些矩阵,但是我不确定它们的有效性(它们是从 DX 立方体贴图的网站上撕下来的,所以我反转了 Z 坐标)。
case 1://Negative X
sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(-1,0,0),glm::vec3(0,-1,0));
break;
case 3://Negative Y
sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(0,-1,0),glm::vec3(0,0,-1));
break;
case 5://Negative Z
sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(0,0,-1),glm::vec3(0,-1,0));
break;
case 0://Positive X
sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(1,0,0),glm::vec3(0,-1,0));
break;
case 2://Positive Y
sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(0,1,0),glm::vec3(0,0,1));
break;
case 4://Positive Z
sideViews[i] = glm::lookAt(glm::vec3(0), glm::vec3(0,0,1),glm::vec3(0,-1,0));
break;
问题仍然存在,我应该用什么来翻译 depthMVP 视图部分,因为这些是 6 个单独的矩阵。这是它当前的截图,使用相同的片段着色器(即实际渲染阴影)http://i.imgur.com/HsOSG5v.png 正如您所见,阴影看起来不错,但定位显然是问题。我用来生成它的视图矩阵只是相机位置的逆转换(就像 lookAt() 函数一样)。
更新 3
目前的代码:Shadow Vertex
void main(){
gl_Position = depthMVP * vec4(position,1);
pos =(M * vec4(position,1)).xyz;
}
暗影碎片
void main(){
fragmentDepth = distance(lightPos, pos);
}
主顶点
void main(){
PositionWorldSpace = (M*vec4(position, 1)).xyz;
ShadowCoord = vec4(PositionWorldSpace - lightPos, 1);
}
主要片段
void main(){
float texDist = texture(shadowMap, ShadowCoord.xyz/ShadowCoord.w).x;
float dist = distance(lightPos, PositionWorldSpace);
if(texDist < distance(lightPos, PositionWorldSpace)
visibility = 0.1;
outColor = vec3(texDist);//This is to visualize the depth maps
}
使用的透视矩阵
glm::mat4 depthProjectionMatrix = glm::perspective(90.f, 1.f, 1.f, 50.f);
目前一切正常。纹理存储的数据(即距离)似乎以一种奇怪的方式存储。它似乎是标准化的,因为所有值都在 0 和 1 之间。此外,查看器周围有一个 1x1x1 区域没有投影,但这是由于截头锥,我认为很容易修复(比如将相机向后偏移 0.5 到中心)。