DirectX11 Shader issue (DX11, HLSL, C++)

Started by
4 comments, last by Beosar 9 years ago

RESOLVED: Constant buffers were set for VS and not for PS

I am currently having issues with HLSL shaders. I am trying to implement point lights but I am getting unusual data when debugging the shader in Visual Studio.

I have read on several sites that say that the data stored in CBuffers should be aligned to 4 bytes, thus I added padding where it was needed (is this correct?).

When I set the data in c++, some of it comes through alright but other data is not. For example the color comes through alright but the range is being displayed as NaN or just zeros in the VS graphics debugger.

Is there something wrong with the code below? (All structs are the same as those in c++ structs)

Please ask if there is anything else you would like to see code wise. Thanks!

All the code is stored in a file called buffers.hlsl which is included by the separate shaders i.e. poingLight.vs/.ps include it and make a call to calcPointLight passing in there normal calculations etc...

Lighting Shader:


//Structs

struct BaseLight
{
	float4 color;
	float intensity;

	float3 padding3; //TEST
};

struct DirectionalLight
{
	BaseLight base;
	float3 direction;
};


struct Attenuation
{
	float constantAtten;
	float linearAtten;
	float exponentAtten;

	float padding;
};

struct PointLight
{
	BaseLight base;
	float3 atten;
	float3 pos;
	float range;
};

struct SpotLight
{
	PointLight pointLight;
	float3 direction;
	float cutoff;

	float padding;
};


cbuffer MatrixBuffer : register(b0)
{
	matrix worldMatrix;
	matrix viewMatrix;
	matrix projectionMatrix;
};


cbuffer LightingBuffer : register(b1)
{
	float4 ambient;

	float specularPower;
	float3 padding3;

	PointLight pointLight;
	//DirectionalLight light;

};


cbuffer CameraBuffer : register(b2)
{
	float4 cameraPos;
};


struct VertexInputType
{
	float4 position : POSITION;
	float4 color : COLOR;
	float2 texCoords : TEXCOORD0;
	float3 normal : NORMAL;
	float3 tangent : TANGENT;
	float3 biTangent : BINORMAL;
};

struct PixelInputType
{
	float4 position : SV_POSITION;
	float4 color : COLOR;
	float3 normal : NORMAL;
	float2 texCoords : TEXCOORD0;
	float3 worldPos : TEXCOORD1;
	float3 tangent : TANGENT;
	float3 biTangent : BINORMAL;
};






//Methods
float4 calcLight(BaseLight base, float3 direction, float3 normal, float3 worldPos0, float4 specularMap)
{
	float diffuseFactor = (dot(normal, -direction));

		float4 diffuseColor = float4(0, 0, 0, 0);
		float4 specularColor = float4(0, 0, 0, 0);

		if (diffuseFactor > 0.0f)
		{
			diffuseColor = base.color * base.intensity * diffuseFactor;
			diffuseColor = saturate(diffuseColor);

			float3 directionToEye = normalize(cameraPos - worldPos0);
			float3 reflectDirection = normalize(reflect(direction, normal));

			float specularFactor = dot(directionToEye, reflectDirection);
			specularFactor = pow(specularFactor, specularPower);

			if (specularFactor > 0)
			{
#if 0
				specularColor = float4(1, 0, 0, 1) * specularFactor; //Debug Specular
#else
				specularColor = base.color * 1.0f * specularFactor; //Normal Specular
#endif

			}
			if (specularMap.a > 0.0f)
				specularColor = specularColor * specularMap;
		}


	return ambient + diffuseColor + specularColor;


}

float4 calcDirectionalLight(DirectionalLight directionalLight, float3 normal, float3 worldPos0, float4 specularMap)
{
	return calcLight(directionalLight.base, -directionalLight.direction, normal, worldPos0, specularMap);
}

float4 calcPointLight(PointLight pointLight, float3 normal, float3 worldPos0, float4 specularMap, float4 diffuseTex)
{
	float3 lightDirection = worldPos0 - pointLight.pos;
	float distanceToPoint = length(lightDirection);

	//	if (distanceToPoint > pointLight.range)
	//	return float4(0, 0, 0, 0);

	lightDirection = normalize(lightDirection);

	float4 color = calcLight(pointLight.base, lightDirection, normal, worldPos0, specularMap);

		float attenuation = pointLight.atten[0] +
		pointLight.atten[1] * distanceToPoint +
		pointLight.atten[2] * distanceToPoint * distanceToPoint +
		0.0001;

	return color / attenuation;
}

The main problem that I have found is caused by the specular calculations in calcLight. The specular seems to be having some kind of odd effect for example in my current build it leaves like a "tail" / "trail" on the point light which just plain looks wrong.

When I inspect it via the VS debugger the cameraPos is showing as float4(0,0,0, Nan) which is clearly incorrect.

