Skip to content

Commit

Permalink
Merge branch 'fix-pbr' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
hudrima1 committed Feb 10, 2024
2 parents 675647c + 4136558 commit c13f925
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 72 deletions.
2 changes: 1 addition & 1 deletion apps/source/AppDemo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ SLDeviceRotation AppDemo::devRot;
SLDeviceLocation AppDemo::devLoc;
SLstring AppDemo::name = "SLProjectApp";
SLstring AppDemo::appTag = "SLProject";
SLstring AppDemo::version = "4.1.002";
SLstring AppDemo::version = "4.1.003";
#ifdef _DEBUG
SLstring AppDemo::configuration = "Debug";
#else
Expand Down
48 changes: 39 additions & 9 deletions data/shaders/PBR_BRDFIntegration.frag
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Purpose: GLSL fragment program for generating a BRDF integration map,
// which is the second part of the specular integral.
// Date: April 2018
// Authors: Carlos Arauz, Marcus Hudritsch
// Authors: Carlos Arauz, Marcus Hudritsch, Marino von Wattenwyl
// License: This software is provided under the GNU General Public License
// Please visit: http://opensource.org/licenses/GPL-3.0
//#############################################################################
Expand All @@ -17,21 +17,51 @@ out vec4 o_FragColor;
// ----------------------------------------------------------------------------
const float PI = 3.14159265359;
// ----------------------------------------------------------------------------
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
// efficient VanDerCorpus calculation.

#if defined(GL_ES) // MacOS doesn't like #if GL_ES (!!!)
// Slow VanDerCorpus calculation when on OpenGL ES because Android drivers
// apparently have issues with bit operations.
// See also: https://learnopengl.com/PBR/IBL/Specular-IBL
float RadicalInverse_VdC(uint n, uint base)
{
float invBase = 1.0 / float(base);
float denom = 1.0;
float result = 0.0;

for(uint i = 0u; i < 32u; ++i)
{
if(n > 0u)
{
denom = mod(float(n), 2.0);
result += denom * invBase;
invBase = invBase / 2.0;
n = uint(float(n) / 2.0);
}
}

return result;
}
#else
// Efficient VanDerCorpus calculation
// based on: http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
float RadicalInverse_VdC(uint bits)
{
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return 0.0; // / 0x100000000
}
#endif
// ----------------------------------------------------------------------------
vec2 Hammersley(uint i, uint N)
{
#if defined(GL_ES)
return vec2(float(i)/float(N), RadicalInverse_VdC(i, 2u));
#else
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
#endif
}
// ----------------------------------------------------------------------------
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
Expand Down
8 changes: 4 additions & 4 deletions data/shaders/PBR_CylinderToCubeMap.frag
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
precision highp float;

//-----------------------------------------------------------------------------
in vec3 v_P_WS; // sample direction in world space
in vec3 v_P_WS; // sample direction in world space

uniform sampler2D u_textureEnvCubemap0; // Equirectagular map
uniform sampler2D u_environmentMap; // environment cube map texture

out vec4 o_fragColor; // output fragment color
out vec4 o_fragColor; // output fragment color
//-----------------------------------------------------------------------------
const vec2 invAtan = vec2(0.1591, 0.3183);
//-----------------------------------------------------------------------------
Expand All @@ -35,7 +35,7 @@ vec2 SampleSphericalMap(vec3 v)
void main()
{
vec2 uv = SampleSphericalMap(normalize(v_P_WS));
vec3 color = texture(u_textureEnvCubemap0, uv).rgb;
vec3 color = texture(u_environmentMap, uv).rgb;

o_fragColor = vec4(color, 1.0);
}
Expand Down
8 changes: 4 additions & 4 deletions data/shaders/PBR_IrradianceConvolution.frag
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
precision highp float;

//-----------------------------------------------------------------------------
in vec3 v_P_WS; // sample direction in world space
in vec3 v_P_WS; // sample direction in world space

