mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-15 07:00:58 +00:00
Implemented experimental direct physically based shading.
The implementation is similar to the one used in Marmoset Toolbag 2 See blog.selfshadow.com/publications/s2013-shading-course/ for more information.
This commit is contained in:
parent
0d3e4733af
commit
e9e0fd3c08
6 changed files with 406 additions and 39 deletions
135
base/renderprogs/BRDF.inc
Normal file
135
base/renderprogs/BRDF.inc
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
===========================================================================
|
||||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 2014 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
||||
|
||||
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
||||
|
||||
===========================================================================
|
||||
*/
|
||||
|
||||
// Normal Distribution Function ( NDF ) or D( h )
|
||||
// GGX ( Trowbridge-Reitz )
|
||||
half Distribution_GGX( half hdotN, half alpha )
|
||||
{
|
||||
// alpha is assumed to be roughness^2
|
||||
float a2 = alpha * alpha;
|
||||
//float tmp = ( hdotN * hdotN ) * ( a2 - 1.0 ) + 1.0;
|
||||
float tmp = ( hdotN * a2 - hdotN ) * hdotN + 1.0;
|
||||
|
||||
return ( a2 / ( PI * tmp * tmp ) );
|
||||
}
|
||||
|
||||
half Distribution_GGX_Disney( half hdotN, half alphaG )
|
||||
{
|
||||
float a2 = alphaG * alphaG;
|
||||
float tmp = ( hdotN * hdotN ) * ( a2 - 1.0 ) + 1.0;
|
||||
//tmp *= tmp;
|
||||
|
||||
return ( a2 / ( PI * tmp ) );
|
||||
}
|
||||
|
||||
half Distribution_GGX_1886( half hdotN, half alpha )
|
||||
{
|
||||
// alpha is assumed to be roughness^2
|
||||
return ( alpha / ( PI * pow( hdotN * hdotN * ( alpha - 1.0 ) + 1.0, 2.0 ) ) );
|
||||
}
|
||||
|
||||
// Fresnel term F( v, h )
|
||||
// Fnone( v, h ) = F(0°) = specularColor
|
||||
half3 Fresnel_Schlick( half3 specularColor, half vdotH )
|
||||
{
|
||||
return specularColor + ( 1.0 - specularColor ) * pow( 1.0 - vdotH, 5.0 );
|
||||
}
|
||||
|
||||
// Visibility term G( l, v, h )
|
||||
// Very similar to Marmoset Toolbag 2 and gives almost the same results as Smith GGX
|
||||
float Visibility_Schlick( half vdotN, half ldotN, float alpha )
|
||||
{
|
||||
float k = alpha * 0.5;
|
||||
|
||||
float schlickL = ( ldotN * ( 1.0 - k ) + k );
|
||||
float schlickV = ( vdotN * ( 1.0 - k ) + k );
|
||||
|
||||
return ( 0.25 / ( schlickL * schlickV ) );
|
||||
//return ( ( schlickL * schlickV ) / ( 4.0 * vdotN * ldotN ) );
|
||||
}
|
||||
|
||||
// see s2013_pbs_rad_notes.pdf
|
||||
// Crafting a Next-Gen Material Pipeline for The Order: 1886
|
||||
// this visibility function also provides some sort of back lighting
|
||||
float Visibility_SmithGGX( half vdotN, half ldotN, float alpha )
|
||||
{
|
||||
// alpha is already roughness^2
|
||||
|
||||
float V1 = ldotN + sqrt( alpha + ( 1.0 - alpha ) * ldotN * ldotN );
|
||||
float V2 = vdotN + sqrt( alpha + ( 1.0 - alpha ) * vdotN * vdotN );
|
||||
|
||||
// RB: avoid too bright spots
|
||||
return ( 1.0 / max( V1 * V2, 0.15 ) );
|
||||
}
|
||||
|
||||
|
||||
// Environment BRDF approximations
|
||||
// see s2013_pbs_black_ops_2_notes.pdf
|
||||
half a1vf( half g )
|
||||
{
|
||||
return ( 0.25 * g + 0.75 );
|
||||
}
|
||||
|
||||
half a004( half g, half vdotN )
|
||||
{
|
||||
float t = min( 0.475 * g, exp2( -9.28 * vdotN ) );
|
||||
return ( t + 0.0275 ) * g + 0.015;
|
||||
}
|
||||
|
||||
half a0r( half g, half vdotN )
|
||||
{
|
||||
return ( ( a004( g, vdotN ) - a1vf( g ) * 0.04 ) / 0.96 );
|
||||
}
|
||||
|
||||
float3 EnvironmentBRDF( half g, half vdotN, float3 rf0 )
|
||||
{
|
||||
float4 t = float4( 1.0 / 0.96, 0.475, ( 0.0275 - 0.25 * 0.04 ) / 0.96, 0.25 );
|
||||
t *= float4( g, g, g, g );
|
||||
t += float4( 0.0, 0.0, ( 0.015 - 0.75 * 0.04 ) / 0.96, 0.75 );
|
||||
half a0 = t.x * min( t.y, exp2( -9.28 * vdotN ) ) + t.z;
|
||||
half a1 = t.w;
|
||||
|
||||
return saturate( a0 + rf0 * ( a1 - a0 ) );
|
||||
}
|
||||
|
||||
|
||||
half3 EnvironmentBRDFApprox( half roughness, half vdotN, half3 specularColor )
|
||||
{
|
||||
const half4 c0 = half4( -1, -0.0275, -0.572, 0.022 );
|
||||
const half4 c1 = half4( 1, 0.0425, 1.04, -0.04 );
|
||||
|
||||
half4 r = roughness * c0 + c1;
|
||||
half a004 = min( r.x * r.x, exp2( -9.28 * vdotN ) ) * r.x + r.y;
|
||||
half2 AB = half2( -1.04, 1.04 ) * a004 + r.zw;
|
||||
|
||||
return specularColor * AB.x + AB.y;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -180,6 +180,8 @@ float rand( float2 co ) {
|
|||
|
||||
#define DEG2RAD( a ) ( ( a ) * PI / 180.0f )
|
||||
#define RAD2DEG( a ) ( ( a ) * 180.0f / PI )
|
||||
|
||||
static const half4 LUMINANCE_VECTOR = half4( 0.2125, 0.7154, 0.0721, 0.0 );
|
||||
// RB end
|
||||
|
||||
#define _half2( x ) half2( x )
|
||||
|
|
|
@ -28,6 +28,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
*/
|
||||
|
||||
#include "renderprogs/global.inc"
|
||||
#include "renderprogs/BRDF.inc"
|
||||
|
||||
uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface bump map
|
||||
uniform sampler2D samp1 : register(s1); // texture 2 is the light falloff texture
|
||||
|
@ -35,7 +36,8 @@ uniform sampler2D samp2 : register(s2); // texture 3 is the light projection tex
|
|||
uniform sampler2D samp3 : register(s3); // texture 4 is the per-surface diffuse map
|
||||
uniform sampler2D samp4 : register(s4); // texture 5 is the per-surface specular map
|
||||
|
||||
struct PS_IN {
|
||||
struct PS_IN
|
||||
{
|
||||
half4 position : VPOS;
|
||||
half4 texcoord0 : TEXCOORD0_centroid;
|
||||
half4 texcoord1 : TEXCOORD1_centroid;
|
||||
|
@ -47,11 +49,13 @@ struct PS_IN {
|
|||
half4 color : COLOR0;
|
||||
};
|
||||
|
||||
struct PS_OUT {
|
||||
struct PS_OUT
|
||||
{
|
||||
half4 color : COLOR;
|
||||
};
|
||||
|
||||
void main( PS_IN fragment, out PS_OUT result ) {
|
||||
void main( PS_IN fragment, out PS_OUT result )
|
||||
{
|
||||
half4 bumpMap = tex2D( samp0, fragment.texcoord1.xy );
|
||||
half4 lightFalloff = idtex2Dproj( samp1, fragment.texcoord2 );
|
||||
half4 lightProj = idtex2Dproj( samp2, fragment.texcoord3 );
|
||||
|
@ -59,6 +63,7 @@ void main( PS_IN fragment, out PS_OUT result ) {
|
|||
half4 specMap = tex2D( samp4, fragment.texcoord5.xy );
|
||||
|
||||
half3 lightVector = normalize( fragment.texcoord0.xyz );
|
||||
half3 viewVector = normalize( fragment.texcoord6.xyz );
|
||||
half3 diffuseMap = ConvertYCoCgToRGB( YCoCG );
|
||||
|
||||
half3 localNormal;
|
||||
|
@ -73,7 +78,7 @@ void main( PS_IN fragment, out PS_OUT result ) {
|
|||
localNormal = normalize( localNormal );
|
||||
|
||||
// traditional very dark Lambert light model used in Doom 3
|
||||
half ldotN = dot3( localNormal, lightVector );
|
||||
half ldotN = saturate( dot3( localNormal, lightVector ) );
|
||||
|
||||
#if defined(USE_HALF_LAMBERT)
|
||||
// RB: http://developer.valvesoftware.com/wiki/Half_Lambert
|
||||
|
@ -84,20 +89,134 @@ void main( PS_IN fragment, out PS_OUT result ) {
|
|||
#else
|
||||
half lambert = ldotN;
|
||||
#endif
|
||||
|
||||
|
||||
half3 halfAngleVector = normalize( lightVector + viewVector );
|
||||
half hdotN = saturate( dot3( halfAngleVector, localNormal ) );
|
||||
|
||||
#if 1
|
||||
/*
|
||||
Physically based shading
|
||||
|
||||
Lambert diffuse BRDF combined with Cook-Torrance microfacet specular BRDF
|
||||
|
||||
D( h ) * F( v, h ) * G( l, v, h )
|
||||
f( l, v ) = diffuse + ---------------------------------
|
||||
4 * ( n * l ) ( n * v )
|
||||
*/
|
||||
|
||||
// RB: compensate r_lightScale 3 and the division of Pi
|
||||
lambert *= 1.3;
|
||||
|
||||
const half3 goldColor = half3( 1.00, 0.71, 0.29 );
|
||||
|
||||
//const half3 baseColor = goldColor;
|
||||
const half3 baseColor = diffuseMap;
|
||||
|
||||
const half metallic = 0.0;
|
||||
|
||||
// rpDiffuseModifier contains light color
|
||||
half3 lightColor = lightProj.xyz * lightFalloff.xyz * rpDiffuseModifier.xyz;
|
||||
|
||||
half vdotN = saturate( dot3( viewVector, localNormal ) );
|
||||
half vdotH = saturate( dot3( viewVector, halfAngleVector ) );
|
||||
|
||||
// the vast majority of real-world materials (anything not metal or gems) have F(0°) values in a very narrow range (~0.02 - 0.06)
|
||||
|
||||
// HACK calculate roughness from D3 gloss maps
|
||||
// converting from linear to sRGB space give pretty results
|
||||
const half glossiness = clamp( pow( dot( LUMINANCE_VECTOR.rgb, specMap.rgb ) * 0.4, 1.0 / 2.2 ) * 1.0, 0.0, 0.98 );
|
||||
|
||||
const half roughness = 1.0 - glossiness;
|
||||
|
||||
// compensate r_lightScale 3 * 2
|
||||
half3 reflectColor = specMap.rgb * rpSpecularModifier.rgb * 0.5;
|
||||
|
||||
// alpha modifications by Disney - s2012_pbs_disney_brdf_notes_v2.pdf
|
||||
const half alpha = roughness * roughness;
|
||||
|
||||
// reduce roughness range from [0 .. 1] to [0.5 .. 1]
|
||||
const half alphaG = pow( 0.5 + roughness * 0.5, 2.0 );
|
||||
|
||||
//half3 D = _half3( pow( abs( hdotN ), 10.0f ) );
|
||||
half3 D = _half3( Distribution_GGX( hdotN, alpha ) );
|
||||
//half3 D = _half3( Distribution_GGX_1886( hdotN, alpha ) );
|
||||
half3 G = _half3( Visibility_Schlick( ldotN, vdotN, alpha ) );
|
||||
//half3 G = _half3( Visibility_SmithGGX( ldotN, vdotN, alpha ) );
|
||||
half3 F = Fresnel_Schlick( reflectColor, vdotH );
|
||||
|
||||
// horizon
|
||||
float horizon = 1.0 - ldotN;
|
||||
horizon *= horizon;
|
||||
horizon *= horizon;
|
||||
half3 specLightColor = lightColor.rgb - lightColor.rgb * horizon;
|
||||
|
||||
float3 specularColor = saturate( D * G * ( F * ( specLightColor.rgb * lambert ) ) );
|
||||
|
||||
//specularColor = EnvironmentBRDFApprox( roughness, vdotN, specularColor.rgb );// * 0.45;
|
||||
|
||||
|
||||
#if 0
|
||||
result.color = float4( _half3( F ), 1.0 );
|
||||
return;
|
||||
#endif
|
||||
|
||||
// see http://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/
|
||||
lambert /= PI;
|
||||
|
||||
//half3 diffuseColor = mix( diffuseMap, F0, metal ) * rpDiffuseModifier.xyz;
|
||||
half3 diffuseColor = baseColor * rpDiffuseModifier.xyz;
|
||||
diffuseColor *= lightColor * lambert;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
maintain energy conservation
|
||||
|
||||
Energy conservation is a restriction on the reflection model
|
||||
that requires that the total amount of reflected light
|
||||
cannot be more than the incoming light.
|
||||
|
||||
http://www.rorydriscoll.com/2009/01/25/energy-conservation-in-games/
|
||||
|
||||
Cdiff + Cspec <= 1
|
||||
*/
|
||||
//diffuseColor.rgb *= ( half3( 1.0 ) - specularColor.rgb );
|
||||
|
||||
|
||||
#if 0 //defined(USE_METALNESS)
|
||||
//specularColor *= ( 0.96 * metallic ) * diffuseColor + half( 0.04 );
|
||||
diffuseColor.rgb *= ( 1.0 - metallic );
|
||||
|
||||
//diffuseColor.rgb = mix( diffuseColor, specularColor, metallic );
|
||||
#endif
|
||||
|
||||
// apply r_lightScale overbright for both diffuse and specular
|
||||
result.color.xyz = ( diffuseColor + specularColor ) * fragment.color.rgb;// + rimColor;
|
||||
result.color.w = 1.0;
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
OLD Blinn Phong
|
||||
*/
|
||||
|
||||
const half specularPower = 10.0f;
|
||||
half hDotN = dot3( normalize( fragment.texcoord6.xyz ), localNormal );
|
||||
|
||||
// RB: added abs
|
||||
half3 specularContribution = _half3( pow( abs( hDotN ), specularPower ) );
|
||||
half3 specularContribution = _half3( pow( abs( hdotN ), specularPower ) );
|
||||
|
||||
half3 diffuseColor = diffuseMap * rpDiffuseModifier.xyz;
|
||||
half3 specularColor = specMap.xyz * specularContribution * rpSpecularModifier.xyz;
|
||||
half3 lightColor = lightProj.xyz * lightFalloff.xyz;
|
||||
|
||||
half rim = 1.0f - saturate( hDotN );
|
||||
/*
|
||||
half rim = 1.0f - saturate( hdotN );
|
||||
half rimPower = 16.0f;
|
||||
half3 rimColor = diffuseColor * lightProj.xyz * lightFalloff.xyz * 1.0f * pow( rim, rimPower ) * fragment.color.rgb;// * halfLdotN;
|
||||
*/
|
||||
|
||||
result.color.xyz = ( diffuseColor + specularColor ) * lambert * lightColor * fragment.color.rgb;// + rimColor;
|
||||
result.color.xyz = ( diffuseColor + specularColor ) * lambert * lightColor * fragment.color.rgb; // + rimColor;
|
||||
result.color.w = 1.0;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -174,13 +174,10 @@ void main( VS_IN vertex, out VS_OUT result ) {
|
|||
//# calculate normalized vector to viewer in R1
|
||||
float4 toView = normalize( rpLocalViewOrigin - modelPosition );
|
||||
|
||||
//# add together to become the half angle vector in object space (non-normalized)
|
||||
float4 halfAngleVector = toLight + toView;
|
||||
|
||||
//# put into texture space
|
||||
result.texcoord6.x = dot3( tangent, halfAngleVector );
|
||||
result.texcoord6.y = dot3( bitangent, halfAngleVector );
|
||||
result.texcoord6.z = dot3( normal, halfAngleVector );
|
||||
result.texcoord6.x = dot3( tangent, toView );
|
||||
result.texcoord6.y = dot3( bitangent, toView );
|
||||
result.texcoord6.z = dot3( normal, toView );
|
||||
result.texcoord6.w = 1.0f;
|
||||
|
||||
#if defined( USE_GPU_SKINNING )
|
||||
|
|
|
@ -28,6 +28,7 @@ If you have questions concerning this license or the applicable additional terms
|
|||
*/
|
||||
|
||||
#include "renderprogs/global.inc"
|
||||
#include "renderprogs/BRDF.inc"
|
||||
|
||||
uniform sampler2D samp0 : register(s0); // texture 1 is the per-surface bump map
|
||||
uniform sampler2D samp1 : register(s1); // texture 2 is the light falloff texture
|
||||
|
@ -35,7 +36,7 @@ uniform sampler2D samp2 : register(s2); // texture 3 is the light projection
|
|||
uniform sampler2D samp3 : register(s3); // texture 4 is the per-surface diffuse map
|
||||
uniform sampler2D samp4 : register(s4); // texture 5 is the per-surface specular map
|
||||
uniform sampler2DArrayShadow samp5 : register(s5); // texture 6 is the shadowmap array
|
||||
uniform sampler2D samp6 : register(s6); // texture 7 is the jitter texture
|
||||
uniform sampler2D samp6 : register(s6); // texture 7 is the jitter texture
|
||||
|
||||
|
||||
|
||||
|
@ -69,6 +70,7 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
half4 specMap = tex2D( samp4, fragment.texcoord5.xy );
|
||||
|
||||
half3 lightVector = normalize( fragment.texcoord0.xyz );
|
||||
half3 viewVector = normalize( fragment.texcoord6.xyz );
|
||||
half3 diffuseMap = ConvertYCoCgToRGB( YCoCG );
|
||||
|
||||
half3 localNormal;
|
||||
|
@ -83,7 +85,7 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
localNormal = normalize( localNormal );
|
||||
|
||||
// traditional very dark Lambert light model used in Doom 3
|
||||
half ldotN = dot3( localNormal, lightVector );
|
||||
half ldotN = saturate( dot3( localNormal, lightVector ) );
|
||||
|
||||
#if defined(USE_HALF_LAMBERT)
|
||||
// RB: http://developer.valvesoftware.com/wiki/Half_Lambert
|
||||
|
@ -94,20 +96,8 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
#else
|
||||
half lambert = ldotN;
|
||||
#endif
|
||||
|
||||
const half specularPower = 10.0f;
|
||||
half hDotN = dot3( normalize( fragment.texcoord6.xyz ), localNormal );
|
||||
// RB: added abs
|
||||
half3 specularContribution = _half3( pow( abs( hDotN ), specularPower ) );
|
||||
|
||||
half3 diffuseColor = diffuseMap * rpDiffuseModifier.xyz;
|
||||
half3 specularColor = specMap.xyz * specularContribution * rpSpecularModifier.xyz;
|
||||
half3 lightColor = lightProj.xyz * lightFalloff.xyz;
|
||||
|
||||
half rim = 1.0f - saturate( hDotN );
|
||||
half rimPower = 16.0f;
|
||||
half3 rimColor = diffuseColor * lightProj.xyz * lightFalloff.xyz * 1.0f * pow( rim, rimPower ) * fragment.color.rgb;// * halfLdotN;
|
||||
|
||||
|
||||
//
|
||||
// shadow mapping
|
||||
//
|
||||
|
@ -278,6 +268,133 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
//float shadow = texture( samp5, shadowTexcoord.xywz );
|
||||
#endif
|
||||
|
||||
|
||||
half3 halfAngleVector = normalize( lightVector + viewVector );
|
||||
half hdotN = saturate( dot3( halfAngleVector, localNormal ) );
|
||||
|
||||
#if 1
|
||||
/*
|
||||
Physically based shading
|
||||
|
||||
Lambert diffuse BRDF combined with Cook-Torrance microfacet specular BRDF
|
||||
|
||||
D( h ) * F( v, h ) * G( l, v, h )
|
||||
f( l, v ) = diffuse + ---------------------------------
|
||||
4 * ( n * l ) ( n * v )
|
||||
*/
|
||||
|
||||
// RB: compensate r_lightScale 3 and the division of Pi
|
||||
lambert *= 1.3;
|
||||
|
||||
const half3 goldColor = half3( 1.00, 0.71, 0.29 );
|
||||
|
||||
//const half3 baseColor = goldColor;
|
||||
const half3 baseColor = diffuseMap;
|
||||
|
||||
const half metallic = 0.0;
|
||||
|
||||
// rpDiffuseModifier contains light color
|
||||
half3 lightColor = lightProj.xyz * lightFalloff.xyz * rpDiffuseModifier.xyz;
|
||||
|
||||
half vdotN = saturate( dot3( viewVector, localNormal ) );
|
||||
half vdotH = saturate( dot3( viewVector, halfAngleVector ) );
|
||||
|
||||
// the vast majority of real-world materials (anything not metal or gems) have F(0°) values in a very narrow range (~0.02 - 0.06)
|
||||
|
||||
// HACK calculate roughness from D3 gloss maps
|
||||
// converting from linear to sRGB space give pretty results
|
||||
const half glossiness = clamp( pow( dot( LUMINANCE_VECTOR.rgb, specMap.rgb ) * 0.4, 1.0 / 2.2 ) * 1.0, 0.0, 0.98 );
|
||||
|
||||
const half roughness = 1.0 - glossiness;
|
||||
|
||||
// compensate r_lightScale 3 * 2
|
||||
half3 reflectColor = specMap.rgb * rpSpecularModifier.rgb * 0.5;
|
||||
|
||||
// alpha modifications by Disney - s2012_pbs_disney_brdf_notes_v2.pdf
|
||||
const half alpha = roughness * roughness;
|
||||
|
||||
// reduce roughness range from [0 .. 1] to [0.5 .. 1]
|
||||
const half alphaG = pow( 0.5 + roughness * 0.5, 2.0 );
|
||||
|
||||
//half3 D = _half3( pow( abs( hdotN ), 10.0f ) );
|
||||
half3 D = _half3( Distribution_GGX( hdotN, alpha ) );
|
||||
//half3 D = _half3( Distribution_GGX_1886( hdotN, alpha ) );
|
||||
half3 G = _half3( Visibility_Schlick( ldotN, vdotN, alpha ) );
|
||||
//half3 G = _half3( Visibility_SmithGGX( ldotN, vdotN, alpha ) );
|
||||
half3 F = Fresnel_Schlick( reflectColor, vdotH );
|
||||
|
||||
// horizon
|
||||
float horizon = 1.0 - ldotN;
|
||||
horizon *= horizon;
|
||||
horizon *= horizon;
|
||||
half3 specLightColor = lightColor.rgb - lightColor.rgb * horizon;
|
||||
|
||||
float3 specularColor = saturate( D * G * ( F * ( specLightColor.rgb * lambert ) ) );
|
||||
|
||||
//specularColor = EnvironmentBRDFApprox( roughness, vdotN, specularColor.rgb );// * 0.45;
|
||||
|
||||
|
||||
#if 0
|
||||
result.color = float4( _half3( F ), 1.0 );
|
||||
return;
|
||||
#endif
|
||||
|
||||
// see http://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/
|
||||
lambert /= PI;
|
||||
|
||||
//half3 diffuseColor = mix( diffuseMap, F0, metal ) * rpDiffuseModifier.xyz;
|
||||
half3 diffuseColor = baseColor * rpDiffuseModifier.xyz;
|
||||
diffuseColor *= lightColor * lambert;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
maintain energy conservation
|
||||
|
||||
Energy conservation is a restriction on the reflection model
|
||||
that requires that the total amount of reflected light
|
||||
cannot be more than the incoming light.
|
||||
|
||||
http://www.rorydriscoll.com/2009/01/25/energy-conservation-in-games/
|
||||
|
||||
Cdiff + Cspec <= 1
|
||||
*/
|
||||
//diffuseColor.rgb *= ( half3( 1.0 ) - specularColor.rgb );
|
||||
|
||||
|
||||
#if 0 //defined(USE_METALNESS)
|
||||
//specularColor *= ( 0.96 * metallic ) * diffuseColor + half( 0.04 );
|
||||
diffuseColor.rgb *= ( 1.0 - metallic );
|
||||
|
||||
//diffuseColor.rgb = mix( diffuseColor, specularColor, metallic );
|
||||
#endif
|
||||
|
||||
// apply r_lightScale overbright for both diffuse and specular
|
||||
result.color.xyz = ( diffuseColor + specularColor ) * fragment.color.rgb * shadow;// + rimColor;
|
||||
result.color.w = 1.0;
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
OLD Blinn Phong
|
||||
*/
|
||||
|
||||
const half specularPower = 10.0f;
|
||||
|
||||
// RB: added abs
|
||||
half3 specularContribution = _half3( pow( abs( hdotN ), specularPower ) );
|
||||
|
||||
half3 diffuseColor = diffuseMap * rpDiffuseModifier.xyz;
|
||||
half3 specularColor = specMap.xyz * specularContribution * rpSpecularModifier.xyz;
|
||||
half3 lightColor = lightProj.xyz * lightFalloff.xyz;
|
||||
|
||||
/*
|
||||
half rim = 1.0f - saturate( hdotN );
|
||||
half rimPower = 16.0f;
|
||||
half3 rimColor = diffuseColor * lightProj.xyz * lightFalloff.xyz * 1.0f * pow( rim, rimPower ) * fragment.color.rgb;// * halfLdotN;
|
||||
*/
|
||||
|
||||
result.color.xyz = ( diffuseColor + specularColor ) * lambert * lightColor * fragment.color.rgb * shadow;// + rimColor;
|
||||
result.color.w = 1.0;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -75,22 +75,22 @@ void main( VS_IN vertex, out VS_OUT result ) {
|
|||
const float w3 = vertex.color2.w;
|
||||
|
||||
float4 matX, matY, matZ; // must be float4 for vec4
|
||||
float joint = vertex.color.x * 255.1 * 3;
|
||||
int joint = int(vertex.color.x * 255.1 * 3.0);
|
||||
matX = matrices[int(joint+0)] * w0;
|
||||
matY = matrices[int(joint+1)] * w0;
|
||||
matZ = matrices[int(joint+2)] * w0;
|
||||
|
||||
joint = vertex.color.y * 255.1 * 3;
|
||||
joint = int(vertex.color.y * 255.1 * 3.0);
|
||||
matX += matrices[int(joint+0)] * w1;
|
||||
matY += matrices[int(joint+1)] * w1;
|
||||
matZ += matrices[int(joint+2)] * w1;
|
||||
|
||||
joint = vertex.color.z * 255.1 * 3;
|
||||
joint = int(vertex.color.z * 255.1 * 3.0);
|
||||
matX += matrices[int(joint+0)] * w2;
|
||||
matY += matrices[int(joint+1)] * w2;
|
||||
matZ += matrices[int(joint+2)] * w2;
|
||||
|
||||
joint = vertex.color.w * 255.1 * 3;
|
||||
joint = int(vertex.color.w * 255.1 * 3.0);
|
||||
matX += matrices[int(joint+0)] * w3;
|
||||
matY += matrices[int(joint+1)] * w3;
|
||||
matZ += matrices[int(joint+2)] * w3;
|
||||
|
@ -177,13 +177,10 @@ void main( VS_IN vertex, out VS_OUT result ) {
|
|||
//# calculate normalized vector to viewer in R1
|
||||
float4 toView = normalize( rpLocalViewOrigin - modelPosition );
|
||||
|
||||
//# add together to become the half angle vector in object space (non-normalized)
|
||||
float4 halfAngleVector = toLightLocal + toView;
|
||||
|
||||
//# put into texture space
|
||||
result.texcoord6.x = dot3( tangent, halfAngleVector );
|
||||
result.texcoord6.y = dot3( bitangent, halfAngleVector );
|
||||
result.texcoord6.z = dot3( normal, halfAngleVector );
|
||||
result.texcoord6.x = dot3( tangent, toView );
|
||||
result.texcoord6.y = dot3( bitangent, toView );
|
||||
result.texcoord6.z = dot3( normal, toView );
|
||||
result.texcoord6.w = 1.0f;
|
||||
|
||||
result.texcoord7 = modelPosition;
|
||||
|
|
Loading…
Reference in a new issue