Billboard in vertex shader

Started by
1 comment, last by B_old 17 years, 6 months ago
Hello, when I draw a billboard I usually do this:

Vector3 up    = camera.getUp();
Vector3 right = camera.getRight();

//pos is the billboard center in worldspace
points[0].m_pos = pos + (-right + up) * size;
points[1].m_pos = pos + ( right + up) * size;
points[2].m_pos = pos + (-right - up) * size;
points[3].m_pos = pos + ( right - up) * size;

This gives me a billboard in worldspace and works quite well in my oppinion. Now I tried to move some off the work to a vertex shader:

points[0].m_pos = pos;
points[0].m_off = Vector3(-size, size, 0.0f);

points[1].m_pos = pos;
points[1].m_off = Vector3(size, size, 0.0f);

points[2].m_pos = pos;
points[2].m_off = Vector3(-size, -size, 0.0f);

points[3].m_pos = pos;
points[3].m_off = Vector3(size, -size, 0.0f);
//---
//vertex shader, g_transform = view * proj
output.pos = mul(float4(pos + off, 1.0f), g_transform);

As you probably can see, this billboard is only facing the camera if it is not rotated. Can I somehow make the billboard face the camera in the vertex shader? Do you think it will be faster/worth it? Thanks.
Advertisement
In my particles system (using shaders), i store the quad's centre position and an 'index' for each vertex.
for the 2 triangles that make up the quad, i store indices (0,1,3) and (3,1,2) where the indices are clockwise around the quad

In the setup for the shader, i then set four vector4's representin each corner (the same as your original version) these are set up based on the view matrix, the same as your non-shader version.

Vector4[] quads = new Vector4[4];DirectX.Matrix view = Camera.ViewMatrix;DirectX.Vector3 right = new DirectX.Vector3(view.M11, view.M21, view.M31);DirectX.Vector3 up = new DirectX.Vector3(view.M12, view.M22, view.M32);right.Normalize();up.Normalize();quads[0] = new Vector4(up.X - right.X, up.Y - right.Y, up.Z - right.Z, 0f) * 0.5f;quads[1] = new Vector4(right.X + up.X, right.Y + up.Y, right.Z + up.Z, 0f) * 0.5f;quads[2] = -quads[0];quads[3] = -quads[1];SetVertexShaderConstant(EShaderConstants.Quads, quads);           SetVertexShaderConstant(EShaderConstants.Transform, Camera.ViewProjectionTranspose);


I then set those 4 vector4's as constants, and in the shader, use the quad index stored with each vertex to index the contants ...

mov r0, v0     ; v0 is the quad's CENTRE positionmov a0.x, v3.x ; v3 is my quad coordadd r0, c[QUADS + a0.x]  ; QUADS is a constant to say which is the first vector4m4x4 oPos, r0, c[TRANSFORM] ; TRANSFORM is my transpose view * proj transform


My particle system does a lot more than that in the shaders - scales, moves, textures and colours the quads, but the above is how it works out the facing etc. Not sure if using indexers is the best way, but it works.

hope that helps

Wyzfen
OK, I believe I understand what you are doing, I am going to try it.
Thanks!

EDIT:
Works well for me, and I assume it might be slightly faster than my old approach, although I have not tested that yet.

[Edited by - B_old on October 3, 2006 8:38:22 AM]

This topic is closed to new replies.

Advertisement