uniform samplerCube u_matTextureDiffuse0; // environment cube map texture
uniform samplerCube u_environmentMap; // environment cube map texture

out vec4 o_fragColor; // output fragment color
out vec4 o_fragColor; // output fragment color
//-----------------------------------------------------------------------------
const float PI = 3.14159265359;
//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -48,7 +48,7 @@ void main()
tangentSample.y * up +
tangentSample.z * N;

irradiance += texture(u_matTextureDiffuse0, sampleVec).rgb * cos(theta) * sin(theta);
irradiance += texture(u_environmentMap, sampleVec).rgb * cos(theta) * sin(theta);
nrSamples++;
}
}
Expand Down
59 changes: 43 additions & 16 deletions data/shaders/PBR_PrefilterRoughness.frag
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@
precision highp float;

//-----------------------------------------------------------------------------
in vec3 v_P_WS; // sample direction
in vec3 v_P_WS; // sample direction

uniform samplerCube u_texture0; // Equirectagular map
uniform float u_roughness; // roughnes value
uniform samplerCube u_environmentMap; // environment cube map
uniform float u_environmentMapSize; // current mip level
uniform float u_roughness; // roughnes value

out vec4 o_fragColor; // output fragment color
out vec4 o_fragColor; // output fragment color
// ----------------------------------------------------------------------------
const float PI = 3.14159265359;
// ----------------------------------------------------------------------------
Expand All @@ -35,21 +36,49 @@ float DistributionGGX(vec3 N, vec3 H, float roughness)
return nom / denom;
}
// ----------------------------------------------------------------------------
// http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
// efficient VanDerCorpus calculation.
#if defined(GL_ES) // MacOS doesn't like #if GL_ES (!!!)
// Slow VanDerCorpus calculation when on OpenGL ES because Android drivers
// apparently have issues with bit operations.
float RadicalInverse_VdC(uint n, uint base)
{
float invBase = 1.0 / float(base);
float denom = 1.0;
float result = 0.0;

for(uint i = 0u; i < 32u; ++i)
{
if(n > 0u)
{
denom = mod(float(n), 2.0);
result += denom * invBase;
invBase = invBase / 2.0;
n = uint(float(n) / 2.0);
}
}

return result;
}
#else
// Efficient VanDerCorpus calculation
// based on: http://holger.dammertz.org/stuff/notes_HammersleyOnHemisphere.html
float RadicalInverse_VdC(uint bits)
{
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
bits = (bits << 16u) | (bits >> 16u);
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
}
#endif
// ----------------------------------------------------------------------------
vec2 Hammersley(uint i, uint N)
{
#if defined(GL_ES) // MacOS doesn't like #if GL_ES (!!!)
return vec2(float(i)/float(N), RadicalInverse_VdC(i, 2u));
#else
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
#endif
}
// ----------------------------------------------------------------------------
vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness)
Expand Down Expand Up @@ -103,13 +132,11 @@ void main()
float HdotV = max(dot(H, V), 0.0);
float pdf = D * NdotH / (4.0 * HdotV) + 0.0001;

float resolution = 512.0; // resolution of source cubemap (per face)
float saTexel = 4.0 * PI / (6.0 * resolution * resolution);
float saTexel = 4.0 * PI / (6.0 * u_environmentMapSize * u_environmentMapSize);
float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001);

float mipLevel = u_roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel);

