Shadow Map -- 点阴影(全方位)
昨晚终于把点阴影(深度CubeMap)程序调通了,思想不难,基本就是在上节定向光阴影基础上稍作修改,但是CG程序不太方便Debug,需要输出中间效果图进行判断,耽搁了一会儿。
过程如下:
1、将深度渲染到CubeMap上
为了以后使用方便,在Texture文件中扩展功能,添加一个生成CubeMap的函数
GLuint WKS::CubeMap::GenDepthCubeMap(GLuint width, GLuint height) {
glGenTextures(, &this->textureID);
glBindTexture(GL_TEXTURE_CUBE_MAP, this->textureID);
for (GLuint i = ; i < ; i++) {
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, , GL_DEPTH_COMPONENT, width, height, , GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
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);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}
glBindTexture(GL_TEXTURE_CUBE_MAP, );
return this->textureID;
}
同样为了以后方便,在DefferredShading文件中扩展功能,添加附加深度CubeMap到帧缓冲的函数
(注:暂时遇到一点奇怪的问题,同时添加颜色缓冲纹理和2D深度缓冲纹理(或深度缓冲对象RBO)是没有问题的。但是如果是深度CubeMap,同时再添加颜色缓冲纹理就会报错,现在没找到解决办法,不过做阴影渲染只需要深度CubeMap,额……)
void DeferredShading::setupDepthBufferByCubeMap(GLuint texId) {
this->BindGBuffer();
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texId, );
//检查帧缓冲是否完整
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cout << "ERROR::FRAMEBUFFER:: Depth CubeMap is not added to FrameBuffer correctly!" << std::endl;
else std::cout << "Successful:: Depth CubeMap is added to FrameBuffer correctly" << std::endl;
this->BindDefaultBuffer();
}
既然渲染深度到CubeMap,那么就需要6个方向的view矩阵,并传入shader,故新建了个ShadowMap文件完成这些操作。
//ShadowMap.h #pragma once
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "../BaseFile/Shader.h" class ShadowMap
{
public:
ShadowMap();
~ShadowMap();
void updateLightSpaceMatrix(glm::vec3 lightPos);
void transmitMat2Shader(Shader* shader); private:
void setup(); private:
glm::mat4 shadowProj;
std::vector<glm::mat4> shadowTransforms;
};
//ShadowMap.cpp #include "./ShadowMap.h" ShadowMap::ShadowMap()
{
this->setup();
} ShadowMap::~ShadowMap()
{
} void ShadowMap::setup() {
this->shadowProj = glm::perspective(glm::radians(90.0f), 800.0f / , 1.0f, 100.0f);
} void ShadowMap::updateLightSpaceMatrix(glm:: vec3 lightPos) {
this->shadowTransforms.clear();
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(-1.0, 0.0, 0.0), glm::vec3(0.0, -1.0, 0.0)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0, 1.0, 0.0), glm::vec3(0.0, 0.0, 1.0)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0, -1.0, 0.0), glm::vec3(0.0, 0.0, -1.0)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0, 0.0, 1.0), glm::vec3(0.0, -1.0, 0.0)));
shadowTransforms.push_back(shadowProj * glm::lookAt(lightPos, lightPos + glm::vec3(0.0, 0.0, -1.0), glm::vec3(0.0, -1.0, 0.0)));
} void ShadowMap::transmitMat2Shader(Shader* shader) {
shader->use();
for (int i = ; i < ; i++) {
std::string name = "shadowMatrices["+std::to_string(i)+"]";
shader->setMat4(name, this->shadowTransforms[i]);
}
}
现在来看看着色器咋样的^_^
我们不必在 OpenGL 程序中控制 View ,渲染六遍,将六个方向的深度分别渲染到 CubeMap 的各个面上。几何着色器可以帮助完成这一点,几何着色器中有一个内建变量 gl_Layer ,可以控制当前渲染的图元输出到CubeMap哪一个面。故我们只需要将每个图元在几何着色器中渲染六次,且每次指定输出到一个面,当然得配合传入的对应的 view * projection 矩阵,这样就实现渲染六个方向的深度到CubeMap。
- 顶点着色器:只需将顶点坐标变换到世界坐标(乘以 model matrix),输出到几何着色器。
#version core
layout (location = ) in vec3 position; uniform mat4 model; void main()
{
gl_Position = model * vec4(position, 1.0);
}
- 几何着色器:需要传入六个view*projection矩阵,通过 gl_Layer 内建变量生成每个方向的深度图。
#version core
layout (triangles) in;
layout (triangle_strip, max_vertices=) out; uniform mat4 shadowMatrices[]; out vec4 FragPos; // FragPos from GS (output per emitvertex) void main()
{
for(int face = ; face < ; ++face)
{
gl_Layer = face; // built-in variable that specifies to which face we render.
for(int i = ; i < ; ++i) // for each triangle's vertices
{
FragPos = gl_in[i].gl_Position;
gl_Position = shadowMatrices[face] * FragPos;
EmitVertex();
}
EndPrimitive();
}
}
- 片段着色器:传入光源位置、远平面距离,计算 当前片元到光源的距离 / 远平面距离,输出到深度值。
#version core
in vec4 FragPos; uniform vec3 lightPos;
uniform float far_plane; void main()
{
// get distance between fragment and light source
float lightDistance = length(FragPos.xyz - lightPos); // map to [0;1] range by dividing by far_plane
lightDistance = lightDistance / far_plane;
// write this as modified depth
gl_FragDepth = lightDistance;
}
这样就完成了深度CubeMap生成。
为了测试深度CubeMap是否正确,可以用天空盒的方式显示生成的CubeMap。
当然了也可以在后续的渲染阴影中,用采样CubeMap的深度值代替颜色值显示深度,这样还可以稍作修改显示实际的深度值(当前片元与光源的距离值),两者直接对比,可以检测第一步(First Pass)是否有问题。
展示一下我实现的采样CubeMap深度值显示(左图)与 实际深度值显示(右图)的对比:

2、使用深度CubeMap渲染全方位阴影
这一部分就很简单了,很往常渲染基本一样,只需要添加阴影判断。
在片段着色器中传入深度CubeMap:
uniform samplerCube shadowMap;
计算当前的片元的深度,并判断是否在阴影中:
float ShadowCalculation(vec3 fragPos)
{
vec3 light2Frag=fragPos-spotLight.position;
float closestDepth = texture(shadowMap, light2Frag).r;
closestDepth*=far_plane;
float currentDepth=length(light2Frag);
float shadow = currentDepth-0.05f > closestDepth ? 1.0 : 0.0;
return shadow;
}
使用这个阴影判断值计算光照值:
color=vec4(result*(1.0f-shadow)+ambient,1.0f);
效果图:

OK,至此完成了Shadow Map的总结啦 ^_^。
Shadow Map -- 点阴影(全方位)的更多相关文章
- [ZZ] Shadow Map
Shadow Map 如何能够高效的产生更接近真实的阴影一直是视频游戏的一个很有挑战的工作,本文介绍目前所为人熟知的两种阴影技术之一的ShadowMap(阴影图)技术. ShadowMap技术 ...
- Unity基础6 Shadow Map 阴影实现
这篇实现来的有点墨迹,前前后后折腾零碎的时间折腾了半个月才才实现一个基本的shadow map流程,只能说是对原理理解更深刻一些,但离实际应用估计还需要做很多优化.这篇文章大致分析下shadow ma ...
- Shadow Map阴影贴图技术之探 【转】
这两天勉勉强强把一个shadowmap的demo做出来了.参考资料多,苦头可不少.Shadow Map技术是目前与Shadow Volume技术并行的传统阴影渲染技术,而且在游戏领域可谓占很大优势.本 ...
- (转)Shadow Map & Shadow Volume
转自:http://blog.csdn.net/hippig/article/details/7858574 shadow volume 这个术语几乎是随着 DOOM3 的发布而成为FPS 玩家和图形 ...
- [工作积累] shadow map问题汇总
1.基本问题和相关 Common Techniques to Improve Shadow Depth Maps: https://msdn.microsoft.com/en-us/library/w ...
- Unity基础(5) Shadow Map 概述
这篇是自己看shadow map是的一些笔记,内容稍稍凌乱,如有错误请帮忙纠正 1.常见阴影处理方式 Shadow Map : using Z-Buffer Shadow Mapping 的原理与实践 ...
- Shadow Map 实现极其细节
这里不介绍算法原理,只说说在实现过程中遇到的问题,以及背后的原因.开发环境:opengl 2.0 glsl 1.0. 第一个问题:产生深度纹理. 在opengl中每一次离屏渲染需要向opengl提供 ...
- Shadow Map 原理和改进 【转】
http://blog.csdn.net/ronintao/article/details/51649664 参考 1.Common Techniques to Improve Shadow Dept ...
- GraphicsLab Project之再谈Shadow Map
作者:i_dovelemon 日期:2019-06-07 主题:Shadow Map(SM), Percentage Closer Filtering(PCF), Variance Shadow Ma ...
随机推荐
- 【戾气满满】Ubuntu 18.04使用QT通过FreeTDS+unixODBC连接MSSQL填坑记(含泪亲测可用)
前言 照例废话几句,想玩下QT,但是学习吧总得想点事情做啊,单纯学习语法用法这些?反正我是学不下去的,脑袋一拍,就先学下怎么连接数据库吧!然而万万没想到,我这是给自己挖了一个深深的坑啊! 学习自然去官 ...
- Hyperledger Fabric私有数据
官方文档:点这里 1简介 在同一个通道中,允许某一组织在对同一通道内其他组织保持部分的数据私有.也就是说有一部分被标识为私有的数据只能具有权限的组织查看和操作,而其余组织不具备查看和操作私有数据的权限 ...
- 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU启动那些事(1)- Boot简介
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列MCU的BootROM功能简介. 截止目前为止i.MX RTyyyy系列已公布的芯片有三款i.MXRT ...
- 前端面试题套路--终极版(Vue、JavaScript)
前言 面试题是永远都准备不完的!!!!! 前端常见的一些问题 1.前端性能优化手段? 1. 尽可能使用雪碧图 2. 使用字体图标代替图片 3. 对HTML,css,js 文件进行压缩 4. 模块按需加 ...
- echarts 部分美化配置项使用记录
一.图表背景色配置项,如背景颜色渐变 https://www.echartsjs.com/zh/option.html#backgroundColor 二.图表中图形的颜色,如柱状图行采用渐变颜色显示 ...
- CMake指南
版权申明: 本文原创首发于以下网站,您可以自由转载,但必须加入完整的版权声明 博客园:https://www.cnblogs.com/MogooStudio/ csdn博客:https://blog. ...
- hadoop搭建的前期准备
这个hadoop的搭建是以比赛前的练习为目的的,所以我直接以root用户来搭建hadoop,主要也是方便我自己以后复习用的 需要的软件:vmware15.5,xshell6,xftp6,jdk Lin ...
- 微服务与K8S容器云平台架构
微服务与K8S容器云平台架构 微服务与12要素 网络 日志收集 服务网关 服务注册 服务治理- java agent 监控 今天先到这儿,希望对技术领导力, 企业管理,系统架构设计与评估,团队管理, ...
- File Zilla server安装完报错could not load TLS libraries. aborting start of administration interface
问题描述: 系统:Windows2008R2x64 安装完filezillaserver以后出现这个问题 解决方法: 需要安装个系统补丁:Windows6.1-KB2533623-x64 安装完重启服 ...
- IT兄弟连 HTML5教程 CSS3揭秘 在HTML文档中放置CSS的几种方式
有很多方法将样式表加入到HTML中,每种方法都有自己的优点和缺点.新的HTML元素和属性已被加入,以允许样式表与HTML文档更简易地组合起来.将样式表加入到HTML中的常用方法有内联样式表.嵌入一张样 ...