Advertisement

Can you show the code where you fill your constant buffers on the CPU side? For example, when you actually put your camera position into the buffer, are you certain that you copy a value for all four elements?

Can you show the code where you fill your constant buffers on the CPU side? For example, when you actually put your camera position into the buffer, are you certain that you copy a value for all four elements?

C++ code is below


bool LightingShader::SetLightingShaderParameters(ID3D11DeviceContext* deviceContext, const Matrix4f& worldMatrix, CameraClass& camera,
	const Material* material, Vector3f lightDirection, Vector4f ambientColor, Vector4f diffuseColor) const
{
	HRESULT result;
	D3D11_MAPPED_SUBRESOURCE mappedResource;
	D3D11_MAPPED_SUBRESOURCE mappedLightResource;
	D3D11_MAPPED_SUBRESOURCE mappedCameraResource;

	MatrixBufferType* matrixBuffer;
	perLightBuffer* lightingBuffer;
	CameraBufferType* cameraBuffer;

	/* MATRIX BUFFER */
	// Lock the constant buffer so it can be written to.
	result = deviceContext->Map(m_matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
	if (FAILED(result))
	{
		return false;
	}

	// Get a pointer to the data in the constant buffer.
	matrixBuffer = (MatrixBufferType*)mappedResource.pData;

	// Copy the matrices into the constant buffer.
	matrixBuffer->world = worldMatrix.Transpose();
	matrixBuffer->view = camera.GetViewMatrix().Transpose();
	matrixBuffer->projection = camera.GetProjectionMatrix().Transpose();
	// Unlock the constant buffer.
	deviceContext->Unmap(m_matrixBuffer, 0);
	deviceContext->VSSetConstantBuffers(MATRIX_BUFFER, 1, &m_matrixBuffer);


	/*!!!! CAMERA BUFFER !!!!*/
	result = deviceContext->Map(m_cameraBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedCameraResource);
	if (FAILED(result))
		return false;


	Vector3f camPos = camera.getTransform().GetTransformedPos();

	cameraBuffer = (CameraBufferType*)mappedCameraResource.pData;
	cameraBuffer->cameraPos = Vector4f(camPos.GetX(), camPos.GetY(), camPos.GetZ(), 1);
	//cameraBuffer->padding = 1.0f;

	deviceContext->Unmap(m_cameraBuffer, 0);
	deviceContext->VSSetConstantBuffers(CAMERA_BUFFER, 1, &m_cameraBuffer);



	/*LIGHTING BUFFER*/
	result = deviceContext->Map(m_lightBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedLightResource);

	if (FAILED(result))
	{
		return false;
	}
	// Get a pointer to the data in the constant buffer.
	lightingBuffer = (perLightBuffer*)mappedLightResource.pData;

	lightingBuffer->ambientLight = Vector4f(0.2f, 0.2f, 0.2f, 1.0f);

	lightingBuffer->specularPower = m_specularPower;
	lightingBuffer->padding = Vector3f(0, 0, 0);

	//Point Light
	lightPos = t.GetTransformedPos();
	lightingBuffer->pointLight.pos = Vector3f(lightPos.GetX(), lightPos.GetY(), lightPos.GetZ()); // camera.getTransform().GetTransformedPos();
	lightingBuffer->pointLight.range = 10.0f;
	lightingBuffer->pointLight.atten = Vector3f(0.0f, 0.2f, 0.0f);
	lightingBuffer->pointLight.base.color= Vector4f(0.0f, 1.0f, 0.0f, 1.0f);
	lightingBuffer->pointLight.base.intensity = 100.0f;


	//TODO: Change so that specular is actually from the model material not the material that is passed in....
	//Possibly within a game object per model? Or something...
	
	deviceContext->Unmap(m_lightBuffer, 0);
	deviceContext->PSSetConstantBuffers(LIGHTING_BUFFER, 1, &m_lightBuffer);

	
	return true;
}

https://msdn.microsoft.com/en-us/library/windows/desktop/bb509632%28v=vs.85%29.aspx

It's a bit hard to tell. You don't show the C++ side structs and even if, different compiler options can produce a different layout. Better be sure about it and check it with sizeof and the offsetof macro. Looking at a shader compiler assembly dump (or using the shader reflection system) also tells you the offsets on shader side.

Neither do we see actual shaders, just functions. One guess though: since cameraPos is used as a lighting parameter, that constant buffer should probably be bound to the pixel shader stage, not vertex shader.

You still may get problems because of packing in the CBuffer. Follow the link I posted before: https://msdn.microsoft.com/en-us/library/windows/desktop/bb509632%28v=vs.85%29.aspx

(Hint: Look at your struct PointLight.)

This topic is closed to new replies.

Advertisement