1 //
2 // Copyright 2015 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24
25 #include "d3d11ControlMeshDisplay.h"
26 #include "../common/d3d11Utils.h"
27
28 #include <vector>
29
30 #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } }
31
32 static const char *s_VS =
33 "cbuffer cbPerFrame : register( b0 ) { matrix g_mViewProjection; }; \n"
34 "struct vertexIn { float3 pos : POSITION0; float sharpness : COLOR0; }; \n"
35 "struct vertexOut { float4 pos : SV_POSITION; float sharpness : COLOR0; }; \n"
36 "vertexOut vs_main(vertexIn IN) { \n"
37 " vertexOut vout; \n"
38 " vout.pos = mul(g_mViewProjection, float4(IN.pos, 1)); \n"
39 " vout.sharpness = IN.sharpness; \n"
40 " return vout; \n"
41 "} \n";
42
43 static const char *s_PS =
44 "struct pixelIn { float4 pos : SV_POSITION; float sharpness : COLOR0; }; \n"
45 "Buffer<float> edgeSharpness : register(t0); \n"
46 "float4 sharpnessToColor(float s) { \n"
47 " // 0.0 2.0 4.0 \n"
48 " // green --- yellow --- red \n"
49 " return float4(min(1, s * 0.5), \n"
50 " min(1, 2 - s * 0.5), \n"
51 " 0, 1); \n"
52 "} \n"
53 "float4 ps_main(pixelIn IN, uint primitiveID : SV_PrimitiveID) \n"
54 " : SV_Target { \n"
55 " float sharpness = edgeSharpness[primitiveID]; \n"
56 " return sharpnessToColor(sharpness); \n"
57 "} \n";
58
59 namespace {
60 struct CB_CONTROL_MESH_DISPLAY
61 {
62 float mViewProjection[16];
63 };
64 };
65
D3D11ControlMeshDisplay(ID3D11DeviceContext * deviceContext)66 D3D11ControlMeshDisplay::D3D11ControlMeshDisplay(
67 ID3D11DeviceContext *deviceContext) :
68 _displayEdges(true), _displayVertices(false),
69 _deviceContext(deviceContext), _inputLayout(0), _vertexShader(0),
70 _pixelShader(0), _rasterizerState(0), _constantBuffer(0),
71 _edgeSharpnessSRV(0), _edgeSharpness(0), _edgeIndices(0),
72 _numEdges(0), _numPoints(0) {
73 }
74
~D3D11ControlMeshDisplay()75 D3D11ControlMeshDisplay::~D3D11ControlMeshDisplay() {
76 SAFE_RELEASE(_inputLayout);
77 SAFE_RELEASE(_vertexShader);
78 SAFE_RELEASE(_pixelShader);
79 SAFE_RELEASE(_rasterizerState);
80 SAFE_RELEASE(_constantBuffer);
81 SAFE_RELEASE(_edgeSharpness);
82 SAFE_RELEASE(_edgeSharpnessSRV);
83 SAFE_RELEASE(_edgeIndices);
84 }
85
86 bool
createProgram()87 D3D11ControlMeshDisplay::createProgram() {
88 ID3D11Device *device = NULL;
89 _deviceContext->GetDevice(&device);
90
91 ID3DBlob* pVSBlob;
92 ID3DBlob* pPSBlob;
93 pVSBlob = D3D11Utils::CompileShader(s_VS, "vs_main", "vs_4_0");
94 pPSBlob = D3D11Utils::CompileShader(s_PS, "ps_main", "ps_4_0");
95 assert(pVSBlob);
96 assert(pPSBlob);
97
98 D3D11_INPUT_ELEMENT_DESC inputElementDesc[] = {
99 { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
100 D3D11_INPUT_PER_VERTEX_DATA, 0 },
101 { "COLOR", 0, DXGI_FORMAT_R32_FLOAT, 0, sizeof(float)*3,
102 D3D11_INPUT_PER_VERTEX_DATA, 0 },
103 };
104 device->CreateInputLayout(inputElementDesc, ARRAYSIZE(inputElementDesc),
105 pVSBlob->GetBufferPointer(),
106 pVSBlob->GetBufferSize(),
107 &_inputLayout);
108 assert(_inputLayout);
109
110 device->CreateVertexShader(pVSBlob->GetBufferPointer(),
111 pVSBlob->GetBufferSize(),
112 NULL, &_vertexShader);
113 assert(_vertexShader);
114
115 device->CreatePixelShader(pPSBlob->GetBufferPointer(),
116 pPSBlob->GetBufferSize(),
117 NULL, &_pixelShader);
118 assert(_pixelShader);
119
120 D3D11_RASTERIZER_DESC rasDesc;
121 rasDesc.FillMode = D3D11_FILL_SOLID;
122 rasDesc.CullMode = D3D11_CULL_NONE;
123 rasDesc.FrontCounterClockwise = FALSE;
124 rasDesc.DepthBias = 0;
125 rasDesc.DepthBiasClamp = 0;
126 rasDesc.SlopeScaledDepthBias = 0.0f;
127 rasDesc.DepthClipEnable = FALSE;
128 rasDesc.ScissorEnable = FALSE;
129 rasDesc.MultisampleEnable = FALSE;
130 rasDesc.AntialiasedLineEnable = FALSE;
131 device->CreateRasterizerState(&rasDesc, &_rasterizerState);
132 assert(_rasterizerState);
133
134 // constant buffer
135 D3D11_BUFFER_DESC cbDesc;
136 cbDesc.Usage = D3D11_USAGE_DYNAMIC;
137 cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
138 cbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
139 cbDesc.MiscFlags = 0;
140 cbDesc.ByteWidth = sizeof(CB_CONTROL_MESH_DISPLAY);
141
142 device->CreateBuffer(&cbDesc, NULL, &_constantBuffer);
143 assert(_constantBuffer);
144 return true;
145 }
146
147
148 void
Draw(ID3D11Buffer * buffer,int stride,const float * modelViewProjectionMatrix)149 D3D11ControlMeshDisplay::Draw(ID3D11Buffer *buffer, int stride,
150 const float *modelViewProjectionMatrix) {
151
152 if (_displayEdges == false && _displayVertices == false) return;
153
154 if (_vertexShader == NULL) createProgram();
155 if (_vertexShader == NULL) return;
156
157 UINT hStrides = stride*sizeof(float);
158 UINT hOffsets = 0;
159 _deviceContext->IASetVertexBuffers(0, 1, &buffer, &hStrides, &hOffsets);
160
161 D3D11_MAPPED_SUBRESOURCE MappedResource;
162 _deviceContext->Map(_constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedResource);
163 CB_CONTROL_MESH_DISPLAY * pData = (CB_CONTROL_MESH_DISPLAY *)MappedResource.pData;
164 memcpy(pData->mViewProjection, modelViewProjectionMatrix, sizeof(float) * 16);
165 _deviceContext->Unmap(_constantBuffer, 0);
166
167 _deviceContext->IASetInputLayout(_inputLayout);
168 _deviceContext->VSSetShader(_vertexShader, NULL, 0);
169 _deviceContext->HSSetShader(NULL, NULL, 0);
170 _deviceContext->DSSetShader(NULL, NULL, 0);
171 _deviceContext->GSSetShader(NULL, NULL, 0);
172 _deviceContext->PSSetShaderResources(0, 1, &_edgeSharpnessSRV);
173 _deviceContext->PSSetShader(_pixelShader, NULL, 0);
174 _deviceContext->RSSetState(_rasterizerState);
175 _deviceContext->VSSetConstantBuffers(0, 1, &_constantBuffer);
176
177 if (_displayEdges) {
178 _deviceContext->IASetIndexBuffer(_edgeIndices, DXGI_FORMAT_R32_UINT, 0);
179 _deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
180 _deviceContext->DrawIndexed(_numEdges * 2, 0, 0);
181 }
182 if (_displayVertices) {
183 // TODO: need geometry shader to draw bigger points
184 _deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST);
185 _deviceContext->Draw(_numPoints, 0);
186 }
187
188 }
189
190 void
SetTopology(OpenSubdiv::Far::TopologyLevel const & level)191 D3D11ControlMeshDisplay::SetTopology(
192 OpenSubdiv::Far::TopologyLevel const &level) {
193 int nEdges = level.GetNumEdges();
194 int nVerts = level.GetNumVertices();
195
196 std::vector<int> edgeIndices;
197 std::vector<float> edgeSharpnesses;
198 std::vector<float> vertSharpnesses;
199
200 edgeIndices.reserve(nEdges * 2);
201 edgeSharpnesses.reserve(nEdges);
202 vertSharpnesses.reserve(nVerts);
203
204 for (int i = 0; i < nEdges; ++i) {
205 OpenSubdiv::Far::ConstIndexArray verts = level.GetEdgeVertices(i);
206 edgeIndices.push_back(verts[0]);
207 edgeIndices.push_back(verts[1]);
208 edgeSharpnesses.push_back(level.GetEdgeSharpness(i));
209 }
210
211 for (int i = 0; i < nVerts; ++i) {
212 vertSharpnesses.push_back(level.GetVertexSharpness(i));
213 }
214
215 _numEdges = nEdges;
216 _numPoints = nVerts;
217
218 ID3D11Device *device = NULL;
219 _deviceContext->GetDevice(&device);
220
221 SAFE_RELEASE(_edgeIndices);
222 // create edge index buffer
223 D3D11_BUFFER_DESC bufferDesc;
224 ZeroMemory(&bufferDesc, sizeof(bufferDesc));
225 bufferDesc.ByteWidth = (int)edgeIndices.size() * sizeof(int);
226 bufferDesc.Usage = D3D11_USAGE_DEFAULT;
227 bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
228 bufferDesc.CPUAccessFlags = 0;
229 bufferDesc.MiscFlags = 0;
230 bufferDesc.StructureByteStride = sizeof(int);
231
232 D3D11_SUBRESOURCE_DATA subData;
233 ZeroMemory(&subData, sizeof(subData));
234 subData.pSysMem = &edgeIndices[0];
235 subData.SysMemPitch = 0;
236 subData.SysMemSlicePitch = 0;
237
238 HRESULT hr = device->CreateBuffer(&bufferDesc, &subData, &_edgeIndices);
239 assert(_edgeIndices);
240
241 // edge sharpness
242 SAFE_RELEASE(_edgeSharpness);
243 SAFE_RELEASE(_edgeSharpnessSRV);
244 ZeroMemory(&bufferDesc, sizeof(bufferDesc));
245 bufferDesc.ByteWidth = (int)edgeSharpnesses.size() * sizeof(float);
246 bufferDesc.Usage = D3D11_USAGE_DEFAULT;
247 bufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
248 bufferDesc.CPUAccessFlags = 0;
249 bufferDesc.MiscFlags = 0;
250 bufferDesc.StructureByteStride = sizeof(float);
251
252 ZeroMemory(&subData, sizeof(subData));
253 subData.pSysMem = &edgeSharpnesses[0];
254 subData.SysMemPitch = 0;
255 subData.SysMemSlicePitch = 0;
256
257 hr = device->CreateBuffer(&bufferDesc, &subData, &_edgeSharpness);
258 assert(_edgeSharpness);
259
260 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
261 ZeroMemory(&srvDesc, sizeof(srvDesc));
262 srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
263 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
264 srvDesc.Buffer.NumElements = _numEdges;
265 hr = device->CreateShaderResourceView(_edgeSharpness, &srvDesc, &_edgeSharpnessSRV);
266 assert(_edgeSharpnessSRV);
267 }
268
269