prefilteredColor += textureLod(u_texture0, L, mipLevel).rgb * NdotL;
prefilteredColor += textureLod(u_environmentMap, L, mipLevel).rgb * NdotL;
totalWeight += NdotL;
}
}
Expand Down
1 change: 1 addition & 0 deletions modules/sl/source/gl/SLGLShader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ SLbool SLGLShader::createAndCompile(SLVLight* lights)
if (compileSuccess == GL_FALSE)
{
GLchar log[1024];
if (Utils::onlyErrorLogs) Utils::onlyErrorLogs = false;
glGetShaderInfoLog(_shaderID, sizeof(log), nullptr, &log[0]);
SL_LOG("*** COMPILER ERROR ***");
SL_LOG("Source file: %s\n", _file.c_str());
Expand Down
76 changes: 42 additions & 34 deletions modules/sl/source/gl/SLGLTextureIBL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <SLScene.h>
#include <SLGLTextureIBL.h>

//-----------------------------------------------------------------------------
const SLint ROUGHNESS_NUM_MIP_LEVELS = 5; //! Number of mip levels for roughness cubemaps
//-----------------------------------------------------------------------------
//! ctor for generated textures from hdr textures
SLGLTextureIBL::SLGLTextureIBL(SLAssetManager* am,
Expand Down Expand Up @@ -54,15 +56,15 @@ SLGLTextureIBL::SLGLTextureIBL(SLAssetManager* am,
_shaderProgram = new SLGLProgramGeneric(am,
shaderPath + "PBR_CubeMap.vert",
shaderPath + "PBR_CylinderToCubeMap.frag");
if (texType == TT_irradianceCubemap)
else if (texType == TT_irradianceCubemap)
_shaderProgram = new SLGLProgramGeneric(am,
shaderPath + "PBR_CubeMap.vert",
shaderPath + "PBR_IrradianceConvolution.frag");
if (texType == TT_roughnessCubemap)
else if (texType == TT_roughnessCubemap)
_shaderProgram = new SLGLProgramGeneric(am,
shaderPath + "PBR_CubeMap.vert",
shaderPath + "PBR_PrefilterRoughness.frag");
if (texType == TT_brdfLUT)
else if (texType == TT_brdfLUT)
_shaderProgram = new SLGLProgramGeneric(am,
shaderPath + "PBR_BRDFIntegration.vert",
shaderPath + "PBR_BRDFIntegration.frag");
Expand Down Expand Up @@ -105,7 +107,6 @@ SLGLTextureIBL::~SLGLTextureIBL()
Build the texture into a cube map, rendering the texture 6 times and capturing
each time one side of the cube (except for the BRDF LUT texture, which is
completely generated by calculations directly with the shader).
@todo Priority 1: These frame buffer ops do not work properly on iOS & Android.
This is probably the most difficult OpenGL code in the project.
*/
void SLGLTextureIBL::build(SLint texUnit)
Expand Down Expand Up @@ -155,7 +156,7 @@ void SLGLTextureIBL::build(SLint texUnit)
if (_sourceTexture != nullptr)
_sourceTexture->bindActive();

_shaderProgram->uniform1i("u_texture0", texUnit);
_shaderProgram->uniform1i("u_environmentMap", texUnit);

glActiveTexture(GL_TEXTURE0 + texUnit);
glBindTexture(_sourceTexture->target(),
Expand Down Expand Up @@ -216,52 +217,58 @@ void SLGLTextureIBL::build(SLint texUnit)
_bytesPerPixel = SL_HDR_PIXEL_BYTES;
_internalFormat = SL_HDR_GL_INTERNAL_FORMAT;

for (unsigned int i = 0; i < 6; ++i)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
0,
_internalFormat,
_width,
_height,
0,
SL_HDR_GL_FORMAT,
SL_HDR_GL_TYPE,
nullptr);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, ROUGHNESS_NUM_MIP_LEVELS - 1);

glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
// Define textures for all mip levels of all six sides of the cube map
for (SLint mipLevel = 0; mipLevel < ROUGHNESS_NUM_MIP_LEVELS; mipLevel++)
{
// Calculate the size of this mip level
SLint mipWidth = _width / (1 << mipLevel);
SLint mipHeight = _height / (1 << mipLevel);

for (SLint i = 0; i < 6; i++)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
mipLevel,
_internalFormat,
mipWidth,
mipHeight,
0,
SL_HDR_GL_FORMAT,
SL_HDR_GL_TYPE,
nullptr);
}
}

_shaderProgram->useProgram();

