Jump to content
  • Advertisement
Sign in to follow this  
DJTN

Billboard Shader Issue (HLSL/DX9)

This topic is 2536 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I’ve manually created a mesh with multiple quads (billboards) for trees. I want the vertex shader to transform their positions to face the camera per quad so I don’t have to update the vertex buffer every frame. I can do it with the entire model like this:



(HLSL)

//face cam
float4x4 worldViewMatrix = mul(matWorld, matView);
float3 positionVS = input.Position + float3(worldViewMatrix._41, worldViewMatrix._42, worldViewMatrix._43);
output.Position = mul(float4(positionVS, 1.0f), matProjection);



But, I need to do it per quad/vertex - I’m having some issues with the concept.

I’ve read several different posts but the solutions offered aren’t complete or explained. My current vertex format is position - normal - textured. Do I need to pass in a “center” position or can the vertex shader calculate the position with my existing data?

The world matrix in the code above (matWorld) is transformed on the CPU with scale, rotation then position.

To convolute matters, I’d like to still be able to scale and move the entire mesh as a whole and still have each quad face the camera. I would think this would be as simple as creating the world matrix in the vertex shader per vertex prior to executing my existing code but is that the proper way to handle my issue?



EDIT: Solution here: http://www.gamedev.net/topic/154890-billboarding-with-vertex-shaders/

Share this post


Link to post
Share on other sites
Advertisement
Sounds like this requires a different rotation per quad. Which means you would have to pass one 3x3 transformation matrix per quad to the vertex shader. I'm not too familiar with the limit of how much data you can pass, but I think you should be fine updating the vertex buffer every frame (why don't you want to update it every frame?)

EDIT: does the tree look too bad if you don't rotate branches/leaves to face the camera?

Share this post


Link to post
Share on other sites

Sounds like this requires a different rotation per quad. Which means you would have to pass one 3x3 transformation matrix per quad to the vertex shader. I'm not too familiar with the limit of how much data you can pass, but I think you should be fine updating the vertex buffer every frame (why don't you want to update it every frame?)

EDIT: does the tree look too bad if you don't rotate branches/leaves to face the camera?


It's a quad with a tree image on it, several of them. If I have to lock the vertex buffer and update it per frame it kind of negates what I'm trying to accomplish. I want to draw all the quads in one call (batch). I'm wanting to move the process of the CPU to the GPU. You would think it would be rather simple.

Share this post


Link to post
Share on other sites
Drawing a static tree in one go is simple... making each branch/leaf face the camera is not that simple... if you want each one to face the camera from their own position (which you already have in the vertex attributes), then it will require a different transformation matrix for each quad, and you'll have to send those to the vertex shader (as uniforms?). You could also try to use a single transformation for all of them, taking into account a "center" point (i think this is what you were talking about). You could send that matrix as a uniform, just like your other transformation matrices. However, using a single position may not look exactly right, depending on how far away the leaves/branches are from the "center".

EDIT: if you will do one TM per quad, then you'll need a way to index into the "array of TM's". You could add an integer vertex attribute, but that means more data per vertex. I still think you should try to update the vertex buffer every frame... maybe it's not as slow as you expect it to be.

Share this post


Link to post
Share on other sites
What is more expensive: updating the vertex buffer every frame or drawing each quad in a loop?

Share this post


Link to post
Share on other sites
[font=arial, verdana, tahoma, sans-serif][size=2]You know what... forget the "send a bunch of 3x3 matrices" method. You don't need to do that... all you need to compute a "camera facing" billboard matrix is the camera position plus the particle position.. so you could compute the matrix in the vertex shader by sending the camera position as a uniform. I'm not sure if doing it per vertex will skew the quad though... and I don't know if this will be faster than updating the vertex buffer every frame... it's something worth testing.[/font]

Share this post


Link to post
Share on other sites

[font="arial, verdana, tahoma, sans-serif"]You know what... forget the "send a bunch of 3x3 matrices" method. You don't need to do that... all you need to compute a "camera facing" billboard matrix is the camera position plus the particle position.. so you could compute the matrix in the vertex shader by sending the camera position as a uniform. I'm not sure if doing it per vertex will skew the quad though... and I don't know if this will be faster than updating the vertex buffer every frame... it's something worth testing.[/font]



I'm confused and my code is a mess. I'm currently trying the "update vertex buffer" concept and I'm getting trees flying all around. I was assuming that I'd update the verticie's position in a loop by transforming their cordinates with a orientation matrix I create from the inverted LookAtLH matrix using the cameras position, target and up vector but this is not working and I have a feeling it is because of the order.
Could you explain the "Camera Facing Billboard Matrix" concept a little more?

Share this post


Link to post
Share on other sites
[font="arial, verdana, tahoma, sans-serif"]

Could you explain the "Camera Facing Billboard Matrix" concept a little more?



The following code can be used to create a billboard matrix. The result is the transformation matrix you use to multiply each vertex of the quad. In my case I used it for particles. Notice how I'm setting the values at the end... this works for a right-handed system. Just to clarify, you'll need to compute this matrix per quad, then use the same matrix to transform every vertex in the quad.[/font]


CreateBillboardMatrix(const Vector3& particlePos, const Vector3& cameraPos, D3DXMATRIXA16& out)
{


// compute billboard basis
Vector3 look = particlePos;
look = look - cameraPos;
look.Normalize();

const Vector3 CAMERA_UP_VECTOR(0, 1, 0);
Vector3 camUp = CAMERA_UP_VECTOR;
camUp.Normalize();

Vector3 right = camUp.CrossProduct(look);
right.Normalize();

Vector3 up = look.CrossProduct(right);
up.Normalize();

// set matrix values
D3DXMatrixIdentity(&out);

out._11 = right.x;
out._12 = right.y;
out._13 = right.z;

out._21 = up.x;
out._22 = up.y;
out._23 = up.z;

out._31 = look.x;
out._32 = look.y;
out._33 = look.z;

out._41 = particlePos.x;
out._42 = particlePos.y;
out._43 = particlePos.z;
}



EDIT: This type of billboard function will make an object face the camera in all directions (spherical billboard)... not sure if that's what you want.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!