-
-
Save riccardobl/373028cd15c6c2ccca83889baeccce61 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "Pipeline/utils/FastMath.glsl" | |
#define _LIGHT_TYPE_DIRECTIONAL 0 | |
#define _LIGHT_TYPE_POSITIONAL 1 | |
#define _LIGHT_TYPE_SPOT 2 | |
#ifndef PI | |
#define PI 3.14159265358979323846264 | |
#endif | |
#ifndef Light | |
struct StdLight{ | |
float invRadius; | |
vec3 position; | |
vec4 color; | |
vec3 spotDirection; | |
float spotAngleCos; | |
int type; | |
}; | |
#define Light StdLight | |
#endif | |
#ifndef ComputedJmeLight | |
struct StdComputedJmeLight { | |
vec3 color; | |
vec3 position; | |
float type; // 0 = direction 1 = positional 2 = spot | |
float attenuation; | |
float invRange; | |
float spotAngleCos; | |
vec3 spotDirection; | |
float NdotL; // cos angle between normal and light direction | |
float NdotH; // cos angle between normal and half vector | |
float LdotH; // cos angle between light direction and half vector | |
float HdotV; // cos angle between view direction and half vector | |
vec3 vector; | |
float fallOff; | |
}; | |
#define ComputedJmeLight StdComputedJmeLight | |
#endif | |
#ifndef LightsData | |
struct StdLightsData { | |
vec4 ambientLight; | |
int nLights; | |
#if MAX_LIGHTS > 0 | |
Light lights[MAX_LIGHTS]; | |
#endif | |
}; | |
#define LightsData StdLightsData | |
#endif | |
#ifndef LightIndex | |
struct StdLightIndex { | |
int index; | |
}; | |
#define LightIndex StdLightIndex | |
#endif | |
//From Frostbite PBR Course | |
//Distance based attenuation | |
// http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf | |
float _distAtt(float distSqrt, float invSqrInfluence){ | |
float factor = distSqrt * invSqrInfluence; | |
float fac = clamp(1.0 - factor * factor,0.,1.); | |
return fac * fac; | |
} | |
void Light_computeFor(vec3 worldPos,vec3 worldNormal, vec3 viewDir, inout ComputedJmeLight light){ | |
float posLight = step(0.5, light.type); | |
light.vector= light.position.xyz * sign(posLight - 0.5) - (worldPos * posLight); | |
// vec3 L=normalize(light.vector); | |
vec3 L; | |
float dist; | |
fast_lengthAndNormalize(light.vector,dist,L); | |
// L=vec3(0,1,0); | |
// dist=length(light.vector); | |
float invRange=light.invRange; | |
const float light_threshold=0.01; | |
if(invRange==0&&light.type==1.0){ | |
// light.color/=10; | |
//Compute max light power. | |
vec3 nc=(light.color.rgb)/length(light.color.rgb); | |
float power = max(max(nc.r,nc.g),nc.b); | |
float energy=length(light.color); | |
power *= abs(energy / 100.0f); | |
// Compute the distance (using the inverse square law) | |
// at which the light power reaches the light_threshold. | |
invRange= fast_inversesqrt(max(1e-16, power / max(1e-16, light_threshold))); | |
} | |
light.attenuation= (1.0 -invRange * dist) / (1.0 + invRange * dist * dist); | |
light.attenuation = clamp( light.attenuation, 1.0 - posLight, 1.0); | |
if(light.type>1.){ | |
vec3 spotdir = normalize(light.spotDirection); | |
float curAngleCos = dot(-L, spotdir); | |
float innerAngleCos = floor(light.spotAngleCos) * 0.001; | |
float outerAngleCos = fract(light.spotAngleCos); | |
float innerMinusOuter = innerAngleCos - outerAngleCos; | |
float falloff= pow(clamp((curAngleCos - outerAngleCos) / innerMinusOuter, 0.0, 1.0), 4.0); | |
light.attenuation*=falloff; | |
} | |
vec3 h=normalize(L+viewDir); | |
light.NdotL = max(dot(worldNormal, L), 0.0); | |
light.NdotH = max(dot(worldNormal, h), 0.0); | |
light.LdotH = max(dot(L, h), 0.0); | |
light.HdotV = max(dot(viewDir,h), 0.); | |
} | |
ComputedJmeLight Light_computeFor(vec3 worldPos,vec3 worldNormal, vec3 viewDir, in Light light){ | |
ComputedJmeLight clight; | |
clight.type = float(light.type); | |
clight.position = light.position; | |
clight.invRange = light.invRadius; | |
clight.color = light.color.rgb; | |
clight.spotDirection = light.spotDirection; | |
clight.spotAngleCos = light.spotAngleCos; | |
Light_computeFor(worldPos,worldNormal,viewDir,clight); | |
return clight; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef PI | |
#define PI 3.14159265358979323846264 | |
#endif | |
#define UE4_GGX | |
#ifndef Surface | |
struct PBRSurface { | |
vec3 normal; // normals w/ normalmap | |
vec3 position; | |
float opacity; | |
float metalness; // metallic value at the surface | |
// vec3 reflectance0; // full reflectance color (normal incidence angle) | |
// vec3 reflectance90; // reflectance color at grazing angle | |
float alphaRoughness; // roughness mapped to a more linear change in the roughness (proposed by [2]) | |
float roughness; | |
// vec3 diffuseColor; // color contribution from diffuse lighting | |
// vec3 specularColor; // color contribution from specular lighting | |
vec3 albedo; | |
vec3 f0; | |
float NdotV; | |
// float lightMask; // inverse of shadow map (1= light 0 =shadow) | |
vec3 emission; | |
vec3 viewDir; | |
vec3 reflectedVec; | |
float ao; | |
float depth; | |
bool frontFacing; //gl_FrontFacing | |
vec3 envLight; | |
}; | |
void PBRSurface_calcMissing(in vec3 cameraPos,in vec3 shininess,in float minRoughness,inout PBRSurface surface){ | |
surface.viewDir = normalize(cameraPos - surface.position); | |
surface.alphaRoughness = clamp(surface.roughness * surface.roughness, minRoughness, 1.0); | |
surface.f0=mix(shininess,surface.albedo,surface.metalness); | |
surface.NdotV = clamp(abs(dot(!surface.frontFacing?-surface.normal:surface.normal, surface.viewDir)), 0.001, 1.0); | |
surface.reflectedVec= normalize(reflect(-surface.viewDir, surface.normal)); | |
} | |
void PBRSurface_toGBuffer(in PBRSurface surface, inout GBuffer gbuffer){ | |
gbuffer.color=vec4(surface.albedo,surface.opacity); | |
gbuffer.emission=surface.emission; | |
gbuffer.ao=surface.ao; | |
gbuffer.worldNormal=surface.normal; | |
gbuffer.roughness=surface.roughness; | |
gbuffer.metallicness=surface.metalness; | |
gbuffer.depth=surface.depth; | |
gbuffer.worldPosition=surface.position; | |
gbuffer.frontFacing=surface.frontFacing; | |
gbuffer.envLight=surface.envLight; | |
} | |
void PBRSurface_fromGBuffer( in GBuffer gbuffer, inout PBRSurface surface){ | |
surface.albedo=gbuffer.color.rgb; | |
surface.emission=gbuffer.emission; | |
surface.ao=gbuffer.ao; | |
surface.normal=gbuffer.worldNormal; | |
surface.roughness=gbuffer.roughness; | |
surface.metalness=gbuffer.metallicness; | |
surface.depth=gbuffer.depth; | |
surface.position=gbuffer.worldPosition; | |
surface.frontFacing=gbuffer.frontFacing; | |
surface.depth=gbuffer.depth; | |
surface.envLight=gbuffer.envLight; | |
surface.opacity=gbuffer.color.a; | |
} | |
#define Surface PBRSurface | |
#endif | |
vec3 fresnelSchlick(in Surface surface,in ComputedJmeLight light){ | |
float cosTheta=light.HdotV; | |
vec3 F0=surface.f0; | |
return F0 + (1.0 - F0) * pow(max(1.0 - cosTheta,0.), 5.0); | |
} | |
// UE4 way to optimise shlick GGX Gometry shadowing term | |
float ue4GGX(in Surface surface,in ComputedJmeLight light){ | |
//G Shchlick GGX Gometry shadowing term, k = alpha/2 | |
float k = surface.alphaRoughness * 0.5; | |
/* | |
//classic Schlick ggx | |
float G_V = ndotv / (ndotv * (1.0 - k) + k); | |
float G_L = ndotl / (ndotl * (1.0 - k) + k); | |
float G = ( G_V * G_L ); | |
float specular =(D* fresnel * G) /(4 * ndotv); | |
*/ | |
//http://graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html | |
float G_V = surface.NdotV + sqrt( (surface.NdotV - surface.NdotV * k) * surface.NdotV + k ); | |
float G_L = light.NdotL + sqrt( (light.NdotL - light.NdotL * k) * light.NdotL + k ); | |
// the max here is to avoid division by 0 that may cause some small glitches. | |
return 1.0/max( G_V * G_L ,0.01); | |
} | |
float GeometrySchlickGGX(float NdotV, float roughness){ | |
float r = (roughness + 1.0); | |
float k = (r*r) / 8.0; | |
float nom = NdotV; | |
float denom = NdotV * (1.0 - k) + k; | |
return nom / denom; | |
} | |
float GeometrySmith(in Surface surface,in ComputedJmeLight light){ | |
#ifdef UE4_GGX | |
return ue4GGX(surface,light); | |
#else | |
float ggx2 = GeometrySchlickGGX(surface.NdotV, surface.roughness); | |
float ggx1 = GeometrySchlickGGX(light.NdotL, surface.roughness); | |
return ggx1 * ggx2; | |
#endif | |
} | |
float DistributionGGX(in Surface surface,in ComputedJmeLight light){ | |
float alpha = surface.alphaRoughness; | |
//D, GGX normaal Distribution function | |
float alpha2 = alpha * alpha; | |
float nom = alpha2; | |
float denom = ((light.NdotH * light.NdotH) * (alpha2 - 1.0)) + 1.0; | |
denom = PI * denom * denom; | |
denom=max(denom,1e-8); | |
return nom / denom; | |
} | |
vec3 PBR_computeDirectLight( | |
inout Surface surface, | |
in ComputedJmeLight light | |
){ | |
if(max(max(light.color.r,light.color.g),light.color.b)<0.0001)return vec3(0); | |
if (light.NdotL <= 0.0 || surface.NdotV <= 0.0||light.attenuation < 1e-8) return vec3(0); | |
vec3 pos=surface.position; | |
vec3 normal=surface.normal; | |
vec3 viewDir=surface.viewDir; | |
vec3 radiance = light.color * light.attenuation; | |
// cook-torrance brdf | |
float NDF = DistributionGGX(surface,light); | |
float G = GeometrySmith(surface,light); | |
vec3 F = fresnelSchlick(surface,light); | |
vec3 nominator = NDF * G * F; | |
float denominator = 4 * surface.NdotV * light.NdotL + 0.001; // 0.001 to prevent divide by zero. | |
vec3 specular = nominator / denominator; | |
specular=max(specular,0.); | |
// kS is equal to Fresnel | |
vec3 kS = F; | |
// for energy conservation, the diffuse and specular light can't | |
// be above 1.0 (unless the surface emits light); to preserve this | |
// relationship the diffuse component (kD) should equal 1.0 - kS. | |
vec3 kD = vec3(1.0) - kS; | |
// multiply kD by the inverse metalness such that only non-metals | |
// have diffuse lighting, or a linear blend if partly metal (pure metals | |
// have no diffuse light). | |
kD *= 1.0 - surface.metalness; | |
// kD=0; | |
vec3 dlight= (kD * surface.albedo / PI + specular) * radiance * light.NdotL; | |
// dlight= vec3( (surface.albedo / PI +specular) * radiance * light.NdotL); | |
// dlight=max(dlight,0); | |
#if defined( SHADOW_MAP) && !defined(NO_SHADOWS) | |
float lmask=surface.lightMask; | |
#ifndef POINT_LIGHT_SHADOWS | |
lmask=mix(lmask,.9,light.type==1.0); | |
#endif | |
#ifndef SPOT_LIGHT_SHADOWS | |
lmask=mix(lmask,.9,light.type==2.0); | |
#endif | |
dlight*=lmask; | |
#endif | |
return dlight; | |
} | |
// from Sebastien Lagarde https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf page 69 | |
vec3 getSpecularDominantDir(const in vec3 N, const in vec3 R, const in float realRoughness){ | |
vec3 dominant; | |
float smoothness = 1.0 - realRoughness; | |
float lerpFactor = smoothness * (sqrt(smoothness) + realRoughness); | |
// The result is not normalized as we fetch in a cubemap | |
dominant = mix(N, R, lerpFactor); | |
return dominant; | |
} | |
vec3 integrateBRDFApprox( const in vec3 specular, float roughness, float NoV ){ | |
const vec4 c0 = vec4( -1, -0.0275, -0.572, 0.022 ); | |
const vec4 c1 = vec4( 1, 0.0425, 1.04, -0.04 ); | |
vec4 r = roughness * c0 + c1; | |
float a004 = min( r.x * r.x, exp2( -9.28 * NoV ) ) * r.x + r.y; | |
vec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw; | |
return specular * AB.x + AB.y; | |
} | |
vec3 sphericalHarmonics( const in vec3 normal, const vec3 sph[9] ){ | |
float x = normal.x; | |
float y = normal.y; | |
float z = normal.z; | |
vec3 result = ( | |
sph[0] + | |
sph[1] * y + | |
sph[2] * z + | |
sph[3] * x + | |
sph[4] * y * x + | |
sph[5] * y * z + | |
sph[6] * (3.0 * z * z - 1.0) + | |
sph[7] * (z * x) + | |
sph[8] * (x*x - y*y) | |
); | |
return max(result, vec3(0.0)); | |
} | |
vec3 ApproximateSpecularIBLPolynomial(samplerCube envMap, vec3 SpecularColor , float Roughness, float ndotv, vec3 refVec, float nbMipMaps){ | |
float Lod = sqrt( Roughness ) * (nbMipMaps - 1.0); | |
vec3 PrefilteredColor = textureLod(envMap, refVec.xyz, Lod).rgb; | |
return PrefilteredColor * integrateBRDFApprox(SpecularColor, Roughness, ndotv); | |
} | |
// vec3 PBR_computeIBLContribution(in samplerCube prefEnv, | |
// in samplerCube irrMap, | |
// in mat4 lightProbeData, | |
// Surface surface | |
// ) { | |
// vec4 probePos = lightProbeData[3]; | |
// float invRadius = fract( probePos.w); | |
// vec3 rv = surface.reflectedVec; | |
// vec3 direction = surface.position - probePos.xyz; | |
// rv = invRadius * direction + rv; | |
// // ambient lighting (we now use IBL as the ambient term) | |
// vec3 F = fresnelSchlickRoughness(surface.NdotV, surface.f0,surface.roughness); | |
// vec3 kS = F; | |
// vec3 kD = 1.0 - kS; | |
// kD *= 1.0 - surface.metalness; | |
// float mipCount = probePos.w - invRadius; | |
// float lod = (surface.roughness * (mipCount)); | |
// // vec3 dominantR ;//= getSpecularDominantDir( surface.normal, rv.xyz, surface.alphaRoughness); | |
// // dominantR=rv.xyz; | |
// vec3 dominantR =getSpecularDominantDir( surface.normal, rv.xyz, surface.alphaRoughness); | |
// #ifdef BRDF | |
// vec2 brdfcoord=vec2(surface.NdotV, 1.0 - surface.roughness); | |
// vec3 brdf = texture(g_BrdfLUT,brdfcoord).xyz; | |
// #else | |
// vec3 brdf=vec3(1,1,1); | |
// #endif | |
// vec3 irradiance = textureCube(irrMap, surface.normal).rgb; | |
// vec3 prefilteredColor = textureCubeLod(prefEnv, dominantR, lod).rgb; | |
// vec3 diffuse = irradiance * surface.albedo; | |
// vec3 specular = prefilteredColor * (F * brdf.x + brdf.y); | |
// vec3 ambient= (kD * diffuse + specular) * surface.ao ; | |
// // #if defined( SHADOW_MAP) && !defined(NO_SHADOWS) | |
// // ambient*=surface.lightMask; | |
// // #endif | |
// // #if defined( SHADOW_MAP) && !defined(NO_SHADOWS) | |
// // // specular*=shadow; | |
// // diffuse=mix(diffuse,diffuse*shadow,.4); | |
// // specular=mix(specular,specular*shadow,.4); | |
// // // diffuse=diffuse*2; | |
// // #endif | |
// return ambient; | |
// } | |
void PBR_computeIBLContribution( | |
in samplerCube prefEnvMap, | |
in vec3 shCoeffs[9], | |
in mat4 lightProbeData, | |
in Surface surface, | |
in vec3 geoNormal, | |
in vec3 specularColor, | |
out float outNdf, | |
out vec3 outColor | |
) { | |
// lightProbeData is a mat4 with this layout | |
// 3x3 rot mat| | |
// 0 1 2 | 3 | |
// 0 | ax bx cx | px | ) | |
// 1 | ay by cy | py | probe position | |
// 2 | az bz cz | pz | ) | |
// --|----------| | |
// 3 | sx sy sz sp | -> 1/probe radius + nbMipMaps | |
// --scale-- | |
// parallax fix for spherical / obb bounds and probe blending from | |
// from https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ | |
vec3 rv = reflect(-surface.viewDir, surface.normal); | |
vec4 probePos = lightProbeData[3]; | |
float invRadius = fract( probePos.w); | |
float nbMipMaps = probePos.w - invRadius; | |
vec3 direction = surface.position - probePos.xyz; | |
float ndf = 0.0; | |
if(lightProbeData[0][3] != 0.0){ | |
// oriented box probe | |
mat3 wToLocalRot = inverse(mat3(lightProbeData)); | |
vec3 scale = vec3(lightProbeData[0][3], lightProbeData[1][3], lightProbeData[2][3]); | |
// probe blending | |
// compute fragment position in probe local space | |
vec3 localPos = wToLocalRot * surface.position; | |
localPos -= probePos.xyz; | |
// compute normalized distance field | |
vec3 localDir = abs(localPos); | |
localDir /= scale; | |
ndf = max(max(localDir.x, localDir.y), localDir.z); | |
// parallax fix | |
vec3 rayLs = wToLocalRot * rv; | |
rayLs /= scale; | |
vec3 positionLs = surface.position - probePos.xyz; | |
positionLs = wToLocalRot * positionLs; | |
positionLs /= scale; | |
vec3 unit = vec3(1.0); | |
vec3 firstPlaneIntersect = (unit - positionLs) / rayLs; | |
vec3 secondPlaneIntersect = (-unit - positionLs) / rayLs; | |
vec3 furthestPlane = max(firstPlaneIntersect, secondPlaneIntersect); | |
float dist = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z); | |
vec3 intersectPositionWs = surface.position + rv * dist; | |
rv = intersectPositionWs - probePos.xyz; | |
} else { | |
// spherical probe | |
// parallax fix | |
rv = invRadius * direction + rv; | |
// probe blending | |
float dist = sqrt(dot(direction, direction)); | |
ndf = dist * invRadius; | |
} | |
vec3 indirectDiffuse = vec3(0.0); | |
vec3 indirectSpecular = vec3(0.0); | |
indirectDiffuse = sphericalHarmonics(surface.normal, shCoeffs) * surface.albedo.rgb; | |
vec3 dominantR = getSpecularDominantDir( surface.normal, rv.xyz, surface.alphaRoughness); | |
indirectSpecular = ApproximateSpecularIBLPolynomial(prefEnvMap, specularColor.rgb, surface.roughness, surface.NdotV, dominantR, nbMipMaps); | |
#ifdef HORIZON_FADE | |
//horizon fade from http://marmosetco.tumblr.com/post/81245981087 | |
float horiz = dot(rv, geoNormal); | |
float horizFadePower = 1.0 - Roughness; | |
horiz = clamp( 1.0 + horizFadePower * horiz, 0.0, 1.0 ); | |
horiz *= horiz; | |
indirectSpecular *= vec3(horiz); | |
#endif | |
vec3 indirectLighting = (indirectDiffuse + indirectSpecular) * surface.ao; | |
outNdf = ndf; | |
outColor = indirectLighting * step( 0.0, probePos.w); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#extension GL_ARB_explicit_attrib_location : enable | |
#define SHININESS 0.04 | |
#define MIN_ROUGHNESS 0.005 | |
#import "Pipeline/utils/Utils.glsl" | |
#import "Pipeline/utils/GBufferF.glsl" | |
#import "Pipeline/utils/Light.glsl" | |
#import "Pipeline/utils/PBR.glsl" | |
#import "Pipeline/utils/WorldParams.glsl" | |
#define BIG_STRUCT uniform | |
#ifdef UPGRADE_BIG_STRUCT_TO_SSBO | |
#undef BIG_STRUCT | |
#define BIG_STRUCT buffer | |
#endif | |
layout (std140) uniform m_Camera { | |
Camera bo_Camera; | |
}; | |
#ifdef IS_DEFERRED | |
layout(location=0) out vec4 outData1; | |
layout(location=1) out vec4 outData2; | |
layout(location=2) out vec4 outData3; | |
#else | |
layout(location=0) out vec4 outColor; | |
layout (std140) BIG_STRUCT m_LightsData { | |
LightsData bo_LightsData; | |
}; | |
// layout (std140) BIG_STRUCT m_LightsData { | |
// LightIndex bo_LightsIndices[MAX_LIGHTS_PER_GEOM]; | |
// }; | |
uniform int m_LightsIndices[MAX_LIGHTS_PER_GEOM]; | |
uniform int m_NLightsPerGeo; | |
#endif | |
#for i=0..3 ( #if defined(PROBE_$i) $0 #endif ) | |
uniform samplerCube m_PrefilteredEnvMap$i; | |
uniform vec3 m_ShCoeff$i[9]; | |
uniform mat4 m_ProbeData$i; | |
#endfor | |
in vec2 TexCoord; | |
in vec3 WorldPos; | |
in vec3 WorldNormal; | |
#if defined(NORMALMAP) ||defined(PARALLAXMAP) | |
in vec3 WorldBinormal; | |
in vec3 WorldTangent; | |
#endif | |
// Base color | |
uniform vec4 m_BaseColor; | |
#ifdef BASECOLORMAP | |
uniform sampler2D m_BaseColorMap; | |
#endif | |
// Surface | |
uniform float m_Metallic; | |
uniform float m_Roughness; | |
#ifdef AO_ROUGHNESS_METALLIC_MAP | |
uniform sampler2D m_AORoughnessMetallicMap; | |
#endif | |
#if defined(NORMALMAP) | |
uniform sampler2D m_NormalMap; | |
#endif | |
#if defined(PARALLAXMAP) | |
uniform sampler2D m_ParallaxMap; | |
#endif | |
// Glow | |
#ifdef EMISSIVE | |
uniform vec4 m_Emissive; | |
#endif | |
#ifdef EMISSIVEMAP | |
uniform sampler2D m_EmissiveMap; | |
#endif | |
#if defined(EMISSIVE) || defined(EMISSIVEMAP) | |
uniform float m_EmissiveIntensity; | |
uniform float m_EmissivePower; | |
#endif | |
// Alpha | |
#ifdef DISCARD_ALPHA | |
uniform float m_AlphaDiscardThreshold; | |
#endif | |
void main(){ | |
#if defined(NORMALMAP) ||defined(PARALLAXMAP) | |
mat3 TBN=mat3(WorldTangent,WorldBinormal,WorldNormal); | |
#endif | |
PBRSurface surface; | |
// Parallax? | |
{ | |
} | |
// Base color & alpha | |
{ | |
vec4 baseColor=m_BaseColor; | |
#ifdef BASECOLORMAP | |
baseColor*=texture(m_BaseColorMap,TexCoord); | |
#endif | |
#ifdef DISCARD_ALPHA | |
if(baseColor.a < m_AlphaDiscardThreshold){ | |
discard; | |
return; | |
} | |
#endif | |
surface.albedo=baseColor.rgb; | |
surface.opacity=baseColor.a; | |
} | |
// Glow | |
{ | |
#ifdef EMISSIVEMAP | |
vec4 emission=texture(m_EmissiveMap,TexCoord).rgba; | |
#ifdef EMISSIVE | |
emission*=m_Emissive; | |
#endif | |
surface.emission= (emission * pow(emission.a, m_EmissivePower) * m_EmissiveIntensity).rgb; | |
#elif defined(EMISSIVE) | |
vec4 emission=m_Emissive; | |
surface.emission=(emission * pow(emission.a, m_EmissivePower) * m_EmissiveIntensity).rgb; | |
#else | |
surface.emission=vec3(0); | |
#endif | |
} | |
// AO Rough Metallic | |
{ | |
surface.ao=1.0; | |
surface.roughness=max(m_Roughness,1e-4); | |
surface.metalness=max(m_Metallic,0.0); | |
#ifdef AO_ROUGHNESS_METALLIC_MAP | |
vec4 gbufferMap=texture(m_AORoughnessMetallicMap,TexCoord); | |
surface.ao*=gbufferMap.r; | |
surface.roughness*=gbufferMap.g; | |
surface.metalness*=gbufferMap.b; | |
#endif | |
} | |
// Normals | |
{ | |
#if defined(NORMALMAP) | |
surface.normal=texture(m_NormalMap,TexCoord).rgb; | |
#ifdef OPENGL_NORMALMAP | |
surface.normal = normalize((surface.normal.xyz * vec3(2.,-2.,2.) - vec3(1.,-1.,1.))); | |
#else | |
surface.normal = normalize((surface.normal.xyz * vec3(2.,2.,2.) - vec3(1.,1.,1.))); | |
#endif | |
surface.normal=TBN*surface.normal; | |
#else | |
surface.normal=WorldNormal; | |
#endif | |
} | |
// Depth | |
{ | |
surface.depth=gl_FragCoord.z; | |
} | |
// // ViewDir | |
// { | |
// surface.viewDir=viewDir; | |
// } | |
// Position | |
{ | |
surface.position=WorldPos; | |
} | |
// gl_FrontFacing | |
{ | |
surface.frontFacing=gl_FrontFacing; | |
} | |
PBRSurface_calcMissing(bo_Camera.cameraPosition,vec3(SHININESS),MIN_ROUGHNESS,surface); | |
// surface.alphaRoughness = clamp(surface.roughness * surface.roughness, MIN_ROUGHNESS, 1.0); | |
// surface.f0=mix(vec3(SHININESS),surface.albedo,surface.metalness); | |
// surface.NdotV = clamp(abs(dot(!gl_FrontFacing?-surface.normal:surface.normal, surface.viewDir)), 0.001, 1.0); | |
// surface.reflectedVec= normalize(reflect(-surface.viewDir, surface.normal)); | |
// surface.albedo=gbuffer.color.rgb; | |
// surface.opacity=gbuffer.color.a; | |
// surface.metalness=gbuffer.metallicness; | |
// surface.roughness=gbuffer.roughness; | |
// surface.normal=gbuffer.worldNormal; | |
// surface.position=gbuffer.worldPosition; | |
// surface.ao=gbuffer.ao; | |
// surface.emission=gbuffer.emission; | |
// surface.viewDir=viewDir; | |
// surface.alphaRoughness = clamp(surface.roughness * surface.roughness, MIN_ROUGHNESS, 1.0); | |
// surface.f0=mix(vec3(SHININESS),surface.albedo,surface.metalness); | |
// surface.NdotV = clamp(abs(dot(!gl_FrontFacing?-surface.normal:surface.normal, surface.viewDir)), 0.001, 1.0); | |
// surface.reflectedVec= normalize(reflect(-surface.viewDir, surface.normal)); | |
// GBuffer gbuffer; | |
// Base color | |
// gbuffer.color=m_BaseColor; | |
// #ifdef BASECOLORMAP | |
// gbuffer.color*=texture(m_BaseColorMap,TexCoord); | |
// #endif | |
// // Glow | |
// #ifdef EMISSIVEMAP | |
// vec4 emission=texture(m_EmissiveMap,TexCoord).rgba; | |
// #ifdef EMISSIVE | |
// emission*=m_Emissive; | |
// #endif | |
// gbuffer.emission= (emission * pow(emission.a, m_EmissivePower) * m_EmissiveIntensity).rgb; | |
// #elif defined(EMISSIVE) | |
// vec4 emission=m_Emissive; | |
// gbuffer.emission=(emission * pow(emission.a, m_EmissivePower) * m_EmissiveIntensity).rgb; | |
// #else | |
// gbuffer.emission=vec3(0); | |
// #endif | |
// Surface | |
// gbuffer.ao=1.0; | |
// gbuffer.roughness=max(m_Roughness,1e-4); | |
// gbuffer.metallicness=max(m_Metallic,0.0); | |
// #ifdef AO_ROUGHNESS_METALLIC_MAP | |
// vec4 gbufferMap=texture(m_AORoughnessMetallicMap,TexCoord); | |
// gbuffer.ao*=gbufferMap.r; | |
// gbuffer.roughness*=gbufferMap.g; | |
// gbuffer.metallicness*=gbufferMap.b; | |
// #endif | |
// Normals | |
// #if defined(NORMALMAP) | |
// gbuffer.worldNormal=texture(m_NormalMap,TexCoord).rgb; | |
// #ifdef OPENGL_NORMALMAP | |
// gbuffer.worldNormal = normalize((gbuffer.worldNormal.xyz * vec3(2.,-2.,2.) - vec3(1.,-1.,1.))); | |
// #else | |
// gbuffer.worldNormal = normalize((gbuffer.worldNormal.xyz * vec3(2.,2.,2.) - vec3(1.,1.,1.))); | |
// #endif | |
// gbuffer.worldNormal=TBN*gbuffer.worldNormal; | |
// #else | |
// gbuffer.worldNormal=WorldNormal; | |
// #endif | |
// gbuffer.depth=gl_FragCoord.z; | |
// Position | |
// gbuffer.worldPosition=WorldPos.xyz; | |
// gbuffer.depth=gl_FragCoord.z; | |
// EnvLight | |
{ | |
#if NUM_PROBES > 0 | |
float probeNdfSum=0; | |
float invProbeNdfSum=0; | |
float probeWeightSum=0; | |
float specular = 0.5; | |
float nonMetalSpec = 0.08 * specular; | |
vec3 specularColor = (nonMetalSpec - nonMetalSpec * surface.metalness) + surface.albedo * surface.metalness; | |
vec3 envReflection=vec3(0); | |
#for i=0..3 ( #ifdef PROBE_$i $0 #endif ) | |
vec3 probeColor$i; | |
float probeNdf$i; | |
float probeInvNdf$i = max(1.0 - probeNdf$i,0.0); | |
PBR_computeIBLContribution(m_PrefilteredEnvMap$i,m_ShCoeff$i,m_ProbeData$i,surface,WorldNormal, specularColor, probeNdf$i, probeColor$i); | |
probeNdfSum += probeNdf$i; | |
invProbeNdfSum += max(1. - probeNdf$i, 0.0); | |
#endfor | |
#if NUM_PROBES > 1 | |
float probeWeightSum=0; | |
#for i=0..3 ( #ifdef PROBE_$i $0 #endif ) | |
float probeWeight$i = ((1.0 - (probeNdf$i / probeNdfSum)) / (NUM_PROBES - 1)) * ( probeInvNdf$i / invProbeNdfSum); | |
probeWeightSum += probeWeight$i; | |
#endfor | |
#for i=0..3 ( #ifdef PROBE_$i $0 #endif ) | |
envReflection.rgb += probeColor$i * clamp( probeWeight$i / probeWeightSum, 0., 1.); | |
#endfor | |
#elif NUM_PROBES > 0 | |
envReflection.rgb += probeColor0; | |
#endif | |
surface.envLight=envReflection.rgb; | |
#else | |
surface.envLight=vec3(0); | |
#endif | |
} | |
#ifdef IS_DEFERRED | |
// Write to gbuffer | |
GBuffer gbuffer; | |
PBRSurface_toGBuffer(surface,gbuffer); // convert to gbuffer | |
packGBuffer(gbuffer,outData1, outData2,outData3); // compress and output | |
#else | |
// Compute lights | |
#if MAX_LIGHTS > 0 | |
vec3 dlightSum=vec3(0); | |
for(int i=0;i<MAX_LIGHTS_PER_GEOM;i++){ | |
if(i>=bo_LightsData.nLights||i>=m_NLightsPerGeo)break; | |
int lightIndex=m_LightsIndices[i]; | |
Light light=bo_LightsData.lights[lightIndex]; | |
ComputedJmeLight clight=Light_computeFor(surface.position, surface.normal, surface.viewDir, light); | |
vec3 lightResult = PBR_computeDirectLight(surface,clight); | |
dlightSum += lightResult; | |
} | |
outColor.rgb+=dlightSum; | |
#endif | |
outColor.rgb += surface.envLight; | |
outColor.rgb += surface.emission; | |
outColor.rgb*=vec3(surface.ao); | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment