Jump to content
  • Advertisement
Jon Alma

3D Billboarding between two points

This topic is 531 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

Some time ago I implemented a particle system using billboarding techniques to ensure that the particles are always facing the viewer.  These billboards are always centered on one 3d coordinate.

I would like to build on this and use billboarding as the basis for things like laser bolts and gunshots.  Here the difference is that instead of a single point particle I now have to draw a billboard between two points - the start and end of the laser bolt for example.  I appreciate that having two end points places limits on how much the billboard can be rotated to face the viewer, but I'm looking to code a best effort solution.  For the moment I am struggling to work out how to do this or find any tutorials / code examples that explain how to draw a billboard between two points ... can anyone help?

Thanks.

Share this post


Link to post
Share on other sites
Advertisement

OpenGL has built in functionality to draw points and lines as "billboards". Use glDrawElements with the GL_POINTS and GL_LINES mode

Share this post


Link to post
Share on other sites

why don't you pass in a single vert and give it a height and direction in as a uniform or in an instance buffer? in fact you'd only need a direction, and the height would be encoded as the magnitude of the direction. when your making your billboard, just add the direction to the vert position. you can cross the direction vector and the vert pos-to-camera vector to get the direction the other two verts need to go

EDIT: I assumed the geometry shader was being used already

Share this post


Link to post
Share on other sites
3 hours ago, missionctrl said:

OpenGL has built in functionality to draw points and lines as "billboards". Use glDrawElements with the GL_POINTS and GL_LINES mode

Until now I have been using GL_LINES with a thicker line width and a one dimensional texture.  Works well, but I want to move to a 2D texture so I can have glow along the edges of the laser bolts for example.  Not sure I can achieve this with GL_LINES and as a result have headed down the direction of using billboards. 

Share this post


Link to post
Share on other sites

If you send a line primitive, then you can expand it into a segment in the geometry shader. I have some geometry shader code to do that.

#version 330 compatibility

// 2 points are expanded into a quad (2 triangles = 4 vertices)
layout(lines) in;
layout(triangle_strip, max_vertices = 4) out;

in VertexShaderOutput
{
    vec4 positionViewSpace;
    vec4 color;
} vertexShaderOutput[];

uniform mat4 projectionMatrix;
uniform float lineWidth;

out GeometryShaderOutput
{
    vec4 color;
} geometryShaderOutput;

void main()
{   
    // We compute the side vector. it is used to know in what direction we need to translate quad vertices for this line.
    vec3 sourceToDestVectorViewSpace = normalize(vertexShaderOutput[1].positionViewSpace - vertexShaderOutput[0].positionViewSpace).xyz;
    vec3 sourceToCameraVectorViewSpace = normalize(-1.0f * vertexShaderOutput[0].positionViewSpace.xyz);    
    
    vec4 sideVectorViewSpace = lineWidth * 0.5f * vec4(normalize(cross(sourceToDestVectorViewSpace, sourceToCameraVectorViewSpace)), 0.0f);    
    
    // Output line quad
    gl_Position = projectionMatrix * (vertexShaderOutput[1].positionViewSpace + sideVectorViewSpace);
    geometryShaderOutput.color = vertexShaderOutput[1].color;
    EmitVertex();
        
    gl_Position = projectionMatrix * (vertexShaderOutput[1].positionViewSpace - sideVectorViewSpace);
    geometryShaderOutput.color = vertexShaderOutput[1].color;
    EmitVertex();
            
    gl_Position = projectionMatrix * (vertexShaderOutput[0].positionViewSpace + sideVectorViewSpace);
    geometryShaderOutput.color = vertexShaderOutput[0].color;
    EmitVertex();
            
    gl_Position = projectionMatrix * (vertexShaderOutput[0].positionViewSpace - sideVectorViewSpace);
    geometryShaderOutput.color = vertexShaderOutput[0].color;
    EmitVertex();
}

Hope this helps!

Share this post


Link to post
Share on other sites

Would like to draw a billboard between two points, and what these points even define? you are aware that to draw a billboard you are anyway using 4 verts (without any special gcard extensions like in example GL_POINT_SPRITE_ARB)

 

Either way you compose world*viewmat and extract screen direction vectors, then you build up a billboard 

 

