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
相关产品推荐
相关产品推荐

