Create Vertices within the HLSL shader

Started by
12 comments, last by Nik02 11 years, 11 months ago
If you call Draw(300000,0), your vertex shader will be invoked 300000 times, and the SV_VertexId parameter is incremented at each vertex. You decide what you want to do with it :)

Niko Suni

Advertisement
It is best to think it this way: since you don't get anything from vertex buffers, you are not limited to any previously allocated memory limits.

There is a practical limitation on the number of vertices per draw call (due to driver timeouts), but the figure is well in millions.

Niko Suni

I don't know. Something wrong with my understanding of what you are saying. Below I show the logic I am using and it works for the triangle, but it doesn't work for square.
As you see below I commented a lot of code and it still consistant. It works, but show only one of the triangles of the square. depends on which one of them are 0,1,2. When I replace the order it shows one triangle or another.


ID3DBlob* pVSBlob = NULL;
hr = CompileShaderFromFile( L"Tutorial02.fx", "vshader", "vs_4_0", &pVSBlob );
if( FAILED( hr ) )
{
MessageBox( NULL,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
return hr;
}
// Create the vertex shader
hr = g_pd3dDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &g_pVertexShader );
if( FAILED( hr ) )
{
pVSBlob->Release();
return hr;
}
//// Define the input layout
//D3D11_INPUT_ELEMENT_DESC layout[] =
//{
// { "SV_VertexId", 0, DXGI_FORMAT_R32G32B32_UINT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
//};
//UINT numElements = ARRAYSIZE( layout );
//// Create the input layout
//hr = g_pd3dDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(),
// pVSBlob->GetBufferSize(), &g_pVertexLayout );
//pVSBlob->Release();
//if( FAILED( hr ) )
// return hr;
// Set the input layout
//g_pImmediateContext->IASetInputLayout( NULL );
// Compile the pixel shader
ID3DBlob* pPSBlob = NULL;
hr = CompileShaderFromFile( L"Tutorial02.fx", "PS", "ps_4_0", &pPSBlob );
if( FAILED( hr ) )
{
MessageBox( NULL,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
return hr;
}
// Create the pixel shader
hr = g_pd3dDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &g_pPixelShader );
pPSBlob->Release();
if( FAILED( hr ) )
return hr;
//// Create vertex buffer
//SimpleVertex vertices[] =
//{
// XMFLOAT3( 0.0f, 0.5f, 0.5f ),
// XMFLOAT3( 0.5f, -0.5f, 0.5f ),
// XMFLOAT3( -0.5f, -0.5f, 0.5f ),
//};
//D3D11_BUFFER_DESC bd;
//ZeroMemory( &bd, sizeof(bd) );
//bd.Usage = D3D11_USAGE_DEFAULT;
//bd.ByteWidth = sizeof( SimpleVertex ) * 3;
//bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
//bd.CPUAccessFlags = 0;
//D3D11_SUBRESOURCE_DATA InitData;
//ZeroMemory( &InitData, sizeof(InitData) );
//InitData.pSysMem = vertices;
//hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
//if( FAILED( hr ) )
// return hr;
//// Set vertex buffer
//UINT stride = sizeof( SimpleVertex );
//UINT offset = 0;
//g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );
// Set primitive topology
g_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );



//--------------------------------------------------------------------------------------
// File: Tutorial02.fx
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
float4 VS( float4 Pos : POSITION ) : SV_POSITION
{
return Pos;
}

//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS( float4 Pos : SV_POSITION ) : SV_Target
{
return float4( 1.0f, 1.0f, 0.0f, 1.0f ); // Yellow, with Alpha = 1
}
struct VS_OUT {
float4 pos : SV_Position;
// insert other vs output fields here as needed
};
// vertex shader that draws a triangle without vbuffers
VS_OUT vshader(uint idx : SV_VertexId)
{
VS_OUT ret = (VS_OUT)0;
switch (idx)
{
case 3:
ret.pos = float4(-0.1,-0.1,1,1);
break;
case 4:
ret.pos = float4(0.1,0.1,1,1);
break;
case 5:
ret.pos = float4(0.1,-0.1,1,1);
break;
case 0:
ret.pos = float4(-0.1,-0.1,1,1);
break;
case 1:
ret.pos = float4(-0.1,0.1,1,1);
break;
case 2:
ret.pos = float4(0.1,0.1,1,1);
break;
}
return ret;
}
The backface culling happens after the primitives have been generated.

The geometric normal of the triangle determines whether it is front facing or back facing. The geometric normal of the triangle is cross product of the normalized triangle edges p1-p0 and p2-p0. If the z component of the cross product is negative, the triangle is considered facing away from the "camera" and therefore invisible (in ordinary rendering). If you exchange places of any two points of the triangle, the cross product's direction (and of course the z component) is negated, and the triangle is effectively flipped to its back.

You can switch of the backface culling by using an appropriate rasterizer state; however, to optimize performance, keep it on and ensure that your triangles are wound consistently.

Niko Suni

This topic is closed to new replies.

Advertisement