diff options
| author | raysan5 <[email protected]> | 2021-04-02 15:34:32 +0200 |
|---|---|---|
| committer | raysan5 <[email protected]> | 2021-04-02 15:34:32 +0200 |
| commit | 51f3129c5dfa4be70787fa9c4473335252abffcd (patch) | |
| tree | ec61049855f0c3d7207c552ba5fb10696cc38cbf /examples/models/models_skybox.c | |
| parent | ccdf7ff335795a7828bf53faedb8f7d5be8c47cf (diff) | |
| download | raylib-51f3129c5dfa4be70787fa9c4473335252abffcd.tar.gz raylib-51f3129c5dfa4be70787fa9c4473335252abffcd.zip | |
Reviewed examples
Diffstat (limited to 'examples/models/models_skybox.c')
| -rw-r--r-- | examples/models/models_skybox.c | 84 |
1 files changed, 81 insertions, 3 deletions
diff --git a/examples/models/models_skybox.c b/examples/models/models_skybox.c index e03aaab0..cef34611 100644 --- a/examples/models/models_skybox.c +++ b/examples/models/models_skybox.c @@ -12,7 +12,8 @@ #include "raylib.h" #include "rlgl.h" -bool useHDR = false; +// Generate cubemap (6 faces) from equirectangular (panorama) texture +static TextureCubemap GenTextureCubemap(Shader shader, Texture2D panorama, int size, int format); int main(void) { @@ -29,6 +30,8 @@ int main(void) // Load skybox model Mesh cube = GenMeshCube(1.0f, 1.0f, 1.0f); Model skybox = LoadModelFromMesh(cube); + + bool useHDR = false; // Load skybox shader and set required locations // NOTE: Some locations are automatically set at shader loading @@ -62,7 +65,7 @@ int main(void) // NOTE 1: New texture is generated rendering to texture, shader calculates the sphere->cube coordinates mapping // NOTE 2: It seems on some Android devices WebGL, fbo does not properly support a FLOAT-based attachment, // despite texture can be successfully created.. so using PIXELFORMAT_UNCOMPRESSED_R8G8B8A8 instead of PIXELFORMAT_UNCOMPRESSED_R32G32B32A32 - skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = rlGenTextureCubemap(shdrCubemap, panorama, 1024, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8); + skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = GenTextureCubemap(shdrCubemap, panorama, 1024, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8); UnloadTexture(panorama); // Texture not required anymore, cubemap already generated } @@ -102,7 +105,7 @@ int main(void) Texture2D panorama = LoadTexture(droppedFiles[0]); // Generate cubemap from panorama texture - skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = rlGenTextureCubemap(shdrCubemap, panorama, 1024, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8); + skybox.materials[0].maps[MATERIAL_MAP_CUBEMAP].texture = GenTextureCubemap(shdrCubemap, panorama, 1024, PIXELFORMAT_UNCOMPRESSED_R8G8B8A8); UnloadTexture(panorama); } else @@ -162,3 +165,78 @@ int main(void) return 0; } + +// Generate cubemap texture from HDR texture +static TextureCubemap GenTextureCubemap(Shader shader, Texture2D panorama, int size, int format) +{ + TextureCubemap cubemap = { 0 }; + + rlDisableBackfaceCulling(); // Disable backface culling to render inside the cube + + // STEP 1: Setup framebuffer + //------------------------------------------------------------------------------------------ + unsigned int rbo = rlLoadTextureDepth(size, size, true); + cubemap.id = rlLoadTextureCubemap(0, size, format); + + unsigned int fbo = rlLoadFramebuffer(size, size); + rlFramebufferAttach(fbo, rbo, RL_ATTACHMENT_DEPTH, RL_ATTACHMENT_RENDERBUFFER, 0); + rlFramebufferAttach(fbo, cubemap.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X, 0); + + // Check if framebuffer is complete with attachments (valid) + if (rlFramebufferComplete(fbo)) TraceLog(LOG_INFO, "FBO: [ID %i] Framebuffer object created successfully", fbo); + //------------------------------------------------------------------------------------------ + + // STEP 2: Draw to framebuffer + //------------------------------------------------------------------------------------------ + // NOTE: Shader is used to convert HDR equirectangular environment map to cubemap equivalent (6 faces) + rlEnableShader(shader.id); + + // Define projection matrix and send it to shader + Matrix matFboProjection = MatrixPerspective(90.0*DEG2RAD, 1.0, RL_CULL_DISTANCE_NEAR, RL_CULL_DISTANCE_FAR); + rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_PROJECTION], matFboProjection); + + // Define view matrix for every side of the cubemap + Matrix fboViews[6] = { + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ -1.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, 1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }), + MatrixLookAt((Vector3){ 0.0f, 0.0f, 0.0f }, (Vector3){ 0.0f, 0.0f, -1.0f }, (Vector3){ 0.0f, -1.0f, 0.0f }) + }; + + rlViewport(0, 0, size, size); // Set viewport to current fbo dimensions + + for (int i = 0; i < 6; i++) + { + rlSetUniformMatrix(shader.locs[SHADER_LOC_MATRIX_VIEW], fboViews[i]); + rlFramebufferAttach(fbo, cubemap.id, RL_ATTACHMENT_COLOR_CHANNEL0, RL_ATTACHMENT_CUBEMAP_POSITIVE_X + i, 0); + + rlEnableFramebuffer(fbo); + rlSetTexture(panorama.id); // WARNING: It must be called after enabling current framebuffer if using internal batch system! + + rlClearScreenBuffers(); + DrawCubeV(Vector3Zero(), Vector3One(), WHITE); + rlDrawRenderBatchActive(); + } + //------------------------------------------------------------------------------------------ + + // STEP 3: Unload framebuffer and reset state + //------------------------------------------------------------------------------------------ + rlDisableShader(); // Unbind shader + rlDisableTexture(); // Unbind texture + rlDisableFramebuffer(); // Unbind framebuffer + rlUnloadFramebuffer(fbo); // Unload framebuffer (and automatically attached depth texture/renderbuffer) + + // Reset viewport dimensions to default + rlViewport(0, 0, rlGetFramebufferWidth(), rlGetFramebufferHeight()); + rlEnableBackfaceCulling(); + //------------------------------------------------------------------------------------------ + + cubemap.width = size; + cubemap.height = size; + cubemap.mipmaps = 1; + cubemap.format = PIXELFORMAT_UNCOMPRESSED_R32G32B32; + + return cubemap; +} |