something like this (thisis for ogl)


vec3 BillboardX;
vec3 BillboardY;
void GetTranslationMatrix(mat4 ModelViewMatrix)
{
	mat4 mvm = ModelViewMatrix;
	mvm.Transpose();

BillboardX.x = mvm.m[0];
BillboardX.y = mvm.m[4];
BillboardX.z = mvm.m[8];

BillboardY.x =	mvm.m[1];
BillboardY.y =	mvm.m[5];
BillboardY.z =	mvm.m[9];

translation_facenormal = Normalize(vectorcross(BillboardX * 1000.0, BillboardY * 1000.0));


translation_facedist = -dot(translation_facenormal, translation_pos);

}

int i;
for (i=0; i < particlenum; i++) {





verts[i*4].v.x = particles[i].pos.x-BillboardX.x*particles[i].size+BillboardY.x*particles[i].size;
verts[i*4].v.y = particles[i].pos.y-BillboardX.y*particles[i].size+BillboardY.y*particles[i].size;
verts[i*4].v.z = particles[i].pos.z-BillboardX.z*particles[i].size+BillboardY.z*particles[i].size;


verts[i*4+1].v.x = particles[i].pos.x+BillboardX.x*particles[i].size+BillboardY.x*particles[i].size;
verts[i*4+1].v.y = particles[i].pos.y+BillboardX.y*particles[i].size+BillboardY.y*particles[i].size;
verts[i*4+1].v.z = particles[i].pos.z+BillboardX.z*particles[i].size+BillboardY.z*particles[i].size;


verts[i*4+2].v.x = particles[i].pos.x+BillboardX.x*particles[i].size-BillboardY.x*particles[i].size;
verts[i*4+2].v.y = particles[i].pos.y+BillboardX.y*particles[i].size-BillboardY.y*particles[i].size;
verts[i*4+2].v.z = particles[i].pos.z+BillboardX.z*particles[i].size-BillboardY.z*particles[i].size;


verts[i*4+3].v.x = particles[i].pos.x-BillboardX.x*particles[i].size-BillboardY.x*particles[i].size;
verts[i*4+3].v.y = particles[i].pos.y-BillboardX.y*particles[i].size-BillboardY.y*particles[i].size;
verts[i*4+3].v.z = particles[i].pos.z-BillboardX.z*particles[i].size-BillboardY.z*particles[i].size;


                                }

 

 

Since you have defined 4 points what do you want to do with these two points?

Share this post


Link to post
Share on other sites
On 6/27/2017 at 3:34 PM, nbertoa said:

If you send a line primitive, then you can expand it into a segment in the geometry shader. I have some geometry shader code to do that.

...

Hope this helps!

I think this is the sort of thing I'm after - I'll work on integrating something along these lines into my code and let you know how I get on.  Thanks.

 

20 hours ago, WiredCat said:

Would like to draw a billboard between two points, and what these points even define? you are aware that to draw a  you are anyway using 4 verts (without any special gcard extensions like in example GL_POINT_SPRITE_ARB)

Either way you compose world*viewmat and extract screen direction vectors, then you build up a billboard 

something like this (thisis for ogl)

...

Since you have defined 4 points what do you want to do with these two points?

I probably wasn't very clear - I 'm already billboarding with 4 verts and using the viewing matrix to work out the 4 points (as in you example).  The problem I'm now facing is that I am moving from a billboard drawn around one 3D point (a particle) to a situation where I am moving up from a line drawn between two points (the start and end point of the laser bolt for example) to ideally drawing a textured quad that is (as much as possible) rotated to face the viewer.  Having to maintain the start and end points mean I cannot simply use the viewing matrix to position the quad - I need to retain the two points as the centre line of the quad and rotate as much as possible around these.  Hope that makes a bit more sense?

Share this post


Link to post
Share on other sites

are you using the geometry shader?

so, if you look up to my previous post, you can cross the vector between those two points, with the vector between the camera and the first point. this will give you a right vector, which you will be able to use to create the billboard vertices so that the primitives face the camera. does that make sense? i could give an example if you need (you don't have to be using a geometry shader to do this, but geometry shader can make billboarding a lot easier)

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

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

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!