在前面章节,只要知道方向向量和颜色,就可以知道该设置什么颜色了。那么为什么还要进行卷积呢?
原因很简单。是间接光不是颜色,是间接光不是颜色,是间接光不是颜色。

我是尽量避免写公式的,但是迟早要看到这个可怕的公式。

每个方向向量可以认为是wi,以前采样的颜色,在这里可以认为是L(p,wi),
而这个公式计算所有间接漫反射光的积分。

通过以往经验可知,积分必定要转换为离散和,也就是说,用N个采样数据之和代替积分。

那么,从哪里开始采样呢?以什么依据采样呢?答案是表面法线中心,从中间到两边。
从下图可以看到很好理解了。
再细化就是当作球体,经纬度,经度从0到360,纬度是0到90度。

由于球的性质,采样不均衡,所以,再加个sin值调节区域采样贡献。又由于较大的角度光比较暗,再加上cos调节。如下图:

采样时,从球面坐标转到3d直角向量,再将该向量从切线空间转到世界空间,然后用该向量采样HDR环境贴图。

似乎看起来很复杂,但是,更复杂的还在后面,镜面IBL,哈哈,

看看采样后的运行结果

代码如下:
#include <osg/TextureCubeMap>
#include <osg/TexGen>
#include <osg/TexEnvCombine>
#include <osgUtil/ReflectionMapGenerator>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/NodeVisitor>
#include <osg/ShapeDrawable>

static const char * vertexShader =
{
“in vec3 aPos;\n”
“varying vec3 WorldPos;”
“void main(void)\n”
“{\n”
“WorldPos = aPos;\n”
" gl_Position = ftransform();\n"
“}\n”
};

static const char *psShader =
{
"varying vec3 WorldPos; "
"uniform samplerCube environmentMap; "
"const float PI = 3.14159265359; "
"void main() "
"{ "
" vec3 N = normalize(WorldPos); "
" vec3 irradiance = vec3(0.0); "
" vec3 up = vec3(0.0, 1.0, 0.0); "
" vec3 right = normalize(cross(up, N)); "
" up = normalize(cross(N, right)); "
" float sampleDelta = 0.025; "
" float nrSamples = 0.0; "
" for (float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta) "
" { "
" for (float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta) "
" { "
" vec3 tangentSample = vec3(sin(theta) * cos(phi), sin(theta) * sin(phi), cos(theta)); "
" vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N; "
" irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta); "
" nrSamples++; "
" } "
" } "
" irradiance = PI * irradiance * (1.0 / float(nrSamples)); "
" gl_FragColor = vec4(irradiance, 1.0); "
“}”
};
class MyNodeVisitor : public osg::NodeVisitor
{
public:
MyNodeVisitor() : osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN)
{

}
void apply(osg::Geode& geode)
{int count = geode.getNumDrawables();for (int i = 0; i < count; i++){osg::ref_ptr<osg::Geometry> geometry = geode.getDrawable(i)->asGeometry();if (!geometry.valid()){continue;}osg::Array* vertexArray = geometry->getVertexArray();geometry->setVertexAttribArray(1, vertexArray);}traverse(geode);
}

};

int main()
{
osg::ref_ptrosg::TextureCubeMap tcm = new osg::TextureCubeMap;
tcm->setTextureSize(512, 512);
tcm->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
tcm->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
tcm->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
tcm->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
tcm->setWrap(osg::Texture::WRAP_R, osg::Texture::CLAMP_TO_EDGE);

std::string strImagePosX = "D:/delete/Right face camera.bmp";
osg::ref_ptr<osg::Image> imagePosX = osgDB::readImageFile(strImagePosX);
tcm->setImage(osg::TextureCubeMap::POSITIVE_X, imagePosX);
std::string strImageNegX = "D:/delete/Left face camera.bmp";
osg::ref_ptr<osg::Image> imageNegX = osgDB::readImageFile(strImageNegX);
tcm->setImage(osg::TextureCubeMap::NEGATIVE_X, imageNegX);std::string strImagePosY = "D:/delete/Front face camera.bmp";;
osg::ref_ptr<osg::Image> imagePosY = osgDB::readImageFile(strImagePosY);
tcm->setImage(osg::TextureCubeMap::POSITIVE_Y, imagePosY);
std::string strImageNegY = "D:/delete/Back face camera.bmp";;
osg::ref_ptr<osg::Image> imageNegY = osgDB::readImageFile(strImageNegY);
tcm->setImage(osg::TextureCubeMap::NEGATIVE_Y, imageNegY);std::string strImagePosZ = "D:/delete/Top face camera.bmp";
osg::ref_ptr<osg::Image> imagePosZ = osgDB::readImageFile(strImagePosZ);
tcm->setImage(osg::TextureCubeMap::POSITIVE_Z, imagePosZ);
std::string strImageNegZ = "D:/delete/Bottom face camera.bmp";
osg::ref_ptr<osg::Image> imageNegZ = osgDB::readImageFile(strImageNegZ);
tcm->setImage(osg::TextureCubeMap::NEGATIVE_Z, imageNegZ);osg::ref_ptr<osg::Box> box = new osg::Box(osg::Vec3(0, 0, 0), 1);
osg::ref_ptr<osg::ShapeDrawable> drawable = new osg::ShapeDrawable(box);
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(drawable);
MyNodeVisitor nv;
geode->accept(nv);
osg::ref_ptr<osg::StateSet> stateset = geode->getOrCreateStateSet();
stateset->setTextureAttributeAndModes(0, tcm, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);//shaderosg::ref_ptr<osg::Shader> vs1 = new osg::Shader(osg::Shader::VERTEX, vertexShader);
osg::ref_ptr<osg::Shader> ps1 = new osg::Shader(osg::Shader::FRAGMENT, psShader);
osg::ref_ptr<osg::Program> program1 = new osg::Program;
program1->addShader(vs1);
program1->addShader(ps1);
program1->addBindAttribLocation("aPos", 1);osg::ref_ptr<osg::Uniform> tex0Uniform = new osg::Uniform("environmentMap", 0);
stateset->addUniform(tex0Uniform);
stateset->setAttribute(program1, osg::StateAttribute::ON);osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
viewer->setSceneData(geode);
viewer->realize();
return viewer->run();

}

十二,HDR环境贴图卷积相关推荐

  1. three.js通过CubeTexture加载环境贴图,和RGBELoader加载器加载hdr环境贴图

    一.使用CubeTexture进行环境贴图 1.CubeTexture使用介绍 Three.js中可以通过使用CubeTexture进行环境贴图,CubeTexture需要将6张图片(正面.反面.上下 ...

  2. React Three.js 增加hdr环境贴图和背景图片的方法

    React Three.js 增加hdr环境贴图和背景图片的方法: import React, { Suspense, useEffect } from 'react' import { Canvas ...

  3. Highcharts翻译系列十二:gauge测量图

    Highcharts翻译系列十二:gauge测量图 说明 测量图需要highcharts-more.js的支持 属性 参数 描述 默认值 animation 动画 true color 主要颜色或序列 ...

  4. 【TensorFlow】TensorFlow从浅入深系列之十二 -- 教你深入理解卷积神经网络中的池化层

    本文是<TensorFlow从浅入深>系列之第12篇 TensorFlow从浅入深系列之一 -- 教你如何设置学习率(指数衰减法) TensorFlow从浅入深系列之二 -- 教你通过思维 ...

  5. 第十二周项目一----图基本算法库

    /*烟台大学计算机与控制工程学院 作者:孙潇 时间:2015年11月13日 问题描述:定义图的邻接矩阵和邻接表存储结构,实现其基本运算,并完成测试. 输入描述:无 输出描述:若干数据 */ 头文件: ...

  6. 量化投资学习必读书目之十二——《日本蜡烛图技术》

    内容简介 <日本蜡烛图技术:古老东方投资术的现代指南>是对技术分析书面资料的一项激动人心的.价值不菲的充实.它以详实.流畅.精辟易懂的语言,有史以来第一次,将这门古老的东方技巧介绍到美国交 ...

  7. D3 二维图表的绘制系列(二十二)桑基图sankey

    上一篇: 仪表盘图 https://blog.csdn.net/zjw_python/article/details/98596174 下一篇: 旭日图 https://blog.csdn.net/z ...

  8. 通俗全面理解图卷积与GCN网络(一):图与图卷积

    下一篇:通俗全面理解图卷积与GCN网络(二):从图卷积到GCN 目录 前言 图 一般表示 度.邻接.拉普拉斯 为什么拉普拉斯 拉普拉斯矩阵的特征值分解 图卷积通式 总结 前言 相信大家都了解普通卷积操 ...

  9. DirectX12(D3D12)基础教程(二十二) ——HDR IBL 等距柱面环境光源加载和解算及 GS 一次性渲染到 CubeMap

    前序文章目录 DirectX12(D3D12)基础教程(一)--基础教程 DirectX12(D3D12)基础教程(二)--理解根签名.初识显存管理和加载纹理.理解资源屏障 DirectX12(D3D ...

  10. 知识图谱论文阅读【十二】【KDD2020】 使用贝叶斯图卷积神经网络推荐精确和多样化项目的框架【看不懂,待续】

    题目: A Framework for Recommending Accurate and Diverse Items Using Bayesian Graph Convolutional Neura ...

最新文章

  1. 项目经理应该具备的技能
  2. pass4side IBM 000-M15
  3. 图像数据流识别圆形_人工智能大赛视觉处理(一)图形识别
  4. boost::mp11::mp_empty相关用法的测试程序
  5. 人际交往的“三有三避”
  6. Hbase的shell出现wrong number of arguments xxx以及undefined method any?for xxxx
  7. [C/C++]BKDRHash
  8. wifi协议_图解 802.11wifi协议
  9. Docker在测试领域的应用
  10. Linux kernel路由机制分析(上)
  11. (四)、jave2加工视频
  12. creo减速器建模实例,减速箱proE整体及零件图
  13. “15分钟核酸检测服务圈”怎样进行采样点选址
  14. 嵌入式编程语言挑选的原则
  15. 怎么把大的文件传送到服务器,大文件如何上传到云服务器
  16. ORA-00119和ORA-00132的解决方案
  17. 简易垂直搜索引擎的核心算法总结
  18. GB9706.1-2020安规三项之漏电流测试方法
  19. html实现游戏鼠标样式,巧妙运用CSS立刻改变鼠标的样式
  20. python网络爬虫权威指南 第2版 pdf微盘_python网络爬虫权威指南第2版pdf-Python网络爬虫权威指南第2版中文PDF+英文PDF+源代码下载_东坡手机下载...

热门文章

  1. 机器学习基础:大数据与深度学习的关系
  2. 16x16LED点阵屏之移动显示汉字
  3. vue 点击文字按钮复制相应内容与复制并打开链接
  4. Jeasyframe 开源框架 预览版 V1.3 发布
  5. Linux线程(3)——pthread_cancel()取消一个线程
  6. 妇女解放是幸事Or倒退?
  7. bga焊盘怎么做_手把手教你BGA焊盘修理技术 | productronica China 慕尼黑上海电子生产设备展...
  8. 基于JAVA校园招聘管理系统计算机毕业设计源码+系统+数据库+lw文档+部署
  9. wordpress下载插件,安装失败,无法创建目录问题
  10. 大数据应用发展史:从搜索引擎到人工智能