Flexible material-shader implementation

Started by
9 comments, last by J. Rakocevic 4 years, 4 months ago

Okay, took me a while because I had a completely out of nowhere bug that made my skybox shake... but this is kind of what I came up with.

void Renderable::updateBuffersAuto(ID3D11DeviceContext* cont) const
{
	for (int i = 0; i < mat->getVS()->_bufferMetaData.size(); i++)
	{
		for (const CBufferFieldDesc& cbfd : mat->getVS()->_bufferMetaData[i]._fields)
		{
			if (cbfd._content == CBUFFER_FIELD_CONTENT::TRANSFORM)
			{
				CBuffer::updateBuffer(cont, mat->getVS()->_cbuffers[i], 
              (UCHAR*)&this->worldTransform.Transpose(), cbfd._size, cbfd._offset);
              }
         }
    }
              
              
    for (int i = 0; i < mat->getPS()->_bufferMetaData.size(); i++)
	{
		for (const CBufferFieldDesc& cbfd : mat->getPS()->_bufferMetaData[i]._fields)
		{
			if (cbfd._content == CBUFFER_FIELD_CONTENT::P_LIGHT)
			{
				CBuffer::updateBuffer(cont, mat->getPS()->_cbuffers[i], (UCHAR*)this->pLight, cbfd._size, cbfd._offset);
			}
		}
	}
}

I do store the buffer in the shader currently (and driver renaming takes care of duplicates) but I understand your reasoning that the buffer data is owned by the entity not the shader, while shader stores the description. I think I'll move it, this is just the draft and, as you can see, only has one option for vs and one for ps (for now) but the idea holds, can maybe make it a switch or a map later if need be. I'm ok with searches since it's at most going to be a few field types. Global buffers (one for proj. matrix at register b10 and one for view matrix, delta time and elapsed time at b11 ) already take some load off of these object-specific cbuffers so they probably won't be too big.

This system is limited to the data that the renderable holds. For other stuff, the material interface provides another function taking a void*, size and the buffer index to just manually send things in to be memcpy-d into stranger buffers.

And this is how I set up my shaders (will be data driven when I get around to define them in json like the other resources... bit lazy on that)

VertexShader* vs = new VertexShader(_sys._shaderCompiler, L"lightvs.hlsl", inLayout, { matrixBufferDesc });
PixelShader* ps = new PixelShader(_sys._shaderCompiler, L"lightps.hlsl", sbSamplerDesc, { lightBufferDesc });

CBufferMeta meta(0, sizeof(SMatrix));
meta._fields.push_back(CBufferFieldDesc(CBUFFER_FIELD_CONTENT::TRANSFORM, 0, sizeof(SMatrix)));
vs->describeBuffers({ meta });

CBufferMeta psmeta(0, sizeof(LightBuffer));
psmeta._fields.push_back(CBufferFieldDesc(CBUFFER_FIELD_CONTENT::P_LIGHT, 0, sizeof(LightBuffer)));
ps->describeBuffers({ psmeta });

Afterwards, renderables are sorted and before drawing them i call these:

r.updateBuffersAuto(_deviceContext);
r.setBuffers(_deviceContext);

For now it works, although it's extremely simple and it might break when some different needs pop up. But that's how it works when you have no experience I guess. Maybe this helps someone in a need for ideas.

This topic is closed to new replies.

Advertisement