当前位置: 首页 > news >正文

二十,镜面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;

}

相关文章:

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

比起以往&#xff0c;这节应该是最轻松的了&#xff0c; 运行结果如下 代码如下&#xff1a; #include <osg/TextureCubeMap> #include <osg/TexGen> #include <osg/TexEnvCombine> #include <osgUtil/ReflectionMapGenerator> #include <osgDB/Re…...

自动驾驶:未来的道路上的挑战与机遇

自动驾驶&#xff1a;未来的道路上的挑战与机遇 文章目录 引言安全与道路事故的减少交通拥堵的缓解城市规划的变革技术和法律挑战结语 2023星火培训【专项营】Apollo开发者社区布道师倾力打造&#xff0c;包含PnC、新感知等的全新专项课程上线了。理论与实践相结合&#xff0c;…...

Go 语言 iota 的神奇力量

前言 当你深入研究官网库、开源库或者任何一个 Go 项目时&#xff0c;你都会发现 iota 这个神奇的标识符无处不在。它扮演着一种重要的角色&#xff0c;让代码变得更加简洁、清晰&#xff0c;并提高了可读性和可维护性。它的应用范围广泛&#xff0c;从枚举类型到位运算&#…...

前端开发和后端开发的一些建议

前端开发和后端开发是Web开发的两个方向 前端开发主要负责实现用户在浏览器上看到的界面和交互体验&#xff0c;包括HTML、CSS和JavaScript等技术。后端开发主要负责处理服务器端的逻辑和数据&#xff0c;包括数据库操作、服务器配置和接口开发等技术。 前端开发 前端开发需…...

基于 SpringBoot+Vue 的教室人事档案管理系统

1 简介 教师人事档案管理系统利用信息的合理管理&#xff0c;动态的、高效的、安全的实现了教师的各种需求&#xff0c;改变了传统的网上查看方式&#xff0c;使教师可以足不出户的在线查看最适合自己个人档案、奖惩信息、档案变动、培训报名或者新闻资讯。 1、教师后台功能模…...

Lua学习笔记:require非.lua拓展名的文件

前言 本篇在讲什么 Lua的require相关的内容 本篇需要什么 对Lua语法有简单认知 对C语法有简单认知 依赖Visual Studio工具 本篇的特色 具有全流程的图文教学 重实践&#xff0c;轻理论&#xff0c;快速上手 提供全流程的源码内容 ★提高阅读体验★ &#x1f449; ♠…...

Python 编程基础 | 第三章-数据类型 | 3.3、浮点数

一、浮点数...

beego---ORM相关操作

Beego框架是go语言开发的web框架。 **那什么是框架呢&#xff1f;**就是别人写好的代码&#xff0c;我们可以直接使用&#xff01;这个代码是专门针对某一个开发方向定制的&#xff0c;例如&#xff1a;我们要做一个网站&#xff0c;利用 beego 框架就能非常快的完成网站的开发…...

【网络原理】初始网络,了解概念

文章目录 1. 网络通信1.1 局域网LAN1.2 广域网WAN 2. 基础概念2.1 IP2.2 端口号 3. 认识协议4. 五元组5. 协议分层5.1 分层的作用5.2 OSI七层模型5.3 TCP/IP五层&#xff08;四层&#xff09;模型 6. 封装和分用 1. 网络通信 计算机与计算机之间是互相独立&#xff0c;是独立模…...

对象存储,从单机到分布式的演进

关于数据存储的相关知识,请大家关注“数据存储张”,各大平台同名。 通过《什么是云存储?从对象存储说起》我们对对象存储的历史、概念和基本使用有了一个大概的认识。而且我们以Minio为例,通过单机部署的模式实际操作了一下对象存储的GUI,感受了一下对象存储的用法。 在上…...

结构型设计模式——桥接模式

摘要 桥接模式(Bridge pattern): 使用桥接模式通过将实现和抽象放在两个不同的类层次中而使它们可以独立改变。 一、桥接模式的意图 将抽象与实现分离开来&#xff0c;使它们可以独立变化。 二、桥接模式的类图 Abstraction: 定义抽象类的接口Implementor: 定义实现类接口 …...

