ФЭНДОМ


ВведениеПравить

В данном уроке мы кратко освоим аппаратную тесселяцию. Само определение слова здесь и здесь.

К сожалению, я не силен в данной теме, поэтому код будет почти без пояснений. Сам код адаптирован из уроков rastertek.

Смысл теселяции - это разбиение одного примитива на несколько. Мы разобьем треугольник на кучу мелких треугольников из которых и будет состоять наш.

Пишем кодПравить

main.cppПравить

#include "MyRender.h"

int main()
{
	Framework framework;

	MyRender *render = new MyRender();

	FrameworkDesc desc;
	desc.render = render;

	framework.Init(desc);
	framework.Run();
	framework.Close();


	return 0;
}

MyRender.hПравить

#pragma once

#include "D3D11_Framework.h"

using namespace D3D11Framework;

class MyRender : public Render
{
public:
	MyRender();
	bool Init();
	bool Draw();
	void Close();
	
private:
	bool LoadShader();

	ID3D11Buffer *m_vb; 
	ID3D11Buffer *m_ib;

	ID3D11Buffer *m_constMatrixBuffer;
	ID3D11Buffer* m_tessellationBuffer;

	ID3D11HullShader* m_hullShader;
	ID3D11DomainShader* m_domainShader;

	Shader *m_shader;

	Camera m_cam;

	ID3D11RasterizerState* m_rasterState;
};

Здесь появились два новых шейдера - hull и domain.

MyRender.cppПравить

#include "MyRender.h"

// описание вершины
struct Vertex
{
	XMFLOAT3 pos;
	XMFLOAT4 color;
};

struct WVPBuffer
{
	XMMATRIX world;
	XMMATRIX view;
	XMMATRIX projection;
};

struct TessellationBufferType
{
	float tessellationAmount;
	XMFLOAT3 padding;
};

MyRender::MyRender()
{
	m_vb = nullptr;
	m_ib = nullptr;
	m_constMatrixBuffer = nullptr;
	m_tessellationBuffer = nullptr;
	m_hullShader = nullptr;
	m_domainShader = nullptr;
	m_shader = nullptr;
	m_rasterState = nullptr;
}

bool MyRender::Init()
{
	// геометрия
	Vertex vert[] =
	{
		{ XMFLOAT3( -1.0f, -1.0f, 0.0f ), XMFLOAT4( 0.0f, 1.0f, 0.0f, 1.0f ) },
		{ XMFLOAT3( 0.0f, 1.0f, 0.0f ), XMFLOAT4( 0.0f, 1.0f, 0.0f, 1.0f ) },
		{ XMFLOAT3( 1.0f, -1.0f, 0.0f ), XMFLOAT4( 0.0f, 1.0f, 0.0f, 1.0f ) }
	};
	unsigned long indices[] = {	0,1,2 };

	// создаем вершинный и индексный буферы
	m_vb = Buffer::CreateVertexBuffer(m_pd3dDevice, sizeof(Vertex)*3, false, &vert);
	m_ib = Buffer::CreateIndexBuffer(m_pd3dDevice, sizeof(unsigned long)*3, false, &indices);

	// создаем константный буфер
	m_constMatrixBuffer = Buffer::CreateConstantBuffer(m_pd3dDevice, sizeof(WVPBuffer), false);

	m_tessellationBuffer = Buffer::CreateConstantBuffer(m_pd3dDevice, sizeof(TessellationBufferType), false);
	
	// инициализируем шейдер и входной формат
	m_shader = new Shader(this);
	m_shader->AddInputElementDesc("POSITION", DXGI_FORMAT_R32G32B32_FLOAT);
	m_shader->AddInputElementDesc("COLOR", DXGI_FORMAT_R32G32B32A32_FLOAT);
	if ( !m_shader->CreateShader(L"shader.vs", L"shader.ps") )
		return false;
			
	// настраиваем камеру
	m_cam.SetPos(0.0f, 0.0f, -2.0f);

	D3D11_RASTERIZER_DESC rasterDesc;
	rasterDesc.AntialiasedLineEnable = false;
	rasterDesc.CullMode = D3D11_CULL_BACK;
	rasterDesc.DepthBias = 0;
	rasterDesc.DepthBiasClamp = 0.0f;
	rasterDesc.DepthClipEnable = true;
	rasterDesc.FillMode = D3D11_FILL_WIREFRAME;
	rasterDesc.FrontCounterClockwise = false;
	rasterDesc.MultisampleEnable = false;
	rasterDesc.ScissorEnable = false;
	rasterDesc.SlopeScaledDepthBias = 0.0f;

	if(FAILED(m_pd3dDevice->CreateRasterizerState(&rasterDesc, &m_rasterState)))
		return false;
	
	m_pImmediateContext->RSSetState(m_rasterState);
	
	return LoadShader();
}

