Phong shader problem, cannot find out the reason

Started by
7 comments, last by politoleo 10 years, 5 months ago

Hello everyone,

This is my first post here, and this is a (very) little "something" about me:
After finished my game in unity, I would like to port it to a custom framework in DX11 to have better performance and graphics, no matter how much time it will takes!
Actually I'm following some tutorial about DX11 here: http://www.rastertek.com/.
The problem I have right now is this:
prob.jpg
As you can see it's a simple plane, subdivided to 4!
The model was imported in the simplest way trough an fbx, so I've got 24 vertices and for each vertices there's normal and uv coords!
The normal for each vertex are 0 0 -1!
The shader is a standard phong shader!
prob_wire.jpg
I cannot define what's the problem here!
The only one I could think is that I should use 24 indices and 9 vertex/normal/uv, but using control point will make me loose hard/soft edge in complex model!
Could you help me to find out the problem?
Thank you very much!
EDIT:
I've tried without duplicated vertices, so 9 vertices and 24 indices!
The problem should be somewere else!
Advertisement

My guess is normal transformation issue, looks like the center vertex normal is (0,0,-1), and the rest are not. The specular highlight is also not distributed in a symetrical way, which is strange.

Can you post you shaders?

Thank you for the reply!

The buffer i'm passing is this one:

buffer.jpg

Here is the shaders (I've just add the smoothstep function, the rest it's exactly like the tutorial, and I can observe the same with tutorial shader also)

VERTEX:


////////////////////////////////////////////////////////////////////////////////
// Filename: light.vs
////////////////////////////////////////////////////////////////////////////////


/////////////
// GLOBALS //
/////////////
cbuffer MatrixBuffer
{
	matrix worldMatrix;
	matrix viewMatrix;
	matrix projectionMatrix;
};

cbuffer CameraBuffer
{
    float3 cameraPosition;
	float padding;
};


//////////////
// TYPEDEFS //
//////////////
struct VertexInputType
{
    float4 position : POSITION;
    float2 tex : TEXCOORD0;
	float3 normal : NORMAL;
};

struct PixelInputType
{
    float4 position : SV_POSITION;
    float2 tex : TEXCOORD0;
	float3 normal : NORMAL;
	float3 viewDirection : TEXCOORD1;
};


////////////////////////////////////////////////////////////////////////////////
// Vertex Shader
////////////////////////////////////////////////////////////////////////////////
PixelInputType LightVertexShader(VertexInputType input)
{
    PixelInputType output;
	float4 worldPosition;


	// Change the position vector to be 4 units for proper matrix calculations.
    input.position.w = 1.0f;

	// Calculate the position of the vertex against the world, view, and projection matrices.
    output.position = mul(input.position, worldMatrix);
    output.position = mul(output.position, viewMatrix);
    output.position = mul(output.position, projectionMatrix);
    
	// Store the texture coordinates for the pixel shader.
	output.tex = input.tex;
    
	// Calculate the normal vector against the world matrix only.
    output.normal = mul(input.normal, (float3x3)worldMatrix);
	
    // Normalize the normal vector.
    output.normal = normalize(output.normal);

	// Calculate the position of the vertex in the world.
    worldPosition = mul(input.position, worldMatrix);

    // Determine the viewing direction based on the position of the camera and the position of the vertex in the world.
    output.viewDirection = cameraPosition.xyz - worldPosition.xyz;
	
    // Normalize the viewing direction vector.
    output.viewDirection = normalize(output.viewDirection);

    return output;
}

PIXEL:


Texture2D shaderTexture;
SamplerState SampleType;

cbuffer LightBuffer
{
	float4 ambientColor;
	float4 diffuseColor;
    float3 lightDirection;
    float  specularPower;
    float4 specularColor;
};


//////////////
// TYPEDEFS //
//////////////
struct PixelInputType
{
    float4 position : SV_POSITION;
    float2 tex : TEXCOORD0;
	float3 normal : NORMAL;
	float3 viewDirection : TEXCOORD1;
};


////////////////////////////////////////////////////////////////////////////////
// Pixel Shader
////////////////////////////////////////////////////////////////////////////////
float4 LightPixelShader(PixelInputType input) : SV_TARGET
{
	float4 textureColor;
	float3 lightDir;
	float lightIntensity;
	float4 color;
	float3 reflection;
    float4 specular;


	// Sample the pixel color from the texture using the sampler at this texture coordinate location.
	textureColor = shaderTexture.Sample(SampleType, input.tex);

	// Set the default output color to the ambient light value for all pixels.
    color = ambientColor;

	// Invert the light direction for calculations.
    lightDir = -lightDirection;

    // Calculate the amount of light on this pixel.
    lightIntensity = saturate(dot(input.normal, lightDir));

    // Determine the final diffuse color based on the diffuse color and the amount of light intensity.
    
	color += (diffuseColor * lightIntensity);

	// Saturate the ambient and diffuse color.
	color = saturate(color);

	// Calculate the reflection vector based on the light intensity, normal vector, and light direction.
    reflection = normalize(2 * lightIntensity * input.normal - lightDir); 

	// Determine the amount of specular light based on the reflection vector, viewing direction, and specular power.
    specular = smoothstep(0.0,0.05,lightIntensity) * pow(saturate(dot(reflection, input.viewDirection)), specularPower);
	
	// Add specular color
	specular = specular * specularColor;

    // Multiply the texture pixel and the input color to get the textured result.
    color = color * textureColor;
	
	// Add the specular component last to the output color.
    color = saturate(color + specular);

    return color;
}

