Skip to content

Commit 46f36d3

Browse files
authored
Cubemap support for Emscripten and pbr cube map caching (#7347)
#changelog #emscripten
1 parent 571b1b0 commit 46f36d3

File tree

8 files changed

+804
-325
lines changed

8 files changed

+804
-325
lines changed

libs/openFrameworks/gl/ofCubeMap.cpp

Lines changed: 691 additions & 272 deletions
Large diffs are not rendered by default.

libs/openFrameworks/gl/ofCubeMap.h

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,33 @@
66

77
#pragma once
88
#include "ofFbo.h"
9+
#include "ofMesh.h"
910
class ofShader;
1011

1112
class ofGLProgrammableRenderer;
1213

1314
class ofCubeMap {
1415
public:
1516

17+
struct ofCubeMapSettings {
18+
std::string filePath = "";
19+
std::string cacheDirectory = "";
20+
21+
bool overwriteCache = false;
22+
bool useCache = false;
23+
bool useLutTex = false;
24+
bool flipVertically = true;
25+
26+
int resolution = 512;
27+
#ifdef TARGET_OPENGLES
28+
int irradianceRes = 16;
29+
int preFilterRes = 64;
30+
#else
31+
int irradianceRes = 32;
32+
int preFilterRes = 128;
33+
#endif
34+
};
35+
1636
class Data{
1737
public:
1838
GLuint cubeMapId = 0;
@@ -24,11 +44,9 @@ class ofCubeMap {
2444

2545
int index = -1;
2646
bool isEnabled = true;
27-
bool useLutTex = false;
2847

29-
int resolution = 512;
30-
int irradianceRes = 32;
31-
int preFilterRes = 128;
48+
ofCubeMapSettings settings;
49+
3250
int maxMipLevels = 5;
3351
float exposure = 1.0;
3452
};
@@ -40,8 +58,6 @@ class ofCubeMap {
4058
static void regenerateAllTextures();
4159
static const ofTexture& getBrdfLutTexture();
4260

43-
static int getNumMipMaps();
44-
4561
ofCubeMap();
4662
ofCubeMap(const ofCubeMap & mom);
4763
ofCubeMap(ofCubeMap && mom);
@@ -61,6 +77,8 @@ class ofCubeMap {
6177
/// \param aPreFilterRes resolution of the prefiltered map. (default is 128).
6278
bool load( std::string apath, int aFaceResolution, bool aBFlipY, int aIrradianceRes, int aPreFilterRes );
6379

80+
bool load( ofCubeMapSettings aSettings );
81+
6482
/// \section Update ofCubeMap
6583
/// \brief Copy a given ofCubeMap into this cube map.
6684
/// \param mom The ofCubeMap to copy from. Reuses internal GL texture IDs.
@@ -82,52 +100,63 @@ class ofCubeMap {
82100
bool hasPrefilteredMap();
83101
bool hasIrradianceMap();
84102

85-
int getFaceResolution() { return data->resolution; }
103+
int getFaceResolution() { return data->settings.resolution; }
86104
GLuint getTextureId();
87105
bool isHdr();
88106

89-
void setExposure(float aExposure) {data->exposure=aExposure;}
107+
void setExposure(float aExposure) {data->exposure=ofClamp(aExposure, 0.0f, 1.0f);}
90108
float getExposure() { return data->exposure; }
91109

92110
void setUseBrdfLutTexture( bool ab );
93-
bool isUsingLutBrdfTexture() { return data->useLutTex; }
111+
bool isUsingLutBrdfTexture() { return data->settings.useLutTex; }
94112

95113
GLuint getIrradianceMapId() { return data->irradianceMapId; }
96114
GLuint getPrefilterMapId() { return data->preFilteredMapId; }
97115

98116
protected:
99117

100-
ofFbo fbo;
101118
std::shared_ptr<ofCubeMap::Data> data;
102119

103120
void _drawCubeStart(GLuint aCubeMapId);
104121
void _drawCubeEnd();
105122

106123
void _checkSetup();
107-
void _createCubeMap();
108-
void _createIrradianceMap();
109-
void _createPrefilteredCubeMap();
124+
void _createCubeMap(ofTexture& aSrcTex);
125+
GLuint _createFloatCubeMap(ofTexture& aSrcTex, int aSrcRes);
126+
void _equiRectToCubeMap( GLuint& aCubeTexId, ofTexture& aSrcTex, int aSrcRes, bool aBConvertToNonFloat );
127+
128+
void _createIrradianceMap(GLuint aSrcCubeFid, bool aBMakeCache, std::string aCachePath);
129+
bool _loadIrradianceMap(std::string aCachePath);
130+
131+
void _createPrefilteredCubeMap(GLuint aSrcCubeFid, int aSrcRes, bool aBMakeCache, std::string aCachePath);
132+
bool _loadPrefilterMap( std::string aCachePath );
133+
110134
static void _createBrdfLUT();
111135

112-
void _configureCubeTextures(GLuint aCubeMapId);
136+
137+
void _configureCubeTextures(GLuint aCubeMapId,bool abLinearMipLinear);
113138
void _initEmptyTextures(GLuint aCubeMapId, int aSize);
114-
void _allocateFbo(int asize);
139+
void _initEmptyTextures(GLuint aCubeMapId, GLuint aInternalFormat, int aSize, int aNumMipMaps );
115140
void _allocateCubeMesh();
116141
std::vector<glm::mat4> _getViewMatrices(const glm::vec3& apos);
117142

118143
bool _loadRenderShader();
144+
bool _loadEquiRectToCubeMapShader();
145+
119146
GLuint getTexStorageFormat();
147+
GLuint getTexStorageFormat( GLuint aInternalFormat );
148+
120149
GLuint getGlTypeFromInternalFormat();
150+
GLuint getGlTypeFromInternalFormat(GLuint aInternalFormat);
151+
int getNumPixelChannels();
121152

122153
GLuint texFormat = GL_RGB;
123154

124-
ofTexture mSourceTex;
125-
bool mBFlipY = true;
126-
127155
glm::mat4 projectionMat;
128156

129157
static ofTexture sBrdfLutTex;
130158
static ofVboMesh sCubeMesh;
159+
//ofMesh sCubeMesh;
131160
ofShader shaderEquiRectToCubeMap;
132161
ofShader shaderRender;
133162
ofShader shaderIrradianceMap;

libs/openFrameworks/gl/ofCubeMapShaders.h

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@ class ofCubeMapShaders {
2323
vstr = "#version "+ofGLSLVersionFromGL(ofGetGLRenderer()->getGLVersionMajor(), ofGetGLRenderer()->getGLVersionMinor())+"\n";
2424
}
2525
#ifdef TARGET_OPENGLES
26+
vstr += "#define TARGET_OPENGLES\n";
27+
//vstr += "#extension GL_OES_standard_derivatives : enable\n";
2628
vstr += "precision highp float;\n";
2729
vstr += "precision highp int;\n";
30+
vstr += "precision highp sampler2D;\n";
31+
vstr += "precision highp samplerCube;\n";
2832
#endif
2933
return vstr;
3034
}
@@ -56,6 +60,7 @@ class ofCubeMapShaders {
5660
in vec3 oLocalPos;
5761
5862
uniform float uFlipY;
63+
uniform float uConvertToNonFloat; // 0.0 // convert hdr to non float texture
5964
6065
uniform sampler2D uEquirectangularTex;
6166
@@ -74,6 +79,14 @@ class ofCubeMapShaders {
7479
void main() {
7580
vec2 uv = SampleSphericalMap(normalize(oLocalPos)); // make sure to normalize localPos
7681
vec3 color = texture(uEquirectangularTex, uv).rgb;
82+
83+
if(uConvertToNonFloat > 0.5) {
84+
// hdr tone mapping
85+
color = color / (color+vec3(1.0));
86+
// gamma correction
87+
//color = pow(color, vec3(1.0 / 2.2));
88+
color = clamp( color, 0.0, 1.0);
89+
}
7790
7891
FRAGCOLOR = vec4(color, 1.0);
7992
}
@@ -89,9 +102,7 @@ class ofCubeMapShaders {
89102
rsource.fragShader += R"(
90103
out vec4 FRAGCOLOR;
91104
in vec3 oLocalPos;
92-
93-
//uniform float uFlipY;
94-
105+
95106
uniform samplerCube environmentMap;
96107
const float PI = 3.14159265359;
97108
@@ -122,11 +133,12 @@ class ofCubeMapShaders {
122133
vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * N;
123134
124135
irradiance += texture(environmentMap, sampleVec).rgb * cos(theta) * sin(theta);
125-
nrSamples++;
136+
//nrSamples++;
137+
nrSamples += 1.0;
126138
}
127139
}
128-
irradiance = PI * irradiance * (1.0 / float(nrSamples));
129-
140+
//irradiance = PI * irradiance * (1.0 / float(nrSamples));
141+
irradiance = irradiance * PI * (1.0 / max(nrSamples, 1.0));
130142
FRAGCOLOR = vec4(irradiance, 1.0);
131143
}
132144
)";
@@ -176,26 +188,26 @@ class ofCubeMapShaders {
176188
vec3 envColor = vec3(0.0);
177189
if( uMaxMips > 1.0 && uRoughness > 0.0 ) {
178190
envColor = getEnvColor(oTexCoords, uRoughness );
179-
// envColor = textureLod(uCubeMap, oTexCoords, getLodRoughness(uRoughness*uRoughness) ).rgb;
180-
// envColor = texture(uCubeMap, oTexCoords, getLodRoughness(uRoughness) ).rgb;
181191
} else {
182192
envColor = texture(uCubeMap, oTexCoords).rgb;
183-
// envColor = textureLod(uCubeMap, oTexCoords, 0.0).rgb;
184193
}
185-
// envColor = textureLod(uCubeMap, oTexCoords, 0.0).rgb;
186-
194+
187195
if( uIsHDR > 0.5 ) {
188-
196+
//envColor = envColor / (envColor + vec3(1.0));
189197
// exposure tone mapping
190198
vec3 mapped = vec3(1.0) - exp(-envColor * uExposure);
199+
191200
// gamma correction
192201
envColor = pow(mapped, vec3(1.0 / 2.2));
193-
202+
194203
//envColor = envColor / (envColor + vec3(1.0));
195204
//envColor = pow(envColor, vec3(1.0/2.2));
196-
}
197-
198-
FRAGCOLOR = vec4(envColor, 1.0);
205+
} else {
206+
// gamma correction
207+
envColor = pow(envColor, vec3(1.0 / max(uExposure*2.2, 0.1) ) );
208+
}
209+
210+
FRAGCOLOR = vec4(clamp(envColor, 0.0, 1.0), 1.0);
199211
}
200212
201213
)";
@@ -319,7 +331,7 @@ class ofCubeMapShaders {
319331
void main(){
320332
vec3 N = normalize(oLocalPos);
321333
322-
float roughness = uroughness;
334+
//float troughness = uroughness;
323335
324336
// make the simplyfying assumption that V equals R equals the normal
325337
vec3 R = N;
@@ -335,22 +347,23 @@ class ofCubeMapShaders {
335347
for(uint i = 0u; i < SAMPLE_COUNT; ++i){
336348
// generates a sample vector that's biased towards the preferred alignment direction (importance sampling).
337349
vec2 Xi = Hammersley(i, SAMPLE_COUNT);
338-
vec3 H = ImportanceSampleGGX(Xi, N, roughness);
350+
vec3 H = ImportanceSampleGGX(Xi, N, uroughness);
339351
vec3 L = normalize(2.0 * dot(V, H) * H - V);
340352
341353
float NdotL = max(dot(N, L), 0.0);
342354
if(NdotL > 0.0){
343355
// sample from the environment's mip level based on roughness/pdf
344-
float D = DistributionGGX(N, H, roughness);
356+
float D = DistributionGGX(N, H, uroughness);
345357
float NdotH = max(dot(N, H), 0.0);
346358
float HdotV = max(dot(H, V), 0.0);
347359
float pdf = D * NdotH / (4.0 * HdotV) + 0.0001;
348360
349-
// float resolution = 512.0; // resolution of source cubemap (per face)
361+
// //float resolution = 512.0; // resolution of source cubemap (per face)
350362
float saTexel = 4.0 * PI / (6.0 * resolution * resolution);
351363
float saSample = 1.0 / (float(SAMPLE_COUNT) * pdf + 0.0001);
352364
353-
float mipLevel = roughness == 0.0 ? 0.0 : 0.5 * log2(saSample / saTexel);
365+
float mipLevel = uroughness == 0.0 ? 0.0 : max(0.5 * log2(saSample / saTexel), 0.0);
366+
//mipLevel = clamp( mipLevel, 0.0, 4.0);
354367
355368
prefilteredColor += textureLod(environmentMap, L, mipLevel).rgb * NdotL;
356369
totalWeight += NdotL;

libs/openFrameworks/gl/ofGLUtils.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,13 @@ void ofDisableGLDebugLog();
150150
#define GL_DEPTH_COMPONENT32 GL_DEPTH_COMPONENT32_OES
151151
#endif
152152
#endif
153+
154+
#ifndef GL_RGBA32F
155+
#ifdef GL_RGBA32F_EXT
156+
#define GL_RGBA32F GL_RGBA32F_EXT
157+
#endif
158+
#endif
159+
153160
#ifdef TARGET_OPENGLES
154161
#ifndef GL_UNSIGNED_INT
155162
#define GL_UNSIGNED_INT GL_UNSIGNED_INT_OES
@@ -163,4 +170,10 @@ void ofDisableGLDebugLog();
163170
#endif
164171
#endif
165172
#endif
173+
174+
#ifndef glTexStorage2D
175+
#ifdef glTexStorage2DEXT
176+
#define glTexStorage2D glTexStorage2DEXT
177+
#endif
178+
#endif
166179
#endif

libs/openFrameworks/gl/ofMaterial.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -741,11 +741,13 @@ void ofMaterial::initShaders(ofGLProgrammableRenderer & renderer) const{
741741
fragment2DHeader += "#define FRAG_COLOR fragColor\n";
742742
fragment2DHeader += "out vec4 fragColor;\n";
743743
fragment2DHeader += "#define SAMPLER sampler2D\n";
744+
fragment2DHeader += "precision highp sampler2D;\n";
745+
fragment2DHeader += "precision highp samplerCube;\n";
744746
// we don't use any samplerCubeShadows
745747
//fragment2DHeader += "precision highp samplerCubeShadow;\n";
746-
fragment2DHeader += "precision highp sampler2DShadow;\n";
748+
fragment2DHeader += "precision mediump sampler2DShadow;\n";
747749
#if defined( GL_TEXTURE_2D_ARRAY ) && defined(glTexImage3D)
748-
fragment2DHeader += "precision highp sampler2DArrayShadow;\n";
750+
fragment2DHeader += "precision mediump sampler2DArrayShadow;\n";
749751
#endif
750752
// fragment2DHeader += "precision highp samplerCubeShadow;\n";
751753
// fragment2DHeader += "precision highp sampler2DShadow;\n";
@@ -871,10 +873,12 @@ void ofMaterial::updateMaterial(const ofShader & shader,ofGLProgrammableRenderer
871873
std::shared_ptr<ofCubeMap::Data> cubeMapData = ofCubeMap::getActiveData();
872874
if( cubeMapData ) {
873875
shader.setUniform1f("mat_ibl_exposure", cubeMapData->exposure );
874-
shader.setUniform1f("uCubeMapEnabled", 1.0);
876+
shader.setUniform1f("uCubeMapEnabled", 1.0f );
877+
shader.setUniform1f("uEnvMapMaxMips", cubeMapData->maxMipLevels );
875878
} else {
876-
shader.setUniform1f("mat_ibl_exposure", 1.0 );
877-
shader.setUniform1f("uCubeMapEnabled", 0.0);
879+
shader.setUniform1f("mat_ibl_exposure", 1.0f );
880+
shader.setUniform1f("uCubeMapEnabled", 0.0f );
881+
shader.setUniform1f("uEnvMapMaxMips", 1.0f );
878882
}
879883

880884
} else {
@@ -1252,7 +1256,7 @@ const std::string ofMaterial::getDefinesString() const {
12521256
if( cmd->bPreFilteredMapAllocated ) {
12531257
bPreFilteredMap=true;
12541258
}
1255-
if( cmd->useLutTex && ofCubeMap::getBrdfLutTexture().isAllocated() ) {
1259+
if( cmd->settings.useLutTex && ofCubeMap::getBrdfLutTexture().isAllocated() ) {
12561260
bBrdfLutTex=true;
12571261
}
12581262
}
@@ -1267,7 +1271,7 @@ const std::string ofMaterial::getDefinesString() const {
12671271
definesString += "#define HAS_TEX_ENV_BRDF_LUT 1\n";
12681272
}
12691273
// need to add .0 to be read as a float in the shader for gl es
1270-
definesString += "#define ENV_MAP_MAX_MIPS "+ofToString(ofCubeMap::getNumMipMaps(),0)+".0\n";
1274+
//definesString += "#define ENV_MAP_MAX_MIPS "+ofToString(ofCubeMap::getNumMipMaps(),0)+".0\n";
12711275

12721276
}
12731277

libs/openFrameworks/gl/ofShader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1510,7 +1510,7 @@ bool ofShader::setPbrEnvironmentMapUniforms( int textureLocation ) const {
15101510
if(cubeMapData->bPreFilteredMapAllocated) {
15111511
setUniformTexture("tex_prefilterEnvMap", GL_TEXTURE_CUBE_MAP, cubeMapData->preFilteredMapId, textureLocation+1 );
15121512
}
1513-
if( cubeMapData->useLutTex && ofCubeMap::getBrdfLutTexture().isAllocated() ) {
1513+
if( cubeMapData->settings.useLutTex && ofCubeMap::getBrdfLutTexture().isAllocated() ) {
15141514
setUniformTexture("tex_brdfLUT", ofCubeMap::getBrdfLutTexture(), textureLocation+2 );
15151515
}
15161516
}

libs/openFrameworks/gl/ofShadow.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1035,7 +1035,7 @@ void ofShadow::_allocateFbo() {
10351035
}
10361036
#endif
10371037

1038-
#ifdef GL_CLAMP_TO_BORDER
1038+
#ifdef GL_CLAMP_TO_BORDER && !defined(TARGET_EMSCRIPTEN)
10391039
glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
10401040
glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
10411041
float borderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };

0 commit comments

Comments
 (0)