Advertisement

Beginning DirectX, Ortho?

Started by August 24, 2018 03:37 PM
28 comments, last by JWColeman 6 years, 3 months ago

Okay, so I'm seeing some code in this example that looks like this:

 


/////////////
// GLOBALS //
/////////////
matrix projectionMatrix;

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

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
    VOut output;

    output.position = position;
    output.color = color;

	output.position = mul(output.position, projectionMatrix);

    return output;
}


float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
}

 

This is my updated shaders.shader file....

 

However, projectionMatrix, at this time I understand it to be uninitialized, so output.position = mul(output.position, projectionMatrix); will effectively do nothing, actually I'm pretty sure its what is causing my quad to disappear.

I don't fully understand how my application talks to this "shader" application, as to pass a value to initialize projectionMatrix...

 

Could it have something to do with this bit here?

 


	// create the input layout object
	D3D11_INPUT_ELEMENT_DESC ied[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
	};

	dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);
	devcon->IASetInputLayout(pLayout);

 

My assumption at this time is that I need projectionMatrix in my shader file to be equal to the ortho matrix I set up here: D3DXMatrixOrthoLH(&m_orthoMatrix, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1);

How do I go about doing that?

 

Quote

However, projectionMatrix, at this time I understand it to be uninitialized, so output.position = mul(output.position, projectionMatrix); will effectively do nothing, actually I'm pretty sure its what is causing my quad to disappear.

Quote

My assumption at this time is that I need projectionMatrix in my shader file to be equal to the ortho matrix I set up here: D3DXMatrixOrthoLH(&m_orthoMatrix, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1);

That all sounds correct. (I haven't used Direct3D in a while and I'm not actually sure what the state of uninitialized shader variables is, but only if the matrix has a convenient default like identity would you get a successful result, and I wouldn't be surprised if it has no such default.)

You may already know this, but note that you don't need both of these lines:


output.position = position;

output.position = mul(output.position, projectionMatrix);

Just the last one.

Quote

Could it have something to do with this bit here?

That code appears to establish the vertex format, which is separate from the projection transform.

As for communicating the matrix to the shader, any tutorial that covers shader transforms should show how to do that. Do you have a particular tutorial you're following? If so, if you can post a link, someone can probably point out the relevant bit.

Advertisement

So, this guy in this tutorial here:

 

http://rastertek.com/dx11tut11.html

 

Appears to just casually be able to write:

projectionMatrix = m_orthoMatrix;

However, my other files have no clue of the existance of projectionMatrix, or the struct in which it is held.

 

Shaders.shader


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

 

Quoting this tutorial: http://rastertek.com/dx11tut04.html

Quote

In shader programs you begin with the global variables. These globals can be modified externally from your C++ code. You can use many types of variables such as int or float and then set them externally for the shader program to use. Generally you will put most globals in buffer object types called "cbuffer" even if it is just a single global variable. Logically organizing these buffers is important for efficient execution of shaders as well as how the graphics card will store the buffers. In this example I've put three matrices in the same buffer since I will update them each frame at the same time. 

 

However, after trying to rip the how to part of this tiny explanation out of this tutorial is proving quite difficult...

Okay.... Conceptually, lets see if I have a handle on this....

 

We create this guy:


D3D11_MAPPED_SUBRESOURCE mappedResource;

This will represent our data from our shader.

Then I can make this one:


MatrixBufferType* dataPtr;

Which will be a pointer to a type equivalent to the junk in the shader class

Then I can get a legit pointer to my shader data, through some kind of magic that the D3D11_MAPPED_SUBRESOURCE provides, pData (this is the voodoo part)


dataPtr = (MatrixBufferType*)mappedResource.pData;

Then I can actually set that data:


    dataPtr->world = worldMatrix;    dataPtr->view = viewMatrix;    dataPtr->projection = projectionMatrix;

 

Wouldn't it be nice if we could just include use some kind of managed shader code in our own code? This process is lame imo :D.

Give me a few to see if I can make this work.

1674024213_SHADERnotcompiling.thumb.png.7197aee7f509ef2ba74ef85690689ed0.png

Any idea why my vertex shader is not compiling?

Here is my shader code:


/////////////
// GLOBALS //
/////////////
cbuffer ConstantBuffer
{
	matrix World;
	matrix View;
	matrix Projection;
};

struct VOut
{
    float4 position : SV_POSITION;
	float4 color : COLOR;

};

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
    VOut output;
	output.position = mul(output.position, Projection);
    output.color = color;
    return output;
}


float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
}

 

Probably because you put vertex and pixel shader into the same file. You can actually precompile shaders in Visual Studio (use file extension .fx and include them in the project and choose some HLSL options such as type and version in the file properties) to get more helpful error messages and you don't need to ship the raw code to your players and save game startup time by not compiling the shaders every time the game starts.

https://stackoverflow.com/a/10759416/9593665

See link for some info on loading the shaders.

Advertisement

Okay, so whatever was going on with my shader is resolved now. Sometimes it just takes walking away for a day or so.

 

Currently, I'm trying to figure out what I'm doing wrong here:

 


void Renderer::InitGraphics()
{
	unsigned int bufferNumber;
	// create a square using the VERTEX struct
	Vertex OurVertices[] =
	{
		{ D3DXVECTOR2(-0.5f,-0.5f), D3DXCOLOR(0.5f, 0.0f, 0.0f, 0.5f) },
		{ D3DXVECTOR2(-0.5f,0.5f), D3DXCOLOR(0.0f, 0.5f, 0.0f, 0.5f) },
		{ D3DXVECTOR2(0.5f,0.5f), D3DXCOLOR(0.0f, 0.0f, 0.5f, 0.5f) },
		{ D3DXVECTOR2(-0.5f,-0.5f), D3DXCOLOR(0.5f, 0.0f, 0.0f, 0.5f) },
		{ D3DXVECTOR2(0.5f,0.5f), D3DXCOLOR(0.0f, 0.5f, 0.0f, 0.5f) },
		{ D3DXVECTOR2(0.5f,-0.5f), D3DXCOLOR(0.0f, 0.0f, 0.5f, 0.5f) }
	};

	// create the vertex buffer
	D3D11_BUFFER_DESC bd;
	ZeroMemory(&bd, sizeof(bd));

	bd.Usage = D3D11_USAGE_DYNAMIC;                // write access access by CPU and GPU
	bd.ByteWidth = sizeof(Vertex) * 6;             // size is the VERTEX struct * 3
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;       // use as a vertex buffer
	bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;    // allow CPU to write in buffer

	dev->CreateBuffer(&bd, NULL, &pVBuffer);       // create the buffer


												   //Set up Ortho Matrix
	D3DXMatrixOrthoLH(&m_orthoMatrix, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1);
	D3D11_MAPPED_SUBRESOURCE ms;
	MatrixBufferType* dataPtr;
	D3DXMatrixTranspose(&m_orthoMatrix, &m_orthoMatrix);
	devcon->Map(pVBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &ms);
	bufferNumber = 0;
	// Get a pointer to the data in the constant buffer.
	dataPtr = (MatrixBufferType*)ms.pData;
	dataPtr->projection = m_orthoMatrix;
	devcon->VSSetConstantBuffers(bufferNumber, 1, &pVBuffer);		// Finanly set the constant buffer in the vertex shader with the updated values.
	memcpy(ms.pData, OurVertices, sizeof(OurVertices));                 // copy the data
	devcon->Unmap(pVBuffer, NULL);                                      // unmap the buffer
																  
}

 

My Shader looks like this:


/////////////
// GLOBALS //
/////////////
cbuffer ConstantBuffer
{
	matrix world;
	matrix view;
	matrix projection;
};

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

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
	VOut output;

	output.position = position;
	output.position = mul(output.position, projection);
	output.color = color;

	return output;
}


float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
	return color;
}

 

Now, before anyone says that I don't nee the two output.position = … lines, I'm fully aware.

 

Just if I take away my first line output.position = position; I get a null ptr when compiling the shader.

Which leads me to believe that my output.position = mul(output.position, projection); line is not creating a desired result.

The result is that my code is not drawing the quad as I have instructed it to, or something..


void Renderer::Update(void)
{

	// clear the back buffer to a deep blue
	devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));

	// select which vertex buffer to display
	UINT stride = sizeof(Vertex);
	UINT offset = 0;
	devcon->IASetVertexBuffers(0, 1, &pVBuffer, &stride, &offset);
	// select which primtive type we are using
	devcon->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	// draw the vertex buffer to the back buffer
	devcon->Draw(6, 0);

	// switch the back buffer and the front buffer
	swapchain->Present(0, 0);
}

 

Quote

Just if I take away my first line output.position = position; I get a null ptr when compiling the shader.

What do you mean by a null pointer when compiling the shader? If you're getting a specific error message, perhaps you could post it here.

Hi Zakwayda, I mean when I remove that line from my shader, this function here:


D3DX11CompileFromFile("Shaders.shader", 0, 0, "VShader", "vs_4_0", 0, 0, 0, &VS, 0, 0);

Produces a NULL pointer..

