具有定向光的Phong着色导致全白色多边形

时间:2016-03-03 02:33:15

标签: hlsl ogre3d

我正试图在Ogre3D 1.9中为我的游戏制作一个Phong lightining着色器。

我可以进行漫反射并将法线贴图添加到平面,但是当我添加镜面反射分量时,每一个都会变成亮白色。

planes with specular

这是没有镜面反射分量的图像

planes without specular

奇怪的是,当我在FX Composer中输入完全相同的着色器代码时,它可以正常工作

Material in FX Composer

这是着色器代码

float4x4 worldViewProj;
float4x4 world;

float4 ambientColor;

float4x4 worldInverseTranspose;

float shininess = 8;

sampler textureSampler : register(s0);

sampler bumpSampler : register(s1);

struct VertexShaderInput
{
    float4 position : POSITION0;
    float3 normal : NORMAL;
    float2 textureCoord : TEXCOORD0;
    float3 tangent : TANGENT;
};

struct VertexShaderOutput
{
float4 position : POSITION0;
    float3 normal : TEXCOORD0;
    float2 textureCoord : TEXCOORD1;
    float3 pixelPos : TEXCOORD2;
    float3 tangent : TEXCOORD3;
    float3 binormal : TEXCOORD4;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    output.position = mul (worldViewProj,input.position);

    output.normal = normalize(mul(worldInverseTranspose, input.normal));
    output.tangent = normalize(mul(worldInverseTranspose,input.tangent));
    output.binormal = normalize(mul(worldInverseTranspose,cross(input.tangent.xyz,input.normal)));

    output.textureCoord = input.textureCoord;
    output.pixelPos = output.position.xyz;

    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input, uniform float3 cameraPos, uniform float4 diffLightPos, uniform float lightCorrection) : COLOR0
{

    //normal
    float3 bump = (tex2D(bumpSampler, input.textureCoord) - (0.5,0.5,0.5));
    float3 bumpNormal = normalize(input.normal + (bump.x * input.tangent + bump.y * input.binormal));

    //diffuse light
    float3 diffuseLightDirection = diffLightPos.xyz;
    float diffuseIntensity = dot(normalize(diffuseLightDirection), bumpNormal);
    if(diffuseIntensity < lightCorrection)
        diffuseIntensity = lightCorrection;

    //specular
    float3 viewVector = normalize(cameraPos - mul(input.pixelPos, world).xyz);
    float3 light = normalize(diffuseLightDirection);
    float3 r = normalize(2 * bumpNormal * diffuseIntensity - light);
    float3 v = normalize(viewVector);
    float dotProduct = dot(r,v);
    float4 specular = max(pow(dotProduct,shininess),0);

    //texture
    float4 textureColor = tex2D(textureSampler, input.textureCoord);
    //clip(textureColor.a - 0.3);
    textureColor.a = 1;

    return ambientColor * ambientColor.x + textureColor * diffuseIntensity + specular;
}

这是我的程序文件,因为我相信问题可能是其中一个参数

vertex_program vertexPlanos hlsl
{
    source Planos.hlsl
    entry_point VertexShaderFunction
    target vs_3_0

    default_params
    {
        param_named_auto worldViewProj worldviewproj_matrix
        param_named_auto worldInverseTranspose inverse_transpose_world_matrix
    }
}

fragment_program pixelPlanos hlsl
{
    source Planos.hlsl
    entry_point PixelShaderFunction
    target ps_3_0
    default_params
    {
        param_named_auto world world_matrix
        param_named_auto cameraPos camera_position_object_space
        param_named_auto ambientColor ambient_light_colour
        param_named_auto diffLightPos light_position_object_space 0
        param_named lightCorrection float 0
    }
}

请原谅我这个问题的长度,但我正在研究这个问题好几个星期而且找不到原因。

1 个答案:

答案 0 :(得分:0)

我注意到代码中存在一些错误。首先,我认为你的bumb正常计算是错误的。通常情况下完成:

inline float3 CalculateNormal(float3 bump, float3 normal, float4 tangent)
{
    //transform sample from [0,1] to [-1,1]
    float3 n = normalize(2.0f * bump - 1.0f);

    //create Matrix
    float3 N = normal; //normal of surface
    float3 T = normalize(tangent.xyz - N * dot(N, tangent.xyz)) * tangent.w;
    float3 B = cross(N, T); //binormal can be calculated or set from vertex data
    float3x3 TBN = float3x3(T, B, N);

    //transform sample to world space
    return mul(n, TBN);
}

然后你在这里:

float3 diffuseLightDirection = diffLightPos.xyz;

你写lightPos,应该是一个光矢量。除此之外,通常使用否定光矢量:

float3 diffuseLightDirection = -diffLightVec.xyz;
float diffuseIntensity = dot(normalize(diffuseLightDirection), bumpNormal);

还有一件优化事项:

normalize(diffuseLightDirection)

在代码中使用了两次。在代码之上计算它,并在进一步的过程中使用它^^。只是提示你的

最后但并非最不重要:

float4 specular = max(pow(dotProduct,shininess),0);

应该

float4 specular = pow(max(dotProduct,0),shininess);

因为如果光从表面后面传来,你想要避免高光照明。如果dotProduct的值始终为positiv,那么您的镜面术语也将始终为正值。

最后,我给你了我的着色器灯光代码。它计算环境,漫反射和镜面反射的术语。

// gLightDirection is normalized
float3 lightVec = -gLightDirection; 

// normal is the bumbed normal
float diffuseFac = dot(lightVec, normal.xyz); 

// check if light is coming from behind
bool isLight = diffuseFac > 0.0f; 

// use reflect function from hlsl, toEye is normalize(camPos - pixelWorldPos);
float3 v = reflect(-lightVec, normal.xyz); 
float specFac = pow(max(dot(v, toEye), 0), specFactor);

// startColor or texture color, matA is my ambient material
float4 ambient = startColor * matA; 

//matD is my diffuse material, isLight is a bool, if it is false, diffuse will be evaluated to 0
float4 diffuse = startColor * matD * diffuseFac * isLight; 

// matS is my specular material
float4 spec = specFac * matS * isLight; 

// final color, diffuse and specular are in color of the light, but maybe reduces by some shadows
float4 color = ambient + ((diffuse + specular) * shadowFactor * gLightColor);

希望这会对你有所帮助。祝你好运!!!