0

I am trying to make a Phong lightining shader for my game in Ogre3D 1.9.

I can make diffuse and add a normal map to a plane, but when i add the specular component everythings turn a bright white.

planes with specular

Here is an image without the specular component

planes without specular

The strange thing is that when i put the exact same shader code in FX Composer, it works

Material in FX Composer

here is the shader code

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;
}

And here is my program file because i believe maybe the problem may be one of the parameters

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
    }
}

Please, forgive me the length of the question, but i am working on this for weeks and can't find the cause.

1 Answers1

0

I've notices some mistakes in your code. First of all, I think your bumb normal calculation is wrong. Typically it is done:

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);
}

Then you have here:

float3 diffuseLightDirection = diffLightPos.xyz;

You write lightPos, should be a light vector. Additional to that normally you use the negated light vector:

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

Just one more thing of optimization:

normalize(diffuseLightDirection)

is used twice in your code. Calculate it on top of your code, and use it in further process^^. Just a hint for your

And last but not least:

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

sould be

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

because you want to avoid specular lighting if light is coming from behind the surface. If value of dotProduct is always positiv, then your specular term will always be positive too.

At the end, i give you my shader code for lighting. It calculates the terms for ambient, diffuse and specular.

// 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);

Hope this will help you. Good Luck!!!

kaiser
  • 940
  • 1
  • 10
  • 25
  • Thank you, but the problem is in Ogre3d(the engine). When writing a shader that only return an arbritary color the object turns transparent. – Brazil Rules Mar 06 '16 at 02:52