二十,镜面IBL--打印BRDF积分贴图

比起以往,这节应该是最轻松的了,
运行结果如下
在这里插入图片描述
代码如下:
#include <osg/TextureCubeMap>
#include <osg/TexGen>
#include <osg/TexEnvCombine>
#include <osgUtil/ReflectionMapGenerator>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/NodeVisitor>
#include <osg/ShapeDrawable>
#include <osg/Texture2D>
#include <osgDB/WriteFile>
static const char * vertexShader =
{
“in vec3 aPos;\n”
“in vec2 texcoord;”
“varying vec2 TexCoords;\n”
“void main(void)\n”
“{\n”
“TexCoords = texcoord;\n”
“gl_Position = ftransform();\n”
//“gl_Position = view * view * vec4(aPos,1.0);”
“}\n”
};

static const char psShader =
{
“#version 330 core \n”
“out vec2 FragColor; \n”
“in vec2 TexCoords; \n”
" \n"
“const float PI = 3.14159265359; \n”
“// ---------------------------------------------------------------------------- \n”
“// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html \n”
“// efficient VanDerCorpus calculation. \n”
“float RadicalInverse_VdC(uint bits) \n”
“{ \n”
" bits = (bits << 16u) | (bits >> 16u); \n"
" bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); \n"
" bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); \n"
" bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); \n"
" bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); \n"
" return float(bits) * 2.3283064365386963e-10; // / 0x100000000 \n"
“} \n”
“// ---------------------------------------------------------------------------- \n”
“vec2 Hammersley(uint i, uint N) \n”
“{ \n”
" return vec2(float(i) / float(N), RadicalInverse_VdC(i)); \n"
“} \n”
“// ---------------------------------------------------------------------------- \n”
“vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness) \n”
“{ \n”
" float a = roughness
roughness; \n"
" \n"
" float phi = 2.0 * PI * Xi.x; \n"
" float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (aa - 1.0) * Xi.y)); \n"
" float sinTheta = sqrt(1.0 - cosTheta
cosTheta); \n"
" \n"
" // from spherical coordinates to cartesian coordinates - halfway vector \n"
" vec3 H; \n"
" H.x = cos(phi) * sinTheta; \n"
" H.y = sin(phi) * sinTheta; \n"
" H.z = cosTheta; \n"
" \n"
" // from tangent-space H vector to world-space sample vector \n"
" vec3 up = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); \n"
" vec3 tangent = normalize(cross(up, N)); \n"
" vec3 bitangent = cross(N, tangent); \n"
" \n"
" vec3 sampleVec = tangent * H.x + bitangent * H.y + N * H.z; \n"
" return normalize(sampleVec); \n"
“} \n”
“// ---------------------------------------------------------------------------- \n”
“float GeometrySchlickGGX(float NdotV, float roughness) \n”
“{ \n”
" // note that we use a different k for IBL \n"
" float a = roughness; \n"
" float k = (a * a) / 2.0; \n"
" \n"
" float nom = NdotV; \n"
" float denom = NdotV * (1.0 - k) + k; \n"
" \n"
" return nom / denom; \n"
“} \n”
“// ---------------------------------------------------------------------------- \n”
“float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) \n”
“{ \n”
" float NdotV = max(dot(N, V), 0.0); \n"
" float NdotL = max(dot(N, L), 0.0); \n"
" float ggx2 = GeometrySchlickGGX(NdotV, roughness); \n"
" float ggx1 = GeometrySchlickGGX(NdotL, roughness); \n"
" \n"
" return ggx1 * ggx2; \n"
“} \n”
“// ---------------------------------------------------------------------------- \n”
“vec2 IntegrateBRDF(float NdotV, float roughness) \n”
“{ \n”
" vec3 V; \n"
" V.x = sqrt(1.0 - NdotV*NdotV); \n"
" V.y = 0.0; \n"
" V.z = NdotV; \n"
" \n"
" float A = 0.0; \n"
" float B = 0.0; \n"
" \n"
" vec3 N = vec3(0.0, 0.0, 1.0); \n"
" \n"
" const uint SAMPLE_COUNT = 1024u; \n"
" for (uint i = 0u; i < SAMPLE_COUNT; ++i) \n"
" { \n"
" // generates a sample vector that’s biased towards the \n"
" // preferred alignment direction (importance sampling). \n"
" vec2 Xi = Hammersley(i, SAMPLE_COUNT); \n"
" vec3 H = ImportanceSampleGGX(Xi, N, roughness); \n"
" vec3 L = normalize(2.0 * dot(V, H) * H - V); \n"
" \n"
" float NdotL = max(L.z, 0.0); \n"
" float NdotH = max(H.z, 0.0); \n"
" float VdotH = max(dot(V, H), 0.0); \n"
" \n"
" if (NdotL > 0.0) \n"
" { \n"
" float G = GeometrySmith(N, V, L, roughness); \n"
" float G_Vis = (G * VdotH) / (NdotH * NdotV); \n"
" float Fc = pow(1.0 - VdotH, 5.0); \n"
" \n"
" A += (1.0 - Fc) * G_Vis; \n"
" B += Fc * G_Vis; \n"
" } \n"
" } \n"
" A /= float(SAMPLE_COUNT); \n"
" B /= float(SAMPLE_COUNT); \n"
" return vec2(A, B); \n"
“} \n”
“// ---------------------------------------------------------------------------- \n”
“void main() \n”
“{ \n”
" vec2 integratedBRDF = IntegrateBRDF(TexCoords.x, TexCoords.y); \n"
" FragColor = integratedBRDF; \n"
“} \n”
};