Because when I attempt to 


dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);

It throws an exception and tells me VS is a null pointer

 

By the way, I have rewritten my InitGraphics function, and separated out my setting the vertex buffer and setting the constant buffer, not sure this is right, but its more understandable to me.

 


	struct cBufferData
	{
		D3DXMATRIX world;
		D3DXMATRIX view;
		D3DXMATRIX projection;
	};

void Renderer::InitGraphics()
{
	// create a square using the VERTEX struct
	Vertex OurVertices[] =
	{
		{ D3DXVECTOR2(-0.5f,-0.5f), D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f) },
	{ D3DXVECTOR2(-0.5f,0.5f), D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f) },
	{ D3DXVECTOR2(0.5f,0.5f), D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f) },
	{ D3DXVECTOR2(-0.5f,-0.5f), D3DXCOLOR(1.0f, 0.0f, 0.0f, 1.0f) },
	{ D3DXVECTOR2(0.5f,0.5f), D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f) },
	{ D3DXVECTOR2(0.5f,-0.5f), D3DXCOLOR(0.0f, 0.0f, 1.0f, 1.0f) }
	};


	// create the vertex buffer
	D3D11_BUFFER_DESC vertexBufferDesc;
	ZeroMemory(&vertexBufferDesc, sizeof(vertexBufferDesc));

	vertexBufferDesc.Usage = D3D11_USAGE_DYNAMIC;                // write access access by CPU and GPU
	vertexBufferDesc.ByteWidth = sizeof(Vertex) * 6;             // size is the VERTEX struct * 3
	vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;       // use as a vertex buffer
	vertexBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;    // allow CPU to write in buffer
	dev->CreateBuffer(&vertexBufferDesc, NULL, &pVBuffer);       // create the buffer
	D3D11_MAPPED_SUBRESOURCE ms_Vertex;
	devcon->Map(pVBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &ms_Vertex);
	memcpy(ms_Vertex.pData, OurVertices, sizeof(OurVertices));                 // copy the data
	devcon->Unmap(pVBuffer, NULL);                                      // unmap the buffer
	devcon->VSSetConstantBuffers(NULL, 1, &pVBuffer);       // Finanly set the constant buffer in the vertex shader with the updated values.


	cBufferData* dataPtr;
	D3D11_BUFFER_DESC cBufferDesc;   // create the constant buffer

	ZeroMemory(&cBufferDesc, sizeof(cBufferDesc));

	cBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	cBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
	cBufferDesc.ByteWidth = sizeof(cBufferData);
	cBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
	cBufferDesc.MiscFlags = 0;
	cBufferDesc.StructureByteStride = 0;
	dev->CreateBuffer(&cBufferDesc, NULL, &pCBuffer);       // create the buffer

	D3D11_MAPPED_SUBRESOURCE ms_CBuffer;
	devcon->Map(pCBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &ms_CBuffer);
	D3DXMatrixOrthoLH(&m_orthoMatrix, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 1);
	D3DXMatrixTranspose(&m_orthoMatrix, &m_orthoMatrix);
	dataPtr = (cBufferData*)ms_CBuffer.pData;
	dataPtr->projection = m_orthoMatrix;
	memcpy(ms_CBuffer.pData, &dataPtr, sizeof(cBufferData));
	devcon->Unmap(pCBuffer, NULL);
	devcon->VSSetConstantBuffers(NULL, 1, &pCBuffer);       // Finally set the constant buffer in the vertex shader with the updated values.
}

I'm really desperate for a comment on the above code, am I performing all the steps correctly to set the buffer data? ^^^^^^^^^^^

 

Current Shader Code:


/////////////
// GLOBALS //
/////////////
cbuffer ConstantBuffer
{
	matrix world;
	matrix view;
	matrix projection;
};

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

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
    VOut output;

    output.position = position;
	output.position = mul(output.position, projection);
    output.color = color;

    return output;
}


float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
}

 

Unfortunately I'm not using Direct3D currently and haven't for quite a while, so I may not be able to help with the particulars of your problem.

I do have a suggestion though. If I were you I'd try to find a simple, self-contained tutorial with complete working source code that does the basics (renders a simple primitive with a matrix transform, etc.). Get a project working from it, copy-pasting or using the code verbatim if needed. Assuming you can get it working, then you'll have some reference code that you know works (assuming the tutorial is sound). You can then try to build your own code from there, and if things go wrong, you'll have working code to check against.

Anyway, just a suggestion. (Of course it's also possible someone who's up to speed with Direct3D will be able to answer your question here.)

This topic is closed to new replies.

Advertisement