Sign in to follow this  
DJTN

Billboard Shader Issue (HLSL/DX9)

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:

[code]

(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);

[/code]

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: [url="http://www.gamedev.net/topic/154890-billboarding-with-vertex-shaders/"]http://www.gamedev.net/topic/154890-billboarding-with-vertex-shaders/[/url]

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?

Share this post


Link to post
Share on other sites
[quote name='gsamour' timestamp='1313085566' post='4847797']
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?
[/quote]

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.[/size][/font]

Share this post


Link to post
Share on other sites
[quote name='gsamour' timestamp='1313092885' post='4847867']
[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.[/size][/font]
[/quote]


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"][size="2"][quote name='DJTN' timestamp='1313093588' post='4847878']
Could you explain the "Camera Facing Billboard Matrix" concept a little more?
[/quote]


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.[/size][/font]

[code]
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;
}
[/code]


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
Gsamour - so you build this matrix based off a position you get from averaging 4 vertices (center) that belong to the same quad, once you have that -you transform each vertices that belongs to that quad with the newly built matrix? This gives the vertices a new position in model space right?


I'm getting strange results...


Share this post


Link to post
Share on other sites
I have a particle position (so, the center of my particles), then build quads around that center...
But I may have a bug in my implementation... because building the billboard matrix requires the camera position and particle position being in the same space (In my program I was thinking world space). But looking at my actual code, I don't think I'm doing that... let me double check my implementation and I'll get back to you.

Share this post


Link to post
Share on other sites
[quote name='gsamour' timestamp='1313163915' post='4848266']
I have a particle position (so, the center of my particles), then build quads around that center...
But I may have a bug in my implementation... because building the billboard matrix requires the camera position and particle position being in the same space (In my program I was thinking world space). But looking at my actual code, I don't think I'm doing that... let me double check my implementation and I'll get back to you.
[/quote]


Am I even going down the right road here? Let me explain my current method so we're on the same page. I'm updating the verticies position in the vertex buffer to face the camera so I can draw them in one call. I would assume I take the 4 vertices that make up the quad, average them (i.e. add all the vectors into 1 and divide by 4) and then apply a rotation matrix. is this correct?

Share this post


Link to post
Share on other sites
[quote name='DJTN' timestamp='1313173149' post='4848347']
Am I even going down the right road here? Let me explain my current method so we're on the same page. I'm updating the verticies position in the vertex buffer to face the camera so I can draw them in one call. I would assume I take the 4 vertices that make up the quad, average them (i.e. add all the vectors into 1 and divide by 4) and then apply a rotation matrix. is this correct?
[/quote]

That sounds right to me (obtaining the centroid, calculating the billboard rotation matrix, then applying it). The question is... are your vertices in local space or world space? I assume your camera position is in world space, is that correct?

Share this post


Link to post
Share on other sites
Yes my camera is in world space and my verticies are in model space. Based off what you're saying, I should move my vertices to world space before the transform. How do I get them back to model space?

Share this post


Link to post
Share on other sites
[quote name='DJTN' timestamp='1313176858' post='4848376']
Yes my camera is in world space and my verticies are in model space. Based off what you're saying, I should move my vertices to world space before the transform. How do I get them back to model space?
[/quote]

The short answer is "you don't". To get them back to model space, you would have to transform them by the inverse of the billboard matrix (which undoes the "looking at the camera" effect... not what you want). You leave them in world space, then in the vertex shader, instead of multiplying by world * view * projection matrices, you just multiply by view * projection matrices. Unfortunately, I think this means you will have to have a big vertex buffer with all the vertices of all your quads (not just for one tree, but for all the trees in the scene).

I apologize if I haven't been clear and if my solution seems inefficient. I'll keep thinking about it to see if there's a better way to solve your problem.

P.S. I don't have a lot of experience with tree rendering, but I've seen a lot of games with static branches/leaves (non-billboard). Is this not good enough for your program?

Share this post


Link to post
Share on other sites
[quote name='gsamour' timestamp='1313177859' post='4848382']
[quote name='DJTN' timestamp='1313176858' post='4848376']
Yes my camera is in world space and my verticies are in model space. Based off what you're saying, I should move my vertices to world space before the transform. How do I get them back to model space?
[/quote]

The short answer is "you don't". To get them back to model space, you would have to transform them by the inverse of the billboard matrix (which undoes the "looking at the camera" effect... not what you want). You leave them in world space, then in the vertex shader, instead of multiplying by world * view * projection matrices, you just multiply by view * projection matrices. Unfortunately, I think this means you will have to have a big vertex buffer with all the vertices of all your quads (not just for one tree, but for all the trees in the scene).

I apologize if I haven't been clear and if my solution seems inefficient. I'll keep thinking about it to see if there's a better way to solve your problem.

P.S. I don't have a lot of experience with tree rendering, but I've seen a lot of games with static branches/leaves (non-billboard). Is this not good enough for your program?
[/quote]

It is too expensive to render 100's of 3d tree models. Usually a couple of 3d tree models are rendered and to give depth- 20-30 billboards with tree images are used in the distance. To solve my problem I could easily re-render the same billboard over and over again changing my world matrix using an array of vectors storing their different locations- but this is inefficient. Asking DirectX to render 2 triangles in a draw call and looping through it 30 times is not the answer. My approach was to dynamically load several quads into a mesh object and draw them all in one batch but I ran into the problem with them not facing the camera. I assumed it would be rather trivial to update the vertex buffer with the position but this has turned into a nightmare.

Someone around here has had to billboard before. I've been searching for weeks for a solution but nothing has turned up. Usually they only discuss how to make ONE quad face the camera using the world matrix to rotate before drawing. What if I have several billboards spaced out? How can you make each one of them face the camera without drawing them separately?




Share this post


Link to post
Share on other sites
It turns out this has already been discussed before:

[url="http://www.gamedev.net/topic/154890-billboarding-with-vertex-shaders/"]http://www.gamedev.net/topic/154890-billboarding-with-vertex-shaders/[/url]

Share this post


Link to post
Share on other sites
[quote name='gsamour' timestamp='1313185149' post='4848424']
It turns out this has already been discussed before:

[url="http://www.gamedev.net/topic/154890-billboarding-with-vertex-shaders/"]http://www.gamedev.n...vertex-shaders/[/url]
[/quote]


Thanks gsamour.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this