Jump to content
  • Advertisement
Sign in to follow this  
cozzie

Vertex to cube using geometry shader

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

Hi all,
While playing around/ experimenting with geometry shaders, I tried to "expand" a point/ vertex (input) to rendering a cube (output). I managed to do this like this:

- create 14 vertices in the GS
- give them all their correct normals and own UV's
- output all vertices as one big triangle strip

Functionally this gives the aimed result.
Although I'm curious if there are better/ other to achieve this with a geometry shader, for example by using a triangle list (indices) or some other way.

Let me know what you think.

Share this post


Link to post
Share on other sites
Advertisement

I'd actually advice against a geometry shader here and use hardware instancing. Not only is it simpler and allows for other geometry without changing the shaders it will also be likely much faster (Edit: Wrong! See MJP's link below, instancing can turn out bad for low vertex count). One can also only do triangle strips and no indexed drawing with a geo shader (at least not without going through other hoops like stream-out).

 

PS: I'm still curious how you pulled that off with 14 vertices only wink.png

Share this post


Link to post
Share on other sites

PS: I'm still curious how you pulled that off with 14 vertices only wink.png

14 tristrip cube in the vertex shader using only vertex ID (no UVs or normals):
b = 1 << i;
x = (0x287a & b) != 0;
y = (0x02af & b) != 0;
z = (0x31e3 & b) != 0;
Edited by Matias Goldberg

Share this post


Link to post
Share on other sites

The bithackery is a bridge too far for me :)

Thanks all, I agree that isn't the 'ideal' situation to achieve what I'm doing, but I'm just trying out Geometry shaders, to understand them.

 

I thought I had it, but I didn't or just broke it.

While trying to fix it, I think I've found a problem with the approach, some vertices are shared in faces, which causes a problem with the normals.

Resulting in 'half a cube' being visible.

Here's the code and the result:

	float3 gNormals[14] =
	{
		float3(0.0f, 0.0f, -1.0f),
		float3(0.0f, 0.0f, -1.0f),
		float3(0.0f, 0.0f, -1.0f),
		float3(0.0f, 0.0f, -1.0f),

		float3(1.0f, 0.0f,  0.0f),
		float3(1.0f, 0.0f,  0.0f),
		float3(1.0f, 0.0f,  0.0f),

		float3(-1.0f, 0.0f,  0.0f),
		float3(-1.0f, 0.0f,  0.0f),
		float3(-1.0f, 0.0f,  0.0f),
		float3(-1.0f, 0.0f,  0.0f),

		float3(0.0f, 0.0f,  1.0f),
		float3(0.0f, 0.0f,  1.0f),
		float3(0.0f, 0.0f,  1.0f)
	};

	float4 boxv[14];
	boxv[0] = float4(gin[0].CenterW.x	-halfWidth, gin[0].CenterW.y	+halfHeight, gin[0].CenterW.z	-halfDepth, 1.0f);
	boxv[1] = float4(gin[0].CenterW.x	+halfWidth, gin[0].CenterW.y	+halfHeight, gin[0].CenterW.z	-halfDepth, 1.0f);
	boxv[2] = float4(gin[0].CenterW.x	-halfWidth, gin[0].CenterW.y	-halfHeight, gin[0].CenterW.z	-halfDepth, 1.0f);
	boxv[3] = float4(gin[0].CenterW.x	+halfWidth, gin[0].CenterW.y	-halfHeight, gin[0].CenterW.z	-halfDepth, 1.0f);
	boxv[4] = float4(gin[0].CenterW.x	+halfWidth, gin[0].CenterW.y	-halfHeight, gin[0].CenterW.z	+halfDepth, 1.0f);
	boxv[5] = float4(gin[0].CenterW.x	+halfWidth, gin[0].CenterW.y	+halfHeight, gin[0].CenterW.z	-halfDepth, 1.0f);
	boxv[6] = float4(gin[0].CenterW.x	+halfWidth, gin[0].CenterW.y	+halfHeight, gin[0].CenterW.z	+halfDepth, 1.0f);
	boxv[7] = float4(gin[0].CenterW.x	-halfWidth, gin[0].CenterW.y	+halfHeight, gin[0].CenterW.z	-halfDepth, 1.0f);
	boxv[8] = float4(gin[0].CenterW.x	-halfWidth, gin[0].CenterW.y	+halfHeight, gin[0].CenterW.z	+halfDepth, 1.0f);
	boxv[9] = float4(gin[0].CenterW.x	-halfWidth, gin[0].CenterW.y	-halfHeight, gin[0].CenterW.z	-halfDepth, 1.0f);
	boxv[10] = float4(gin[0].CenterW.x	-halfWidth, gin[0].CenterW.y	-halfHeight, gin[0].CenterW.z	+halfDepth, 1.0f);
	boxv[11] = float4(gin[0].CenterW.x	+halfWidth, gin[0].CenterW.y	-halfHeight, gin[0].CenterW.z	+halfDepth, 1.0f);
	boxv[12] = float4(gin[0].CenterW.x	-halfWidth, gin[0].CenterW.y	+halfHeight, gin[0].CenterW.z	+halfDepth, 1.0f);
	boxv[13] = float4(gin[0].CenterW.x	+halfWidth, gin[0].CenterW.y	+halfHeight, gin[0].CenterW.z	+halfDepth, 1.0f);

	int index[14] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};

	GeoOut gout;
	[unroll]
	for(int i=0;i<14;++i)
	{
		gout.PosH     = mul(boxv[index[i]], gViewProj);
		gout.PosW     = boxv[index[i]].xyz;
		gout.NormalW  = gNormals[index[i]];
		gout.Tex      = gTexC[index[i]];
		gout.PrimID   = primID;
		
		triStream.Append(gout);
	}

geom_cube_NOK1.jpg

geom_cube_NOK2.jpg

 

I might be able to fix it, by adding additional vertices and coming to 6 faces * 4 vertices = 24 vertices.

Any other ideas?

Share this post


Link to post
Share on other sites
Not really, that's why I was stumped. I don't think you can get any better, IIRC 24 vertices is the minimal amount if you need normals (and tex-coords for that matter). For the geo shader also a restart-strip after every quad.

One could probably play merging the tex-coords somehow, but I expect some (undesired?) mirroring or something. And you can generate the normals in the pixel shader if you pass along a position (using gradients):

normal = normalize(cross(ddx(pos), ddy(pos)));
It may be a good exercise, but that's really too complicated for a simple cube IMO.

Share this post


Link to post
Share on other sites
Thanks. For practice I'll go for 24 vertices and restart strip per quad. Then I'll call it enough for practice.
Update: besides the normals/ UV's it actualy did work, I just didn't change the max vertices output of the GS from 8 to 14.

The actual exercise was making a cylinder without caps, but I wanted to play around first and see if a cube was possible. Edited by cozzie

Share this post


Link to post
Share on other sites
Thanks, interesting and clearly related.
Also good to see that he also achieved it with 14 vertices (probably accepting the overlapping normals and UV issue).

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!