OpenB3D - CubeMap

BlitzMax Forums/MiniB3D Module/OpenB3D - CubeMap

icebeararmy(Posted 2016) [#1]
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



angros47(Posted 2016) [#2]
In OpenB3D a cubemap texture is loaded with LoadAnimTexture (to load all the faces, in different frames), and has the flag 128. Those textures can be used in shaders, too, using the command ShaderTexture (OpenB3D will know, by the flag, that it's a cubemap, so a command like ShaderCube is not needed)


icebeararmy(Posted 2016) [#3]
Ah I see.
But how does it know what texture belongs to what side of the cube?

It also doesn't work for me. This code makes my shader black:
RadMap=LoadAnimTexture("skytiled.png",128,683,341,0,5)
ShaderTexture Shader,Radmap,"uRadianceMap",0



angros47(Posted 2016) [#4]
Is each frame of the file "skytiled.png" of 683x341 pixels?


icebeararmy(Posted 2016) [#5]
yes

I also tried a map with square tiles, doesn't work either:


I also can't texture entities the old way with that texture:
RadMap=LoadAnimTexture("skytiled512.png",1+128,512,512,0,5)
EntityTexture Sky,RadMap,3


EDIT: However, it works when I don't use LoadAnimTexture:
RadMap=LoadTexture("skytiled512.png",1+128)



angros47(Posted 2016) [#6]
Whoops, my mistake