You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HLSL法线映射异常:阴影区域出现不应有的高光

法线映射后阴影区域出现异常高光问题

我刚接触HLSL,跟着YouTube上Ben Cloward的DVD教程学习。教程虽过时,但大部分失效函数都能自己搞定。但加了法线映射后出问题了——本该光值全为0的阴影区域,法线却产生了高光效果。不确定是代码本身的问题,还是用的旧驱动导致的,完全没头绪。

软硬件环境

  • 应用:3DS Max 2023.2.2
  • 视口驱动:Legacy Direct3D(Direct3D 9.0,NVIDIA GeForce RTX 3080)
  • 顶点着色器编译器:vs_1_1
  • 像素着色器编译器:ps_2_0

可疑代码片段

纹理设置

texture normalMap : NormalMap
<
    string name = "default_bump_normal.dds";
    string UIName = "Normal Texture";
    string TextureType = "2D";
>;

[...] 

sampler2D normalMapSampler = sampler_state
{
    Texture = <normalMap>;
    AddressU = Wrap;
    AddressV = Wrap;
    MinFilter = linear;
    MagFilter = linear;
    MipFilter = anisotropic;
};

结构体定义

// 应用输入
struct a2v {
    float4 position     : POSITION;
    float2 texCoord     : TEXCOORD0;
    float3 normal       : NORMAL;
    float3 binormal     : BINORMAL;
    float3 tangent      : TANGENT;
};

// 片元着色器输出
struct v2f {
    float4 position        : POSITION;
    float2 texCoord        : TEXCOORD0;
    float3 lightVec        : TEXCOORD1;
    float3 worldNormal     : TEXCOORD2;
    float3 worldBinormal   : TEXCOORD3;
    float3 worldTangent    : TEXCOORD4;
};

顶点着色器

v2f v(a2v In, uniform float4 lightPosition)
{
    v2f Out;                                                            // 创建输出结构体
    Out.worldNormal = mul(In.normal, WorldInverseTranspose).xyz;        // 将法线转换到世界空间传递给像素着色器
    Out.worldBinormal = mul(In.binormal, WorldInverseTranspose).xyz;    // 将副法线转换到世界空间传递给像素着色器
    Out.worldTangent = mul(In.tangent, WorldInverseTranspose).xyz;      // 将切线转换到世界空间传递给像素着色器
    float4 worldSpacePos = mul(In.position, World);                     // 将顶点转换到世界空间
    Out.lightVec = lightPosition - worldSpacePos;                       // 创建世界空间光照向量传递给像素着色器
    Out.texCoord.xy = In.texCoord;                                      // 传递UV坐标给像素着色器
    Out.position = mul(In.position, WorldViewProjection);               // 将顶点转换到裁剪空间传递给像素着色器
    return Out;
}

像素着色器

float4 f(v2f In,uniform float4 lightColor) : COLOR
{
    // 采样漫反射和法线贴图
    float4 ColorTexture = tex2D(diffuseMapSampler, In.texCoord);
    float4 normal = tex2D(normalMapSampler, In.texCoord)*2-1;
    normal = normal * float4(.5,.5,1,1);

    float3 Nn = In.worldNormal;
    float3 Bn = In.worldBinormal;
    float3 Tn = In.worldTangent;

    float3 N = (normal.z * Nn) + (normal.x * Bn) + (normal.y * -Tn);    // Y轴向上环境下公式应为(normal.z *Nn) + (normal.x * Tn) + (normal.y * -Bn)

    N = normalize(N);

    // 创建光照向量 - 视图向量和光照向量
    float3 L = normalize(In.lightVec.xyz);                              // 光照向量需在此归一化,确保所有向量归一化

    // 光照计算
    // 环境光
    float4 Ambient = AmbientColor * ColorTexture;                       // 环境项为环境色与漫反射贴图的乘积

    // 漫反射光
    float4 diffuselight = saturate(dot(N, L)) * lightColor;             // 漫反射值为光照向量与法线的点积
    float4 Diffuse = DiffuseColor * ColorTexture * diffuselight;        // 最终漫反射色为漫反射色、漫反射贴图与漫反射值的乘积

    //return Diffuse + Ambient;
    return saturate(dot(N,L)) * lightColor;
}

已尝试的操作

  • 调整顶点着色器输出,效果甚微
  • 修改部分数值后发现,视图放大时异常效果增强,缩小则减弱
  • 查找相关资料未找到类似问题,微软文档内容繁杂也未定位到相关内容

恳请帮忙分析问题原因或指出解决方向。

内容的提问来源于stack exchange,提问作者jordan.dion-duval

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 22:47:25