osg::ref_ptrosg::Texture2D createFloatRectangleTexture(int width, int height)
{
osg::ref_ptrosg::Texture2D tex2D = new osg::Texture2D;
tex2D->setTextureSize(width, height);
tex2D->setInternalFormat(GL_RGBA16F_ARB);
tex2D->setSourceFormat(GL_RGBA);
tex2D->setSourceType(GL_FLOAT);

tex2D->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
tex2D->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
tex2D->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
tex2D->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
return tex2D.release();

}
osg::ref_ptrosg::Geode createTexturePanelGeode()
{
osg::ref_ptrosg::Vec3Array vertices = new osg::Vec3Array;
vertices->push_back(osg::Vec3(-1.0f, -1.0f, 0.0f));
vertices->push_back(osg::Vec3(1.0f, -1.0f, 0.0f));
vertices->push_back(osg::Vec3(1.0f, 1.0f, 0.0f));
vertices->push_back(osg::Vec3(-1.0f, 1.0f, 0.0f));

osg::ref_ptr<osg::Vec2Array> texCoord = new osg::Vec2Array;
texCoord->push_back(osg::Vec2(0.0, 0.0));
texCoord->push_back(osg::Vec2(1.0, 0.0));
texCoord->push_back(osg::Vec2(1.0, 1.0));
texCoord->push_back(osg::Vec2(0.0, 1.0));osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
geom->setVertexArray(vertices);
geom->setTexCoordArray(0, texCoord);
geom->addPrimitiveSet(new osg::DrawArrays(GL_QUADS, 0, 4));geom->setVertexAttribArray(1, vertices, osg::Array::BIND_PER_VERTEX);
geom->setVertexAttribArray(2, texCoord, osg::Array::BIND_PER_VERTEX);osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(geom);
return geode;

}
int main()
{
//std::string strHDRImageName = “D:/tutorial/LearnOpenGL-master/LearnOpenGL-master/resources/textures/hdr/newport_loft.hdr”;
//osg::ref_ptrosg::Image image = osgDB::readImageFile(strHDRImageName);
//
//int imageWidth = image->s();
//int imageHeight = image->t();
int texWidth = 512;
int texHeight = 512;
osg::ref_ptrosg::Texture2D tex = createFloatRectangleTexture(texWidth, texHeight);
osg::ref_ptrosg::Geode panelGeode = createTexturePanelGeode();

osg::ref_ptr<osg::Camera> finalCamera = new osg::Camera;osg::ref_ptr<osg::StateSet> stateset = finalCamera->getOrCreateStateSet();
stateset->setTextureAttributeAndModes(0, tex);
finalCamera->addChild(panelGeode);
finalCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);finalCamera->setViewport(new osg::Viewport(0, 0, 512, 512));
osg::ref_ptr<osg::Image> printImage = new osg::Image;
printImage->allocateImage(512, 512, 1, GL_RGBA, GL_UNSIGNED_BYTE);
finalCamera->attach(osg::Camera::COLOR_BUFFER0, printImage); //关联采样贴图//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);
program1->addBindAttribLocation("texcoord", 2);osg::ref_ptr<osg::Uniform> tex0Uniform = new osg::Uniform("tex0", 0);
stateset->addUniform(tex0Uniform);
stateset->setAttribute(program1, osg::StateAttribute::ON);osgViewer::Viewer viewer;
viewer.setSceneData(finalCamera.get());bool bPrinted = false;
while (!viewer.done())
{viewer.frame();if (!bPrinted){bPrinted = true;std::string strBRDFLUTImageName = "e:/hdr/lut/brdflut.bmp";osgDB::writeImageFile(*printImage, strBRDFLUTImageName);}
}
return 0;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/143796.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kafka环境搭建以及基本原理

