Skip to main content
Grammar fixes, making context of cone-drawing clearer in the title
Source Link

Does it makesmake sense to use ComputeShadera compute shader with Dispatch(1,1,1) and Numthreads[1,1,1] to draw a cone?

I was working on this idea of drawing a rotating cone rotating on the y axis with a parametric equation, using a computeshadercompute shader with a function CS(SV_GroupID, uint3 nDTid like: SV_DispatchThreadID, SV_GroupThreadID).

CS(SV_GroupID, uint3 nDTid : SV_DispatchThreadID, SV_GroupThreadID). 

To avoid multiple rendering, I was using a test on nDTidnDTid to draw only in a given nDTid.xynDTid.xy interval. I

I found this tricky and finally I decided to use a Dispatch(1,1,1)Dispatch(1,1,1) and numthreads[1,1numthreads[1,1,1],1] which remove the requirement for the nDTidnDTid interval test and the cone is drawn only once.

What I have noticed is an eraticerratic framerate that I guess depends on the number of pixel drawn.

This becomes more an exerciceexercise than something applicable to my regular project, but is it of interest to limit DispatchDispatch and numthreadnumthread as I did with computeshaders and howcompute shaders? How can I reduce this eraticerratic framerate?

Below someis a code example and screenthe rendered result.

Preparing constant shaderPreparing constant shader

setting the computeshader.Setting the compute shader. Instead of progressing along the cone axis and drawdrawing a circle at each step, which required one transform  /lightning lighting calculation per circle pixel drawn, I loop first for each pixel of the circle at the base and draw a line from top cone to this pixel. This requires only one transform  /lightning lighting calculation per line drawn. It is not really efficient may I say, as top pixels can be drawn several times. This shader does not draw the base of the cone and did not z test-test. For some resonsreasons, the lightninglighting makes the cone reddish instead of going grey, which I have not solved yet.

screen shot Screen shot

enter image description hereCone with some stripes of missing pixels

An alternative solution is to use a geometry shader to output a triangle from the top to two successive pixel circlecircles.

Does it makes sense to use ComputeShader with Dispatch(1,1,1) and Numthreads[1,1,1]

I was working on this idea of drawing a rotating cone on the y axis with a parametric equation using a computeshader with a function CS(SV_GroupID, uint3 nDTid : SV_DispatchThreadID, SV_GroupThreadID). To avoid multiple rendering I was using a test on nDTid to draw only in a given nDTid.xy interval. I found this tricky and finally I decided to use a Dispatch(1,1,1) and numthreads[1,1,1] which remove the requirement for the nDTid interval test and the cone is drawn only once.

What I have noticed is an eratic framerate that I guess depends on the number of pixel drawn.

This becomes more an exercice than something applicable to my regular project but is it of interest to limit Dispatch and numthread as I did with computeshaders and how can I reduce this eratic framerate?

Below some code and screen result

Preparing constant shader

setting the computeshader. Instead of progressing along the cone axis and draw a circle each step, which required one transform/lightning per circle pixel drawn, I loop first for each pixel of the circle at the base and draw a line from top cone to this pixel. This requires only one transform/lightning per line drawn. It is not really efficient may I say as top pixels can be drawn several times. This shader does not draw the base of the cone and did not z test. For some resons the lightning makes the cone reddish instead of going grey which I have not solved yet.

screen shot enter image description here

An alternative solution is to use geometry shader to output a triangle from top to two successive pixel circle.

Does it make sense to use a compute shader with Dispatch(1,1,1) and Numthreads[1,1,1] to draw a cone?

I was working on this idea of drawing a cone rotating on the y axis with a parametric equation, using a compute shader with a function like:

CS(SV_GroupID, uint3 nDTid : SV_DispatchThreadID, SV_GroupThreadID). 

To avoid multiple rendering, I was using a test on nDTid to draw only in a given nDTid.xy interval.

I found this tricky and finally I decided to use Dispatch(1,1,1) and numthreads[1,1,1], which remove the requirement for the nDTid interval test and the cone is drawn only once.

What I have noticed is an erratic framerate that I guess depends on the number of pixel drawn.

This becomes more an exercise than something applicable to my regular project, but is it of interest to limit Dispatch and numthread as I did with compute shaders? How can I reduce this erratic framerate?

Below is a code example and the rendered result.

Preparing constant shader

Setting the compute shader. Instead of progressing along the cone axis and drawing a circle at each step, which required one transform  / lighting calculation per circle pixel drawn, I loop first for each pixel of the circle at the base and draw a line from top cone to this pixel. This requires only one transform  / lighting calculation per line drawn. It is not really efficient may I say, as top pixels can be drawn several times. This shader does not draw the base of the cone and did not z-test. For some reasons, the lighting makes the cone reddish instead of going grey, which I have not solved yet.

Screen shot

Cone with some stripes of missing pixels

An alternative solution is to use a geometry shader to output a triangle from the top to two successive pixel circles.

added 3828 characters in body
Source Link
philB
  • 333
  • 2
  • 11

