赞
踩
略
E 2 = P A 2 = P A 1 cos θ = E 1 cos θ = E 1 ( n ⋅ L ) E_2 = \frac{P}{A_2} = \frac{P}{A_1} \cos \theta = E_1 \cos \theta = E_1 (\mathbf{n} \cdot \mathbf{L}) E2=A2P=A1Pcosθ=E1cosθ=E1(n⋅L)
c d = max ( L ⋅ n , 0 ) ⋅ B L ⊗ m d \mathbf{c}_d = \max(\mathbf{L} \cdot \mathbf{n}, 0) \cdot \mathbf{B}_L \otimes \mathbf{m}_d cd=max(L⋅n,0)⋅BL⊗md
c a = A L ⊗ m d \mathbf{c}_a = \mathbf{A}_L \otimes \mathbf{m}_d ca=AL⊗md
R F ( θ i ) = R F ( 0 ) + ( 1 − R F ( 0 ) ) ( 1 − cos ( θ i ) ) 5 \mathbf{R}_F(\theta_i) = \mathbf{R}_F(0) + (1 - \mathbf{R}_F(0)) (1 - \cos(\theta_i))^5 RF(θi)=RF(0)+(1−RF(0))(1−cos(θi))5
S ( θ h ) = m + 8 8 cos m ( θ h ) = m + 8 8 ( n ⋅ h ) m S(\theta_h) = \frac{m+8}{8} \cos^m (\theta_h) = \frac{m+8}{8} (\mathbf{n} \cdot \mathbf{h})^m S(θh)=8m+8cosm(θh)=8m+8(n⋅h)m
c s = max ( L ⋅ n , 0 ) ⋅ B L ⊗ R F ( α h ) m + 8 8 ( n ⋅ h ) m \mathbf{c}_s = \max(\mathbf{L} \cdot \mathbf{n}, 0) \cdot \mathbf{B}_L \otimes R_F(\alpha_h) \frac{m+8}{8} (\mathbf{n} \cdot \mathbf{h})^m cs=max(L⋅n,0)⋅BL⊗RF(αh)8m+8(n⋅h)m
c = c a + c d + c s \mathbf{c} = \mathbf{c}_a + \mathbf{c}_d + \mathbf{c}_s c=ca+cd+cs
max ( cos ( ϕ ) , 0 ) s \max(\cos(\phi), 0)^s max(cos(ϕ),0)s
struct Light {
XMFLOAT3 Strenth; // 光强(颜色)
float FalloffStart; // 线性衰减替代二次衰减,开始衰减位置(仅点光源和聚光源)
XMFLOAT3 Direction; // 光照方向(仅平行光和聚光源)
float FalloffEnd; // 终止衰减位置(仅点光源和聚光源)
XMFLOAT3 Position; // 位置(仅点光源和聚光源)
float SpotPower; // 聚光衰减系数(仅聚光源)
};
CD3DX12_ROOT_PARAMETER slotRootParameter[4];
// 初始化root parameter
// ......
array<const CD3DX12_STATIC_SAMPLER_DESC, 6> staticSamplers;
// 填写静态sampler结构
// ......
CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(4, slotRootParameter,
(UINT)staticSamplers.size(), staticSamplers.data(),
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
// 创建root signature
// ......
Texture2D gDiffuseMap : register(t0);
SamplerState gsamPointWrap : register(s0);
float4 diffuseAlbedo = gDiffuseMap.Sample(gsamPointWrap, pin.TexC) * gDiffuseAlbedo;
C = ( C d s t ⊗ F d s t ) ⊕ ( C s r c ⊗ F s r c ) C = (C_{dst} \otimes F_{dst}) \oplus (C_{src} \otimes F_{src}) C=(Cdst⊗Fdst)⊕(Csrc⊗Fsrc)
mPsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
typedef struct D3D12_BLEND_DESC { // 在多重采样中,将采样点的alpha纳入考虑中,从而达到柔和边缘的作用, // 在绘制叶子、草时较为有用 // 参考:https://blog.csdn.net/leonwei/article/details/53099634 BOOL AlphaToCoverageEnable; // 默认为False // Direct3D支持同时渲染八个对象,它们的融合系数和运算都不同; // 若关闭,则多个对象都使用第一个元素的参数 BOOL IndependentBlendEnable; // 默认为False D3D11_RENDER_TARGET_BLEND_DESC RenderTarget[8]; } D3D11_BLEND_DESC; typedef struct D3D12_RENDER_TARGET_BLEND_DESC { // 前两个只有一个可以为true BOOL BlendEnable; // 默认为False BOOL LogicOpEnable; // 默认为False D3D12_BLEND SrcBlend; // 默认为D3D12_BLEND_ONE D3D12_BLEND DstBlend; // 默认为D3D12_BLEND_ZERO D3D12_BLEND_OP BlendOp; // 默认为D3D12_BLEND_OP_ADD D3D12_BLEND SrcBlendAlpha; // 默认为D3D12_BLEND_ONE D3D12_BLEND DstBlendAlpha; // 默认为D3D12_BLEND_ZERO D3D12_BLEND_OP BlendOpAlpha; // 默认为D3D12_BLEND_OP_AD D3D12_LOGIC_OP LogicOp; // 默认为D3D12_LOGIC_OP_NOOP // 可以选择只融合某一个或某几个RGBA通道 UINT8 RenderTargetWriteMask; // 默认为D3D12_COLOR_WRITE_ENABLE_ALL }
C f o g = C d s t + s ( C f o g − C d s t ) C_{fog} = C_{dst} + s(C_{fog} - C_{dst}) Cfog=Cdst+s(Cfog−Cdst)
KaTeX parse error: Undefined control sequence: \mbox at position 5: s = \̲m̲b̲o̲x̲{saturate} \lef…
if (comp(StencilRef & StencilReadMask, Value & StencilReadMask))
// accept pixel
else // reject pixel
typedef struct D3D12_DEPTH_STENCIL_DESC { // 是否启用depth buffer,如果为false,则DepthWriteMask无效 BOOL DepthEnable; // 默认:true // D3D11_DEPTH_WRITE_MASK_ZERO:禁止写入depth buffer,但仍depth test // D3D11_DEPTH_WRITE_MASK_ALL:允许写入,通过depth test和stencil test才能绘制 D3D12_DEPTH_WRITE_MASK DepthWriteMask; // 默认:D3D11_DEPTH_WRITE_MASK_ALL D3D12_COMPARISON_FUNC DepthFunc; // 默认:D3D11_COMPARISON_LESS // 是否启用stencil buffer BOOL StencilEnable; // 默认:false // 读取时的掩码,在stencil test中使用 UINT8 StencilReadMask; // 默认:0xff // 写入时的掩码 UINT8 StencilWriteMask; // 默认:0xff // 前面和后面使用stencil buffer的方法 D3D12_DEPTH_STENCILOP_DESC FrontFace; D3D12_DEPTH_STENCILOP_DESC BackFace; } D3D12_DEPTH_STENCIL_DESC; typedef struct D3D12_DEPTH_STENCILOP_DESC { D3D12_STENCIL_OP StencilFailOp; // 默认:D3D12_STENCIL_OP_KEEP D3D12_STENCIL_OP StencilDepthFailOp; // 默认:D3D12_STENCIL_OP_KEEP D3D12_STENCIL_OP StencilPassOp; // 默认:D3D12_STENCIL_OP_KEEP D3D12_COMPARISON_FUNC StencilFunc; // 默认:D3D12_COMPARISON_ALWAYS } D3D12_DEPTH_STENCILOP_DESC; typedef enum D3D12_STENCIL_OP { D3D12_STENCIL_OP_KEEP, // 不修改stencil buffer的值 xxx_ZERO, // stencil buffer设置为0 xxx_REPLACE, // 使用StencilRef的值进行替换 xxx_INCR_SAT, // stencil buffer值加一,直到最大值 xxx_DECR_SAT, // stencil buffer值减一,直到最小值 xxx_INVERT, // stencil buffer的值取逆 xxx_INCR, // stencil buffer值加一,到最大值继续增加溢出到最小值 xxx_DECR, // stencil buffer值减一,到最小值继续减小溢出到最大值 } D3D12_STENCIL_OP;
for (UINT i=0; i<numTriangles; ++i) {
OutputPrimitiveList = GeometryShader(T[i].vertexList);
}
[maxvertexcount(N)]
void ShaderName(
PrimitiveType InputVertexType InputName[NumElements],
inout StreamOutputObject<OutputVertexType> OutputName) {
// 代码主体
}
struct VertexOut { float3 PosL : POSITION; float3 NormalL : NORMAL; float2 Tex : TEXCOORD; }; struct GeoOut { float4 PosH : SV_POSITION; float3 PosW : POSITION; float3 NormalW : NORMAL; float3 Tex : TEXCOORD; float2 FogLerp : FOG; }; // 顶点为0-1-2的三角形,0-1中点为m0,1-2中点为m1,0-2中点为m2 void Subdivide(VertexOut inVerts[3], out VertexOut outVerts[6]) { VertexOut m[3]; m[0].PosL = 0.5f * (inVerts[0].PosL + inVerts[1].PosL); m[1].PosL = 0.5f * (inVerts[1].PosL + inVerts[2].PosL); m[2].PosL = 0.5f * (inVerts[2].PosL + inVerts[0].PosL); // 投影到圆上 m[0].PosL = normalize(m[0].PosL); m[1].PosL = normalize(m[1].PosL); m[2].PosL = normalize(m[2].PosL); m[0].NormalL = m[0].PosL; m[1].NormalL = m[1].PosL; m[2].NormalL = m[2].PosL; m[0].Tex = 0.5f * (inVerts[0].Tex + inVerts[1].Tex); m[1].Tex = 0.5f * (inVerts[1].Tex + inVerts[2].Tex); m[2].Tex = 0.5f * (inVerts[2].Tex + inVerts[0].Tex); outVerts[0] = inVerts[0]; outVerts[1] = m[0]; outVerts[2] = m[2]; outVerts[3] = m[1]; outVerts[4] = inVerts[2]; outVerts[5] = inVerts[1]; } void OutputSubdivision(VertexOut v[6], inout TriangleStream<GeoOut> triStream) { GeoOut gout[6]; [unroll] for (int i=0; i<6; ++i) { // 转换到世界坐标 gout[i].PosW = mul(float4(v[i].PosL, 1.0f), gWorld).xyz; gout[i].NormalW = mul(v[i].NormalL, (float3x3)gWorldInvTranspose); // 转换到裁剪坐标 gout[i].PosH = mul(float4(v[i].PosL, 1.0f), gWorldViewProj); gout[i].Tex = v[i].Tex; } // 1 // m0 m1 // 0 m2 2 // 将三角形按照triangle strips的方式排列到triStream中 // 注意,上述4个三角形不可能由一个strip完成,因此需要restart,用两个strip组合 // 第一个是0-m0-m2-m1-2,第二个是m0-1-m1 [unroll] for (int j=0; j<5; ++j) { triStream.Append(gout[j]); } triStream.RestartStrip(); triStream.Append(gout[1]); triStream.Append(gout[5]); triStream.Append(gout[3]); } [maxvertexcount(8)] void GS(triangle VertexOut gin[3], inout TriangleStream<GeoOut>) { VertexOut v[6]; Subdivide(gin, v); OutputSubdivision(v, triStream); }
[maxvertexcount(4)]
void GS(point VertexOut gin[1],
uint primID : SV_PrimitiveID,
inout TriangleStream<GeoOut> triStream)
cbuffer cbSettings {
// compute shader可以从constant buffer中获取值
};
Texture2D gInputA;
Texture2D gInputB;
RWTexture2D<float4> gOutput;
// 一个thread group中thread的数量
[numthreads(16,16,1)]
void CS(int3 dispatchThreadID : SV_DispatchThreadID) {
gOutput[dispatchThreadID.xy] = gInputA[dispatchThreadID.xy] + gInputB[dispatchThreadID.xy];
}
ThrowIfFailed(md3dDevice->CreateCommitedResource( &CD3DX12_HEAP_PEOPERTIES(D3D12_HEAP_TYPE_READBACK), D3D12_HEAP_FLAG_NONE, &CD3DX12_RESOURCE_DESC::Buffer(byteSize), D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&mReadBackBuffer))); // 完成computer shader计算,保存在mOutputBuffer中 mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mOutputBuffer.Get(), D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_COPY_SOURCE)); mCommandList->CopyResource(mReadBackBuffer.Get(), mOutputBuffer.Get()); mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mOutputBuffer.Get(), D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_COMMON)); // 关闭mCommandList,等待command执行完成 FlushCommandQueue(); Data* mappedData = nullptr; ThrowifFailed( mReadBackBuffer->Map(0, nullptr, reinterpret<void**>(&mappedData))); // 使用数据 mReadBackBuffer->Unmap(0, nullptr);
( 1 , 1 , 0 ) ⊗ ( 8 , 8 , 0 ) + ( 2 , 5 , 0 ) = ( 10 , 13 , 0 ) (1,1,0) \otimes (8,8,0) + (2,5,0) = (10,13,0) (1,1,0)⊗(8,8,0)+(2,5,0)=(10,13,0)
* SV_GroupIndex为1*3+1=4
struct Particle {
float3 Position, Velocity, Acceleration;
};
float TimeStep = 1.0f / 60.0f;
ConsumeStructuredBuffer<Particle> gInput;
AppendStructuredBuffer<Particle> gOutput;
[numthreads(16, 16, 1)]
void CS() {
Particle p = gInput.Consume();
// 计算p
// ......
gOutput.Append(p);
}
groupshared float4 gCache[256];
Texture2D gInput;
RWTexture2D<float4> gOutput;
groupshared float4 gCache[256];
[numthreads(256, 1, 1)]
void CS(int3 groupThreadID : SV_GroupThreadID,
int3 dispatchThreadID : SV_DispatchThreadID) {
// 每个线程先采样,保存到共享内存中
gCache[groupThreadID.x] = gInput[dispatchThreadID.xy];
// 如果直接进行运算,则无法保证其他thread已经完成采样的工作,因此这里需要先进行同步
GroupMemoryBarrierWithGroupSync();
// 其他运算
// ......
}
struct PatchTess { // 决定了四边形的四条边如何细分 float EdgeTess[4] : SV_TessFactor; // 决定四边形的内部(二维流形,因此只有u轴和v轴,水平/竖直)如何细分 float InsideTess[2] : SV_InsideTessFactor; // 以及其他vertex shader传出的数据 }; PatchTess ConstantHS(InputPatch<VertexOut, 4> patch, // 四个控制点 uint patchID : SV_PrimitiveID // 第几个patch ) { PatchTess pt; // 均匀细分3次 pt.EdgeTess[0] = 3; // 左边 pt.EdgeTess[1] = 3; // 上边 pt.EdgeTess[2] = 3; // 右边 pt.EdgeTess[3] = 3; // 下边 pt.InsideTess[0] = 3; // u轴 pt.InsideTess[1] = 3; // v轴 return pt; }
struct HullOut { float3 PosL : POSITION; }; [domain("quad")] // patch类型,可以是tri,quad和isoline [partitioning("integer")] // 分割模式,integer表示新的顶点只会增加在整数tessellation factor的位置,fractional_even/fractional_odd表示新的顶点会增加在整数位置,但稍稍偏移,这适用于细分数慢慢增加或减少时,可以平滑过渡,而不会发生跳变 [outputtopology("triangle_cw")] // 输出拓扑:triangle_cw表示顺时针三角形,triangle_ccw表示逆时针三角形,line表示线细分 [outputcontrolpoints(4)] // 一共输出4个控制点,由于每个输出控制点运行一次,因此整个shader运行了4次 [patchconstantfunc("ConstantHS")] // 指定constant hull shader名称 [maxtessfactor(64.0f)] // 最大tessellation factor PHullOut HS(InputPatch<VertexOut, 4> p, uint i : SV_OutputControlPointID, // 输出控制点ID uint patchId : SV_PrimitiveID ) { HullOut hout; hout.PosL = p[i].PosL; return hout; }
struct DomainOut { float4 PosH : SV_POSITION; }; [domain("quad")] DomainOut DS(PatchTess patchTess, float2 uv : SV_DomainLocation, const OutputPatch<HullOut, 4> quad ) { DomainOut dout; // 双线性插值 float3 v1 = lerp(quad[0].PosL, quad[1].PosL, uv.x); float3 v2 = lerp(quad[2].PosL, quad[3].PosL, uv.x); float3 p = lerp(v1, v2, uv.y); float4 posW = mul(float4(p, 1.0f), gWorld); dout.PosH = mul(posW, gViewProj); return dout; }
struct VertexIn { float3 PosL : POSITION; }; struct VertexOut { float3 PosL : POSITION; }; VertexOut VS(VertexIn vin) { VertexOut vout; vout.PosL = vin.PosL; return vout; } struct PatchTess { float EdgeTess[4] : SV_TessFactor; float InsideTess[2] : SV_InsideTessFactor; }; PatchTess ConstantHS(InputPatch<VertexOut, 4> patch, uint patchID : SV_PrimitiveID) { PatchTess pt; // 测量摄像机与物体的距离 float3 centerL = 0.25 * (patch[0].PosL + ... + patch[3].PosL); float3 centerW = mul(float4(centerL, 1.0f), gWorld).xyz; float d = distance(centerW, gEyePosW); // 在最近距离和最远距离之间,按0-64插值 const float d0 = 20.0f, d1 = 100.0f; float tess = 64.0f * saturate( (d1-d)/(d1-d0) ); // 均匀细分 pt.EdgeTess[0] = ... = pt.EdgeTess[3] = tess; pt.InsideTess[0] = pt.InsideTess[1] = tess; return pt; } struct HullOut { float3 PosL : POSITION; }; [domain("quad")] [partitioning("integer")] [outputtopology("triangle_cw")] [outputcontrolpoints(4)] [patchconstantfunc("ConstantHS")] [maxtessfactor(64.0f)] PHullOut HS(InputPatch<VertexOut, 4> p, uint i : SV_OutputControlPointID, // 输出控制点ID uint patchId : SV_PrimitiveID ) { HullOut hout; hout.PosL = p[i].PosL; return hout; } struct DomainOut { float4 PosH : SV_POSITION; }; [domain("quad")] DomainOut DS(PatchTess patchTess, float2 uv : SV_DomainLocation, const OutputPatch<HullOut, 4> quad ) { DomainOut dout; // 双线性插值 float3 v1 = lerp(quad[0].PosL, quad[1].PosL, uv.x); float3 v2 = lerp(quad[2].PosL, quad[3].PosL, uv.x); float3 p = lerp(v1, v2, uv.y); // 山峦位移 p.y = 0.3f * (p.z * sin(p.x)+ p.x * sin(p.z)); float4 posW = mul(float4(p, 1.0f), gWorld); dout.PosH = mul(posW, gViewProj); return dout; } float4 PS(DomainOut pin) : SV_Target { return float4(1.0f, 1.0f, 1.0f, 1.0f); }
q
0
(
u
)
=
B
0
3
(
u
)
p
0
,
0
+
B
1
3
(
u
)
p
0
,
1
+
B
2
3
(
u
)
p
0
,
2
+
B
3
3
(
u
)
p
0
,
3
q
1
(
u
)
=
B
0
3
(
u
)
p
1
,
0
+
B
1
3
(
u
)
p
1
,
1
+
B
2
3
(
u
)
p
1
,
2
+
B
3
3
(
u
)
p
1
,
3
q
2
(
u
)
=
B
0
3
(
u
)
p
2
,
0
+
B
1
3
(
u
)
p
2
,
1
+
B
2
3
(
u
)
p
2
,
2
+
B
3
3
(
u
)
p
2
,
3
q
3
(
u
)
=
B
0
3
(
u
)
p
3
,
0
+
B
1
3
(
u
)
p
3
,
1
+
B
2
3
(
u
)
p
3
,
2
+
B
3
3
(
u
)
p
3
,
3
p ( u , v ) = B 0 3 ( u ) q 0 ( u ) + B 1 3 ( u ) q 1 ( u ) + B 2 3 ( u ) q 2 ( u ) + B 3 3 ( u ) q 3 ( u ) p(u,v) = B_0^3(u) q_0(u) + B_1^3(u) q_1(u) + B_2^3(u) q_2(u) + B_3^3(u) q_3(u) p(u,v)=B03(u)q0(u)+B13(u)q1(u)+B23(u)q2(u)+B33(u)q3(u)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。