2015-11-03 56 views
1

好吧,我快要卡住了。我一直在试图将Nvidia WireFrame效果转换为vs,gs和ps HLSL文件,并在我的DirectX11.1应用程序中使用。转换看起来很简单。这里是Nvida SampleDirectX从效果转换为HLSL vs,gs和ps

这里是我的作为在VS:

cbuffer WorldViewProjectionType : register(b0) 
{ 
matrix World; 
matrix View; 
matrix Projection; 
}; 

struct VS_INPUT 
{ 
    float3 Pos : POSITION; 
    float3 Norm : NORMAL; 
    float2 Tex : TEXCOORD0; 
}; 

struct GS_INPUT 
{ 
    float4 Pos : POSITION; 
    float4 PosV : TEXCOORD0; 
}; 

GS_INPUT main(VS_INPUT input) 
{ 
GS_INPUT output; 

matrix WorldView = mul(World, View); 
matrix WorldViewProjection = mul(WorldView, Projection); 

output.Pos = mul(float4(input.Pos, 1), WorldViewProjection); 
output.PosV = mul(float4(input.Pos, 1), WorldView); 


return output; 
} 

了GS:

float4 LightVector = float4(0, 0, 1, 0); 
float4 FillColor = float4(0.0f, 0.125f, 0.3f, 1.0f); 

struct GS_INPUT 
{ 
float4 Pos : POSITION; 
float4 PosV : TEXCOORD0; 
}; 

struct PS_INPUT_WIRE 
{ 
float4 Pos : SV_POSITION; 
float4 Col : TEXCOORD0; 
noperspective float3 Heights : TEXCOORD1; 
}; 

// Compute the triangle face normal from 3 points 
float3 faceNormal(in float3 posA, in float3 posB, in float3 posC) 
{ 
return normalize(cross(normalize(posB - posA), normalize(posC - posA))); 
} 

// Compute the final color of a face depending on its facing of the light 
float4 shadeFace(in float4 verA, in float4 verB, in float4 verC) 
{ 
// Compute the triangle face normal in view frame 
float3 normal = faceNormal(verA, verB, verC); 

    // Then the color of the face. 
    float shade = 0.5*abs(dot(normal, LightVector)); 

return float4(FillColor.xyz*shade, 1); 
} 

[maxvertexcount(3)] 
void main(triangle GS_INPUT input[3], inout TriangleStream<PS_INPUT_WIRE> outStream) 
{ 
PS_INPUT_WIRE output; 

// Shade and colour face. 
output.Col = shadeFace(input[0].PosV, input[1].PosV, input[2].PosV); 

// Emit the 3 vertices 
// The Height attribute is based on the constant 
output.Pos = input[0].Pos; 
output.Heights = float3(1, 0, 0); 
outStream.Append(output); 

output.Pos = input[1].Pos; 
output.Heights = float3(0, 1, 0); 
outStream.Append(output); 

output.Pos = input[2].Pos; 
output.Heights = float3(0, 0, 1); 
outStream.Append(output); 

outStream.RestartStrip(); 
} 

和PS:

float4 WireColor = float4(1, 1, 1, 1); 
float LineWidth = 0.15; 
float PatternPeriod = 0.15; 
float4 PatternColor = float4(1, 1, 0.5, 1); 

struct PS_INPUT_WIRE 
{ 
float4 Pos : SV_POSITION; 
float4 Col : TEXCOORD0; 
noperspective float3 Heights : TEXCOORD1; 
}; 

float det(float2 a, float2 b) 
{ 
return (a.x*b.y - a.y*b.x); 
} 