Здесь мы создали  m_rasterState для того чтобы выводить сетку геометрии (D3D11_FILL_WIREFRAME) иначе мы просто не увидим результат.

bool MyRender::LoadShader()
{
	HRESULT result;
	
	ID3D10Blob *errorMessage = nullptr;
	ID3D10Blob *hullShaderBuffer = nullptr;
	ID3D10Blob *domainShaderBuffer = nullptr;
	
	// Компиляция hull shader.
	result = D3DX11CompileFromFile(L"shader.hs", NULL, NULL, "HS", "hs_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL, &hullShaderBuffer, &errorMessage, NULL);
	if(FAILED(result))
		return false;

	// Компиляция domain shader.
	result = D3DX11CompileFromFile(L"shader.ds", NULL, NULL, "DS", "ds_5_0", D3D10_SHADER_ENABLE_STRICTNESS, 0, NULL,  &domainShaderBuffer, &errorMessage, NULL);
	if(FAILED(result))
		return false;
	
	// Создание hull shader.
	result = m_pd3dDevice->CreateHullShader(hullShaderBuffer->GetBufferPointer(), hullShaderBuffer->GetBufferSize(), NULL, &m_hullShader);
	if(FAILED(result))
		return false;

	// Создание domain shader.
	result = m_pd3dDevice->CreateDomainShader(domainShaderBuffer->GetBufferPointer(), domainShaderBuffer->GetBufferSize(), NULL, &m_domainShader);
	if(FAILED(result))
		return false;
	
	_RELEASE(hullShaderBuffer);
	_RELEASE(domainShaderBuffer);

	return true;
}

Компилируем и создаем два новых шейдера.

bool MyRender::Draw()
{		
	m_cam.Render();

	XMMATRIX camView = m_cam.GetViewMatrix();
		
	WVPBuffer cb;
	cb.world = XMMatrixTranspose(XMMatrixIdentity());
	cb.view = XMMatrixTranspose(camView);
	cb.projection = XMMatrixTranspose(m_Projection);

	m_pImmediateContext->UpdateSubresource(m_constMatrixBuffer, 0, NULL, &cb, 0, 0);
	m_pImmediateContext->DSSetConstantBuffers(0, 1, &m_constMatrixBuffer);

	TessellationBufferType tes;
	tes.tessellationAmount = 12.0f;
	tes.padding = XMFLOAT3(0.0f, 0.0f, 0.0f);

	m_pImmediateContext->UpdateSubresource(m_tessellationBuffer, 0, NULL, &tes, 0, 0);
	m_pImmediateContext->HSSetConstantBuffers(0, 1, &m_tessellationBuffer);
	
	unsigned int stride = sizeof(Vertex); 
	unsigned int offset = 0;
	m_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST);		
	m_pImmediateContext->IASetVertexBuffers(0, 1, &m_vb, &stride, &offset);
	m_pImmediateContext->IASetIndexBuffer(m_ib, DXGI_FORMAT_R32_UINT, 0);
	
	m_pImmediateContext->HSSetShader(m_hullShader, NULL, 0);
	m_pImmediateContext->DSSetShader(m_domainShader, NULL, 0);
	m_shader->Draw();

	m_pImmediateContext->DrawIndexed(6, 0, 0);
		
	return true;
}