Below some code and screen result

Preparing constant shader

void UpdateShaderConstantCone()
{
    FLOAT R = 10.0f;//radius at cone base
    FLOAT H = 30.0f;//height of Cone
    XMVECTOR U = XMVectorSet(R, 0, 0, 1);//vector for plane of base cone
    XMVECTOR DirC = XMVectorSet(0, 0, H, 360);//initial direction of cone along Z axis
    XMMATRIX M = XMMatrixRotationY(RotCone);
    M.r[3] = XMVectorSet(20, 50, 0, 1);//position of the cone top = purple ball center
    gCBCone.mWorld = XMMatrixTranspose(M*gVP);//set World.View.Perspective mat
    XMStoreFloat4(&gCBCone.DirC, DirC);
    XMStoreFloat4(&gCBCone.U, U);
    FLOAT C = 0.5f * 255.0f;
    gCBCone.Color = XMFLOAT4(0 * C, C * 255 , C * 255 * 255, 1.0f);
    gpDC11->UpdateSubresource(gpCBBufferCone, 0, NULL, &gCBCone, 0, 0);
    gpDC11->CSSetConstantBuffers(dwSlotCone, 1, &gpCBBufferCone);
}

setting the computeshader. Instead of progressing along the cone axis and draw a circle each step, which required one transform/lightning per circle pixel drawn, I loop first for each pixel of the circle at the base and draw a line from top cone to this pixel. This requires only one transform/lightning per line drawn. It is not really efficient may I say as top pixels can be drawn several times. This shader does not draw the base of the cone and did not z test. For some resons the lightning makes the cone reddish instead of going grey which I have not solved yet.

#define SM_SCREENX 1920.0
#define SM_SCREENY 1080.0
RWTexture2D<uint> UAVDiffuse0  : register( u0 );

cbuffer cbCone: register(b6)
{
    matrix WVP;
    float4 DirC;//direction of cone, w=Height
    float4 U;//vector plane of circle w=radius / Height
    //Note the plane requires two vectors UP(R,0,0) and VP(0,R,0).
    //so U is used as U.xyy is UP and U.yxy is VP
    float4 C;//color precalculated half
};

#define CPInc 2*3.14159265359f
static const float3 f3_u3 = float3(255,255*255,255*255*255);
static const float3 LDir = normalize(float3(-1,-1, 1));//Light dir
static const float3 LCol = float3(0.5f,0.5f,0.5f)*f3_u3;//ambient color 0.5f,0.5f,0.5f
static const float2 Sd2a = float2(SM_SCREENX, SM_SCREENY)*0.5f;
static const float2 Sd2m = float2(SM_SCREENX, -SM_SCREENY)*0.5f;
[numthreads(1,1,1)]
void CS_PostDeferred( uint3 nGid : SV_GroupID, uint3 nDTid : SV_DispatchThreadID, uint3 nGTid : SV_GroupThreadID )
{
    float4 P = mul(float4(0,0,0,1),WVP);
    P/=P.w;
    P.xy=P.xy*Sd2m+Sd2a;
    float4 E = float4(0,0,0,1);
    float k=CPInc/DirC.w;//angle increment to draw the circle
    float Angle = 0;
    float2 sd2aP = Sd2a-P.xy;//precalculate delta for line tracing
    for ( int a = 0; a < DirC.w; a++ )//make a circle at height h
    {
        float3 D = U.xyy*cos(Angle)+U.yxy*sin(Angle);//calculate circle pixel pos
        E.xyz = DirC.xyz+D;//add base position from top eg 0,0,Height
        Angle+=k;
        E = mul(E,WVP);//convert to screen space
        E/=E.w;
        E.xy=mad(E.xy,Sd2m,sd2aP);//convert pixel position E to distance in pixel from top cone
        float2 dXY = abs(E.xy);//calculate longest screen pixel path
        int L = (dXY.x>dXY.y)?dXY.x:dXY.y;//determine number of step
        float3 CL = C*dot(normalize(D),LDir)+LCol;//calculate ambient lighting
        //we assume the normal D along the line is constant
        E.xy/=L;//convert E to pixel path step
        float2 XY = P.xy;
        for (int l=0;l<L;l++)
        {
            UAVDiffuse0[int2(XY)]= (uint(CL.r)&0xFF) | (uint(CL.g)&0xFF00) | (uint(CL.b)&0xFF0000);
            XY+=E.xy;
        }
    }
}
    

screen shot enter image description here

An alternative solution is to use geometry shader to output a triangle from top to two successive pixel circle.

Below some code and screen result

Preparing constant shader

