PBR-ish stuff
Subsurface scattering doesn't work, though
This commit is contained in:
parent
aabf8949a8
commit
df06cf16ad
5 changed files with 207 additions and 113 deletions
|
@ -26,6 +26,8 @@ T_Raymarcher::T_Raymarcher(
|
||||||
glGenProgramPipelines( 1 , &pipeline_ );
|
glGenProgramPipelines( 1 , &pipeline_ );
|
||||||
|
|
||||||
program_.addFile( "raymarch-header.glsl" );
|
program_.addFile( "raymarch-header.glsl" );
|
||||||
|
program_.addFile( "pbr.glsl" );
|
||||||
|
program_.addFile( "blinn-phong.glsl" );
|
||||||
program_.addFile( "map.glsl" );
|
program_.addFile( "map.glsl" );
|
||||||
program_.addFile( "raymarcher.glsl" );
|
program_.addFile( "raymarcher.glsl" );
|
||||||
program_.load( );
|
program_.load( );
|
||||||
|
@ -67,7 +69,7 @@ void T_Raymarcher::render( )
|
||||||
glProgramUniform3fv( program_.id( ) , U_CAM_UP , 1 , &camera_.up.x );
|
glProgramUniform3fv( program_.id( ) , U_CAM_UP , 1 , &camera_.up.x );
|
||||||
glProgramUniform1f( program_.id( ) , U_NEAR_PLANE , camera_.np );
|
glProgramUniform1f( program_.id( ) , U_NEAR_PLANE , camera_.np );
|
||||||
|
|
||||||
glProgramUniform3f( program_.id( ) , U_LIGHT_DIR , 0 , 1 , 1 );
|
glProgramUniform3f( program_.id( ) , U_LIGHT_DIR , 0 , 1 , -1 );
|
||||||
|
|
||||||
glProgramUniform4f( program_.id( ) , U_RAYMARCHER , rmIterations , rmStep ,
|
glProgramUniform4f( program_.id( ) , U_RAYMARCHER , rmIterations , rmStep ,
|
||||||
rmEpsilon , rmMaxDist );
|
rmEpsilon , rmMaxDist );
|
||||||
|
|
21
shaders/blinn-phong.glsl
Normal file
21
shaders/blinn-phong.glsl
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
struct T_BPMaterial
|
||||||
|
{
|
||||||
|
vec3 cAlbedo, cSpecular;
|
||||||
|
float specPower , ambient;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
vec3 BP_Shade(
|
||||||
|
in T_BPMaterial material ,
|
||||||
|
in vec3 rayDir ,
|
||||||
|
in vec3 normal ,
|
||||||
|
in vec3 lightDir )
|
||||||
|
{
|
||||||
|
const vec3 halfVec = normalize( rayDir + lightDir );
|
||||||
|
const float nDotL = dot( normal , lightDir ) ,
|
||||||
|
nDotH = dot( normal , halfVec ) ,
|
||||||
|
si = pow( clamp( nDotH , 0 , 1 ) , material.specPower ) ,
|
||||||
|
di = material.ambient + ( 1 - material.ambient )
|
||||||
|
* clamp( nDotL , 0 , 1 );
|
||||||
|
return mix( material.cAlbedo * di , material.cSpecular , si );
|
||||||
|
}
|
|
@ -1,3 +1,38 @@
|
||||||
|
#define USE_GLOW
|
||||||
|
#define USE_MAP_MATERIAL
|
||||||
|
|
||||||
|
T_BPMaterial BPMaterials[1] = {
|
||||||
|
{ vec3( 1 , 1 , 0 ) , vec3( 1 ) , 4 , .3 }
|
||||||
|
};
|
||||||
|
|
||||||
|
T_PBRMaterial PBRMaterials[1] = {
|
||||||
|
{
|
||||||
|
// Albedo / specular colors
|
||||||
|
vec3( 1 , 1 , 0 ) , vec3( 1 , 1 , .4 ) ,
|
||||||
|
// Roughness , anisotropy , subsurface , metallic
|
||||||
|
.1 , 0 , 0 , .75
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
vec3 Glow[1] = {
|
||||||
|
vec3( 5. , .1 , 4. )
|
||||||
|
};
|
||||||
|
|
||||||
|
void mapMaterial(
|
||||||
|
in int matIndex ,
|
||||||
|
out int type ,
|
||||||
|
out int tIndex ,
|
||||||
|
out int glowIndex )
|
||||||
|
{
|
||||||
|
if ( matIndex == 0 ) {
|
||||||
|
type = 0;
|
||||||
|
} else {
|
||||||
|
type = 1;
|
||||||
|
}
|
||||||
|
tIndex = 0;
|
||||||
|
glowIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
vec2 map( vec3 pos )
|
vec2 map( vec3 pos )
|
||||||
{
|
{
|
||||||
vec3 q = pos;
|
vec3 q = pos;
|
||||||
|
|
102
shaders/pbr.glsl
Normal file
102
shaders/pbr.glsl
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
struct T_PBRMaterial
|
||||||
|
{
|
||||||
|
vec3 cAlbedo, cSpecular;
|
||||||
|
float roughness , anisotropy , subsurface , metallic;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct T_PBRPrecomputed
|
||||||
|
{
|
||||||
|
float nDotC;
|
||||||
|
float ffndc; // Fresnel from n.c
|
||||||
|
vec3 tangent, bitangent;
|
||||||
|
float specAlpha , viewSpecular;
|
||||||
|
float aAspectX , aAspectY; // Anisotropy
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
float PBR_FresnelFrom( in float dotProduct ) {
|
||||||
|
float d = clamp( 1.0 - dotProduct , 0.0 , 1.0 );
|
||||||
|
return d * d * d * d * d;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PBR_GetSpecular( in float cosine , in float alpha )
|
||||||
|
{
|
||||||
|
float cs = cosine * cosine;
|
||||||
|
float as = alpha * alpha;
|
||||||
|
return 1. / ( cosine + sqrt( cs + as - cs * as ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Precompute some of the material's properties. This is independant of the
|
||||||
|
// light source.
|
||||||
|
T_PBRPrecomputed PBR_Precompute(
|
||||||
|
in T_PBRMaterial material ,
|
||||||
|
in vec3 rayDir ,
|
||||||
|
in vec3 normal )
|
||||||
|
{
|
||||||
|
T_PBRPrecomputed rv;
|
||||||
|
|
||||||
|
rv.nDotC = dot( normal , rayDir );
|
||||||
|
rv.ffndc = PBR_FresnelFrom( rv.nDotC );
|
||||||
|
|
||||||
|
rv.tangent = cross( vec3( 0. , 1. , 0. ) , normal );
|
||||||
|
if ( length( rv.tangent ) == 0.0 ) {
|
||||||
|
rv.tangent = cross( vec3( 1. , 0. , 0. ) , normal );
|
||||||
|
}
|
||||||
|
rv.tangent = normalize( rv.tangent );
|
||||||
|
rv.bitangent = normalize( cross( normal , rv.tangent ) );
|
||||||
|
|
||||||
|
rv.specAlpha = pow( material.roughness * .5 + .5 , 2. );
|
||||||
|
rv.viewSpecular = PBR_GetSpecular( rv.nDotC , rv.specAlpha );
|
||||||
|
|
||||||
|
const float sRoughness = material.roughness * material.roughness;
|
||||||
|
const float aspect = sqrt( 1.0 - material.anisotropy * .9 );
|
||||||
|
rv.aAspectX = max( .001, sRoughness / aspect );
|
||||||
|
rv.aAspectY = max( .001, sRoughness * aspect );
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actually compute a light source's contribution
|
||||||
|
vec3 PBR_Shade(
|
||||||
|
in T_PBRMaterial material ,
|
||||||
|
in T_PBRPrecomputed precomputed ,
|
||||||
|
in vec3 rayDir ,
|
||||||
|
in vec3 normal ,
|
||||||
|
in vec3 lightDir )
|
||||||
|
{
|
||||||
|
const float nDotL = dot( normal , lightDir );
|
||||||
|
if ( nDotL <= 0. ) {
|
||||||
|
return vec3( 0. );
|
||||||
|
}
|
||||||
|
|
||||||
|
const vec3 halfVec = normalize( lightDir + rayDir );
|
||||||
|
const float nDotH = dot( normal , halfVec );
|
||||||
|
const float lDotH = dot( lightDir , halfVec );
|
||||||
|
|
||||||
|
const float ffndl = PBR_FresnelFrom( nDotL );
|
||||||
|
float grazingDiffuse = lDotH * lDotH * material.roughness;
|
||||||
|
float dSubsurface = mix( 1.0 , grazingDiffuse , ffndl )
|
||||||
|
* mix( 1.0 , grazingDiffuse , precomputed.ffndc );
|
||||||
|
dSubsurface = 1.25 * ( dSubsurface * ( 1.0 / ( nDotL + precomputed.nDotC ) - .5 ) + .5 );
|
||||||
|
grazingDiffuse = .5 + 2. * grazingDiffuse;
|
||||||
|
const float dFresnel = mix( 1.0 , grazingDiffuse , ffndl )
|
||||||
|
* mix( 1.0 , grazingDiffuse , precomputed.ffndc );
|
||||||
|
|
||||||
|
float specular = PBR_GetSpecular( nDotL , precomputed.specAlpha )
|
||||||
|
* precomputed.viewSpecular;
|
||||||
|
specular = mix( specular , 1.0 , PBR_FresnelFrom( lDotH ) );
|
||||||
|
|
||||||
|
const vec3 d = vec3(
|
||||||
|
dot( halfVec , precomputed.tangent ) / precomputed.aAspectX ,
|
||||||
|
dot( halfVec , precomputed.bitangent ) / precomputed.aAspectY ,
|
||||||
|
nDotH );
|
||||||
|
const float ds = dot( d , d );
|
||||||
|
const float anisotropic = precomputed.aAspectX * precomputed.aAspectY
|
||||||
|
* ds * ds * 3.14159265;
|
||||||
|
|
||||||
|
return nDotL * ( material.cAlbedo
|
||||||
|
* mix( dFresnel , dSubsurface , material.subsurface )
|
||||||
|
* pow( 1.0 - material.metallic , 3 )
|
||||||
|
+ specular * material.cSpecular / anisotropic
|
||||||
|
);
|
||||||
|
}
|
|
@ -28,23 +28,6 @@ vec3 march( vec3 o , vec3 d , int steps , float factor )
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
/*
|
|
||||||
float computeIsolines( in float value , in float dist )
|
|
||||||
{
|
|
||||||
float f0 = u_DebugPlaneLines.w , f1 = f0 * f0 , f2 = f1 * f0;
|
|
||||||
vec3 iso = vec3(
|
|
||||||
fract( value * f0 ) * 2 - 1 ,
|
|
||||||
fract( value * f1 ) * 2 - 1 ,
|
|
||||||
fract( value * f2 ) * 2 - 1 );
|
|
||||||
iso = pow( abs( iso ) , 100 / vec3( f0 , f1 , f2 ) )
|
|
||||||
* pow( 1 - dist * .02 , 8 );
|
|
||||||
return mix( mix( iso.z , iso.y , step( 1 / f1 , value ) ) ,
|
|
||||||
iso.x , step( 1 / f0 , value ) );
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void main( )
|
void main( )
|
||||||
{
|
{
|
||||||
setCamFromUniforms( );
|
setCamFromUniforms( );
|
||||||
|
@ -60,105 +43,56 @@ void main( )
|
||||||
vec3 r = march( camPos , rayDir , int( u_Render.x ) , u_Render.y );
|
vec3 r = march( camPos , rayDir , int( u_Render.x ) , u_Render.y );
|
||||||
vec3 hitPos = camPos + rayDir * r.x;
|
vec3 hitPos = camPos + rayDir * r.x;
|
||||||
|
|
||||||
vec3 bc;
|
vec3 bc = vec3( 0 );
|
||||||
if ( r.y >= 0. ) {
|
if ( r.y >= 0. ) {
|
||||||
bc = vec3( 1. , 1. , 0. );
|
const int midx = int( r.y );
|
||||||
vec3 hvec = normalize( rayDir - u_LightDir ) ,
|
const vec3 normal = getNormal( hitPos );
|
||||||
norm = getNormal( hitPos );
|
|
||||||
float ndotl = dot( norm , -normalize( u_LightDir ) ) ,
|
#if defined( USE_BP )
|
||||||
ndoth = dot( norm , hvec );
|
// Blinn-Phong only
|
||||||
float si = pow( clamp( ndoth , 0 , 1 ) , 4 ) ,
|
bc = BP_Shade( BPMaterials[ midx ] ,
|
||||||
di = .6 + .3 * clamp( ndotl , 0 , 1 );
|
rayDir , normal , -u_LightDir );
|
||||||
bc = mix( bc * di , vec3( 1. ) , si );
|
|
||||||
if ( r.y >= 1. ) {
|
#else
|
||||||
bc += vec3( 5. , .1 , 4. ) * 4;
|
#if defined( USE_PBR )
|
||||||
}
|
// PBR only
|
||||||
|
T_PBRMaterial material = PBRMaterials[ midx ];
|
||||||
|
T_PBRPrecomputed precomputed = PBR_Precompute(
|
||||||
|
material , rayDir , normal );
|
||||||
|
bc = PBR_Shade( material , precomputed ,
|
||||||
|
rayDir , normal , -u_LightDir );
|
||||||
|
|
||||||
|
#else
|
||||||
|
#if defined( USE_MAP_MATERIAL )
|
||||||
|
// Remap materials through mapMaterials
|
||||||
|
int mtype , mtidx , glowidx;
|
||||||
|
mapMaterial( midx , mtype , mtidx , glowidx );
|
||||||
|
if ( mtype == 0 ) {
|
||||||
|
bc = BP_Shade( BPMaterials[ mtidx ] ,
|
||||||
|
rayDir , normal , -u_LightDir );
|
||||||
} else {
|
} else {
|
||||||
bc = vec3( 0. );
|
T_PBRMaterial material = PBRMaterials[ mtidx ];
|
||||||
|
T_PBRPrecomputed precomputed = PBR_Precompute(
|
||||||
|
material , rayDir , normal );
|
||||||
|
bc = PBR_Shade( material , precomputed ,
|
||||||
|
rayDir , normal , -u_LightDir );
|
||||||
|
}
|
||||||
|
#if defined( USE_GLOW )
|
||||||
|
if ( glowidx > 0 ) {
|
||||||
|
bc += Glow[ glowidx ];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_GLOW
|
||||||
|
#ifndef USE_MAP_MATERIAL
|
||||||
|
bc += Glow[ midx ];
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
o_Color = bc;
|
o_Color = bc;
|
||||||
o_Z = r.x;
|
o_Z = r.x;
|
||||||
|
|
||||||
/*
|
|
||||||
if ( r.y == -2 ) {
|
|
||||||
// Debug plane
|
|
||||||
float v = map( hitPos ).x;
|
|
||||||
vec3 pc = mix( mix( mix(
|
|
||||||
vec3( .4 , .05 , .4 ) ,
|
|
||||||
vec3( .6 , .2 , .2 ) ,
|
|
||||||
smoothstep( 0 , 1 , v ) ) ,
|
|
||||||
vec3( 1 , .8 , .4 ) ,
|
|
||||||
smoothstep( 1 , 2 , v ) ) ,
|
|
||||||
vec3( 1 ) , smoothstep( 2 , 3 , v ) );
|
|
||||||
color = vec4( mix( pc , u_DebugPlaneLines.rgb ,
|
|
||||||
computeIsolines( v , r.x ) ) , 1 );
|
|
||||||
|
|
||||||
} else if ( r.y == -1 ) {
|
|
||||||
color = vec4( 0 , 0 , 0 , 1 );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Base color
|
|
||||||
vec3 bc;
|
|
||||||
if ( dispMode == 1 ) {
|
|
||||||
// Single color mode
|
|
||||||
bc = u_ObjColor;
|
|
||||||
} else if ( dispMode == 2 ) {
|
|
||||||
// Iterations
|
|
||||||
bc = mix( u_ObjColor , u_ObjColor2 , r.z / u_Render.x );
|
|
||||||
} else {
|
|
||||||
// Distance
|
|
||||||
bc = mix( u_ObjColor , u_ObjColor2 , r.x / u_Render.w );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Grid
|
|
||||||
if ( ( u_DebugFeatures.x & 0x04 ) != 0 ) {
|
|
||||||
vec3 hpf = fract( hitPos / u_DebugGrid.x ) * 2 - 1;
|
|
||||||
hpf = 1 - smoothstep( vec3( 1 - .01 / u_DebugGrid.x ) ,
|
|
||||||
vec3( 1 ) , abs( hpf ) );
|
|
||||||
bc = mix( u_DebugGrid.yzw , bc ,
|
|
||||||
hpf.x * hpf.y * hpf.z );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ( u_DebugFeatures & 0x20 ) != 0 ) {
|
|
||||||
vec3 hvec = normalize( rayDir - u_LightDir ) ,
|
|
||||||
norm = getNormal( hitPos );
|
|
||||||
float ndotl = dot( norm , -normalize( u_LightDir ) ) ,
|
|
||||||
ndoth = dot( norm , hvec );
|
|
||||||
float si = pow( clamp( ndoth , 0 , 1 ) , 4 ) ,
|
|
||||||
di = .6 + .3 * clamp( ndotl , 0 , 1 );
|
|
||||||
bc = mix( bc * di , vec3( u_ObjColor ) , si );
|
|
||||||
}
|
|
||||||
|
|
||||||
color = vec4( bc , 1 );
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Translucent isolines
|
|
||||||
/*
|
|
||||||
if ( ( u_DebugFeatures.x & 3 ) == 2 ) {
|
|
||||||
float pint = dot( rayDir , u_DebugPlane.xyz );
|
|
||||||
if ( abs( pint ) > .0001 ) {
|
|
||||||
float pdist = u_DebugPlane.w - .5 * u_DebugPlaneTrans.x * u_DebugPlaneTrans.y;
|
|
||||||
float cpdotpn = dot( camPos , u_DebugPlane.xyz );
|
|
||||||
int nbp = int( u_DebugPlaneTrans.x );
|
|
||||||
for ( int i = 0 ; i < nbp ; i ++ ) {
|
|
||||||
float t = ( pdist - cpdotpn ) / pint;
|
|
||||||
if ( t > .0001 && ( t < r.x || r.y == -1. ) ) {
|
|
||||||
float v = map( camPos + t * rayDir ).x;
|
|
||||||
bool inside = v <= 0;
|
|
||||||
vec3 col = inside
|
|
||||||
? ( vec3(1) - u_DebugPlaneLines.rgb )
|
|
||||||
: u_DebugPlaneLines.rgb;
|
|
||||||
color.rgb += mix(
|
|
||||||
vec3( .05 ) ,
|
|
||||||
col * u_DebugPlaneTrans.w ,
|
|
||||||
computeIsolines( v , t ) )
|
|
||||||
* ( 1 - min( 1 , abs( v ) / u_DebugPlaneTrans.z ) );
|
|
||||||
}
|
|
||||||
pdist += u_DebugPlaneTrans.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue