答案 0 :(得分:0)
对于正常计算,您有两种选择。您可以使用三角形的两条边的叉积,显示为here,这将使三角形的每个顶点具有相同的法线,从而为您提供平面着色。另一个选项为您提供平滑法线,并通过线性插值12个顶点中每个顶点的差异来完成。邻居。 GPU Gems article执行此操作。
float d = 1.0/(float)voxels_per_block;
float3 grad;
grad.x = density_vol.Sample(TrilinearClamp, uvw + float3( d, 0, 0)) -
density_vol.Sample(TrilinearClamp, uvw + float3(-d, 0, 0));
grad.y = density_vol.Sample(TrilinearClamp, uvw + float3( 0, d, 0)) -
density_vol.Sample(TrilinearClamp, uvw + float3( 0,-d, 0));
grad.z = density_vol.Sample(TrilinearClamp, uvw + float3( 0, 0, d)) -
density_vol.Sample(TrilinearClamp, uvw + float3( 0, 0,-d));
output.wsNormal = -normalize(grad);
遗憾的是,我没有任何关于创建索引缓冲区的第一手经验,但对于UV坐标,您最好使用三平面纹理映射。使用世界坐标和法线在像素着色器中计算UV坐标,同样的GPU Gems文章提供了您可能使用的示例代码,只需稍加修改:
// Determine the blend weights for the 3 planar projections.
// N_orig is the vertex-interpolated normal vector.
float3 blend_weights = abs( N_orig.xyz ); // Tighten up the blending zone:
blend_weights = (blend_weights - 0.2) * 7;
blend_weights = max(blend_weights, 0); // Force weights to sum to 1.0 (very important!)
blend_weights /= (blend_weights.x + blend_weights.y + blend_weights.z ).xxx;
// Now determine a color value and bump vector for each of the 3
// projections, blend them, and store blended results in these two
// vectors:
float4 blended_color; // .w hold spec value
float3 blended_bump_vec;
{
// Compute the UV coords for each of the 3 planar projections.
// tex_scale (default ~ 1.0) determines how big the textures appear.
float2 coord1 = v2f.wsCoord.yz * tex_scale;
float2 coord2 = v2f.wsCoord.zx * tex_scale;
float2 coord3 = v2f.wsCoord.xy * tex_scale;
// This is where you would apply conditional displacement mapping.
//if (blend_weights.x > 0) coord1 = . . .
//if (blend_weights.y > 0) coord2 = . . .
//if (blend_weights.z > 0) coord3 = . . .
// Sample color maps for each projection, at those UV coords.
float4 col1 = colorTex1.Sample(coord1);
float4 col2 = colorTex2.Sample(coord2);
float4 col3 = colorTex3.Sample(coord3);