Thank you again!

PS.

It's not simmetrical because i was moving with the camera!

What's your input layout (CreateInputLayout, IASetInputLayout)?

This is the part of code for input layout initialisation for that shader:


	// Create the vertex input layout description.
	// This setup needs to match the VertexType stucture in the Model and in the shader.
	polygonLayout[0].SemanticName = "POSITION";
	polygonLayout[0].SemanticIndex = 0;
	polygonLayout[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
	polygonLayout[0].InputSlot = 0;
	polygonLayout[0].AlignedByteOffset = 0;
	polygonLayout[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
	polygonLayout[0].InstanceDataStepRate = 0;

	polygonLayout[1].SemanticName = "TEXCOORD";
	polygonLayout[1].SemanticIndex = 0;
	polygonLayout[1].Format = DXGI_FORMAT_R32G32_FLOAT;
	polygonLayout[1].InputSlot = 0;
	polygonLayout[1].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
	polygonLayout[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
	polygonLayout[1].InstanceDataStepRate = 0;

	polygonLayout[2].SemanticName = "NORMAL";
	polygonLayout[2].SemanticIndex = 0;
	polygonLayout[2].Format = DXGI_FORMAT_R32G32B32_FLOAT;
	polygonLayout[2].InputSlot = 0;
	polygonLayout[2].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT;
	polygonLayout[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
	polygonLayout[2].InstanceDataStepRate = 0;

	// Get a count of the elements in the layout.
	numElements = sizeof(polygonLayout) / sizeof(polygonLayout[0]);

	// Create the vertex input layout.
	result = device->CreateInputLayout(polygonLayout, numElements, vertexShaderBuffer->GetBufferPointer(), vertexShaderBuffer->GetBufferSize(), &m_layout);

Thanks!

Not sure if that is the problem, but you need to normalize the viewDirection and Normal inside the pixel shader, as they are not guranteed to be normalized after interpolation. And also make sure that lightDir is normalized.

Thank you satanir, it really helped a lot!

Now everything looks ok from distance, but when you moove the camera the reflection will follow the poligon edge:

this is the pixel shader now:


Texture2D shaderTexture;
SamplerState SampleType;

cbuffer LightBuffer
{
	float4 ambientColor;
	float4 diffuseColor;
    float3 lightDirection;
    float  specularPower;
    float4 specularColor;
};


//////////////
// TYPEDEFS //
//////////////
struct PixelInputType
{
    float4 position : SV_POSITION;
    float2 tex : TEXCOORD0;
	float3 normal : NORMAL;
	float3 viewDirection : TEXCOORD1;
};


////////////////////////////////////////////////////////////////////////////////
// Pixel Shader
////////////////////////////////////////////////////////////////////////////////
float4 LightPixelShader(PixelInputType input) : SV_TARGET
{
	float4 textureColor;
	float3 lightDir;
	float lightIntensity;
	float4 color;
	float3 reflection;
    float4 specular;


	// Sample the pixel color from the texture using the sampler at this texture coordinate location.
	textureColor = shaderTexture.Sample(SampleType, input.tex);

	// Set the default output color to the ambient light value for all pixels.
    color = ambientColor;

	// Invert the light direction for calculations.
    lightDir = -lightDirection;
	
	// Normalize view direction
	input.viewDirection = normalize(input.viewDirection);

    // Calculate the amount of light on this pixel.
    lightIntensity = saturate(dot(input.normal, lightDir));

    // Determine the final diffuse color based on the diffuse color and the amount of light intensity.
    
	color += (diffuseColor * lightIntensity);

	// Saturate the ambient and diffuse color.
	color = saturate(color);

	// Calculate the reflection vector based on the light intensity, normal vector, and light direction.
    reflection = normalize(2 * lightIntensity * input.normal - lightDir); 

	// Determine the amount of specular light based on the reflection vector, viewing direction, and specular power.
    specular = smoothstep(0.0,0.05,lightIntensity) * pow(saturate(dot(reflection, input.viewDirection)), specularPower);
	
	// Add specular color
	specular = specular * specularColor;

    // Multiply the texture pixel and the input color to get the textured result.
    color = color * textureColor;
	
	// Add the specular component last to the output color.
    color = saturate(color + specular);

    return color;
}

FAR:

far.jpg

NEAR:

near.jpg

Thank you!

Fixed it by removing the viewDirection normalization in the vertex shader!

Thank you very much for the help guys!

This topic is closed to new replies.

Advertisement