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

成人大专咨询整站优化排名

成人大专咨询,整站优化排名,关于seo网站优化公司,个人网站做淘宝客违规1. 延迟渲染的原理 延迟渲染主要包含了两个Pass。在第一个Pass中,我们不进行任何光照计算,而是仅仅计算哪些片元是可见的,这主要是通过深度缓冲技术来实现,当发现一个片元是可见的,我们就把它的相关信息存储到G缓冲区…

1. 延迟渲染的原理

延迟渲染主要包含了两个Pass。在第一个Pass中,我们不进行任何光照计算,而是仅仅计算哪些片元是可见的,这主要是通过深度缓冲技术来实现,当发现一个片元是可见的,我们就把它的相关信息存储到G缓冲区中。然后,在第二个Pass中,我们利用G缓冲区的各个片元信息,例如表面法线、视角方向、漫反射系数等,进行真正的光照计算。

延迟渲染的过程大致可以用下面的伪代码来描述:

// 第一个 Pass 不进行真正的光照计算
// 仅仅把光照计算需要的信息存储到 G 缓冲中
for (each primitive in this model) {for (each fragment covered by this primitive) {if (failed in depth test) {// 如果没有通过深度测试,说明该片元是不可见的discard;} else {// 如果该片元可见// 就把需要的信息存储到 G 缓冲中writeGBuffer(materialInfo, pos, normal, lightDir, viewDir);}}
}// 利用 G 缓冲中的信息进行真正的光照计算
for (each pixel in the screen) {if (the pixel is valid) {// 如果该像素是有效的// 读取它对应的 G 缓冲中的信息readGBuffer(pixel, materialInfo, pos, normal, lightDir, viewDir);// 根据读取到的信息进行光照计算float4 color = Shading(materialInfo, pos, normal, lightDir, viewDir);// 更新帧缓冲writeFrameBuffer(pixel, color);}
}

Unity 里面的延迟渲染

一、代码结构

Shader "Hidden/Internal-DeferredShading" {Properties {// 光照贴图(用于点光源/聚光灯衰减)_LightTexture0 ("Light Texture", any) = "" {}// 光照方向贴图(用于聚光灯方向衰减)_LightTextureB0 ("Light Direction Texture", 2D) = "" {}// 阴影贴图(来自深度缓冲)_ShadowMapTexture ("Shadow Map", any) = "" {}// 混合模式参数(源/目标混合因子)_SrcBlend ("Source Blend", Float) = 1_DstBlend ("Destination Blend", Float) = 1}SubShader {Pass {// Pass 1: 延迟光照计算(叠加或减法混合)}Pass {// Pass 2: LDR模式最终解码(将对数值转为线性)}Fallback Off // 无备用着色器
}

二、第一个Pass

Pass {ZWrite Off               // 关闭深度写入Blend [_SrcBlend] [_DstBlend] // 动态混合模式(HDR时为加法,LDR时为减法)CGPROGRAM#pragma target 3.0          // 要求SM3.0以上#pragma vertex vert_deferred // 使用Unity内置延迟渲染顶点着色器#pragma fragment frag        // 片段着色器#pragma multi_compile_lightpass // 多编译光照传递模式#pragma multi_compile ___ UNITY_HDR_ON // 根据是否启用HDR编译不同路径#pragma exclude_renderers nomrt // 排除不支持多渲染目标的平台#include "UnityCG.cginc"        // Unity基础CG库#include "UnityDeferredLibrary.cginc" // 延迟渲染专用库#include "UnityPBSLighting.cginc" // 物理渲染光照计算#include "UnityStandardUtils.cginc" // 标准着色器工具#include "UnityGBuffer.cginc"    // GBuffer解包#include "UnityStandardBRDF.cginc" // BRDF计算// GBuffer纹理采样器(包含材质信息)sampler2D _CameraGBufferTexture0; // Albedo + 金属度sampler2D _CameraGBufferTexture1; // 法线 + 粗糙度sampler2D _CameraGBufferTexture2; // 前照光 + 漫反射// 计算单个光源的光照贡献half4 CalculateLight (unity_v2f_deferred i) {float3 wpos;          // 世界空间坐标float2 uv;            // GBuffer纹理坐标float atten, fadeDist;// 光照衰减和雾化距离UnityLight light;     // 光照结构体UNITY_INITIALIZE_OUTPUT(UnityLight, light); // 初始化光照结构UnityDeferredCalculateLightParams (i, wpos, uv, light.dir, atten, fadeDist); // 计算光照参数(方向、衰减等)// 设置光照颜色(光源颜色 * 衰减)light.color = _LightColor.rgb * atten;// 从GBuffer解包材质属性 //“Unity Standard Shader 解析(六)之Deferred”里面,可以看到Gbuffer的数据来源half4 gbuffer0 = tex2D(_CameraGBufferTexture0, uv);half4 gbuffer1 = tex2D(_CameraGBufferTexture1, uv);half4 gbuffer2 = tex2D(_CameraGBufferTexture2, uv);UnityStandardData data = UnityStandardDataFromGbuffer(gbuffer0, gbuffer1, gbuffer2); // 转换为标准材质数据结构// 计算视角方向(世界空间)float3 eyeVec = normalize(wpos - _WorldSpaceCameraPos);// 计算非高光部分(1 - 反射率)half oneMinusReflectivity = 1 - SpecularStrength(data.specularColor.rgb);// 环境光(此处设为0,因为延迟渲染通常单独处理)UnityIndirect ind;UNITY_INITIALIZE_OUTPUT(UnityIndirect, ind);ind.diffuse = 0;ind.specular = 0;// 使用标准BRDF计算光照结果return UNITY_BRDF_PBS(data.diffuseColor,      // 漫反射颜色data.specularColor,     // 高光颜色oneMinusReflectivity,   // 非高光部分data.smoothness,        // 粗糙度data.normalWorld,       // 法线方向-eyeVec,                // 视角方向(取反)light,                  // 光照参数ind                    // 环境光(未使用));}// 主片段着色器入口#ifdef UNITY_HDR_ONhalf4 frag (unity_v2f_deferred i) : SV_Target {#elsefixed4 frag (unity_v2f_deferred i) : SV_Target {#endifhalf4 c = CalculateLight(i); // 计算光照#ifdef UNITY_HDR_ONreturn c; // HDR模式直接返回线性值#elsereturn exp2(-c); // LDR模式对数编码#endif}ENDCG}

1.顶点着色器

vert_deferred定义在UnityDeferredLibrary.cginc里面

// 顶点着色器部分
// 延迟渲染顶点着色器输出结构体
struct unity_v2f_deferred {float4 pos : SV_POSITION; // 裁剪空间顶点坐标float4 uv : TEXCOORD0;    // 屏幕空间UV坐标(用于采样GBuffer)float3 ray : TEXCOORD1;   // 视线方向向量(用于光照计算)
};// 控制是否使用全屏四边形模式的Shader变量
float _LightAsQuad;// 延迟渲染顶点着色器入口函数
unity_v2f_deferred vert_deferred (float4 vertex : POSITION, float3 normal : NORMAL) 
{unity_v2f_deferred o;// 1. 将顶点从物体空间转换为裁剪空间o.pos = UnityObjectToClipPos(vertex);// 2. 计算屏幕空间UV坐标(范围[0,1],保留深度信息)o.uv = ComputeScreenPos(o.pos);// 3. 计算视线方向向量(视图空间下的相机到顶点方向)// UnityObjectToViewPos将顶点转换为视图空间坐标// 乘以float3(-1,-1,1)调整坐标方向(可能与坐标系转换有关)o.ray = UnityObjectToViewPos(vertex) * float3(-1, -1, 1);// 4. 根据_LightAsQuad选择ray的来源://    - 当_LightAsQuad=1时:使用传入的normal参数(实际是相机到近平面角落的向量)//    - 当_LightAsQuad=0时:使用顶点计算的rayo.ray = lerp(o.ray, normal, _LightAsQuad);return o;
}

2.UnityDeferredCalculateLightParams

// --------------------------------------------------------
// 核心光照参数计算函数void UnityDeferredCalculateLightParams (unity_v2f_deferred i,out float3 outWorldPos, // 输出世界空间坐标out float2 outUV,       // 输出屏幕UV坐标out half3 outLightDir,  // 输出光照方向out float outAtten,     // 输出光照衰减out float outFadeDist)  // 输出阴影衰减距离
{// 1. 计算视线方向(归一化到近裁剪面)i.ray = i.ray * (_ProjectionParams.z / i.ray.z);float2 uv = i.uv.xy / i.uv.w;// 2. 从深度缓冲区重建世界坐标float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv);depth = Linear01Depth(depth); // 将深度转换为线性0-1范围float4 vpos = float4(i.ray * depth, 1); // 视图空间坐标float3 wpos = mul(unity_CameraToWorld, vpos).xyz; // 世界空间坐标// 3. 计算阴影衰减距离float fadeDist = UnityComputeShadowFadeDistance(wpos, vpos.z);// 4. 根据光照类型计算光照参数#if defined (SPOT) // 聚光灯float3 tolight = _LightPos.xyz - wpos; // 光源到顶点向量half3 lightDir = normalize(tolight);    // 光照方向float4 uvCookie = mul(unity_WorldToLight, float4(wpos,1)); // 光源空间坐标// 聚光灯衰减(带贴图)float atten = tex2Dbias(_LightTexture0, float4(uvCookie.xy / uvCookie.w, 0, -8)).w;atten *= uvCookie.w < 0; // 防止背面采样float att = dot(tolight, tolight) * _LightPos.w; // 距离衰减atten *= tex2D(_LightTextureB0, att.rr).r; // 衰减贴图采样// 计算阴影atten *= UnityDeferredComputeShadow(wpos, fadeDist, uv);#elif defined (DIRECTIONAL) || defined (DIRECTIONAL_COOKIE) // 方向光half3 lightDir = -_LightDir.xyz; // 光方向(反向)float atten = 1.0;// 计算阴影atten *= UnityDeferredComputeShadow(wpos, fadeDist, uv);#if defined (DIRECTIONAL_COOKIE) // 带贴图的方向光// 采样方向光贴图(如天空盒投影)atten *= tex2Dbias(_LightTexture0, float4(mul(unity_WorldToLight, half4(wpos,1)).xy, 0, -8)).w;#endif#elif defined (POINT) || defined (POINT_COOKIE) // 点光源float3 tolight = wpos - _LightPos.xyz; // 顶点到光源向量half3 lightDir = -normalize(tolight); // 光照方向(反向)float att = dot(tolight, tolight) * _LightPos.w; // 距离衰减float atten = tex2D(_LightTextureB0, att.rr).r; // 衰减贴图// 计算阴影atten *= UnityDeferredComputeShadow(tolight, fadeDist, uv);#if defined (POINT_COOKIE) // 带贴图的点光源// 采样立方体阴影贴图atten *= texCUBEbias(_LightTexture0, float4(mul(unity_WorldToLight, half4(wpos,1)).xyz, -8)).w;#endif#else // 无效光照类型half3 lightDir = 0;float atten = 0;#endif// 输出结果outWorldPos = wpos;outUV = uv;outLightDir = lightDir;outAtten = atten;outFadeDist = fadeDist;
}

3,UnityComputeShadowFadeDistance

// 计算阴影衰减距离(用于混合实时阴影和烘焙阴影)
//float3 wpos:顶点的世界空间坐标(通过深度缓冲区重建)。
//float z:顶点的归一化设备坐标(NDC)的Z值(范围 [0,1]),表示顶点到相机的距离。
float UnityComputeShadowFadeDistance(float3 wpos, float z)
{// 1. 计算顶点到阴影衰减中心点的线性距离// unity_ShadowFadeCenterAndType.xyz 是阴影衰减球体的中心点坐标(世界空间)float sphereDist = distance(wpos, unity_ShadowFadeCenterAndType.xyz);// 2. 根据混合因子 lerp 在 z(深度值)和 sphereDist(球体距离)之间插值// unity_ShadowFadeCenterAndType.w 是混合权重(0~1):// - 当为0时,完全使用 z(深度值)作为衰减距离// - 当为1时,完全使用 sphereDist(球体距离)作为衰减距离// - 中间值则线性插值return lerp(z, sphereDist, unity_ShadowFadeCenterAndType.w);
}

4.UnityDeferredComputeShadow

// 计算混合阴影(实时+烘焙)
half UnityDeferredComputeShadow(float3 vec, float fadeDist, float2 uv)
{half fade = UnityComputeShadowFade(fadeDist); // 计算阴影衰减因子half shadowMaskAttenuation = UnityDeferredSampleShadowMask(uv); // 烘焙阴影half realtimeShadowAttenuation = UnityDeferredSampleRealtimeShadow(fade, vec, uv); // 实时阴影// 混合烘焙和实时阴影return UnityMixRealtimeAndBakedShadows(realtimeShadowAttenuation, shadowMaskAttenuation, fade);
}

5.UnityComputeShadowFade

half UnityComputeShadowFade(float fadeDist)
{// 计算衰减因子:将 fadeDist 乘以比例因子(scale),加上偏移因子(offset)// 然后通过 saturate() 将结果限制在 [0, 1] 范围内return saturate(fadeDist * _LightShadowData.z + _LightShadowData.w);
}

6.UnityDeferredSampleShadowMask


// 采样阴影掩码(烘焙阴影)
half UnityDeferredSampleShadowMask(float2 uv)
{half shadowMaskAttenuation = 1.0f;#if defined (SHADOWS_SHADOWMASK)// 从GBuffer的第四通道(_CameraGBufferTexture4)读取阴影掩码half4 shadowMask = tex2D(_CameraGBufferTexture4, uv);// 使用unity_OcclusionMaskSelector计算最终的阴影衰减shadowMaskAttenuation = saturate(dot(shadowMask, unity_OcclusionMaskSelector));#endifreturn shadowMaskAttenuation;
}

7.UnityDeferredSampleRealtimeShadow

// 采样实时阴影(动态阴影)
half UnityDeferredSampleRealtimeShadow(half fade, float3 vec, float2 uv)
{half shadowAttenuation = 1.0f;// 方向光/带贴图的方向光的阴影计算(屏幕空间阴影)#if defined (DIRECTIONAL) || defined (DIRECTIONAL_COOKIE)#if defined(SHADOWS_SCREEN)// 从_ShadowMapTexture采样阴影值shadowAttenuation = tex2D(_ShadowMapTexture, uv).r;#endif#endif// 快速分支优化(Unity 5.6+)#if defined(UNITY_FAST_COHERENT_DYNAMIC_BRANCHING) && defined(SHADOWS_SOFT) && !defined(LIGHTMAP_SHADOW_MIXING)// 当衰减小于阈值时,跳过计算(提升性能)UNITY_BRANCHif (fade < (1.0f - 1e-2f)){#endif// 聚光灯阴影(深度阴影)#if defined(SPOT)#if defined(SHADOWS_DEPTH)// 转换到阴影坐标系并采样float4 shadowCoord = mul(unity_WorldToShadow[0], float4(vec, 1));shadowAttenuation = UnitySampleShadowmap(shadowCoord);#endif#endif// 点光源/带贴图的点光源阴影(立方体贴图阴影)#if defined (POINT) || defined (POINT_COOKIE)#if defined(SHADOWS_CUBE)// 直接采样立方体阴影贴图shadowAttenuation = UnitySampleShadowmap(vec);#endif#endif#if defined(UNITY_FAST_COHERENT_DYNAMIC_BRANCHING) && defined(SHADOWS_SOFT) && !defined(LIGHTMAP_SHADOW_MIXING)}#endifreturn shadowAttenuation;
}

8.UnitySampleShadowmap

// ------------------------------------------------------------------
// Spot 光源阴影采样逻辑
// ------------------------------------------------------------------
// 仅在启用深度阴影(SHADOWS_DEPTH)且光源类型为 Spot(SPOT)时编译此部分
#if defined(SHADOWS_DEPTH) && defined(SPOT)// 阴影采样函数(核心逻辑)inline fixed UnitySampleShadowmap (float4 shadowCoord){#if defined(SHADOWS_SOFT)half shadow = 1; // 默认全亮(无阴影)// 情况1:不支持硬件比较采样器(如部分移动设备或 Xbox360)#if !defined(SHADOWS_NATIVE)float3 coord = shadowCoord.xyz / shadowCoord.w; // 将齐次坐标转换为归一化坐标 [0,1]// 使用四个偏移量进行软阴影采样(PCF)float4 shadowVals;shadowVals.x = SAMPLE_DEPTH_TEXTURE(_ShadowMapTexture, coord + _ShadowOffsets[0].xy);shadowVals.y = SAMPLE_DEPTH_TEXTURE(_ShadowMapTexture, coord + _ShadowOffsets[1].xy);shadowVals.z = SAMPLE_DEPTH_TEXTURE(_ShadowMapTexture, coord + _ShadowOffsets[2].xy);shadowVals.w = SAMPLE_DEPTH_TEXTURE(_ShadowMapTexture, coord + _ShadowOffsets[3].xy);// 比较采样深度与当前坐标深度,计算阴影权重(0为全黑,1为全亮)half4 shadows = (shadowVals < coord.zzzz) ? _LightShadowData.rrrr : 1.0f;shadow = dot(shadows, 0.25f); // 四个采样的平均值#else // 情况2:支持硬件比较采样器(如移动设备)// 使用硬件比较采样器进行高效采样float3 coord = shadowCoord.xyz / shadowCoord.w;half4 shadows;shadows.x = UNITY_SAMPLE_SHADOW(_ShadowMapTexture, coord + _ShadowOffsets[0]);shadows.y = UNITY_SAMPLE_SHADOW(_ShadowMapTexture, coord + _ShadowOffsets[1]);shadows.z = UNITY_SAMPLE_SHADOW(_ShadowMapTexture, coord + _ShadowOffsets[2]);shadows.w = UNITY_SAMPLE_SHADOW(_ShadowMapTexture, coord + _ShadowOffsets[3]);shadow = dot(shadows, 0.25f); // 四个采样的平均值#else // 情况3:其他平台(如PC)// 使用更复杂的3x3采样(PCF3x3)提高阴影质量float3 coord = shadowCoord.xyz / shadowCoord.w;float3 receiverPlaneDepthBias = UnityGetReceiverPlaneDepthBias(coord, 1.0f);shadow = UnitySampleShadowmap_PCF3x3(float4(coord, 1), receiverPlaneDepthBias);#endif// 根据光照阴影强度混合阴影效果shadow = lerp(_LightShadowData.r, 1.0f, shadow);#else // 情况4:硬阴影(非软阴影)// 硬阴影直接采样(1-tap)#if defined(SHADOWS_NATIVE)// 使用硬件比较采样器half shadow = UNITY_SAMPLE_SHADOW_PROJ(_ShadowMapTexture, shadowCoord);shadow = lerp(_LightShadowData.r, 1.0f, shadow);#else// 手动比较深度half shadow = SAMPLE_DEPTH_TEXTURE_PROJ(_ShadowMapTexture, UNITY_PROJ_COORD(shadowCoord)) < (shadowCoord.z / shadowCoord.w) ? _LightShadowData.r : 1.0;#endif#endifreturn shadow;}#endif // #if defined(SHADOWS_DEPTH) && defined(SPOT)

三、第二个Pass

Pass {ZTest Always      // 总是通过深度测试Cull Off         // 不剔除面ZWrite Off       // 关闭深度写入Stencil {// 只渲染非背景区域(通过Stencil缓冲区)ref [_StencilNonBackground] // 参考值来自Unity的Stencil设置readmask [_StencilNonBackground] // 读取掩码compback equal // 后面面的比较函数compfront equal // 前面面的比较函数(修复bug,见注释)}CGPROGRAM#pragma target 3.0#pragma vertex vert#pragma fragment frag#pragma exclude_renderers nomrt#include "UnityCG.cginc"sampler2D _LightBuffer; // 光照缓冲区纹理struct v2f {float4 vertex : SV_POSITION;float2 texcoord : TEXCOORD0;};// 顶点着色器(传递屏幕坐标)v2f vert (float4 vertex : POSITION, float2 texcoord : TEXCOORD0) {v2f o;o.vertex = UnityObjectToClipPos(vertex);o.texcoord = texcoord.xy;#ifdef UNITY_SINGLE_PASS_STEREOo.texcoord = TransformStereoScreenSpaceTex(o.texcoord, 1.0f);#endifreturn o;}// 片段着色器(解码对数值)fixed4 frag (v2f i) : SV_Target {return -log2(tex2D(_LightBuffer, i.texcoord)); // 对数解码}ENDCG}

总结Unity中关于内部延迟渲染(Deferred Shading)的实现,主要包括了原理介绍、代码结构和关键函数的作用。

延迟渲染的原理

延迟渲染通过两个Pass完成:第一个Pass只计算哪些片元是可见的,并将这些片元的相关信息存储到G缓冲区中;第二个Pass利用G缓冲区的信息进行光照计算。这种方法允许在不增加额外复杂度的情况下处理大量光源。

Unity里面的延迟渲染

一、代码结构
  • Shader “Hidden/Internal-DeferredShading”:定义了一个隐藏的着色器,用于内部延迟渲染。
  • Properties块:定义了各种纹理属性,如光纹理、阴影贴图等。
  • SubShader块:包含了具体的渲染过程,分为多个Pass来执行不同的渲染任务。
二、第一个Pass
  • ZWrite Off 和 Blend:关闭深度写入并设置混合模式。
  • CGPROGRAM块:包含了顶点和片段着色器的实现,使用多编译指令以适应不同平台和配置。
  • CalculateLight函数:根据从GBuffer读取的信息计算单个光源对像素颜色的贡献。
  • frag函数:主片段着色器入口,根据是否启用高动态范围(HDR)选择不同的返回值处理方式。
关键函数
  • vert_deferred:延迟渲染使用的顶点着色器,负责转换坐标系并将必要信息传递给片段着色器。
  • UnityDeferredCalculateLightParams:核心光照参数计算函数,根据当前片元的位置和其他信息计算出光照方向、衰减等因素。
  • UnityComputeShadowFadeDistance:计算阴影衰减距离,用于混合实时阴影和烘焙阴影。
  • UnityDeferredComputeShadow:计算混合阴影效果,结合实时阴影和烘焙阴影。
  • UnityComputeShadowFade:计算阴影衰减因子。
  • UnityDeferredSampleShadowMask:采样阴影掩码,即烘焙阴影。
  • UnityDeferredSampleRealtimeShadow:采样实时阴影,即动态生成的阴影。
  • UnitySampleShadowmap:阴影贴图采样逻辑,支持多种情况下的阴影采样,包括软阴影和硬阴影。
第二个Pass
  • ZTest Always, Cull Off, ZWrite Off:总是通过深度测试,不剔除面,关闭深度写入。
  • Stencil块:仅渲染非背景区域,通过模板缓冲区实现。
  • CGPROGRAM块:解码对数值,主要是通过对数运算将HDR颜色值转换为线性空间颜色值。
http://www.dtcms.com/wzjs/137127.html

相关文章:

  • 网站建设甲方原因造成停工汕头seo
  • 电子商务网站营销方案免费正规大数据查询平台
  • 济南做公司网站人工智能教育培训机构排名
  • 哪里有做网站的教程识图搜索在线 照片识别
  • 常见的网站空间今日最新新闻重大事件
  • 网站权重如何做淄博搜索引擎优化
  • 外贸seo网站重庆森林电影
  • 做神马网站优化快速排电商网站有哪些
  • 承德网站建设费用宁夏百度推广代理商
  • wordpress换中文北京自动seo
  • 做网站正规公司中国工商业联合会
  • 兰州网站制作公司服务电话新闻今日要闻
  • 外网专门做钙片的网站谷歌seo推广培训班
  • 制作网站的软件手机版百度站长收录
  • 关于做真实的自己视频网站廊坊网络推广公司
  • 河北沧州网站建设最新足球赛事
  • 建设电商网站的个人网站的制作
  • 古董交易网站怎么做必应搜索引擎网址
  • 网站备案 游戏南京seo网站优化推广
  • 北京城建一建设发展有限公司网站网络销售怎么样
  • 做微商截图的网站制作网页完整步骤
  • 今日全国疫情地图分布图seo网站优化怎么做
  • 百度怎么建立自己的网站seo网络搜索引擎优化
  • 河南郑州百度网站建设百度营销登录平台
  • 江西做网站找谁广州百度网站推广
  • 网站建设中怎么编辑图片网址域名注册
  • 武昌做网站公司推荐北京seo顾问外包
  • 蚌埠网站建设哪家好网络营销推广的特点
  • ssm+html实现网站开发最近三天的新闻大事简短
  • 网站站内内链建设新闻投稿平台