Help with 3D camera please

Started by
9 comments, last by DividedByZero 8 years, 6 months ago

Hi guys,

I have created a simple 3D perspective camera for my project. Which is rendering a simple triangle correctly as anticipated.

I am wondering how to go about setting the 'look at' position.

This is my main code:


// CAMERA
XMMATRIX viewMatrix = XMMatrixIdentity();
XMMATRIX projMatrix = XMMatrixPerspectiveFovLH(60.0f * 0.0174533f, float((float)nWidth) / ((float)nHeight), 1.0f, 1000.0f);
viewMatrix = XMMatrixTranspose(viewMatrix);
projMatrix = XMMatrixTranspose(projMatrix);
 
// position the camera
XMMATRIX rotationMatrix = XMMatrixRotationZ(0.0f);
XMMATRIX translationMatrix = XMMatrixTranslation(0.0f, 0.0f, 0.0f);
XMMATRIX worldMat = rotationMatrix*translationMatrix;
worldMat = XMMatrixTranspose(worldMat);
 
d3dContext->UpdateSubresource(worldCB, 0, 0, &worldMat, 0, 0);
d3dContext->UpdateSubresource(viewCB, 0, 0, &viewMatrix, 0, 0);
d3dContext->UpdateSubresource(projCB, 0, 0, &projMatrix, 0, 0);
 
d3dContext->VSSetConstantBuffers(0, 1, &worldCB);
d3dContext->VSSetConstantBuffers(1, 1, &viewCB);
d3dContext->VSSetConstantBuffers(2, 1, &projCB);

This is the vertex part of my shader:

struct VS_Input
{
     float4 pos  : POSITION;
};
 
struct VS_Output
{
     float4 pos  : SV_POSITION;
};
 
VS_Output VShader(VS_Input IN)
{
     VS_Output OUT;
     matrix mvp = mul(projectionMatrix, mul(viewMatrix, worldMatrix));
     OUT.pos = mul(mvp, IN.pos);
     return OUT;
}

A nudge in the right direction would be greatly appreciated.

Thanks in advance smile.png

Advertisement
Again one of those things, where when you take a step back and think the answer reveals itself. rolleyes.gif

I needed to add this to the mix:



XMVECTOR eyePosition = XMVectorSet(0, 0, -20, 1);
XMVECTOR focusPoint = XMVectorSet(0, 0, 0, 1);
XMVECTOR upDirection = XMVectorSet(0, 1, 0, 0);
viewMatrix = XMMatrixLookAtLH(eyePosition, focusPoint, upDirection);
viewMatrix = XMMatrixTranspose(viewMatrix);

[edit]
Although, it seems something still isn't quite right here, as the camera movement isn't what I'd expect. I'll test a few thing out and possibly enquire further smile.png
I found that part of the problem was that I had two of the constant buffers around the wrong way, so they were receiving the wrong matrix data.

After correcting this, I am now not seeing anything rendered to the screen. This is the code that I have at the moment, after a lot of re-working.


cbuffer PerObject : register(b0)
{
	matrix worldMatrix;
}

cbuffer PerFrame : register(b1)
{
	matrix viewMatrix;
}

cbuffer PerApplication : register(b2)
{
	matrix projectionMatrix;
}

struct VS_Input
{
	float4 pos  : POSITION;
};

struct VS_Output
{
	float4 pos  : SV_POSITION;
};

VS_Output VShader(VS_Input IN)
{
	VS_Output OUT;
	matrix mvp = mul(projectionMatrix, mul(viewMatrix, worldMatrix));
	OUT.pos = mul(mvp, IN.pos);

	return OUT;
}

