locked
Scaling of the point sprites (Direc3D 9)

    Question

  • Hello, friends. Tell me please what values should ​​I set for D3DRS_POINTSCALE_A, D3DRS_POINTSCALE_B, D3DRS_POINTSCALE_С to point sprites scaled just like other objects in the scene. The parameters A = 0 B = 0 and C = 1 (proposed by F. D. Luna) not suitable because the scale is not accurate enough and the distance between the particles (point sprites) can be greater than it should be. If I replace the point sprites to billboards, the scale of the particles is correct, but the rendering is much slower. Help me please because the speed of rendering particles for my task is very important but the precise of their scale is very important too.

    Direct3D computes the screen-space point size according to the following formula:http://msdn.microsoft.com/en-us/library/windows/desktop/bb147281%28v=vs.85%29.aspx  I can not understand what values ​​should be set for A, B, C to scaling was correct

    P.S. Sorry for my english I'm from Russia

    Wednesday, January 25, 2012 10:37 PM

Answers

  • Hello Kofan_,

    After further research, it seems that setting C to 1 will square the size of the point sprites, base on the formula.

    A is by default set to 1.0f and C is set to 0.0f and these values should remain unchanged.

    You should however change the value of B to 1.0f as it is multiplied by the distance in the formula.

    float fPointSize = 1.0f, fPointScaleB = 1.0f;
    m_pDirect3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE,true);
    m_pDirect3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE,true);
    m_pDirect3DDevice->SetRenderState(D3DRS_POINTSIZE,
                                      *((DWORD*)&fPointSize));
    m_pDirect3DDevice->SetRenderState(D3DRS_POINTSCALE_B,
                                      *((DWORD*)&fPointScaleB));

    I have not tried this in an application, so I think you will need to test this, but based on the formula: S s = Vh * S i * sqrt(1/(A + B * D e + C *( D e2 )))

    this should be correct, as we want to depend on the distance.

    Thank You,

    Kind Regards,

    -Joseph


    • Proposed as answer by Joseph Viola Wednesday, February 1, 2012 1:58 PM
    • Marked as answer by Joseph Viola Monday, February 6, 2012 1:21 PM
    • Edited by Joseph Viola Wednesday, February 8, 2012 6:20 PM
    Wednesday, February 1, 2012 1:58 PM

All replies

  • Hello Kofan_,

    Based on the formula it looks like the values proposed are correct, and if you change the other value you will ofset the size. But you also have to take the following int consideration:

    D3DRS_POINTSCALEENABLE needs to be enabled.

    the correct size needs to be set in D3DRS_POINTSIZE.

    And you need to keep in mind that there is a limitiation on the minimum and maximum size of point sprites:

    The maximum point size, Pmax, is determined by taking the smaller of either the D3DCAPS9 structure's MaxPointSize member or the D3DRS_POINTSIZE_MAX render state. The minimum point size, Pmin, is determined by querying the value of D3DRS_POINTSIZE_MIN. Thus the final screen-space point size, S, is determined in the following manner.

    • If Ss > Pmax, then S = P max
    • if S < Pmin, then S = P min
    • Otherwise, S = S s

    Ballboard will always be more precise. If you write a vertex shader which deals with Billboards, performances shouldn't be much worse than the point sprites.

    Also, remember that, point sprites do not exist anymore in DX10 and 11, so migrating your application to newer versions would be impossible.

    Hope that helps.

    -Joseph

    • Proposed as answer by Joseph Viola Wednesday, February 1, 2012 1:39 PM
    • Unproposed as answer by Joseph Viola Wednesday, February 1, 2012 1:47 PM
    Wednesday, February 1, 2012 1:39 PM
  • Hello Kofan_,

    After further research, it seems that setting C to 1 will square the size of the point sprites, base on the formula.

    A is by default set to 1.0f and C is set to 0.0f and these values should remain unchanged.

    You should however change the value of B to 1.0f as it is multiplied by the distance in the formula.

    float fPointSize = 1.0f, fPointScaleB = 1.0f;
    m_pDirect3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE,true);
    m_pDirect3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE,true);
    m_pDirect3DDevice->SetRenderState(D3DRS_POINTSIZE,
                                      *((DWORD*)&fPointSize));
    m_pDirect3DDevice->SetRenderState(D3DRS_POINTSCALE_B,
                                      *((DWORD*)&fPointScaleB));

    I have not tried this in an application, so I think you will need to test this, but based on the formula: S s = Vh * S i * sqrt(1/(A + B * D e + C *( D e2 )))

    this should be correct, as we want to depend on the distance.

    Thank You,

    Kind Regards,

    -Joseph


    • Proposed as answer by Joseph Viola Wednesday, February 1, 2012 1:58 PM
    • Marked as answer by Joseph Viola Monday, February 6, 2012 1:21 PM
    • Edited by Joseph Viola Wednesday, February 8, 2012 6:20 PM
    Wednesday, February 1, 2012 1:58 PM