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

多语言网站开发公司想要网站推广版

多语言网站开发公司,想要网站推广版,营销型网站建设套餐,芜湖县住房建设局网站延迟渲染学习笔记 一、基本概念二、G-BufferMRT 三、Lighting Pass四、结合延迟渲染和前向渲染五、更多光源 我们之前使用的一直是 前向渲染(正向渲染 Forward Rendering),指的是在场景中根据所有光源照亮一个物体,之后再渲染下一…

延迟渲染学习笔记

  • 一、基本概念
  • 二、G-Buffer
    • MRT
  • 三、Lighting Pass
  • 四、结合延迟渲染和前向渲染
  • 五、更多光源

我们之前使用的一直是 前向渲染(正向渲染 Forward Rendering),指的是在场景中根据所有光源照亮一个物体,之后再渲染下一个物体。对程序性能影响很大,因为对于每一个需要渲染的物体,程序都要对每一个光源每一个需要渲染的片段进行迭代。 而且还有一部分被渲染的片段会被覆盖遮挡,造成浪费

一、基本概念

延迟渲染(Deferred Rendering) ,包含两个Pass:

  • 第一个是几何处理Pass:先渲染场景一次,之后获取对象的各种几何信息(比如顶点位置、颜色、法线、高光信息等),并存储在G-Buffer中
    在这里插入图片描述
  • 然后第二个Pass是用于计算光照信息——Lighting Pass:我们将会渲染一个满屏的方片并根据G-Buffer中的几何数据信息来为每个片元进行光照计算(在G-Buffer中每个像素进行迭代)。
    在这里插入图片描述

与前向渲染不同,延迟渲染并不是将每个对象进行顶点着色器到片元着色器的计算,而是将片元着色器移动到后期处理。这样保证了对于在光照处理阶段中处理的每一个像素都只处理一次,所以我们能够省下很多无用的渲染调用。

缺陷:

  • 显存消耗会较大:G-Buffer需要我们存储较大的几何数据
  • 不能使用MSAA:因为我们通过只有几何数据的G-Buffer来进行着色

二、G-Buffer

G-Buffer是一个用来存储光照计算所需数据的纹理的总称。

  • 3D位置向量,来计算片段位置变量 lightDir,viewDir
  • 3D法向量,normal
  • RGB漫反射颜色向量,Albedo
  • 镜面强度(高光反射强度)
  • 光源的位置向量、颜色向量
  • 观察者的位置向量

在前向渲染中,我们每个物体的光照计算都是根据特定实时数据的,所以如何给Lighting Pass传递正确的光照数据是很重要的。延迟渲染G-Buffer已经把几何数据渲染到一张2D纹理中,纹理允许我们存储各种各样的数据类型,所以纹理上每个片元都有正确的几何数据供光照计算

while(...) // render loop
{// 1. geometry pass: render all geometric/color data to g-buffer glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);glClearColor(0.0, 0.0, 0.0, 1.0); // keep it black so it doesn't leak into g-bufferglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);gBufferShader.use();for(Object obj : Objects){ConfigureShaderTransformsAndUniforms();obj.Draw();}  // 2. lighting pass: use g-buffer to calculate the scene's lightingglBindFramebuffer(GL_FRAMEBUFFER, 0);lightingPassShader.use();BindAllGBufferTextures();SetLightingUniforms();RenderQuad();
}

MRT

在几何处理阶段,我们需要渲染场景中所有物体,并且存储这些几何数据在G-Buffer中。我们可以使用 MRT 来在一个Pass中渲染多个颜色缓冲。

我们需要初始化一个帧缓冲gBuffer(这个gBuffer会有多个颜色缓冲附件,以及一个深度渲染缓冲对象)。对于位置和法向量的纹理,我们希望使用高精度的纹理(每分量16或32位的浮点数),而对于反照率和镜面值,使用默认的纹理(每分量8位浮点数)就够了。

GLuint gBuffer;
glGenFramebuffer(1, &gBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, gBuffer);
GLuint gPosition, gNormal, gColorSpec;
//位置颜色缓冲
glGenTextures(1, &gPosition);
glBindTexture(GL_TEXTURE_2D, gPosition);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCRHEIGHT, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0);//法线颜色缓冲
glGenTextures(1, &gNormal);
glBindTexture(GL_TEXTURE_2D, gNormal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0);//颜色+镜面颜色缓冲
glGenTextures(1, &gAlbedoSpec);
glBindTexture(GL_TEXTURE_2D, gAlbedoSpec);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gAlbedoSpec, 0);//告诉OpenGL我们将用哪个颜色附件来渲染
GLuint attatchments[3] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2};
glDrawBuffers(3, attachments);// 之后同样添加渲染缓冲对象(Render Buffer Object)为深度缓冲(Depth Buffer),并检查完整性
[...]

接下来就是将数据渲染到G-Buffer中,我们将使用一下片元着色器

#version 330 core
layout (location = 0) out vec3 gPosition;
layout (location = 1) out vec3 gNormal;
layout (location = 2) out vec4 gAlbedoSpec;in vec2 TexCoords;
in vec3 FragPos;
in vec3 Normal;uniform sampler2D texture_diffuse1;
uniform sampler2D texture_specular1;void main()
{    // 存储第一个G缓冲纹理中的片段位置向量gPosition = FragPos;// 同样存储对每个逐片段法线到G缓冲中gNormal = normalize(Normal);// 和漫反射对每个逐片段颜色gAlbedoSpec.rgb = texture(texture_diffuse1, TexCoords).rgb;// 存储镜面强度到gAlbedoSpec的alpha分量gAlbedoSpec.a = texture(texture_specular1, TexCoords).r;
}  

因为有光照计算,所以要将所有坐标转换到一个坐标系下,此处我们是将所有坐标转换到世界空间下

三、Lighting Pass

我们通过对G-Buffer进行逐像素的遍历,将其数据作为光照计算的输入,来计算场景最终的光照颜色。

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
shaderLightingPass();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gPosition);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, gNormal);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, gAlbedoSpec);//发送光照相关的uniform
SendAllLightUniformsToShader(shaderLightingPass);
glUniform3fv(glGetUniformLocation(shaderLightingPass.Program, "viewPos"), 1, &camera.Position[0]);
RenderQuad();  

在片元着色器中,我们将会在G-Buffer中直接采样

#version 330 core
out vec4 FragColor;
in vec2 TexCoords;uniform sampler2D gPosition;
uniform sampler2D gNormal;
uniform sampler2D gAlbedoSpec;struct Light {vec3 Position;vec3 Color;
};
const int NR_LIGHTS = 32;
uniform Light lights[NR_LIGHTS];
uniform vec3 viewPos;void main()
{             // 从G缓冲中获取数据vec3 FragPos = texture(gPosition, TexCoords).rgb;vec3 Normal = texture(gNormal, TexCoords).rgb;vec3 Albedo = texture(gAlbedoSpec, TexCoords).rgb;float Specular = texture(gAlbedoSpec, TexCoords).a;// 然后和往常一样地计算光照vec3 lighting = Albedo * 0.1; // 硬编码环境光照分量vec3 viewDir = normalize(viewPos - FragPos);for(int i = 0; i < NR_LIGHTS; ++i){// 漫反射vec3 lightDir = normalize(lights[i].Position - FragPos);vec3 diffuse = max(dot(Normal, lightDir), 0.0) * Albedo * lights[i].Color;lighting += diffuse;}FragColor = vec4(lighting, 1.0);
}  

四、结合延迟渲染和前向渲染

在延迟渲染中,光源通常被视为无形的点或方向,而不是具有材质和颜色的物体。如果我们想将光源渲染为一个带有光照颜色的立方体,就需要额外的几何处理,而这超出了延迟渲染的范畴,就需要结合前向渲染(透明物体、镜面反射、光源模型等)。

前向渲染的部分会在延迟渲染操作之后进行。

// 延迟渲染光照渲染阶段
[...]
RenderQuad();// 现在像正常情况一样正向渲染所有光立方体
shaderLightBox.Use();
glUniformMatrix4fv(locProjection, 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(locView, 1, GL_FALSE, glm::value_ptr(view));
for (GLuint i = 0; i < lightPositions.size(); i++)
{model = glm::mat4();model = glm::translate(model, lightPositions[i]);model = glm::scale(model, glm::vec3(0.25f));glUniformMatrix4fv(locModel, 1, GL_FALSE, glm::value_ptr(model));glUniform3fv(locLightcolor, 1, &lightColors[i][0]);RenderCube();
}

在这里插入图片描述
不过现在的深度结果并不正确,因为除了光源立方体的深度信息都在延迟渲染过程中,所以我们需要将延迟渲染中的深度信息提取出来,然后再渲染光立方体。

我们可以使用glBlitFramebuffer复制一个帧缓冲的内容到另一个帧缓冲中。我们需要指定一个帧缓冲为读帧缓冲(Read Framebuffer),并且类似地指定一个帧缓冲为写帧缓冲(Write Framebuffer)

glBindFramebuffer(GL_READ_FRAMEBUFFER, gBuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // 写入到默认帧缓冲
glBlitFramebuffer(0, 0, SCR_WIDTH, SCR_HEIGHT, 0, 0, SCR_WIDTH, SCR_HEIGHT, GL_DEPTH_BUFFER_BIT, GL_NEAREST
);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// 现在像之前一样渲染光立方体
[...]  

在这里我们复制整个读帧缓冲的深度缓冲信息到默认帧缓冲的深度缓冲,对于颜色缓冲和模板缓冲我们也可以这样处理。

在这里插入图片描述

五、更多光源

延迟渲染本身并不能支持非常大量的光源,但是我们可以为其引入一个优化:光体积(Light Volumes)。因为对于场景中的物体,有的光是影响非常非常小的,所以我们就可以计算光的影响半径。

我们可以通过光源的衰减值,来计算光的影响范围,我们只需要对在光影响范围内的片段进行光照计算就可以了。

http://www.hkea.cn/news/255723/

相关文章:

  • 中国城乡建设部人力网站首页优化落实疫情防控
  • 做网站到底能不能赚钱网络优化工程师前景
  • 乌镇网站建设标书百度站长工具域名查询
  • 制作公司网站价格腾讯广告代理商加盟
  • 大学生活动网站开发文案苏州seo门户网
  • 阿里云认证网站建设题库seo助理
  • 凤岗网站仿做靠谱seo外包定制
  • xampp安装wordpress说明徐州seo外包
  • 啥网站都能看的浏览器下载百度收录查询工具
  • 福田附近公司做网站建设哪家效益快奶糖 seo 博客
  • 临沂免费自助建站模板品牌整合营销
  • iis做本地视频网站找客户资源的网站
  • 做调查用哪个网站网络推广有多少种方法
  • 开发一个交易网站多少钱在线工具
  • 网站平台怎么建立的软文范例
  • 移动应用开发专业学什么东莞seo软件
  • 做宣传网站的公司手机百度极速版app下载安装
  • 私人可以做慈善网站吗外贸如何推广
  • 网站页面模板页面布局如何成为百度广告代理商
  • 瑞安外贸网站建设曲靖百度推广
  • 先做网站还是服务器销售营销方案100例
  • 用卫生纸做的礼物街网站免费网页空间到哪申请
  • 手游网站做cpc还是cpm广告号厦门网页搜索排名提升
  • 人个做外贸用什么网站好宁波百度seo点击软件
  • 诈骗网站怎么做的企业网站seo案例分析
  • 如何做网站接口湖南营销型网站建设
  • 进入兔展网站做PPt软文营销ppt
  • app网站新闻危机公关
  • 东莞关键词优化实力乐云seo南宁seo外包服务商
  • 做网站都是用源码么免费注册个人网站不花钱