And the main project side of things.


		// Camera
		XMMATRIX projMatrix = XMMatrixPerspectiveFovLH(60.0f * 0.0174533f, float((float)nWidth) / ((float)nHeight), 1.0f, 1000.0f);
		projMatrix = XMMatrixTranspose(projMatrix);

		// Position the camera
		XMVECTOR eyePosition = XMVectorSet(0.0f, 0.0f, -10.0f, 0.0f);
		XMVECTOR focusPoint = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
		XMVECTOR upDirection = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
		XMMATRIX viewMatrix = XMMatrixLookAtLH(eyePosition, focusPoint, upDirection);
		viewMatrix = XMMatrixTranspose(viewMatrix);

		// Position the object at 0,0,0 for the moment
		XMMATRIX translationMatrix = XMMatrixTranslation(0.0f, 0.0f, 0.0f);
		XMMATRIX worldMat = translationMatrix;
		worldMat = XMMatrixTranspose(worldMat);


		// Update and set the contant buffers
		d3dContext->UpdateSubresource(worldCB, 0, 0, &worldMat, 0, 0);
		d3dContext->UpdateSubresource(viewCB, 0, 0, &viewMatrix, 0, 0);
		d3dContext->UpdateSubresource(projCB, 0, 0, &projMatrix, 0, 0);

		d3dContext->VSSetConstantBuffers(0, 1, &worldCB);
		d3dContext->VSSetConstantBuffers(1, 1, &viewCB);
		d3dContext->VSSetConstantBuffers(2, 1, &projCB);

I know that I must be reasonably close. But, if someone could shed an eye over this, that would be awesome smile.png

Try setting projMatrix with a znear lesser than 1.0f, maybe 0.1f or something, and maybe your camera is pointing in the wrong direction for stuff to be seen?

Note: It would be better to keep all matrices in one cbuffer, so you potentially get less UpdateSubresource() calls overall - but not entirely sure.. :)

.:vinterberg:.

Hi there.

Tried both of your suggestions. Positioned the camera at both -20 and +20, and changed the znear value. But the result is still the same unfortunately.

was the triangle always in world space, was the camera previously at origin? I can't see where you create the triangle, so i'm not sure where you *should* find it. what does the view transform look like immediately before being sent to the shader?

EDIT: looking at the original code I'm not sure how you got anything displayed! Both the view and the world transforms were identity matrices. ie the camera and triangle were in the same place, unless the tri verts put it somewhere else (since they would be in world space at that time)

Hi Bunrt_Fyr,

Yeah, I am pretty new to martices. So, I am confident that the problem lies in there somewhere.

Any advice on how it should look would be awesome. I am still trying to get my head around what is happening here. Even though I have been reading up on this since the OP - hehe.

Thanks again smile.png
From the above code, this is what should be happening (in my understanding).

Triangle - 0,0,0
Camera - 0,0,-10
Looking at - 0,0,0

I just can't seem to understand what is going wrong here. sad.png

I have tried the camera at z=10 in case of a culling issue. But to no avail. The triangle is definitely in a RHW winding order.
Turns out the other half of the problem was in the shader.

I have changed the shader to this and the whole scene seems to be working correctly now smile.png


VS_Output VShader(VS_Input IN)
{
	VS_Output OUT = IN;

	OUT.pos = mul(IN.pos, worldMatrix);
	OUT.pos = mul(OUT.pos, viewMatrix);
	OUT.pos = mul(OUT.pos, projectionMatrix);

	return OUT;
}

Turns out the other half of the problem was in the shader.

I have changed the shader to this and the whole scene seems to be working correctly now smile.png


VS_Output VShader(VS_Input IN)
{
	VS_Output OUT = IN;

	OUT.pos = mul(IN.pos, worldMatrix); // transform from model to world space
	OUT.pos = mul(OUT.pos, viewMatrix); // transform from world to camera space
	OUT.pos = mul(OUT.pos, projectionMatrix); // transform from camera to projection space

	return OUT;
}

Sorry i kind of afk'd on the convo here, but I see you solved it. Working your critical thinking skills will payback 10x the effort you put into them. I find myself answering so many more questions than i have to ask now. When I run into an issue, I have the experience, as well as the critical thinking to pinpoint the problem in a fraction of the time that i would have spent even a year ago, so good on you for solving your own problem.

Looking back at the original shader


 matrix mvp = mul(projectionMatrix, mul(viewMatrix, worldMatrix));

should probably have been


 matrix mvp = mul(mul(worldMatrix, viewMatrix), projectionMatrix);

so that the matrices are being concatenated in the right order. An even better idea would be to concatenate those transforms per object on the CPU, and then upload the fully formed model->projection transform(via update subresource) to the shader as a single matrix, so you are not performing all of those muls in the first place.

This topic is closed to new replies.

Advertisement