float4 main(PS_INPUT_WIRE input) : SV_Target 
{ 
// Compute the shortest square distance between the fragment and the edges. 
float3 eDists; 
float3 vDists; 
uint3 order = uint3(0, 1, 2); 

    float dist; 

float3 ddxHeights = ddx(input.Heights); 
    float3 ddyHeights = ddy(input.Heights); 
    float3 invddHeights = 1.0/sqrt(ddxHeights*ddxHeights + ddyHeights*ddyHeights); 

    eDists = input.Heights * invddHeights; 
vDists = (1.0 - input.Heights) * invddHeights; 

if (eDists[1] < eDists[0]) 
{ 
    order.xy = order.yx; 
} 
if (eDists[2] < eDists[order.y]) 
{ 
    order.yz = order.zy; 
} 
if (eDists[2] < eDists[order.x]) 
{ 
    order.xy = order.yx; 
} 

// Now compute the coordinate of the fragment along each edges 

float2 hDirs[3]; 
hDirs[0] = float2(ddxHeights[0], ddyHeights[0]) * invddHeights[0]; 
hDirs[1] = float2(ddxHeights[1], ddyHeights[1]) * invddHeights[1]; 
hDirs[2] = float2(ddxHeights[2], ddyHeights[2]) * invddHeights[2]; 

float2 hTans[3]; 
hTans[0] = float2(-hDirs[0].y, hDirs[0].x); 
hTans[1] = float2(-hDirs[1].y, hDirs[1].x); 
hTans[2] = float2(-hDirs[2].y, hDirs[2].x); 

float2 ePoints[3]; 
ePoints[0] = input.Pos.xy - hDirs[0] * eDists[0]; 
ePoints[1] = input.Pos.xy - hDirs[1] * eDists[1]; 
ePoints[2] = input.Pos.xy - hDirs[2] * eDists[2]; 

float2 eCoords[3]; 
eCoords[0].x = det(hTans[1], ePoints[0] - ePoints[1])/det(hTans[0], hTans[1]); 
eCoords[0].y = det(hTans[2], ePoints[0] - ePoints[2])/det(hTans[0], hTans[2]); 

eCoords[1].x = det(hTans[2], ePoints[1] - ePoints[2])/det(hTans[1], hTans[2]); 
eCoords[1].y = det(hTans[0], ePoints[1] - ePoints[0])/det(hTans[1], hTans[0]); 

eCoords[2].x = det(hTans[0], ePoints[2] - ePoints[0])/det(hTans[2], hTans[0]); 
eCoords[2].y = det(hTans[1], ePoints[2] - ePoints[1])/det(hTans[2], hTans[1]); 


float2 edgeCoord; 

// Current coordinate along closest edge in pixels 
edgeCoord.x = abs(eCoords[order.x].x); 
// Length of the closest edge in pixels 
edgeCoord.y = abs(eCoords[order.x].y - eCoords[order.x].x); 

dist = eDists[order.x]; 

// Standard wire color 
float4 color = WireColor; 
    float realLineWidth = 0.5*LineWidth; 

// if on the diagonal edge apply pattern 
if (2 == order.x) 
{ 
    if (dist > LineWidth + 1) discard; 

    float patternPos = (abs(edgeCoord.x - 0.5 * edgeCoord.y)) % (PatternPeriod * 2 * LineWidth) - PatternPeriod * LineWidth; 
    dist = sqrt(patternPos*patternPos + dist*dist); 

    color = PatternColor; 
    realLineWidth = LineWidth; 

    // Filling the corners near the vertices with the WireColor 
    if (eDists[order.y] < (0.5*LineWidth + 1)) 
    { 
     dist = eDists[order.y]; 
     color = WireColor; 
     realLineWidth = 0.5*LineWidth; 
    } 
} 
// Cull fragments too far from the edge. 
else if (dist > 0.5*LineWidth + 1) discard; 

// Map the computed distance to the [0,2] range on the border of the line. 
dist = clamp((dist - (realLineWidth - 1)), 0, 2); 

// Alpha is computed from the function exp2(-2(x)^2). 
dist *= dist; 
float alpha = exp2(-2 * dist); 

color.a *= alpha; 
return color; 
} 

非常直接拷贝有执行。在vs2013中,我将HLSL编译器设置为版本5.0,并输出包含字节码的头文件。

在我的应用程序中,我定义了一个新类{SolidWireFrame.cpp},它使用字节码创建vs,gs和ps头文件。

这些构建vs,gs和ps着色器没有任何异常/我知道的错误。

该效果还设置DepthStencilState,RasterizerState和BlendStates。所以我在我的SolidWireFrame类中创建了复制这些状态的方法。

bool SolidWireFrame::InitializeBlendState(ID3D11Device* device) 
{ 
    D3D11_BLEND_DESC blendStateDescription; 
    // Clear the blend state description. 
    ZeroMemory(&blendStateDescription, sizeof(D3D11_BLEND_DESC)); 
    blendStateDescription.RenderTarget[0].BlendEnable = TRUE; 
    blendStateDescription.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; 
    blendStateDescription.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; 
    blendStateDescription.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; 
    blendStateDescription.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA; 
    blendStateDescription.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA; 
    blendStateDescription.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; 
    blendStateDescription.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; 

    // Create the blend state using the description. 
    HRESULT result = device->CreateBlendState(&blendStateDescription, &m_pBlendingState); 
    if (FAILED(result)) 
    { 
     return false; 
    } 
    return true; 
} 