keepalived的vip实现nginx节点的主备

nginx wget http://nginx.org/download/nginx-1.18.0.tar.gz tar zxvf nginx-1.18.0.tar.gzyum install -y gcc gcc-c pcre pcre-devel zlib zlib-devel openssl openssl-devel libnl3-develcd nginx-1.18.0 mkdir -p /usr/local/nginx #需要使用https&#xff0c;在编译时启用…...

C++之std::atomic解决多线程7个问题(二百四)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…...

tailwindcss 如何在 uniapp 中使用

直接使用https://tailwindcss.com/docs/guides/vite这篇官方教程的写法是跑不通的&#xff0c;摸索以后整理了一下&#xff0c;最关键的是第6步 npm install -D tailwindcss postcss autoprefixernpx tailwindcss init -p在 tailwind.config.js 中写入 export default {conten…...

oracle-使用PLSQL工具自行修改用户密码

1、使用PLSQL工具&#xff0c;输入用户名和原密码登录&#xff0c;如下图 2、登录后&#xff0c;在会话下拉菜单中找到”Change password..” 3、在跳出的窗口中配置新密码&#xff0c;修改完成后单击”确认”&#xff0c;后退出PLSQL 4、重新打开PLSQL&#xff0c;使用新密码登…...

自动驾驶技术:现状与未来

自动驾驶技术&#xff1a;现状与未来 文章目录 引言自动驾驶技术的现状自动驾驶技术的挑战自动驾驶技术的未来结论结论 2023星火培训【专项营】Apollo开发者社区布道师倾力打造&#xff0c;包含PnC、新感知等的全新专项课程上线了。理论与实践相结合&#xff0c;全新的PnC培训不…...

C++ 类构造函数 析构函数

类的构造函数 类的构造函数是类的一种特殊的成员函数&#xff0c;它会在每次创建类的新对象时执行。 构造函数的名称与类的名称是完全相同的&#xff0c;并且不会返回任何类型&#xff0c;也不会返回 void。构造函数可用于为某些成员变量设置初始值。 下面的实例有助于更好地…...

C++标准模板(STL)- 输入/输出操纵符-(std::get_time,std::put_time)

操纵符是令代码能以 operator<< 或 operator>> 控制输入/输出流的帮助函数。 不以参数调用的操纵符&#xff08;例如 std::cout << std::boolalpha; 或 std::cin >> std::hex; &#xff09;实现为接受到流的引用为其唯一参数的函数。 basic_ostream::…...

蓝桥等考Python组别九级004

第一部分:选择题 1、Python L9 (15分) 运行下面程序,可以输出几行“*”?( ) for i in range(3): for j in range(4): print(*, end = ) print() 2345正确答案:B 2、Python L9...

gitee 远程仓库操作基础(二)

(1&#xff09;clone远端仓库,本地建立分支推送 (基于远程仓库版本库 本地建立分支开发新功能) git clone gitgitee.com:xxxxx/alsa_test.git git remote add origin gitgitee.com:xxxxx/alsa_test.git进入clone过后路径代码,查看本地分支,发现该项目远程仓库有很多分支 基于…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

ServerTrust 并非唯一

NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

ubuntu22.04有线网络无法连接,图标也没了

今天突然无法有线网络无法连接任何设备&#xff0c;并且图标都没了 错误案例 往上一顿搜索&#xff0c;试了很多博客都不行&#xff0c;比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动&#xff0c;重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...

阿里云Ubuntu 22.04 64位搭建Flask流程(亲测)

cd /home 进入home盘 安装虚拟环境&#xff1a; 1、安装virtualenv pip install virtualenv 2.创建新的虚拟环境&#xff1a; virtualenv myenv 3、激活虚拟环境&#xff08;激活环境可以在当前环境下安装包&#xff09; source myenv/bin/activate 此时&#xff0c;终端…...

车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...