Hello everyone,
Phong shader problem, cannot find out the reason
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:
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!
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:
NEAR:
Thank you!