kafka最先是作为日志数据采集&#xff0c;后用于消息传递&#xff0c;kafka能承担tb级别数据存储&#xff0c;确保服务的可用性&#xff0c;允许少量数据的丢失 作为消息中间件就有异步、解耦、削峰三个作用 一、单机搭建 单机ip&#xff1a;192.168.64.133 下载地址&#…

启动 React APP 后经历了哪些过程

本文作者为 360 奇舞团前端开发工程师 前言 本文中使用的React版本为18&#xff0c;在摘取代码的过程中删减了部分代码&#xff0c;具体以源代码为准。 在React 18里&#xff0c;通过ReactDOM.createRoot创建根节点。并且通过调用原型链上的render来渲染。 本文主要是从以下两个…

刘强东再次拿起低价武器,杀入这个万亿市场

京东的低价策略也要在汽车后市场打起来了&#xff1f; 9月26日&#xff0c;途虎养车于港交所挂牌上市当天&#xff0c;京东集团副总裁、京东零售汽车事业部总裁缪钦在朋友圈发文祝贺&#xff0c;同时表示京东养车“所有‘震虎价’商品都比友商低5%”。贺词与战书&#xff0c;同…

紧固螺栓的常见类型有哪些?

大螺丝、小螺丝 螺丝有各种各样的叫法。螺丝、小螺丝、螺栓、鋲螺、螺杆、螺子、小螺钉等。螺丝的大小、以现代的技术细的可以加工到1毫米以下。例如用于手表、计算机、手机等螺丝能加工到0.5毫米。粗的螺丝一般使用到50毫米&#xff0c;主要用于建筑、桥梁等。根据需要可加工…

使用cpolar端口映射的方法轻松实现在Linux环境下SVN服务器的搭建与公网访问

文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…

Spring 学习(八)事务管理

1. 事务 1.1 事务的 ACID 原则 数据库事务&#xff08;transaction&#xff09;是访问并可能操作各种数据项的一个数据库操作序列。事务必须满足 ACID 原则——即原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔离性&#xff08;Iso…

【EI会议征稿】2023年第二届信号处理、计算机网络与通信国际学术会议(SPCNC2023)

2023年第二届信号处理、计算机网络与通信国际学术会议&#xff08;SPCNC2023&#xff09; The 2nd International Conference on Signal Processing, Computer Networks and Communications 2023年第二届信号处理、计算机网络与通信国际学术会议&#xff08;SPCNC2023&#x…

基于Linux系统聊天室增加数据库sqlite功能实现(08)

全部掌握后&#xff0c;开始进入本篇。 一. 调整目录结构 为了方便编译&#xff0c;现在我们将前面文章的代码结构做如下调整。 rootubuntu:/mnt/hgfs/code/chat# tree . . ├── chat_client │ ├── include │ ├── Makefile │ ├── obj │ │ └── …

CSS滚动条详解(::-webkit-scrollbar )