if (_sourceTexture != nullptr)
_sourceTexture->bindActive();
_shaderProgram->uniform1i("u_texture0", texUnit);
glActiveTexture(GL_TEXTURE0 + texUnit);
glBindTexture(_sourceTexture->target(), _sourceTexture->texID());

// Get and check power of 2
float power = log2((float)_width);
if (ceil(power) != floor(power))
SL_EXIT_MSG("SLGLTextureIBL::build: Mipmap texture must be power of two!");
_shaderProgram->uniform1i("u_environmentMap", texUnit);
_shaderProgram->uniform1f("u_environmentMapSize", (float)_sourceTexture->width());

SLuint maxMipLevels = (SLuint)power + 1;
glActiveTexture(GL_TEXTURE0 + texUnit);
glBindTexture(_sourceTexture->target(), _sourceTexture->texID());

for (SLuint mip = 0; mip < maxMipLevels; ++mip)
for (SLint mipLevel = 0; mipLevel < ROUGHNESS_NUM_MIP_LEVELS; ++mipLevel)
{
// resize framebuffer according to mip-level size
SLuint mipWidth = (SLuint)(_width * pow(0.5, mip));
SLuint mipHeight = (SLuint)(_height * pow(0.5, mip));
glViewport(0, 0, (SLsizei)mipWidth, (SLsizei)mipHeight);
// Resize framebuffer according to mip level size
SLint mipWidth = _width / (1 << mipLevel);
SLint mipHeight = _height / (1 << mipLevel);
glViewport(0, 0, mipWidth, mipHeight);

glBindFramebuffer(GL_FRAMEBUFFER, fboID);

SLfloat roughness = (SLfloat)mip / (SLfloat)(maxMipLevels - 1);
SLfloat roughness = (SLfloat)mipLevel / (SLfloat)(ROUGHNESS_NUM_MIP_LEVELS - 1);
_shaderProgram->uniform1f("u_roughness", roughness);

for (SLuint i = 0; i < 6; ++i)
{
SLMat4f mvp = _captureProjection * _captureViews[i];
Expand All @@ -270,7 +277,8 @@ void SLGLTextureIBL::build(SLint texUnit)
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + i,
_texID,
(SLint)mip);
mipLevel);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

logFramebufferStatus();
Expand All @@ -280,7 +288,7 @@ void SLGLTextureIBL::build(SLint texUnit)
if (_readBackPixels)
{
string name = "roughnessCubemap_mip" +
std::to_string(mip) + "_side" +
std::to_string(mipLevel) + "_side" +
std::to_string(i) + ".png";
readPixels((SLint)mipWidth,
(SLint)mipHeight,
Expand Down
4 changes: 2 additions & 2 deletions modules/utils/externals/zlib/contrib/minizip/zip.c
Original file line number Diff line number Diff line change
Expand Up @@ -1473,8 +1473,8 @@ extern int ZEXPORT zipWriteInFileInZip (zipFile file,const void* buf,unsigned in
err=deflate(&zi->ci.stream, Z_NO_FLUSH);
if(uTotalOutBefore > zi->ci.stream.total_out)
{
int bBreak = 0;
bBreak++;
//int bBreak = 0;
//bBreak++;
}

zi->ci.pos_in_buffered_data += (uInt)(zi->ci.stream.total_out - uTotalOutBefore) ;
Expand Down
3 changes: 1 addition & 2 deletions modules/utils/source/Utils_iOS.mm
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@

NSString* nsPath = [NSString stringWithCString:path.c_str()
encoding:[NSString defaultCStringEncoding]];
NSString* nsFolder = [NSString stringWithCString:folder.c_str()
encoding:[NSString defaultCStringEncoding]];
[NSString stringWithCString:folder.c_str() encoding:[NSString defaultCStringEncoding]];

NSFileManager* fileManager = [NSFileManager defaultManager];

Expand Down

0 comments on commit c13f925

Please sign in to comment.