Jump to content
  • Advertisement
Sign in to follow this  
neroziros

Generate Billboards from Tesselation Shaders possible?

This topic is 1317 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 there! I was wondering if anyone know if it is possible to create billboards through hull and domain shaders? (akin the geometry shader method)
 
I ask this because I'd like to tessellate my billboard's to add better shadow reception quality by moving the calculations from GS to the DS, but I'm not sure if it is possible to create billboards using the tessellation stages and how to go about it.
 
Cheers and thanks for any info!
 
PS: I don´t create the billboards with the GS and then tessellate them because from what I understand, the GS is executed AFTER the tesselation stages
 
PS2: http://developer.download.nvidia.com/assets/gamedev/files/sdk/11/OpacityMappingSDKWhitePaper.pdf  I read this example´s source code, and though they do have tesselate billboards I didn´t understand how they did it as I didn´t see the vertex expansion into view aligned quads anywhere.

Share this post


Link to post
Share on other sites
Advertisement

Oh I see,  do you mean using a function like DrawInstancedIndirect to render the particles?

 

But how do I set the correct number of instances (particles) to render in the indirect argument buffer? if I'm correct if I use CopyStructureCount(g_pIndirectArg,0,bufferWithParticles), the function will copy the particle amount to the slot [0] which contains the VertexCountPerInstance instead of the desired InstanceCount.

 

http://msdn.microsoft.com/en-us/library/windows/hardware/ff556147(v=vs.85).aspx

 

Sorry if I am misunderstanding something and thank you so much for your help. 

Share this post


Link to post
Share on other sites

if I'm correct if I use CopyStructureCount(g_pIndirectArg,0,bufferWithParticles), the function will copy the particle amount to the slot [0] which contains the VertexCountPerInstance instead of the desired InstanceCount.

 

So change the second argument of CopyStructureCount, DstAlignedByteOffset (Offset from the start of pDstBuffer to write 32-bit UINT structure count), to 4 ( size of VertexCountPerInstance). 

This way the number of particles will be copied to the correct location.

CopyStructureCount(g_pIndirectArg, 4,bufferWithParticles)
Edited by TiagoCosta

Share this post


Link to post
Share on other sites
Thanks it worked perfectly! by the way if anyone else is doing this, remember to change your
 
 IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
 
for 
 
 IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST);
 
otherwise it won't work properly.
 
Again thanks for your help, now I will look for tesselation examples so I can tesselate the particles based on their screen size.
 
Cheers.
Edited by neroziros

Share this post


Link to post
Share on other sites

Hmm odd I can't seem to get the Hull and Domain shaders working. I tried the code without them and no there was no problem (the particles are rendered as 4 unconnected points, see IMG1). But once I bind the Hull and Domain shaders it stops working (the particles are only visible if you are too close to them).

 
Here is my Vertex, Hull, Domain and Pixel shaders. Any help is welcomed!
 
UPDATE: Now I can see the particles! but they are still looking weird (IMG2). To  make them visible I moved the line:
 
output.position = mul(float4(position, 1.0), g_mWorldViewProj); from the vertex shader, to the domain shader. 
 
Does anyone knows why that worked and how to fix the particles? I'm obviously missing something here
 
UPDATE 2: Nvm now they are looking perfectly, I had to swap the g_positions´s coordinates for some reason. Still if someone could explain me why I had to move the g_mWorldViewProj transformation from the VS to the DS I'd be very grateful!
 
Cheers
 
PARTICLE'S CORNERS
static const float3 g_TessPositions[4] =
{
float3(-1, 1, 0),
float3(1, 1, 0),
float3(1, -1, 0),
float3(-1, -1, 0)
}
/* OLD, NOT WORKING static const float3 g_positions[4] = 
{ float3(-1, 1, 0), float3(1, 1, 0), float3(-1, -1, 0), float3(1, -1, 0), };*/
STRUCTS
struct VS_INPUT_TESSELATED
{
  uint vertexid : SV_VertexID;
  uint instanceid : SV_InstanceID;
};
struct VS_CONTROL_POINT_OUTPUT
{
  float3 position : POSITION;
};
//-----------------------------------------------
struct HS_OUTPUT
{
  float3 position : POSITION;
};
struct HS_CONSTANT_DATA_OUTPUT
{
  float Edges[4]  : SV_TessFactor;
  float Inside[2] : SV_InsideTessFactor;
};
//-----------------------------------------------
struct PS_INPUT // All of this (Except position) is ignored since I'm just rendering white quads for debugging
{
  float4 position : SV_POSITION;
  float4 color : Color;
  float2 texcoords : TEXCOORD0;
  float3 basis_col0 : TEXCOORD1;
  float3 basis_col1 : TEXCOORD2;
  float3 basis_col2 : TEXCOORD3;
  float3 normal : TEXCOORD4;
};
 
VERTEX SHADER
VS_CONTROL_POINT_OUTPUT VSMAIN_TESSELATED(in VS_INPUT_TESSELATED input)
{
  VS_CONTROL_POINT_OUTPUT output;


  // There is one particle per vertex, so use the vertex id as an index into the sorted list
  uint particleIndex = input.instanceid;


  // Get the global particle index
  uint index = (uint)g_SortedIndexBuffer[CurrentParticles.x - particleIndex - 1].y;


  // Get Particle's center Position
  float3 center = SimulationState[index].position;


  // Send the billboarded position
  float3 position = g_positions[input.vertexid] * sizeAndCurvature.x;
  output.position =  mul(position, (float3x3)g_mInvView) + center;
  //output.position = mul(float4(position, 1.0), g_mWorldViewProj); // Moved to Domain Shader
  
  return output;
}
HULL SHADER (CONST FUNCTION AND SHADER)
 
HS_CONSTANT_DATA_OUTPUT ConstantHS(InputPatch<VS_CONTROL_POINT_OUTPUT, 4> ip, 
  uint PatchID : SV_PrimitiveID)
{
  HS_CONSTANT_DATA_OUTPUT Output;
  float tess = 1.0; 


  Output.Edges[0] = tess;
  Output.Edges[1] = tess;
  Output.Edges[2] = tess;
  Output.Edges[3] = tess;


  Output.Inside[0] = tess;
  Output.Inside[1] = tess;


  return Output;
}


[domain("quad")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(4)]
[patchconstantfunc("ConstantHS")]
HS_OUTPUT HSMAIN(const InputPatch<VS_CONTROL_POINT_OUTPUT, 4> p,
                 uint i : SV_OutputControlPointID,
                  uint PatchID : SV_PrimitiveID)
{
  HS_OUTPUT Output;
  Output.position = p[i].position;
  return Output;
}
DOMAIN SHADER
 
[domain("quad")]
PS_INPUT DSMAIN(HS_CONSTANT_DATA_OUTPUT input,
float2 UV : SV_DomainLocation,
const OutputPatch<HS_OUTPUT, 4> quad)
{
  PS_INPUT Output = (PS_INPUT) 0;


  float3 verticalPos1 = lerp(quad[0].position, quad[1].position, UV.y);
  float3 verticalPos2 = lerp(quad[3].position, quad[2].position, UV.y);
  float3 finalPos = lerp(verticalPos1, verticalPos2, UV.x);


  //Output.position = float4(finalPos,1); // I tried with hard wired values like float4(0,0,0,1) and still nothing shows
  Output.position = mul(float4(finalPos, 1), g_mWorldViewProj); / New Version, it works (somehow)


return Output; }
Edited by neroziros

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!