bool SolidWireFrame::InitializeDepthStencilState(ID3D11Device* device) 
{ 
    D3D11_DEPTH_STENCIL_DESC depthStencilDesc; 
    // Initialize the description of the stencil state. 
    ZeroMemory(&depthStencilDesc, sizeof(depthStencilDesc)); 
    // Set up the description of the stencil state. 
    depthStencilDesc.DepthEnable = TRUE; 
    depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; 
    depthStencilDesc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; 

    depthStencilDesc.StencilEnable = FALSE; 
    depthStencilDesc.StencilReadMask = 255; 
    depthStencilDesc.StencilWriteMask = 255; 
    depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; 
    depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; 
    depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; 
    depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; 
    depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; 
    depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; 
    depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; 
    depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; 

    // Create the depth stencil state. 
    HRESULT result = device->CreateDepthStencilState(&depthStencilDesc, &m_pdepthLessEqualStencilState); 
    if (FAILED(result)) 
    { 
     return false; 
    } 
    return true; 
} 

bool SolidWireFrame::InitializeRaterizerState(ID3D11Device* device) 
{ 
    D3D11_RASTERIZER_DESC rasterizerDescription; 
    ZeroMemory(&rasterizerDescription, sizeof(D3D11_RASTERIZER_DESC)); 
    rasterizerDescription.FillMode = D3D11_FILL_SOLID; 
    rasterizerDescription.CullMode = D3D11_CULL_NONE; 
    rasterizerDescription.DepthBias = FALSE; 
    rasterizerDescription.MultisampleEnable = TRUE; 

    rasterizerDescription.FrontCounterClockwise = FALSE; 
    rasterizerDescription.DepthBiasClamp = 0.000000000; 
    rasterizerDescription.SlopeScaledDepthBias = 0.000000000; 
    rasterizerDescription.DepthClipEnable = TRUE; 
    rasterizerDescription.ScissorEnable = FALSE; 
    rasterizerDescription.AntialiasedLineEnable = FALSE; 

    HRESULT hr = device->CreateRasterizerState(&rasterizerDescription, &m_pfillRasterizerState); 
    if (FAILED(hr)) 
     return false; 
    return true; 
} 

现在在我的渲染循环我只需拨打solidWireFrame-> ApplySolidWirePatter(devicecontext),它能够有效地设置InputLayout,三种状态和VS,GS和PS。

void SolidWireFrame::ApplySolidWirePattern(ID3D11DeviceContext* deviceContext) 
{ 
    deviceContext->IASetInputLayout(m_vertexLayout); 
    SetDepthStencilState(deviceContext, m_pdepthLessEqualStencilState); 
    SetRasterizerState(deviceContext, m_pfillRasterizerState); 
    SetBlendState(deviceContext, m_pBlendingState); 
    deviceContext->VSSetShader(m_vertexShader, NULL, 0); 
    deviceContext->GSSetShader(m_geometrySolidWireShader, NULL, 0); 
    deviceContext->PSSetShader(m_pixelSolidWireShader, NULL, 0); 
} 

但我看到的只是一个清除屏幕。有什么可能是错的?

请大家帮忙。

哦,渲染工作,如果wireframe没有设置。

Normal No WireFrame

回答

0

看来我在我的代码有一个小错误。当我用纹理渲染时,我正在使用不同的vs,ps。所以当我翻转到线框vs,gs和ps我没有更新vs Constantbuffers,其中包含世界,视图,投影。

所以现在我有线框,但我想我的绕线是不正确的,因为它隐藏了不正确的边缘。但我会解决这个问题。

void SolidWireFrame::ApplySolidWirePattern(ID3D11DeviceContext* deviceContext, ID3D11Buffer* worldViewProjectionType) 
{ 


    deviceContext->IASetInputLayout(m_vertexLayout); 
    deviceContext->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 
    SetDepthStencilState(deviceContext, m_pdepthLessEqualStencilState); 
    SetRasterizerState(deviceContext, m_pfillRasterizerState); 
    SetBlendState(deviceContext, m_pBlendingState); 
    deviceContext->VSSetShader(m_vertexShader, NULL, 0); 
    deviceContext->VSSetConstantBuffers(0, 1, &worldViewProjectionType); 
    deviceContext->GSSetShader(m_geometrySolidWireShader, NULL, 0); 
    deviceContext->PSSetShader(m_pixelSolidWireShader, NULL, 0); 
}