我的目标是呈现一个体积点光,在这本书的第10章解释:FGED渲染这本书解释的数学相当好,但我不确定我不知道什么是必要的设置,一个体积点光晕是可见的。本书描述了计算体积光晕亮度的下列代码片段:
float R = 5.f; // Radius of the volumetric point light halo.
float R2 = R * R;
float recipR2 = 1.f / R2;
float recip3R2 = 1.f / (3.f * R2);
float normalizer = 3.f / (4.f * R);
// This shader renders a halo effect of radius R at the object-space position pobject.
// The object-space camera position c and view direction z are given by cameraPosition
// and cameraView. The pixelCoord parameter specifies the viewport coordinates of the
// pixel being processed, and it is used to read from the depth buffer.
float CalculateHaloBrightness(float3 pobject, float2 pixelCoord)
{
float3 vdir = cameraPosition - pobject;
float v2 = dot(vdir, vdir);
float p2 = dot(pobject, pobject);
float pv = -dot(pobject, vdir);
float m = sqrt(max(pv * pv - v2 * (p2 - R2), 0.0));
// Read z0 from the depth buffer.
float2 depth = texture(depthBuffer, pixelCoord);
float t0 = 1.0 + depth / dot(cameraView, vdir);
// Calculate clamped limits of integration.
float t1 = clamp((pv - m) / v2, t0, 1.0);
float t2 = clamp((pv + m) / v2, t0, 1.0);
float u1 = t1 * t1;
float u2 = t2 * t2;
// Evaluate density integral, normalize, and square.
float B = ((1.0 - p2 * recipR2) * (t2 - t1) + pv * recipR2 * (u2 - u1) - v2 * recip3R2 * (t2 * u2 - t1 * u1)) * normalizer;
return (B * B * v2);
}有几件事我不明白
pobject,cameraPosition和cameraView在对象空间中的确切含义?这是否意味着它们都必须在世界空间中才能正常工作呢?pobject为中心的立方体上,但我不确定。我意识到这是一个很难回答的问题,因为我还没有把所有的解释都包括在这里的书中。我想提交人不会喜欢的。所以我希望也许这里的人大概能理解发生了什么,并指出了正确的方向。
编辑:我快到了!下面是我当前的HLSL实现:
ConstantBuffer<pass_data> cb_pass : register(b0);
Texture2D<float> Depth : register(t3);
SamplerState linear_wrap_sampler : register(s0);
float4 ps_main(vertex_out pin) : SV_Target
{
float2 uv = pin.posh.xy / cb_pass.sceen_size;
float depth = Depth.SampleLevel(linear_wrap_sampler, uv, 0.f);
// Volumetric halo variables.
float halo = 0.f;
float halo_radius = cb_pass.radius;
float halo_radius2 = halo_radius * halo_radius;
float rcp_halo_radius2 = 1.f / halo_radius2;
float rcp_3halo_radius2 = 1.f / (3.f * halo_radius2);
float density_integral_normalizer = 3.f / (4.f * halo_radius);
// Render volumetric halo.
float4 world_space_pixel = float4(pin.posw, 1.f);
float3 pobject = float3(mul(world_space_pixel, cb_pass.world_to_object).xyz);
float3 cam_pos = mul(float4(cb_pass.eye_pos, 1.f), cb_pass.world_to_object).xyz;
float3 vdir = cam_pos - pobject;
float v2 = dot(vdir, vdir);
float p2 = dot(pobject, pobject);
float pv = -dot(pobject, vdir);
float m = sqrt(max(pv * pv - v2 * (p2 - halo_radius2), 0.f));
float3 cam_view = mul(float4(cb_pass.eye_forward, 0.f), cb_pass.world_to_object).xyz;
float t0 = 1.f + depth / dot(cam_view, vdir);
float t1 = clamp((pv - m) / v2, t0, 1.f);
float t2 = clamp((pv + m) / v2, t0, 1.f);
float u1 = t1 * t1;
float u2 = t2 * t2;
float B = ((1.f - p2 * rcp_halo_radius2) * (t2 - t1) + pv * rcp_halo_radius2 * (u2 - u1) - v2 * rcp_3halo_radius2 * (t2 * u2 - t1 * u1)) * density_integral_normalizer;
halo = (B * B * v2);
return float4(halo, halo, halo, 1.f);
}剩下的唯一问题是,只有当摄像机非常接近光环时,光环才会出现。但是,当相机足够接近时,它确实会正确地显示出来。我注意到缩放cb_pass.eye_forward会使光环从更远的地方出现,但我不知道是什么原因造成的。
发布于 2021-10-13 13:19:17
以下是(希望)帮助您开始工作的几个步骤:
绘制立方体:对于几何学来说,需要一个简单的立方体,所以第一步就是像你期望的那样得到一个立方体呈现,我建议把立方体放在世界和物体空间的原点。
在您对多维数据集的呈现方式感到满意之后,更改三角形的缠绕方向--最简单的方法就是快速调用API。因此,如果API被设置为逆时针显示为正面,只需更改它,使正面顺时针方向。这使得立方体的“内部”可见。
在这一点上,你实际上不是试图渲染光环,只是内部的立方体。所以片段着色器应该只返回一个颜色。一旦这些都设置好了,并且你对此很满意,下一步将是光环的实际渲染,并将在片段着色器中调用光环函数。
考虑到对象空间:立方体本身在“对象空间”中,通常有一个世界矩阵的模型,我们把这个立方体乘以它在世界空间中。当书中提到“对象空间”时,它指的是立方体的对象空间。(我认为这本书实际上涵盖了物体/世界空间-很好-你可能想查一下上面的章节,以帮助澄清主题)
不需要雾,光环将在没有任何特殊介质的情况下正确渲染。
阿尔法混合将需要为最终光环启用,但你可以跳过,直到晕的基本轮廓是正确的渲染。
编辑:下面是一些帮助cameraPosition和cameraView的代码
mat4 Camera2World = inverse(view_matrix); // The view matrix
mat4 World2Object = inverse(object_matrix); // The object2world matrix
vec3 cameraPosition = (World2Object * Camara2World[3]).xyz;
vec3 cameraView = (World2Object * Camera2World[2]).xyz;请注意,这是使用列主矩阵。
这不是最有效的代码,但希望它能帮助您运行。
https://computergraphics.stackexchange.com/questions/12252
复制相似问题