We have a pixel shader constant buffer that contains the light data for the item that is currently rendered.

To implement tangent space normal mapping, i would need to transform each light into tangent space.

Is it a valid approach to instead bind the light data to the vertex shader and then send the transformed Light Data to the pixel shader since the vertex shader runs less frequently than the pixel shader?

As a side note: I am using forward rendering with a limited light count.
Our pixel shader constant buffer looks like this:

struct RendererLight {
    float3 Position;
    float3 Color;
    float3 Direction;
    float Intensity;
    float In;
    float Out;
    float Range;

cbuffer LightsBuffer : register(b2)
    RendererLight Lights[8];
    uint NumLights;

1 Answer 1


It's valid, but you have a limited number of interpolators between the two shader stages, and depending how much data you're sending you may bump into that limit. You'll almost certainly need to split your cbuffer in two - lights per-vertex and lights per-pixel - with the per-vertex buffer containing the bare minimum of data.

However, you should also bear in mind that modern GPUs are very unlikely to be ALU-bound with the number of computations you're currently doing, and that in certain cases you can almost treat ALU as if it were effectively free. Compare that to the trade-offs involved in splitting your cbuffer, complicating your shaders, and using those extra interpolators (which are very much not free) and you will probably be better off just leaving your shaders as they are.

Ultimately what it comes down is: have you benchmarked this, and is it actually a performance problem for you?

  • \$\begingroup\$ I haven't benchmarked this because i am at the start of implementing Normal mapping. This was an initial question i had in mind because I dont want to rewrite the shaders once i notice that transforming the lights into tangent space per pixel is too heavy. \$\endgroup\$
    – Raildex
    Jul 18, 2020 at 8:00
  • 1
    \$\begingroup\$ @Raildex - then you're definitely better off implementing the simple case from the beginning. It's much easier to add special cases to simpler code than it is to go back and do a simplification pass over tangled spaghetti. \$\endgroup\$ Jul 18, 2020 at 9:17

You must log in to answer this question.

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