Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ protected void cleanup(Application app) {

protected Image.Format getImageFormat(Renderer renderer) {
if (this.imageFormat == null) {
this.imageFormat = renderer.getBestColorTargetFormat(true, false, false);
this.imageFormat = renderer.getBestColorTargetFormat(true, false, false, false);
}
return this.imageFormat;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ protected GenericEnvBaker(RenderManager rm, AssetManager am, Format colorFormat,

protected Format getColorFormat() {
if (colorFormat == null) {
this.colorFormat = renderManager.getRenderer().getBestColorTargetFormat(true, false, false);
this.colorFormat = renderManager.getRenderer().getBestColorTargetFormat(true, false, false, false);
}
return colorFormat;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,11 @@ public void bakeSphericalHarmonicsCoefficients() {
float remapMaxValue = 0;
Format format = Format.RGBA32F;
if (!renderManager.getRenderer().getCaps().contains(Caps.FloatColorBufferRGBA)) {
LOG.warning("Float textures not supported, using RGB8 instead. This may cause accuracy issues.");
format = Format.RGBA8;
remapMaxValue = 0.05f;
format = renderManager.getRenderer().getBestColorTargetFormat(true, true, true, false);
if(!format.isFloatingPont()){
LOG.warning("Float textures not supported, using RGB8 instead. This may cause accuracy issues.");
remapMaxValue = 0.05f;
}
}

if (remapMaxValue > 0) {
Expand Down Expand Up @@ -170,6 +172,7 @@ else if (weightAccum != c.a) {
for (int i = 0; i < NUM_SH_COEFFICIENT; ++i) {
if (remapMaxValue > 0) shCoef[i].divideLocal(remapMaxValue);
shCoef[i].multLocal(4.0f * FastMath.PI / weightAccum);
assert Vector3f.isValidVector(shCoef[i]);
}
EnvMapUtils.prepareShCoefs(shCoef);
img.dispose();
Expand Down
35 changes: 28 additions & 7 deletions jme3-core/src/main/java/com/jme3/renderer/Renderer.java
Original file line number Diff line number Diff line change
Expand Up @@ -568,13 +568,34 @@ public default Format getBestColorTargetFormat(boolean floatingPoint) {
return getBestColorTargetFormat(floatingPoint, true, false);
}

/**
* Returns the best color target format based on the requested properties and renderer capabilities.
*
* @param floatingPoint true if a floating point format is required.
* @param highPrecision true if high precision (e.g. 16-bit or 32-bit) is preferred over packed formats.
* @param withAlpha true if an alpha channel is required.
* @return the best matching Image.Format.
*/
public default Format getBestColorTargetFormat(boolean floatingPoint, boolean highPrecision, boolean withAlpha) {
return getBestColorTargetFormat(floatingPoint, highPrecision, withAlpha, true);
}

/**
* Returns the best color target format based on the requested properties and renderer capabilities.
*
* @param floatingPoint true if a floating point format is required.
* @param highPrecision true if high precision (e.g. 16-bit or 32-bit) is preferred over packed formats.
* @param withAlpha true if an alpha channel is required.
* @param supportPackedFloat true if packed float formats (e.g. RGB111110F) are allowed.
* @return the best matching Image.Format.
*/
public default Format getBestColorTargetFormat(boolean floatingPoint, boolean highPrecision, boolean withAlpha, boolean supportPackedFloat) {
Comment thread
riccardobl marked this conversation as resolved.
if (!floatingPoint) {
return Format.RGBA8;
}

if (!highPrecision) {
if (getCaps().contains(Caps.PackedFloatTexture)
if (!highPrecision && !withAlpha) {
if (supportPackedFloat && getCaps().contains(Caps.PackedFloatTexture)
&& getCaps().contains(Caps.PackedFloatColorBuffer)) {
return Format.RGB111110F;
}
Expand All @@ -586,16 +607,16 @@ && getCaps().contains(Caps.HalfFloatColorBufferRGBA)) {
return Format.RGBA16F;
}
} else {
if (getCaps().contains(Caps.PackedFloatTexture)
&& getCaps().contains(Caps.PackedFloatColorBuffer)) {
return Format.RGB111110F;
} else if (getCaps().contains(Caps.HalfFloatTexture)
if (getCaps().contains(Caps.HalfFloatTexture)
&& getCaps().contains(Caps.HalfFloatColorBufferRGB)) {
return Format.RGB16F;
} else if (getCaps().contains(Caps.HalfFloatTexture)
&& getCaps().contains(Caps.HalfFloatColorBufferRGBA)) {
return Format.RGBA16F;
}
} else if (supportPackedFloat && getCaps().contains(Caps.PackedFloatTexture)
&& getCaps().contains(Caps.PackedFloatColorBuffer)) {
return Format.RGB111110F;
}
}

return Format.RGBA8;
Expand Down
19 changes: 10 additions & 9 deletions jme3-core/src/main/resources/Common/IBL/IBLKernels.frag
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/
#import "Common/ShaderLib/GLSLCompat.glsllib"
#import "Common/IBL/Math.glsl"

#import "Common/ShaderLib/Math.glsllib"
in vec2 TexCoords;
in vec3 LocalPos;

Expand All @@ -15,12 +15,12 @@ uniform float m_Roughness;
uniform int m_FaceId;

void brdfKernel(){
float NdotV=TexCoords.x;
float roughness=TexCoords.y;
float NdotV = Math_saturate(TexCoords.x);
float roughness = Math_saturate(TexCoords.y);
float alpha = roughness * roughness;

vec3 V;
V.x = sqrt(1.0 - NdotV*NdotV);
V.x = sqrt(Math_saturate(1.0 - NdotV * NdotV));
V.y = 0.0;
V.z = NdotV;
float A = 0.0;
Expand All @@ -36,8 +36,9 @@ void brdfKernel(){
float VdotH = max(dot(V, H), 0.0);
if(NdotL > 0.0){
float G = GeometrySmith(N, V, L, alpha);
float G_Vis = (G * VdotH) / (NdotH * NdotV);
float Fc = pow(1.0 - VdotH, 5.0);
float G_Vis = (G * VdotH) / max(NdotH * NdotV, IBL_EPSILON);
float oneMinusVdotH = 1.0 - Math_saturate(VdotH);
float Fc = oneMinusVdotH * oneMinusVdotH * oneMinusVdotH * oneMinusVdotH * oneMinusVdotH;
A += (1.0 - Fc) * G_Vis;
B += Fc * G_Vis;
}
Expand All @@ -52,8 +53,8 @@ void irradianceKernel(){
// the sample direction equals the hemisphere's orientation
vec3 N = normalize(LocalPos);
vec3 irradiance = vec3(0.0);
vec3 up = vec3(0.0, 1.0, 0.0);
vec3 right = cross(up, N);
vec3 up = abs(N.y) < 0.999 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0);
vec3 right = normalize(cross(up, N));
up = cross(N, right);
float sampleDelta = 0.025;
float nrSamples = 0.0;
Expand All @@ -72,7 +73,7 @@ void irradianceKernel(){
}

void prefilteredEnvKernel(){
vec3 N = normalize(LocalPos);
vec3 N = normalize(LocalPos);
vec3 R = N;
vec3 V = R;

Expand Down
8 changes: 6 additions & 2 deletions jme3-core/src/main/resources/Common/IBL/Math.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* https://learnopengl.com/PBR/IBL/Specular-IBL
* - Riccardo Balbo
*/
#import "Common/ShaderLib/Math.glsllib"
const float PI = 3.14159265359;

float RadicalInverse_VdC(uint bits) {
Expand Down Expand Up @@ -58,6 +59,9 @@ vec4 Hammersley(uint i, uint N){
//
// ImportanceSampleGGX() and GeometrySmith() both expect alpha.
const float MIN_GGX_ALPHA = 0.0064;
const float IBL_EPSILON = 1e-6;



float SafeGGXAlpha(float alpha) {
return max(alpha, MIN_GGX_ALPHA);
Expand All @@ -66,8 +70,8 @@ float SafeGGXAlpha(float alpha) {
vec3 ImportanceSampleGGX(vec4 Xi, float alpha, vec3 N){
alpha = SafeGGXAlpha(alpha);
float alpha2 = alpha * alpha;
float cosTheta = sqrt((1.0 - Xi.y) / (1.0 + (alpha2 - 1.0) * Xi.y));
float sinTheta = sqrt(1.0 - cosTheta*cosTheta);
float cosTheta = sqrt(Math_saturate((1.0 - Xi.y) / (1.0 + (alpha2 - 1.0) * Xi.y)));
float sinTheta = sqrt(Math_saturate(1.0 - cosTheta * cosTheta));

// from spherical coordinates to cartesian coordinates
vec3 H;
Expand Down
7 changes: 4 additions & 3 deletions jme3-core/src/main/resources/Common/IBLSphH/IBLSphH.frag
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ vec3 getVectorFromCubemapFaceTexCoord(float x, float y, float mapSize, int face)


// Warp texel centers in the proximity of the edges.
float a = pow(mapSize, 2.0) / pow(mapSize - 1., 3.0);
float warpDenom = max(mapSize - 1.0, 1.0);
float a = (mapSize * mapSize) / (warpDenom * warpDenom * warpDenom);

u = a * pow(u, 3.) + u;
v = a * pow(v, 3.) + v;
u = a * u * u * u + u;
v = a * v * v * v + v;
//compute vector depending on the face
// Code from Nvtt : https://github.com/castano/nvidia-texture-tools/blob/master/src/nvtt/CubeSurface.cpp#L101
vec3 o =vec3(0);
Expand Down
4 changes: 3 additions & 1 deletion jme3-core/src/main/resources/Common/ShaderLib/Math.glsllib
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ void Math_lengthAndNormalize(in vec3 vec,out float outLength,out vec3 outNormal)
outLength=invl*dotv;
}


float Math_saturate(float value) {
return clamp(value, 0.0, 1.0);
}
#endif
34 changes: 27 additions & 7 deletions jme3-core/src/main/resources/Common/ShaderLib/PBR.glsllib
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,28 @@
#define NB_PROBES 0
#endif

#import "Common/ShaderLib/Math.glsllib"
// Internal GGX stability floor. This does not change the user-facing
// roughness convention or probe LOD mapping; it only prevents extremely sharp
// microfacet lobes from reaching pathological peaks that can destabilize some
// drivers and screenshot-test software renderers.
const float MIN_GGX_ALPHA = 0.0064;
const float PBR_EPSILON = 1e-6;

float pbrNonZero(float value) {
if (abs(value) < PBR_EPSILON) {
return value < 0.0 ? -PBR_EPSILON : PBR_EPSILON;
}
return value;
}

vec3 pbrSafeReciprocal(vec3 value) {
return vec3(
1.0 / pbrNonZero(value.x),
1.0 / pbrNonZero(value.y),
1.0 / pbrNonZero(value.z)
);
}

// BEGIN-@jhonkkk,Specular AA --------------------------------------------------------------
// see:http://www.jp.square-enix.com/tech/library/pdf/ImprovedGeometricSpecularAA(slides).pdf
Expand Down Expand Up @@ -165,16 +182,18 @@ vec3 ApproximateSpecularIBL(samplerCube envMap,sampler2D integrateBRDF, vec3 Spe
// The specular bake stores roughness quadratically across mip levels:
// mipNorm = mip / (nbMipMaps - 1), roughness = mipNorm * mipNorm.
// Runtime therefore samples with sqrt(roughness) to recover mipNorm.
float Lod = sqrt( Roughness ) * (nbMipMaps - 1.0);
float roughness = Math_saturate(Roughness);
float Lod = sqrt(roughness) * max(nbMipMaps - 1.0, 0.0);
vec3 PrefilteredColor = textureCubeLod(envMap, refVec.xyz,Lod).rgb;
vec2 EnvBRDF = texture2D(integrateBRDF,vec2(ndotv, Roughness)).rg;
vec2 EnvBRDF = texture2D(integrateBRDF,vec2(Math_saturate(ndotv), roughness)).rg;
return PrefilteredColor * ( SpecularColor * EnvBRDF.x+ EnvBRDF.y );
}

vec3 ApproximateSpecularIBLPolynomial(samplerCube envMap, vec3 SpecularColor , float Roughness, float ndotv, vec3 refVec, float nbMipMaps){
float Lod = sqrt( Roughness ) * (nbMipMaps - 1.0);
float roughness = Math_saturate(Roughness);
float Lod = sqrt(roughness) * max(nbMipMaps - 1.0, 0.0);
vec3 PrefilteredColor = textureCubeLod(envMap, refVec.xyz, Lod).rgb;
return PrefilteredColor * integrateBRDFApprox(SpecularColor, Roughness, ndotv);
return PrefilteredColor * integrateBRDFApprox(SpecularColor, roughness, clamp(ndotv, 0.0, 1.0));
}


Expand Down Expand Up @@ -203,7 +222,7 @@ float renderProbe(vec3 viewDir, vec3 worldPos, vec3 normal, vec3 norm, float Rou
// mat3_sub our compat wrapper for mat3(mat4)
mat3 wToLocalRot = inverse(mat3_sub(lightProbeData));

vec3 scale = vec3(lightProbeData[0][3], lightProbeData[1][3], lightProbeData[2][3]);
vec3 scale = max(abs(vec3(lightProbeData[0][3], lightProbeData[1][3], lightProbeData[2][3])), vec3(PBR_EPSILON));
#if NB_PROBES >= 2
// probe blending
// compute fragment position in probe local space
Expand All @@ -223,8 +242,9 @@ float renderProbe(vec3 viewDir, vec3 worldPos, vec3 normal, vec3 norm, float Rou
positionLs /= scale;

vec3 unit = vec3(1.0);
vec3 firstPlaneIntersect = (unit - positionLs) / rayLs;
vec3 secondPlaneIntersect = (-unit - positionLs) / rayLs;
vec3 invRayLs = pbrSafeReciprocal(rayLs);
vec3 firstPlaneIntersect = (unit - positionLs) * invRayLs;
vec3 secondPlaneIntersect = (-unit - positionLs) * invRayLs;
vec3 furthestPlane = max(firstPlaneIntersect, secondPlaneIntersect);
float distance = min(min(furthestPlane.x, furthestPlane.y), furthestPlane.z);

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading