Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


Paksas

Member Since 15 Mar 2008
Offline Last Active Oct 04 2012 04:20 PM

Posts I've Made

In Topic: specular light flickers when a ray is parallel to the lit surface

26 September 2012 - 04:22 PM

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?

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:
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:

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:

//--------------------------------------------------------------------------------------

// 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?

PARTNERS