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, 2016 at 2:02
  • \$\begingroup\$ Also, does DX not complain about materialProperties not being a multiple of 4? \$\endgroup\$
    – Jon
    Mar 15, 2016 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, 2016 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, 2016 at 4:49

1 Answer 1


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.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .