I'm researching simple shaders to add to my DirectX 11 project such as a per-vertex diffuse shader plus specular reflection component.

I'll begin with the results:

enter image description here

Seems specular reflection is working, but do you see the border and upper objects? They don't seem to be lit well, as a shader based on this lighting equation is not supposed to gray-scale the diffuse component (excepting when dot product < 0 in backfaces,etc).

My HLSL vertex shader rationale is as follows, I dont know at this point of the day, if i'm missing something.

Vertex shader input / Output structs are defined as:

// Output and Input Structs
// ------------------------

struct VS_OUTPUT {
    float4 pos       : SV_POSITION;
    float4 color     : COLOR;

struct VS_INPUT {
    float4 pos : POSITION;
    float4 norm: NORMAL;

1) Transform the input position to world coordinates:

vo.pos = mul(vi.pos, worldMatrix);

2) Transform normal to world and normalize:

float4 N = normalize(mul(vi.norm, worldMatrix));

3) Calculate the vector from the light position to the current vertex position. Lighting is already in world coordinates. w=1.0, so:

 float4 L = float4(normalize(float4(light[0].pos.xyz,1.0f) - vo.pos));

I have camera position in world coordinates passed through Cbuffer, so camera minus vertex position yields V vector.

float4 V = normalize(cameraPos - vo.pos);

4) Use reflect intrinsic to calculate R, negating L since it's pointing towards light.

float4 R = reflect(-L, N);

5) Finally I calculate the color to pass to the pixel shader, and transform the vertex position with the view/projection matrices.

 vo.color = ka + ke + kd * saturate(dot(N, L)) + (ks * pow(saturate(dot(V, R)), specp));
    vo.pos = mul(mul(vo.pos, viewMatrix), projMatrix);
    return vo;

Just for completion, here are the constant buffers:

#define MAX_LIGHTS 16

cbuffer bufWorldMatrix : register (b0) {
    float4x4 worldMatrix;

cbuffer bufViewProjMatrix : register (b1) {
    float4x4 viewMatrix;
    float4x4 projMatrix;
    float4   cameraPos;

cbuffer materialProperties : register (b2) {
    float4 kd;
    float4 ka;
    float4 ks;
    float4 ke;
    float  specp; // Specular-power (shininess)

struct LightBase {
    float3 pos;
    float3 color;
    float  intensity;
    float  isOn;

THanks, any help is appreciated. I'm sure normals are OK, but I can recheck in case. I can post additional debugging/ code if it's required.

  • \$\begingroup\$ I don't know if it's the only issue but, if dot(N, L)) is negative, specular should not be added. \$\endgroup\$
    – Jon
    Mar 15 '16 at 2:02
  • \$\begingroup\$ Also, does DX not complain about materialProperties not being a multiple of 4? \$\endgroup\$
    – Jon
    Mar 15 '16 at 2:20
  • \$\begingroup\$ materialProperties is already padded to multiple of 16-bytes in the constant buffer creation (CPU-side). 2) I do [ sat(V*R) ]^s where s=specular power. Sat(x) clamps the dot product between 0 and 1. Thanks. \$\endgroup\$
    – Hernán
    Mar 15 '16 at 3:10
  • 1
    \$\begingroup\$ If you are, for some reason, actually drawing backfaces: CPU-side, please normalize (1,-1,0), reflect it against both (0,1,0) and (0,-1,0), and inspect the results. \$\endgroup\$
    – Jon
    Mar 15 '16 at 4:49

I fixed it. First I fixed the mess I was having with the W-coordinate, for example, I multiply now the normal with worldmatrix but casted to 3x3 to discard the w coordinate.

Also, I was modulating the specular term instead of adding it to the diffuse color output. Seemed to give a metallic appearance instead of a "shiny" one.

For vertex lighting , mesh subdivision is very important to obtain adequate results, I refined the meshes a bit to get more accurate results.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.