first commit
This commit is contained in:
199
ios/include/ibl/Cubemap.h
Normal file
199
ios/include/ibl/Cubemap.h
Normal file
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef IBL_CUBEMAP_H
|
||||
#define IBL_CUBEMAP_H
|
||||
|
||||
#include <ibl/Image.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <math/vec4.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec2.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace filament {
|
||||
namespace ibl {
|
||||
|
||||
/**
|
||||
* Generic cubemap class. It handles writing / reading into the 6 faces of a cubemap.
|
||||
*
|
||||
* Seamless trilinear filtering is handled.
|
||||
*
|
||||
* This class doesn't own the face data, it's just a "view" on the 6 images.
|
||||
*
|
||||
* @see CubemapUtils
|
||||
*
|
||||
*/
|
||||
class UTILS_PUBLIC Cubemap {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Initialize the cubemap with a given size, but no face is set and no memory is allocated.
|
||||
*
|
||||
* Usually Cubemaps are created using CubemapUtils.
|
||||
*
|
||||
* @see CubemapUtils
|
||||
*/
|
||||
explicit Cubemap(size_t dim);
|
||||
|
||||
Cubemap(Cubemap&&) = default;
|
||||
Cubemap& operator=(Cubemap&&) = default;
|
||||
|
||||
~Cubemap();
|
||||
|
||||
|
||||
enum class Face : uint8_t {
|
||||
PX = 0, // left +----+
|
||||
NX, // right | PY |
|
||||
PY, // bottom +----+----+----+----+
|
||||
NY, // top | NX | PZ | PX | NZ |
|
||||
PZ, // back +----+----+----+----+
|
||||
NZ // front | NY |
|
||||
// +----+
|
||||
};
|
||||
|
||||
using Texel = filament::math::float3;
|
||||
|
||||
|
||||
//! releases all images and reset the cubemap size
|
||||
void resetDimensions(size_t dim);
|
||||
|
||||
//! assigns an image to a face.
|
||||
void setImageForFace(Face face, const Image& image);
|
||||
|
||||
//! retrieves the image attached to a face
|
||||
inline const Image& getImageForFace(Face face) const;
|
||||
|
||||
//! retrieves the image attached to a face
|
||||
inline Image& getImageForFace(Face face);
|
||||
|
||||
//! computes the center of a pixel at coordinate x, y
|
||||
static inline filament::math::float2 center(size_t x, size_t y);
|
||||
|
||||
//! computes a direction vector from a face and a location of the center of pixel in an Image
|
||||
inline filament::math::float3 getDirectionFor(Face face, size_t x, size_t y) const;
|
||||
|
||||
//! computes a direction vector from a face and a location in pixel in an Image
|
||||
inline filament::math::float3 getDirectionFor(Face face, float x, float y) const;
|
||||
|
||||
//! samples the cubemap at the given direction using nearest neighbor filtering
|
||||
inline Texel const& sampleAt(const filament::math::float3& direction) const;
|
||||
|
||||
//! samples the cubemap at the given direction using bilinear filtering
|
||||
inline Texel filterAt(const filament::math::float3& direction) const;
|
||||
|
||||
//! samples an image at the given location in pixel using bilinear filtering
|
||||
static Texel filterAt(const Image& image, float x, float y);
|
||||
static Texel filterAtCenter(const Image& image, size_t x, size_t y);
|
||||
|
||||
//! samples two cubemaps in a given direction and lerps the result by a given lerp factor
|
||||
static Texel trilinearFilterAt(const Cubemap& c0, const Cubemap& c1, float lerp,
|
||||
const filament::math::float3& direction);
|
||||
|
||||
//! reads a texel at a given address
|
||||
inline static const Texel& sampleAt(void const* data) {
|
||||
return *static_cast<Texel const*>(data);
|
||||
}
|
||||
|
||||
//! writes a texel at a given address
|
||||
inline static void writeAt(void* data, const Texel& texel) {
|
||||
*static_cast<Texel*>(data) = texel;
|
||||
}
|
||||
|
||||
//! returns the size of the cubemap in pixels
|
||||
size_t getDimensions() const;
|
||||
|
||||
/**
|
||||
* Prepares a cubemap for seamless access to its faces.
|
||||
*
|
||||
* @warning All faces of the cubemap must be backed-up by the same Image, and must already
|
||||
* be spaced by 2 lines/rows.
|
||||
*/
|
||||
void makeSeamless();
|
||||
|
||||
struct Address {
|
||||
Face face;
|
||||
float s = 0;
|
||||
float t = 0;
|
||||
};
|
||||
|
||||
//! returns the face and texture coordinates of the given direction
|
||||
static Address getAddressFor(const filament::math::float3& direction);
|
||||
|
||||
private:
|
||||
size_t mDimensions = 0;
|
||||
float mScale = 1;
|
||||
float mUpperBound = 0;
|
||||
Image mFaces[6];
|
||||
};
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
inline const Image& Cubemap::getImageForFace(Face face) const {
|
||||
return mFaces[int(face)];
|
||||
}
|
||||
|
||||
inline Image& Cubemap::getImageForFace(Face face) {
|
||||
return mFaces[int(face)];
|
||||
}
|
||||
|
||||
inline filament::math::float2 Cubemap::center(size_t x, size_t y) {
|
||||
return { x + 0.5f, y + 0.5f };
|
||||
}
|
||||
|
||||
inline filament::math::float3 Cubemap::getDirectionFor(Face face, size_t x, size_t y) const {
|
||||
return getDirectionFor(face, x + 0.5f, y + 0.5f);
|
||||
}
|
||||
|
||||
inline filament::math::float3 Cubemap::getDirectionFor(Face face, float x, float y) const {
|
||||
// map [0, dim] to [-1,1] with (-1,-1) at bottom left
|
||||
float cx = (x * mScale) - 1;
|
||||
float cy = 1 - (y * mScale);
|
||||
|
||||
filament::math::float3 dir;
|
||||
const float l = std::sqrt(cx * cx + cy * cy + 1);
|
||||
switch (face) {
|
||||
case Face::PX: dir = { 1, cy, -cx }; break;
|
||||
case Face::NX: dir = { -1, cy, cx }; break;
|
||||
case Face::PY: dir = { cx, 1, -cy }; break;
|
||||
case Face::NY: dir = { cx, -1, cy }; break;
|
||||
case Face::PZ: dir = { cx, cy, 1 }; break;
|
||||
case Face::NZ: dir = { -cx, cy, -1 }; break;
|
||||
}
|
||||
return dir * (1 / l);
|
||||
}
|
||||
|
||||
inline Cubemap::Texel const& Cubemap::sampleAt(const filament::math::float3& direction) const {
|
||||
Cubemap::Address addr(getAddressFor(direction));
|
||||
const size_t x = std::min(size_t(addr.s * mDimensions), mDimensions - 1);
|
||||
const size_t y = std::min(size_t(addr.t * mDimensions), mDimensions - 1);
|
||||
return sampleAt(getImageForFace(addr.face).getPixelRef(x, y));
|
||||
}
|
||||
|
||||
inline Cubemap::Texel Cubemap::filterAt(const filament::math::float3& direction) const {
|
||||
Cubemap::Address addr(getAddressFor(direction));
|
||||
addr.s = std::min(addr.s * mDimensions, mUpperBound);
|
||||
addr.t = std::min(addr.t * mDimensions, mUpperBound);
|
||||
return filterAt(getImageForFace(addr.face), addr.s, addr.t);
|
||||
}
|
||||
|
||||
} // namespace ibl
|
||||
} // namespace filament
|
||||
|
||||
#endif /* IBL_CUBEMAP_H */
|
||||
Reference in New Issue
Block a user