void UpdateShaderConstantCone()
{
    FLOAT R = 10.0f;//radius at cone base
    FLOAT H = 30.0f;//height of Cone
    XMVECTOR U = XMVectorSet(R, 0, 0, 1);//vector for plane of base cone
    XMVECTOR DirC = XMVectorSet(0, 0, H, 360);//initial direction of cone along Z axis
    XMMATRIX M = XMMatrixRotationY(RotCone);
    M.r[3] = XMVectorSet(20, 50, 0, 1);//position of the cone top = purple ball center
    gCBCone.mWorld = XMMatrixTranspose(M*gVP);//set World.View.Perspective mat
    XMStoreFloat4(&gCBCone.DirC, DirC);
    XMStoreFloat4(&gCBCone.U, U);
    FLOAT C = 0.5f * 255.0f;
    gCBCone.Color = XMFLOAT4(0 * C, C * 255 , C * 255 * 255, 1.0f);
    gpDC11->UpdateSubresource(gpCBBufferCone, 0, NULL, &gCBCone, 0, 0);
    gpDC11->CSSetConstantBuffers(dwSlotCone, 1, &gpCBBufferCone);
}

setting the computeshader. Instead of progressing along the cone axis and draw a circle each step, which required one transform/lightning per circle pixel drawn, I loop first for each pixel of the circle at the base and draw a line from top cone to this pixel. This requires only one transform/lightning per line drawn. It is not really efficient may I say as top pixels can be drawn several times. This shader does not draw the base of the cone and did not z test. For some resons the lightning makes the cone reddish instead of going grey which I have not solved yet.

#define SM_SCREENX 1920.0
#define SM_SCREENY 1080.0
RWTexture2D<uint> UAVDiffuse0  : register( u0 );

cbuffer cbCone: register(b6)
{
    matrix WVP;
    float4 DirC;//direction of cone, w=Height
    float4 U;//vector plane of circle w=radius / Height
    //Note the plane requires two vectors UP(R,0,0) and VP(0,R,0).
    //so U is used as U.xyy is UP and U.yxy is VP
    float4 C;//color precalculated half
};

#define CPInc 2*3.14159265359f
static const float3 f3_u3 = float3(255,255*255,255*255*255);
static const float3 LDir = normalize(float3(-1,-1, 1));//Light dir
static const float3 LCol = float3(0.5f,0.5f,0.5f)*f3_u3;//ambient color 0.5f,0.5f,0.5f
static const float2 Sd2a = float2(SM_SCREENX, SM_SCREENY)*0.5f;
static const float2 Sd2m = float2(SM_SCREENX, -SM_SCREENY)*0.5f;
[numthreads(1,1,1)]
void CS_PostDeferred( uint3 nGid : SV_GroupID, uint3 nDTid : SV_DispatchThreadID, uint3 nGTid : SV_GroupThreadID )
{
    float4 P = mul(float4(0,0,0,1),WVP);
    P/=P.w;
    P.xy=P.xy*Sd2m+Sd2a;
    float4 E = float4(0,0,0,1);
    float k=CPInc/DirC.w;//angle increment to draw the circle
    float Angle = 0;
    float2 sd2aP = Sd2a-P.xy;//precalculate delta for line tracing
    for ( int a = 0; a < DirC.w; a++ )//make a circle at height h
    {
        float3 D = U.xyy*cos(Angle)+U.yxy*sin(Angle);//calculate circle pixel pos
        E.xyz = DirC.xyz+D;//add base position from top eg 0,0,Height
        Angle+=k;
        E = mul(E,WVP);//convert to screen space
        E/=E.w;
        E.xy=mad(E.xy,Sd2m,sd2aP);//convert pixel position E to distance in pixel from top cone
        float2 dXY = abs(E.xy);//calculate longest screen pixel path
        int L = (dXY.x>dXY.y)?dXY.x:dXY.y;//determine number of step
        float3 CL = C*dot(normalize(D),LDir)+LCol;//calculate ambient lighting
        //we assume the normal D along the line is constant
        E.xy/=L;//convert E to pixel path step
        float2 XY = P.xy;
        for (int l=0;l<L;l++)
        {
            UAVDiffuse0[int2(XY)]= (uint(CL.r)&0xFF) | (uint(CL.g)&0xFF00) | (uint(CL.b)&0xFF0000);
            XY+=E.xy;
        }
    }
}
    

screen shot enter image description here

An alternative solution is to use geometry shader to output a triangle from top to two successive pixel circle.

Source Link
philB
  • 333
  • 2
  • 11

Does it makes sense to use ComputeShader with Dispatch(1,1,1) and Numthreads[1,1,1]

I was working on this idea of drawing a rotating cone on the y axis with a parametric equation using a computeshader with a function CS(SV_GroupID, uint3 nDTid : SV_DispatchThreadID, SV_GroupThreadID). To avoid multiple rendering I was using a test on nDTid to draw only in a given nDTid.xy interval. I found this tricky and finally I decided to use a Dispatch(1,1,1) and numthreads[1,1,1] which remove the requirement for the nDTid interval test and the cone is drawn only once.

What I have noticed is an eratic framerate that I guess depends on the number of pixel drawn.

This becomes more an exercice than something applicable to my regular project but is it of interest to limit Dispatch and numthread as I did with computeshaders and how can I reduce this eratic framerate?