Backing up a bit - turns out the problem's still there.
It just became less visible, because the specular power is now calculated correctly, but that doesn't change the fact that when a light is perpendicular to object's surface, the highlight flickers.
Any ides?
- Viewing Profile: Posts: Paksas
Community Stats
- Group Members
- Active Posts 28
- Profile Views 531
- Member Title Member
- Age Age Unknown
- Birthday Birthday Unknown
-
Gender
Not Telling
132
Neutral
User Tools
Contacts
Paksas hasn't added any contacts yet.
Posts I've Made
In Topic: specular light flickers when a ray is parallel to the lit surface
26 September 2012 - 04:22 PM
In Topic: specular light flickers when a ray is parallel to the lit surface
26 September 2012 - 07:21 AM
Ok - found it.
There were two problems hidden in the directional light shader:
1.) I don't know if I mentioned that I'm running all calculations in camera ( view ) space.
Anyway - the light direction I passed to calculate the reflection was flipped
2.) You guys were barking at the right tree with the whole min/max thing - right tree, wrong branch ;)
That's the original code:
and here's the corrected code:
I was decoding the shininess in the wrong way, having the value divided by 255 in the engine code ( that I didn't paste here, so you guys couldn't have possibly known ) so that I can output it in the alpha channel of my normals texture, but then I forgot to invert the operation before I calculated the factor, so in fact I was calculating a power with a factor in range ( 0..1 ).
The shininess value in my engine can be equal 0, if the material's not supposed to be shiny at all - I forgot to filter that case out.
Anyway - thank you all for help.
Cheers
There were two problems hidden in the directional light shader:
1.) I don't know if I mentioned that I'm running all calculations in camera ( view ) space.
Anyway - the light direction I passed to calculate the reflection was flipped
2.) You guys were barking at the right tree with the whole min/max thing - right tree, wrong branch ;)
That's the original code:
const float matShininess = matSpecularCol.a * 2 - 1; /// ... float specularFactor = pow( max( specularValue, 1.0 ), matShininess );
and here's the corrected code:
const float matShininess = matSpecularCol.a * 255.0; /// ... float specularFactor = pow( max( specularValue, 1.0 ), max( matShininess, 1.0 ) );
I was decoding the shininess in the wrong way, having the value divided by 255 in the engine code ( that I didn't paste here, so you guys couldn't have possibly known ) so that I can output it in the alpha channel of my normals texture, but then I forgot to invert the operation before I calculated the factor, so in fact I was calculating a power with a factor in range ( 0..1 ).
The shininess value in my engine can be equal 0, if the material's not supposed to be shiny at all - I forgot to filter that case out.
Anyway - thank you all for help.
Cheers
In Topic: specular light flickers when a ray is parallel to the lit surface
26 September 2012 - 05:55 AM
@Ashaman73 - I tried, but that doesn't change anything. As a matter of fact if you look at the code you pasted ( the original one ), you can see that I'm actually maxin' it to 1.0,
before I pass it to the 'pow' function:
before I pass it to the 'pow' function:
float specularFactor = pow( max( specularValue, 1.0 ), matShininess );
In Topic: specular light flickers when a ray is parallel to the lit surface
26 September 2012 - 03:50 AM
No division by zero there.
Here are the shaders:
Object shader:
Directional light shader:
Here are the shaders:
Object shader:
//--------------------------------------------------------------------------------------
// Global variables
//--------------------------------------------------------------------------------------
float4 g_MaterialAmbientColor; // Material's ambient color
float4 g_MaterialDiffuseColor; // Material's diffuse color
bool g_DiffuseTexSet;
bool g_NormalTexSet;
bool g_SpecularTexSet;
float g_farZ = 1024;
int g_materialIdx;
//--------------------------------------------------------------------------------------
// Texture samplers
//--------------------------------------------------------------------------------------
sampler g_DiffuseTexture;
sampler g_NormalTexture;
sampler g_SpecularTexture;
//--------------------------------------------------------------------------------------
// This shader outputs the pixel's color by modulating the texture's
// color with diffuse material color
//--------------------------------------------------------------------------------------
// <psMain>
DEFERRED_PS_OUTPUT main( VS_OUTPUT In )
{
DEFERRED_PS_OUTPUT output = (DEFERRED_PS_OUTPUT)0;
// calculate the color component
output.Color = g_MaterialDiffuseColor;
if ( g_DiffuseTexSet )
{
float4 texColor = tex2D( g_DiffuseTexture, In.TextureUV );
output.Color = texColor + g_MaterialDiffuseColor * ( 1 - texColor.a );
}
// calculate normal
float3 surfaceNormalViewSpace = 0;
if ( g_NormalTexSet )
{
float3 normalVS = normalize( In.Normal );
float3 tangentVS = normalize( In.Tangent );
float3 binormalVS = cross( normalVS, tangentVS );
float3x3 mtx = float3x3( tangentVS, binormalVS, normalVS );
float3 surfaceNormalTanSpace = tex2D( g_NormalTexture, In.TextureUV ) * 2.0 - 1.0;
// I noticed the other day that normal maps exported from Blender have y coordinate flipped.
// So I'm unflipping it here - but keep that fact in mind and pay attention to other
// normal maps - perhaps I got something wrong in the code
surfaceNormalTanSpace.y *= -1.0;
surfaceNormalViewSpace = mul( surfaceNormalTanSpace, mtx );
surfaceNormalViewSpace = normalize( surfaceNormalViewSpace );
}
else
{
surfaceNormalViewSpace = normalize( In.Normal );
}
// Flip the Z direction, so that Z values decrease as they get further away from the camera.
// It's required in order for our normals compression algorithm to work correctly
output.NormalSpec.rgb = surfaceNormalViewSpace * float3( 0.5, 0.5, -0.5 ) + 0.5;
output.DepthNormal = encodeDepthAndNormal( surfaceNormalViewSpace, In.PositionCS.z, g_farZ );
// calculate the specular color ( store info about the specularity in albedo's alpha channel
if ( g_SpecularTexSet )
{
output.NormalSpec.a = tex2D( g_SpecularTexture, In.TextureUV ).r;
}
else
{
// full specularity
output.NormalSpec.a = 1;
}
// store the material index and the UV coordinates
output.MatIdx = storeMaterialIndex( g_materialIdx );
return output;
}
Directional light shader:
// -------------------------------------------------------------------------------
// constants
// -------------------------------------------------------------------------------
float4 g_halfPixel;
float4 g_lightDirVS; // light direction in view space
float4 g_lightColor; // light color
float g_strength; // light strength
bool g_drawShadows; // should we take the shadow map into account while rendering the light?
int g_materialsTexSize;
//--------------------------------------------------------------------------------------
// Texture samplers
//--------------------------------------------------------------------------------------
sampler g_Normals;
sampler g_Specular;
sampler g_SceneColor;
sampler g_ShadowMap;
sampler g_MaterialIndices;
sampler g_MaterialsDescr;
//--------------------------------------------------------------------------------------
// Helper structure that describes light parameters at the sampled point of the screen
//--------------------------------------------------------------------------------------
struct LightValues
{
float3 m_direction;
float m_reflectionFactor;
float3 m_reflectionVector;
float4 m_color;
};
//--------------------------------------------------------------------------------------
// Calculates the color of the pixel lit by the light described by the specified values
//--------------------------------------------------------------------------------------
float4 calcLightContribution( float2 UV, LightValues lightValues, sampler sceneColorTex, sampler materialIndices, sampler materialsDescr, int materialsTexSize )
{
// get the material's ambient color
float4 encodedMaterialIdx = tex2D( materialIndices, UV );
int materialIdx = readMaterialIndex( encodedMaterialIdx );
float4 matDiffuseCol = getMaterialComponent( materialsDescr, materialIdx, DIFFUSE_COLOR, materialsTexSize );
float4 matSpecularCol = getMaterialComponent( materialsDescr, materialIdx, SPECULAR_COLOR, materialsTexSize );
// I don't remember encoding the value of specular power, but for some reason
// it's encoded in the same way as the normals - investigate!
const float matShininess = matSpecularCol.a * 2 - 1;
matSpecularCol.a = 1;
float4 baseColor = tex2D( sceneColorTex, UV );
float4 outputColor = float4( 0, 0, 0, 1 );
if ( lightValues.m_reflectionFactor > 0.0 )
{
// calculate the specular factor
float specularValue = dot( lightValues.m_reflectionVector, float3( 0, 0, 1 ) );
float specularFactor = pow( max( specularValue, 1.0 ), matShininess );
// shininess occurs only where we allow it to be, and in our case that is regulated
// by the contents of the albedo texture alpha channel
specularFactor *= baseColor.a;
// calculate component albedo contributions for both the specular and alpha channels
float3 specularColor = matSpecularCol * specularFactor;
float3 diffuseColor = matDiffuseCol * baseColor.rgb * lightValues.m_reflectionFactor;
// calculate the final color by adding the two albedo colors and modulating them using the light's color
outputColor.rgb += ( diffuseColor + specularColor ) * lightValues.m_color.rgb;
}
return saturate( outputColor );
}
//--------------------------------------------------------------------------------------
// This method calculates light parameters values
//--------------------------------------------------------------------------------------
LightValues calculateDirectionalLightValue( float2 UV )
{
LightValues Out = (LightValues)0;
// set light ray direction
Out.m_direction = g_lightDirVS.xyz * float3( -1, -1, 1 );
// calculate the reflection factor of the light ray hitting the lit surface
float3 pixelNormalVS = normalize( tex2D( g_Normals, UV ) * 2.0 - 1.0 );
Out.m_reflectionFactor = dot( pixelNormalVS, Out.m_direction );
Out.m_reflectionVector = normalize( -reflect( Out.m_direction.xyz, pixelNormalVS ) );
// set the color of the light ( no attenuation requires, since directional lights have the same strength
// at every point in space )
Out.m_color = g_lightColor * g_strength;
return Out;
}
// -------------------------------------------------------------------------------
// main function
// -------------------------------------------------------------------------------
LIGHT_PS_OUT main( float2 UV : TEXCOORD0 )
{
LIGHT_PS_OUT Out = (LIGHT_PS_OUT)0;
// align texture coordinates
UV -= g_halfPixel.xy;
float lightPercentage = 1.0f;
if( g_drawShadows )
{
// use the shadow map to determine if we should render there
lightPercentage = tex2D( g_ShadowMap, UV ).r;
}
// color light and direction are constant across the entire space
if ( lightPercentage > 0.0f )
{
LightValues lightValue = calculateDirectionalLightValue( UV );
// calculate the light contribution to the scene color
Out.vColor = calcLightContribution( UV, lightValue, g_SceneColor, g_MaterialIndices, g_MaterialsDescr, g_materialsTexSize );
// modulate the output color by the light value
Out.vColor *= lightPercentage;
}
else
{
// save precious cycles - if the light doesn't reach the spot, don't calculate its contribution
Out.vColor = 0.0f;
}
return Out;
}
In Topic: the best ssao ive seen
16 November 2011 - 04:11 PM
@Paksas: I had this exact same problem with the noise texture! I didn't find a solution, though
I established that when I increase the sampling radius, the weird "cross" in the middle of the screen disappears, and the "overlayed scattered pattern" along with it.
But another problem arises - the edges start bleeding white color further and further.
The radius I'm taking about here equals 100.0f - so it's pretty big...
Any clues - anyone?
- Home
- » Viewing Profile: Posts: Paksas

Find content