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.

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 on other sites

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 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 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 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;
};

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;
}


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;
}

[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("quad")]
PS_INPUT DSMAIN(HS_CONSTANT_DATA_OUTPUT input,
float2 UV : SV_DomainLocation,
{
PS_INPUT Output = (PS_INPUT) 0;

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

• 23
• 10
• 19
• 15
• 14