滚动条出现的事件&#xff1a; 当设置定宽或者定高的元素添加overflow:scroll属性&#xff0c;会出现滚动条&#xff0c;但是原生样式的会比较丑影响美观。 <div class"content"><div class"contain"></div> </div>.content {wid…

我试试专属勋章

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

windows:批处理bat实例

文章目录 文件/文件夹管理实例批量更改文件名创建编号从0到9的10个文件自动循环运行某个程序显示批处理的完整路径信息将文件名更名为当前系统日期使用批处理命令自动接收用户输入的信息计算当前目录及子目录&#xff08;中文件&#xff09;所占硬盘空间自动删除当前目录及子目…

深信服云桌面用户忘记密码后的处理

深信服云桌面用户忘记了密码&#xff0c;分两种情况&#xff0c;一个是忘记了登录深信服云桌面的密码&#xff0c;另外一个是忘记了进入操作系统的密码。 一、忘记了登录深信服云桌面的密码 登录虚拟桌面接入管理系统界面&#xff0c;在用户管理中选择用户后&#xff0c;点击后…

7.网络原理之TCP_IP(下)

文章目录 4.传输层重点协议4.1TCP协议4.1.1TCP协议段格式4.1.2TCP原理4.1.2.1确认应答机制 ACK&#xff08;安全机制&#xff09;4.1.2.2超时重传机制&#xff08;安全机制&#xff09;4.1.2.3连接管理机制&#xff08;安全机制&#xff09;4.1.2.4滑动窗口&#xff08;效率机制…

IntelliJ IDEA 左侧Commit栏不见了

1.点击File->Settings->Version Control->Commit 2.勾选Use non-modal commit interface

喜讯 | 怿星科技获评SAE“优秀核心零部件企业”,测试软件平台工具广受赞誉

2023年9月22日-23日&#xff0c;SAE 2023汽车智能与网联技术国际学术会议成功举行。此次学术会议由SAE International与南昌智能新能源汽车研究院联合主办&#xff0c;大会汇聚了来自国内外智能网联领域的顶尖专家和学者。大会同期颁布的奖项旨在向行业推选出更多新时代涌现的杰…

conan入门(二十七):因profile [env]字段废弃导致的boost/1.81.0 在aarch64-linux-gnu下交叉编译失败

今天在尝试用conan 1.60.0使用aarch64-linux-gnu编译器交叉编译boost/1.81.0时报错了&#xff1a; conan install boost/1.81.0 -pr:h aarch64-linux-gnu.jinja -pr:b default --build boost输出如下&#xff1a; Configuration (profile_host): [settings] archarmv8 arch_b…

26606-2011 工业用氰乙酸甲酯 阅读笔记

声明 本文是学习GB-T 26606-2011 工业用氰乙酸甲酯. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了工业用氰乙酸甲酯的要求、试验方法、检验规则、标志、包装、运输、贮存和安全。 本标准适用于以氯乙酸、氰化钠、甲醇等为原料…

fiddler抓包番外————了解工具栏

前言 作为一款功能强大的工具&#xff0c;Fiddler 提供了许多实用的功能和工具栏&#xff0c;可以帮助用户更加高效地使用它。 如果您想了解 Fiddler 的工具栏及其功能&#xff0c;那么本篇文章就是为您准备的。 在这里&#xff0c;我将为大家详细介绍 Fiddler 的工具栏及其各…

蓝牙核心规范(V5.4)11.1-LE Audio 笔记之诞生的前世今生

专栏汇总网址:蓝牙篇之蓝牙核心规范学习笔记(V5.4)汇总_蓝牙核心规范中文版_心跳包的博客-CSDN博客 爬虫网站无德,任何非CSDN看到的这篇文章都是盗版网站,你也看不全。认准原始网址。!!! 1.LE Audio应用的场景 这里面有四个场景是LE Audio最初需要应用的场景。比如助…

工业交换机一般的价格是多少呢?

工业交换机是一种应用于工业领域的网络设备。它的性能和所有安全指标都比一般商业交换机更加稳定。所以&#xff0c;工业级交换机的价格相对于普通的交换机要稍稍昂贵一些。工业交换机一般的价格是多少呢&#xff1f;每个厂家的交换机价格是不是都一样呢&#xff1f; 首先&…