Hay :)
I am working on some kind of PBR-Shader with GLSL. It works good so far, but now I want to add specularity with the help of a radiance and an irradiance map. Therefor the shader needs a cubemap. The cubemap-demo (https://github.com/markcwm/openb3d.mod/blob/b9bffe0dd2766728c85faede570202eaf410ae04/examples/extended/sl_cubemap.bmx) renders the whole scene into the texture and the shader mostly ignores the other textures, so I need something like a "ShaderCube" in OpenB3D instead of "ShaderTexture". Is that possible maybe?
Here is my fragment-Shader:
uniform samplerCube uRadianceMap; //skybox
uniform samplerCube uIrradianceMap; //blurry skybox
uniform sampler2D uNormalMap;
uniform sampler2D uRoughnessMap;
uniform sampler2D uMetallicMap;
uniform sampler2D uSpecularMap;
uniform sampler2D uColorMap;
const float uExposure=20.0;
const float uGamma=2.2;
varying vec3 vNormal;
varying vec3 vPosition;
varying vec3 vEyePosition;
varying vec3 vWsNormal;
#define saturate(x) clamp(x, 0.0, 1.0)
#define PI 3.1415926535897932384626433832795
const float A = 0.15;
const float B = 0.50;
const float C = 0.10;
const float D = 0.20;
const float E = 0.02;
const float F = 0.30;
vec3 Uncharted2Tonemap( vec3 x )
{
return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;
}
vec3 EnvBRDFApprox( vec3 SpecularColor, 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 SpecularColor * AB.x + AB.y;
}
vec3 fix_cube_lookup( vec3 v, float cube_size, float lod ) {
float M = max(max(abs(v.x), abs(v.y)), abs(v.z));
float scale = 1 - exp2(lod) / cube_size;
if (abs(v.x) != M) v.x *= scale;
if (abs(v.y) != M) v.y *= scale;
if (abs(v.z) != M) v.z *= scale;
return v;
}
vec3 blendNormalsUnity( vec3 baseNormal, vec3 detailsNormal )
{
vec3 n1 = baseNormal;
vec3 n2 = detailsNormal;
mat3 nBasis = mat3(
vec3(n1.z, n1.y, -n1.x), // +90 degree rotation around y axis
vec3(n1.x, n1.z, -n1.y), // -90 degree rotation around x axis
vec3(n1.x, n1.y, n1.z));
return normalize(n2.x*nBasis[0] + n2.y*nBasis[1] + n2.z*nBasis[2]);
}
vec3 blendNormals( vec3 n1, vec3 n2 )
{
return blendNormalsUnity( n1, n2 );
}
void main() {
const float range = 0.75;
vec3 baseColor = texture2D( uColorMap, gl_TexCoord[0]).rgb;
//vec3 ao = texture( uAOMap, gl_TexCoord[0]).rgb;
float roughness = texture2D( uRoughnessMap, gl_TexCoord[0]).r;
float roughness4 = pow(roughness, 4.0);
float metallic = texture2D( uMetallicMap, gl_TexCoord[0]).r;
float _specular = texture2D( uSpecularMap, gl_TexCoord[0]).r; //_specular im Original
vec3 N = normalize( vWsNormal );
vec3 newN = blendNormals( N, texture( uNormalMap, gl_TexCoord[0] ).xyz );
// N = mix(N, newN, uNormalMapScale);
// vec3 N = vWsNormal + texture( uNormalMap, gl_TexCoord[0] ).xyz * uNormalMapScale * .5;
// N = normalize(N);
vec3 V = normalize( vEyePosition );
vec3 diffuseColor = baseColor - baseColor * metallic;
vec3 specularColor = mix( vec3( 0.08 * _specular ), baseColor, metallic );
vec3 color;
int numMips = 6;
float mip = numMips - 1 + log2(roughness);
vec3 lookup = -reflect( V, N );
lookup = fix_cube_lookup( lookup, 512, mip );
vec3 radiance = pow( textureLod( uRadianceMap, lookup, mip ).rgb, vec3( 2.2 ) );
vec3 irradiance = pow( texture( uIrradianceMap, N ).rgb, vec3( 2.2 ) );
float NoV = saturate( dot( N, V ) );
vec3 reflectance = EnvBRDFApprox( specularColor, roughness4, NoV );
vec3 diffuse = diffuseColor * irradiance;
vec3 specular = radiance * reflectance;
color = diffuse + specular;
color = Uncharted2Tonemap( color * uExposure );
color = color * ( 1.0 / Uncharted2Tonemap( vec3( 50.0 ) ) );
color = pow( color, vec3( 1.0 / uGamma ) );
gl_FragColor.rgb=color; //texture2D( uColorMap, gl_TexCoord[0]).rgb;
gl_FragColor.a=1.0;
}
I tried to give the shader the texture I used for the skybox, but somehow it still uses the whole rendered scene. Not sure why. So these two codes produce the same output:
Map_SkyTex=LoadTexture("sky1.png")
Map_SkyTex2=LoadTexture("sky1blurry.png")
ShaderTexture Shader,Map_SkyTex,"uRadianceMap",0
ShaderTexture Shader,Map_SkyTex2,"uIrradianceMap",1 and
ShaderTexture Shader,t,"uRadianceMap",0
ShaderTexture Shader,t,"uIrradianceMap",1
cube_cam=CreateCamera()
CameraToTex t,cube_cam
Do
UpdateCubemap(t,cube_cam,entity)
Loop
|