Обратите внимание, константные буферы передаем в domain и hull шейдеры.

void MyRender::Close()
{
	_RELEASE(m_vb);
	_RELEASE(m_ib);
	_RELEASE(m_constMatrixBuffer);
	_RELEASE(m_tessellationBuffer);
	_RELEASE(m_hullShader);
	_RELEASE(m_domainShader);
	_RELEASE(m_rasterState);

	_CLOSE(m_shader);
}

shader.vsПравить

struct VertexInputType
{
    float3 position : POSITION;
    float4 color : COLOR;
};

struct HullInputType
{
    float3 position : POSITION;
    float4 color : COLOR;
};

HullInputType VS(VertexInputType input)
{
	HullInputType output;
	output.position = input.position;
	output.color = input.color;
	return output;
}

shader.hsПравить

cbuffer TessellationBuffer
{
	float tessellationAmount;
	float3 padding;
};

struct HullInputType
{
	float3 position : POSITION;
	float4 color : COLOR;
};

struct ConstantOutputType
{
	float edges[3] : SV_TessFactor;
	float inside : SV_InsideTessFactor;
};

struct HullOutputType
{
	float3 position : POSITION;
	float4 color : COLOR;
};

// Patch Constant Function
ConstantOutputType ColorPatchConstantFunction(InputPatch<HullInputType, 3> inputPatch, uint patchId : SV_PrimitiveID)
{    
	ConstantOutputType output;

	// Set the tessellation factors for the three edges of the triangle.
	output.edges[0] = tessellationAmount;
	output.edges[1] = tessellationAmount;
	output.edges[2] = tessellationAmount;

	// Set the tessellation factor for tessallating inside the triangle.
	output.inside = tessellationAmount;

	return output;
}

[domain("tri")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("ColorPatchConstantFunction")]

HullOutputType HS(InputPatch<HullInputType, 3> patch, uint pointId : SV_OutputControlPointID, uint patchId : SV_PrimitiveID)
{
	HullOutputType output;

	// Set the position for this control point as the output position.
	output.position = patch[pointId].position;

	// Set the input color as the output color.
	output.color = patch[pointId].color;

    return output;
}

shader.dsПравить

cbuffer MatrixBuffer
{
	matrix worldMatrix;
	matrix viewMatrix;
	matrix projectionMatrix;
};

struct ConstantOutputType
{
	float edges[3] : SV_TessFactor;
	float inside : SV_InsideTessFactor;
};

struct HullOutputType
{
	float3 position : POSITION;
	float4 color : COLOR;
};

struct PixelInputType
{
	float4 position : SV_POSITION;
	float4 color : COLOR;
};

[domain("tri")]

PixelInputType DS(ConstantOutputType input, float3 uvwCoord : SV_DomainLocation, const OutputPatch<HullOutputType, 3> patch)
{
	float3 vertexPosition;
	PixelInputType output;
 
	// Determine the position of the new vertex.
	vertexPosition = uvwCoord.x * patch[0].position + uvwCoord.y * patch[1].position + uvwCoord.z * patch[2].position;
    
	// Calculate the position of the new vertex against the world, view, and projection matrices.
	output.position = mul(float4(vertexPosition, 1.0f), worldMatrix);
	output.position = mul(output.position, viewMatrix);
	output.position = mul(output.position, projectionMatrix);

	// Send the input color into the pixel shader.
	output.color = patch[0].color;

	return output;
}

shader.psПравить

struct PixelInputType
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};

float4 PS(PixelInputType input) : SV_TARGET
{
    return input.color;
}

ЗавершениеПравить

скачать

Lesson 2013-04-27 15-11-34-19
Материалы сообщества доступны в соответствии с условиями лицензии CC-BY-SA , если не указано иное.