首页 > 其他分享 >基于物理的渲染(3):OSG中PBR实践

基于物理的渲染(3):OSG中PBR实践

时间:2024-01-20 22:36:57浏览次数:26  
标签:1.0 渲染 float PBR roughness vec3 uniform osg OSG

1.1 单光源直接光照

void main()
{
	//创建小球几何
	osg::ref_ptr<osg::ShapeDrawable> sphere =new osg::ShapeDrawable;
	sphere->setShape(new osg::Sphere(osg::Vec3(0,0,0),radius));
	sphere->setColor(osg::Vec4(col));
	//创建小球节点
	osg::ref_ptr<osg::Geode> pbrGeode =new osg::Geode;
	pbrGeode->addChild(sphere);
	//创建纹理
	QVector<QString> paths={
	"height.png",
	"metakkic.png",
	"normal.png",
	"roughness.png",
	"albedo.png",
	"ao.png"};
	for(int i=0;i<paths.size();i++)
	{
		osg::ref_ptr<osg::Texture2D> texture =new osg::Texture2D;
		osg::ref_ptr<osg::Image> img =nullptr;
		texture->setImage(img );
		pbrGeode->getOrcreateStateSet()->setTextureAttributeAndModes(i,texture);
		auto num=("tex"+QString::number(i)).toStdString();
		pbrGeode->getOrcreateStateSet()->addUniform(new osg::Uniform(num.data(),(int)i));
	}
	//顶点着色器	
	static const char* vertCode="#version 330\n"
	"layout(location =0) in vec3 Position;\n"
	"layout(location =2) in vec3 Normal;\n"
	"layout(location =8) in vec3 TexCoord;\n"
	
	"uniform mat4 osg_ModelViewProjectionMatrix;\n"
	"uniform mat4 osg_ModelViewMatrix;\n"
	"uniform mat4 osg_NormalMatrix;\n"	
	
	"out vec3 vNormal;\n"
	"out vec3 vCameraPos;\n"
	"out vec3 vWorldPos;\n"
	"out vec2 texCoord;\n"
	
	"void main()\n"
	"{"
	"	texCoord=TexCoord;\n"
	"	vNormal=normalize(osg_NormalMatrix*vec4(Position,1.0));\n"
	"	gl_position=osg_ModelViewProjectionMatrix*vec4(Position,1.0);\n"
	//实时计算相机世界坐标
	"	vCameraPos=inverse(osg_ModelViewMatrix)*vec4(0.0,0.0,0.0,1.0);\n"
	"	vWorldPos=Position;\n"
	"}"
	//片段着色器	
	static const char* fragCode="#version 330\n"
	"uniform sampler2D tex0;\n"	
	"uniform sampler2D tex1;\n"	
	"uniform sampler2D tex2;\n"	
	"uniform sampler2D tex3;\n"	
	"uniform sampler2D tex4;\n"	
	"uniform sampler2D tex5;\n"	
	"uniform vec3 lightPos=vec3(100.0,0.0,100.0);\n"
	"uniform vec3 lightCol=vec3(150.0,150.0,150.0);\n"	
	"in vec3 vNormal;\n"
	"in vec3 vCameraPos;\n"
	"in vec3 vWorldPos;\n"
	"in vec2 texCoord;\n"
	"out vec4 fragColor;\n"
	//菲涅尔方程
	"vec3 fresnelSchlick(float cosTheta, vec3 F0)\n"
    "{\n"
    "    return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);\n"
    "}\n"
	//法线分布函数
	"float distributionGGX(float NdotV, float roughness)\n"
    "{\n"
    "    float a4 = roughness*roughness*roughness*roughness;\n"
    "    float NdotH = max(dot(N, H), 0.0);\n"
    "    float NdotH2 = NdotH*NdotH;\n"
    "    float denom = (NdotH2 * (a4 - 1.0) + 1.0);\n"
    "    denom = 3.1415 * denom * denom;\n"
    "    return a4 / denom;\n"
    "}\n"
	//观察方向几何遮蔽函数
	"float geometrySchlickGGX(float NdotV, float roughness)\n"
    "{\n"
    "    float k = ((roughness + 1.0)*(roughness + 1.0)) / 8.0;\n"
    "    float denom = NdotV * (1.0 - k) + k;\n"
    "    return NdotV / denom;\n"
    "}\n"
    //光线方向几何阴影函数
    "float geometrySmith(float NdotV,float NdotL, float roughness)\n"
    "{\n"
    "    float ggx2 = GeometrySchlickGGX(NdotV, roughness);\n"
    "    float ggx1 = GeometrySchlickGGX(NdotL, roughness);\n"
    "    return ggx1 * ggx2;\n"
    "}\n"
    //计算切线空间到世界空间坐标转换矩阵
    "vec3 tangToWorldMat()\n"
    "{\n"
    "    vec3 tangentNormal = texture(tex2, texCoord).xyz * 2.0 - 1.0;\n"
    "    vec3 Q1  = dFdx(WorldPos);\n"
    "    vec3 Q2  = dFdy(WorldPos);\n"
    "    vec2 st1 = dFdx(texCoord);\n"
    "    vec2 st2 = dFdy(texCoord);\n"
    "    vec3 N   = normalize(Normal);\n"
    "    vec3 T  = normalize(Q1*st2.t - Q2*st1.t);\n"
    "    vec3 B  = -normalize(cross(N, T));\n"
    "    mat3 TBN = mat3(T, B, N);\n"
    "    return normalize(TBN * tangentNormal);\n"
    "}\n"
    "void main()\n"
	"{"
	//获取纹理参数
	"	vec3  albdo=texture(tex4,texCoord).rgb;\n"
	"	float metalic=texture(tex1,texCoord).r;\n"
	"	float rough=texture(tex3,texCoord).r;\n"
	"	float ao=texture(tex5,texCoord).r;\n"
	//计算世界坐标系下法线
	"	vec3 N=tangToWorldMat();\n"
	"   V=normailze(vCameraPos-vWorldPos);\n"
	//计算F0
	"	vec3 F0=vec3(0.4);\n"
	"	F0=mix(F0,albdo,metallic);\n"
	"	vec3 L=normailze(lightPos-vWorldPos);\n"
	"	vec3 H=normailze(V+L);\n"
	"	float distan=length(lightPos-vWorldPos);\n"
	"	float atten=200.0/(distan*distan);\n"	
	"	vec3  radiance=lightCol*atten;\n"
	"	float NdotV=max(dot(N,V),0.0);\n"	
	"	float NdotL=max(dot(N,L),0.0);\n"	
	"	float NdotH=max(dot(N,H),0.0);\n"	
	"	float HdotV=max(dot(H,V),0.0);\n"	
	//计算BRDF
	"	float D=distributionGGX(NdotH,rough);\n"
	"	float G=geometrySmith(NdotV,NdotL,rough);\n"
	"	vec3  F=fresnelSchlick(HdotV,F0);\n"
	"	vec3  spec=D*F*G/(4.0*NdotV*NdotL+0.00001);\n"
	"	kD=(vec3(1.0)-F)*(1.0-metalic);\n"
	"	Lo=(kD*albdo/3.1415+spec)*radiance*NdotL;\n"
	"	vec3 ambient=vec3(1.0)*albdo*ao;\n"
	"	vec3 color=ambient+Lo;\n"
	"	fragColor=vec4(color,1.0);\n"
	"}";
	//编译shader
	osg::ref_ptr<osg::Shader> vertShader=new osg::Shader(osg::Shader::VERT,vertCode);
	osg::ref_ptr<osg::Shader> fragShader=new osg::Shader(osg::Shader::FRAG,fragCode);
	osg::ref_ptr<osg::Program> program=new osg::Program;
	program->addShader(vertShader);
	program->addShader(fragShader);
	pbrGeode->getOrCreateStateSet()->setAttributeAndModes(program,OVERRIDE_ON);
	return pbrGeode;
}

1.2 PBR结合视差贴图

  要达到模型表面凹凸不平的效果,可以使用高度贴图对几何顶点做偏移,但是这要求模型顶点足够多,以呈现较好的视觉效果,此外也可以使用视差贴图技术实现相同效果。

  视差贴图原理:如上图所示,红线为高度贴图上顶点高度偏移值,黄线为视点和像素点连线,A点为实际纹理坐标,这样不用A点纹理坐标取得的高度,而是用B点高度,也就是说将A点纹理坐标加上一个偏移量得到修正后纹理坐标,来采样得到修正高度。视差贴图需要在切线空间计算,以便在不同视角上观察都可以得到正常的视觉效果。

vec2 ParallaxMapping(vec2 texCoords, vec3 viewDir)
{ 
    float height =  texture(depthMap, texCoords).r;    
    vec2 p = clamp(viewDir.xy / (viewDir.z=0.0001),-1.0,1.0);
    return p* (height * height_scale);    
}

标签:1.0,渲染,float,PBR,roughness,vec3,uniform,osg,OSG
From: https://www.cnblogs.com/wangxydela/p/17977239

相关文章

  • 前端歌谣-第六十五课-express之服务端渲染和客户端渲染
    前言我是歌谣微信公众号关注前端小歌谣一起学习前端知识今天继续给大家讲解服务端渲染和客户端渲染静态资源的讲解案列index.html<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,init......
  • c4d阿诺德怎么渲染高清图片
    c4d作为也可热门建模工具,该渲染器支持多种渲染器使用,很多人在选择阿诺德渲染器是出现了高清图片无法渲染的问题,阿诺德可提供逼真的光影效果和物理材质,那么怎么利永阿诺德渲染高清的图片呢,一起来简单看看吧。c4d阿诺德怎么渲染高清图片1、调整输出设置:在渲染设置中找到"输出"(O......
  • 个人小型渲染农场搭建需要准备什么?
    ​渲染农场是指具备一定计算机资源平台,这类平台通常拥有庞大渲染机器,并且需要足够的资金,还要有专业人员进行维护。个人小型渲染农场的搭建,第一要点就是需要资金,这样能购买足够的硬件、渲染软件、3d建模软件、配置网络等。一、渲染农场搭建分析在搭建小型渲染农场的时候,需要明......
  • Java实现基于GDAL将单波段影像转为三波段影像-唯一值渲染
    在处理遥感影像的渲染时,经常需要处理单波段影像。单波段影像没有任何颜色,只有一个波段的值。渲染时只能采用色带拉伸、离散颜色、唯一值渲染这几种方式。直接将单波段影像转成三波段的影像,并将三个波段转为颜色对应的rgb值,这样可以加速渲染、切片的过程。这里我有一张单波段影像,需......
  • 第29节: Vue3 列表渲染
    在UniApp中使用Vue3框架时,你可以使用列表渲染语法来动态地渲染一个列表。下面是一个示例,演示了如何在UniApp中使用Vue3框架使用列表渲染:<template><view><button@click="addItem">AddItem</button><ul><liv-for="(item,index)initems":......
  • 第28节: Vue3 条件渲染
    在UniApp中使用Vue3框架时,你可以使用条件渲染来根据条件动态地显示或隐藏元素。下面是一个示例,演示了如何在UniApp中使用Vue3框架使用条件渲染:<template><view><button@click="toggleActive">ToggleActive</button><pv-if="isActive">Thisisactive</p......
  • osg设置材质
      #include<osg/Material>#include<osg/Geode>#include<osgDB/ReadFile>#include<osgViewer/Viewer>intmain(){//创建一个场景节点osg::ref_ptr<osg::Node>root=newosg::Geode();//创建一个模型节点,这里读取一个模型文件作为场景节点下的子......
  • 电影动画用云渲染好吗?有什么优势
    动画电影的创作是一个将声音和图像融合以产生视觉故事的过程,电影通常是由一系列静止图像构成,其中每一幅静止图像称为一帧。动画电影的流畅度依赖于每秒播放的帧数,常见的帧率有25、60、90或120帧每秒等,具体取决于制片方的选择和制作标准。这些影片通常具有高分辨率,以及对细节的......
  • WidgetsBinding.instance.addPostFrameCallback widget首次渲染完成执行其他操作
    使用场景Flutter中的界面组件(控件)只要一帧就能绘制渲染在屏幕上,当然,这一帧Flutter做了很多事,包括Build、Layout和Painting阶段。而 addPostFrameCallback 就是在每一帧绘制完成后再回调执行一些自己的方法。这个机制的使用场景非常多。比如组件渲染完后做一些操作,像开......
  • 记一个vue2中使用路由时,在同一个页面跳转,但是url参数不同,不会重新渲染页面的问题
    vue2中使用路由时,页面自己跳转自己,但是携带的参数不一样预期想要的结果是:感冒2会跟随着url的参数进行变化,但是并没用 解决方法: 在App.vue这个页面中的router-view添加  :key="$route.fullPath"结果在自己跳转自己之后会刷新页面 达成:参考:https://blog.csdn.ne......