Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ee82dc43f | ||
|
|
33da5fa38e | ||
|
|
d136d85402 | ||
|
|
a44f6d9498 | ||
|
|
b5aeee3dfd | ||
|
|
d5ee54ff7e | ||
|
|
cfd75743a2 | ||
|
|
6fd4f94418 | ||
|
|
e155fad7ef | ||
|
|
3683f94704 | ||
|
|
34e2b81855 | ||
|
|
edebd8eed8 | ||
|
|
36f7911917 | ||
|
|
f64117fa26 | ||
|
|
1422c8cba9 | ||
|
|
29ed42fa98 | ||
|
|
93029d2318 | ||
|
|
c4a304788f | ||
|
|
dfcdc9ca1e | ||
|
|
dd844b1183 | ||
|
|
a29f3a3011 | ||
|
|
84218f6ba2 | ||
|
|
f9960fb065 | ||
|
|
172d6d1045 | ||
|
|
2cfae31e9a | ||
|
|
f44d1cbfe4 | ||
|
|
f8eaa14a31 | ||
|
|
3d29cffd5d | ||
|
|
3b1522ab56 | ||
|
|
f6f7082b55 | ||
|
|
4e50e64888 | ||
|
|
27f7b198a6 | ||
|
|
dc6c9996f6 | ||
|
|
e0d19c8442 | ||
|
|
086f81a49d | ||
|
|
4879a0a124 | ||
|
|
637affefeb | ||
|
|
8d219d3bc0 | ||
|
|
a7289da05f | ||
|
|
98eea205f3 | ||
|
|
1c22b48893 | ||
|
|
249dd9752d | ||
|
|
bb4cd43835 | ||
|
|
954d1021c7 | ||
|
|
bf598071a3 | ||
|
|
5cbc2321c7 | ||
|
|
6bee5fb56f | ||
|
|
eb0fcc065b | ||
|
|
117535364b | ||
|
|
b15ae15f39 | ||
|
|
74445904f2 | ||
|
|
678ad4ff98 | ||
|
|
b6d7ed2b35 | ||
|
|
725e33763a | ||
|
|
f24146c169 | ||
|
|
67288d483f | ||
|
|
c80c504a2a | ||
|
|
1f8cacdd70 | ||
|
|
a3ae9431f1 | ||
|
|
3d0653604f | ||
|
|
42a0a41be0 | ||
|
|
468d9cccb7 | ||
|
|
6cfd058e3d | ||
|
|
8234549cb9 |
@@ -23,7 +23,7 @@ jobs:
|
||||
GH_TOKEN: ${{ secrets.FILAMENTBOT_TOKEN }}
|
||||
run: |
|
||||
GOLDEN_BRANCH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | python3 test/renderdiff/src/commit_msg.py)
|
||||
COMMIT_HASH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | head -n 1 | tr -d 'commit ')
|
||||
COMMIT_HASH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | head -n 1 | sed "s/commit //g")
|
||||
if [[ "${GOLDEN_BRANCH}" != "main" ]]; then
|
||||
git config --global user.email "filament.bot@gmail.com"
|
||||
git config --global user.name "Filament Bot"
|
||||
@@ -33,3 +33,25 @@ jobs:
|
||||
python3 test/renderdiff/src/update_golden.py --branch=${GOLDEN_BRANCH} \
|
||||
--merge-to-main --filament-tag=${COMMIT_HASH} --golden-repo-token=${GH_TOKEN}
|
||||
fi
|
||||
|
||||
update-docs:
|
||||
name: update-docs
|
||||
runs-on: 'ubuntu-24.04-4core'
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/linux-prereq
|
||||
- id: get_commit_msg
|
||||
uses: ./.github/actions/get-commit-msg
|
||||
- name: Prerequisites
|
||||
run: pip install selenium
|
||||
- name: Run update script
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.FILAMENTBOT_TOKEN }}
|
||||
run: |
|
||||
COMMIT_HASH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | head -n 1 | sed "s/commit //g")
|
||||
git config --global user.email "filament.bot@gmail.com"
|
||||
git config --global user.name "Filament Bot"
|
||||
git config --global credential.helper cache
|
||||
bash docs_src/build/postsubmit.sh ${COMMIT_HASH} ${GH_TOKEN}
|
||||
|
||||
@@ -54,7 +54,6 @@ jobs:
|
||||
build-android:
|
||||
name: build-android
|
||||
runs-on: 'ubuntu-24.04-16core'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
@@ -73,7 +72,6 @@ jobs:
|
||||
build-ios:
|
||||
name: build-iOS
|
||||
runs-on: macos-14-xlarge
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
@@ -89,7 +87,6 @@ jobs:
|
||||
build-web:
|
||||
name: build-web
|
||||
runs-on: 'ubuntu-24.04-16core'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
@@ -107,11 +104,12 @@ jobs:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- id: get_commit_msg
|
||||
uses: ./.github/actions/get-commit-msg
|
||||
- name: Check for manual edits to /docs
|
||||
run: |
|
||||
echo "${{ github.event.pull_request.head.sha }} -- ${{ github.event.pull_request.head.sha }}"
|
||||
# disable for now
|
||||
# bash docs_src/build/presubmit_check.sh ${{ github.event.pull_request.head.sha }}
|
||||
COMMIT_ID=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | head -n 1 | sed "s/commit //g")
|
||||
bash docs_src/build/presubmit_check.sh ${COMMIT_ID}
|
||||
|
||||
test-renderdiff:
|
||||
name: test-renderdiff
|
||||
@@ -132,13 +130,30 @@ jobs:
|
||||
run: |
|
||||
bash build/common/get-mesa.sh
|
||||
pip install tifffile numpy
|
||||
- name: Run Test
|
||||
- name: Render
|
||||
run: |
|
||||
echo "${{ steps.get_commit_msg.outputs.msg }}" | bash test/renderdiff/test.sh
|
||||
TEST_DIR=test/renderdiff
|
||||
source ${TEST_DIR}/src/preamble.sh
|
||||
start_
|
||||
GOLDEN_BRANCH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | python3 ${TEST_DIR}/src/commit_msg.py)
|
||||
bash ${TEST_DIR}/generate.sh && \
|
||||
python3 ${TEST_DIR}/src/golden_manager.py \
|
||||
--branch=${GOLDEN_BRANCH} \
|
||||
--output=${GOLDEN_OUTPUT_DIR}
|
||||
# Note that we need to upload the output even if comparison fails
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: presubmit-renderdiff-result
|
||||
path: ./out/renderdiff
|
||||
- name: Compare output
|
||||
run: |
|
||||
TEST_DIR=test/renderdiff
|
||||
source ${TEST_DIR}/src/preamble.sh
|
||||
python3 ${TEST_DIR}/src/compare.py \
|
||||
--src=${GOLDEN_OUTPUT_DIR} \
|
||||
--dest=${RENDER_OUTPUT_DIR} \
|
||||
--out=${DIFF_OUTPUT_DIR}
|
||||
end_
|
||||
|
||||
validate-wgsl-webgpu:
|
||||
name: validate-wgsl-webgpu
|
||||
@@ -173,3 +188,17 @@ jobs:
|
||||
./build.sh -p desktop debug gltf_viewer
|
||||
- name: Run test
|
||||
run: bash test/code-correctness/test.sh
|
||||
|
||||
test-mdbook:
|
||||
name: test-mdbook
|
||||
runs-on: 'ubuntu-24.04-4core'
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: ./.github/actions/linux-prereq
|
||||
- name: Run build script
|
||||
run: |
|
||||
bash docs_src/build/install_mdbook.sh && source ~/.bashrc
|
||||
mdbook --version
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ option(FILAMENT_ENABLE_ASAN_UBSAN "Enable Address and Undefined Behavior Sanitiz
|
||||
|
||||
option(FILAMENT_ENABLE_TSAN "Enable Thread Sanitizer" OFF)
|
||||
|
||||
option(FILAMENT_ENABLE_COVERAGE "Enable LLVM code coverage" OFF)
|
||||
|
||||
option(FILAMENT_ENABLE_FEATURE_LEVEL_0 "Enable Feature Level 0" ON)
|
||||
|
||||
option(FILAMENT_ENABLE_MULTIVIEW "Enable multiview for Filament" OFF)
|
||||
@@ -460,6 +462,10 @@ if (NOT MSVC AND NOT WEBGL)
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${EXTRA_SANITIZE_OPTIONS}")
|
||||
|
||||
if (FILAMENT_ENABLE_COVERAGE)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-instr-generate -fcoverage-mapping")
|
||||
endif()
|
||||
|
||||
# Disable the stack check for macOS to workaround a known issue in clang 11.0.0.
|
||||
# See: https://forums.developer.apple.com/thread/121887
|
||||
if (APPLE)
|
||||
@@ -786,6 +792,7 @@ add_subdirectory(${LIBRARIES}/filabridge)
|
||||
add_subdirectory(${LIBRARIES}/filaflat)
|
||||
add_subdirectory(${LIBRARIES}/filagui)
|
||||
add_subdirectory(${LIBRARIES}/filameshio)
|
||||
add_subdirectory(${LIBRARIES}/generatePrefilterMipmap)
|
||||
add_subdirectory(${LIBRARIES}/gltfio)
|
||||
add_subdirectory(${LIBRARIES}/ibl)
|
||||
add_subdirectory(${LIBRARIES}/iblprefilter)
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.62.0'
|
||||
implementation 'com.google.android.filament:filament-android:1.62.1'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
|
||||
iOS projects can use CocoaPods to install the latest release:
|
||||
|
||||
```shell
|
||||
pod 'Filament', '~> 1.62.0'
|
||||
pod 'Filament', '~> 1.62.1'
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -7,6 +7,16 @@ A new header is inserted each time a *tag* is created.
|
||||
Instead, if you are authoring a PR for the main branch, add your release note to
|
||||
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
|
||||
|
||||
## v1.62.2
|
||||
|
||||
- Metal: fix, respect alpha to coverage rasterization
|
||||
- engine: removed `Texture::generatePrefilterMipmap`, a new `libfilament-generatePrefilterMipmap` library can be used in its stead [⚠️ **API BREAKAGE**]
|
||||
|
||||
## v1.62.1
|
||||
|
||||
- Add new shader define `VARIANT_DEPTH`, defined when a material is compiled for depth variants
|
||||
(e.g., shadows) [**Requires recompiling materials**]
|
||||
|
||||
## v1.62.0
|
||||
|
||||
- Add new `unfilterable` field to Filament Material's `sampler` [⚠️ **New Material Version**]
|
||||
|
||||
@@ -13,6 +13,10 @@ add_library(filament STATIC IMPORTED)
|
||||
set_target_properties(filament PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilament.a)
|
||||
|
||||
add_library(filament-generatePrefilterMipmap STATIC IMPORTED)
|
||||
set_target_properties(filament-generatePrefilterMipmap PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilament-generatePrefilterMipmap.a)
|
||||
|
||||
add_library(backend STATIC IMPORTED)
|
||||
set_target_properties(backend PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libbackend.a)
|
||||
@@ -120,6 +124,7 @@ add_library(filament-jni SHARED
|
||||
|
||||
# Ordering is significant in the following list. The PRIVATE qualifier prevents transitive deps.
|
||||
target_link_libraries(filament-jni
|
||||
PRIVATE filament-generatePrefilterMipmap
|
||||
PRIVATE filament
|
||||
PRIVATE backend
|
||||
PRIVATE filaflat
|
||||
|
||||
@@ -556,7 +556,8 @@ extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBu
|
||||
jlong resourceAllocatorCacheSizeMB, jlong resourceAllocatorCacheMaxAge,
|
||||
jboolean disableHandleUseAfterFreeCheck,
|
||||
jint preferredShaderLanguage,
|
||||
jboolean forceGLES2Context, jboolean assertNativeWindowIsValid) {
|
||||
jboolean forceGLES2Context, jboolean assertNativeWindowIsValid,
|
||||
jint gpuContextPriority) {
|
||||
Engine::Builder* builder = (Engine::Builder*) nativeBuilder;
|
||||
Engine::Config config = {
|
||||
.commandBufferSizeMB = (uint32_t) commandBufferSizeMB,
|
||||
@@ -574,6 +575,7 @@ extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBu
|
||||
.preferredShaderLanguage = (Engine::Config::ShaderLanguage) preferredShaderLanguage,
|
||||
.forceGLES2Context = (bool) forceGLES2Context,
|
||||
.assertNativeWindowIsValid = (bool) assertNativeWindowIsValid,
|
||||
.gpuContextPriority = (Engine::GpuContextPriority) gpuContextPriority,
|
||||
};
|
||||
builder->config(&config);
|
||||
}
|
||||
|
||||
@@ -23,16 +23,20 @@
|
||||
#include <android/bitmap.h>
|
||||
#endif
|
||||
|
||||
#include <backend/BufferDescriptor.h>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/Stream.h>
|
||||
#include <filament/Texture.h>
|
||||
|
||||
#include <filament-generatePrefilterMipmap/generatePrefilterMipmap.h>
|
||||
|
||||
#include <backend/BufferDescriptor.h>
|
||||
|
||||
#include "common/CallbackUtils.h"
|
||||
#include "common/NioUtils.h"
|
||||
|
||||
#include "private/backend/VirtualMachineEnv.h"
|
||||
|
||||
|
||||
using namespace filament;
|
||||
using namespace backend;
|
||||
|
||||
@@ -421,7 +425,7 @@ Java_com_google_android_filament_Texture_nGeneratePrefilterMipmap(JNIEnv *env, j
|
||||
Engine *engine = (Engine *) nativeEngine;
|
||||
|
||||
jint *faceOffsetsInBytes = env->GetIntArrayElements(faceOffsetsInBytes_, nullptr);
|
||||
Texture::FaceOffsets faceOffsets;
|
||||
filament::FaceOffsets faceOffsets;
|
||||
std::copy_n(faceOffsetsInBytes, 6, faceOffsets.offsets);
|
||||
env->ReleaseIntArrayElements(faceOffsetsInBytes_, faceOffsetsInBytes, JNI_ABORT);
|
||||
|
||||
@@ -444,10 +448,11 @@ Java_com_google_android_filament_Texture_nGeneratePrefilterMipmap(JNIEnv *env, j
|
||||
(uint32_t) left, (uint32_t) top, (uint32_t) stride,
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
Texture::PrefilterOptions options;
|
||||
filament::PrefilterOptions options;
|
||||
options.sampleCount = sampleCount;
|
||||
options.mirror = mirror;
|
||||
texture->generatePrefilterMipmap(*engine, std::move(desc), faceOffsets, &options);
|
||||
|
||||
filament::generatePrefilterMipmap(texture, *engine, std::move(desc), faceOffsets, &options);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -175,6 +175,36 @@ public class Engine {
|
||||
MULTIVIEW,
|
||||
};
|
||||
|
||||
/**
|
||||
* This controls the priority level for GPU work scheduling, which helps prioritize the
|
||||
* submitted GPU work and enables preemption.
|
||||
*/
|
||||
public enum GpuContextPriority {
|
||||
/**
|
||||
* Backend default GPU context priority (typically MEDIUM)
|
||||
*/
|
||||
DEFAULT,
|
||||
/**
|
||||
* For non-interactive, deferrable workloads. This should not interfere with standard
|
||||
* applications.
|
||||
*/
|
||||
LOW,
|
||||
/**
|
||||
* The default priority level for standard applications.
|
||||
*/
|
||||
MEDIUM,
|
||||
/**
|
||||
* For high-priority, latency-sensitive workloads that are more important than standard
|
||||
* applications.
|
||||
*/
|
||||
HIGH,
|
||||
/**
|
||||
* The highest priority, intended for system-critical, real-time applications where missing
|
||||
* deadlines is unacceptable (e.g., VR/AR compositors or other system-critical tasks).
|
||||
*/
|
||||
REALTIME,
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructs <code>Engine</code> objects using a builder pattern.
|
||||
*/
|
||||
@@ -233,7 +263,8 @@ public class Engine {
|
||||
config.resourceAllocatorCacheSizeMB, config.resourceAllocatorCacheMaxAge,
|
||||
config.disableHandleUseAfterFreeCheck,
|
||||
config.preferredShaderLanguage.ordinal(),
|
||||
config.forceGLES2Context, config.assertNativeWindowIsValid);
|
||||
config.forceGLES2Context, config.assertNativeWindowIsValid,
|
||||
config.gpuContextPriority.ordinal());
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -489,6 +520,11 @@ public class Engine {
|
||||
* @Deprecated use "backend.opengl.assert_native_window_is_valid" feature flag instead
|
||||
*/
|
||||
public boolean assertNativeWindowIsValid = false;
|
||||
|
||||
/**
|
||||
* GPU context priority level. Controls GPU work scheduling and preemption.
|
||||
*/
|
||||
public GpuContextPriority gpuContextPriority = GpuContextPriority.DEFAULT;
|
||||
}
|
||||
|
||||
private Engine(long nativeEngine, Config config) {
|
||||
@@ -1492,7 +1528,8 @@ public class Engine {
|
||||
long resourceAllocatorCacheSizeMB, long resourceAllocatorCacheMaxAge,
|
||||
boolean disableHandleUseAfterFreeCheck,
|
||||
int preferredShaderLanguage,
|
||||
boolean forceGLES2Context, boolean assertNativeWindowIsValid);
|
||||
boolean forceGLES2Context, boolean assertNativeWindowIsValid,
|
||||
int gpuContextPriority);
|
||||
private static native void nSetBuilderFeatureLevel(long nativeBuilder, int ordinal);
|
||||
private static native void nSetBuilderSharedContext(long nativeBuilder, long sharedContext);
|
||||
private static native void nSetBuilderPaused(long nativeBuilder, boolean paused);
|
||||
|
||||
@@ -1390,8 +1390,8 @@ public class View {
|
||||
*
|
||||
* \note
|
||||
* Dynamic resolution is only supported on platforms where the time to render
|
||||
* a frame can be measured accurately. Dynamic resolution is currently only
|
||||
* supported on Android.
|
||||
* a frame can be measured accurately. On platform where this is not supported,
|
||||
* Dynamic Resolution can't be enabled unless minScale == maxScale.
|
||||
*
|
||||
* @see Renderer::FrameRateOptions
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.62.0
|
||||
VERSION_NAME=1.62.1
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.google.android.filament.gltf
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.*
|
||||
@@ -50,6 +51,7 @@ class MainActivity : Activity() {
|
||||
// Load the library for the utility layer, which in turn loads gltfio and the Filament core.
|
||||
init { Utils.init() }
|
||||
private const val TAG = "gltf-viewer"
|
||||
private const val STATIC_MODEL_TAG = "use-static-model"
|
||||
}
|
||||
|
||||
private lateinit var surfaceView: SurfaceView
|
||||
@@ -69,6 +71,7 @@ class MainActivity : Activity() {
|
||||
private var loadStartTime = 0L
|
||||
private var loadStartFence: Fence? = null
|
||||
private val viewerContent = AutomationEngine.ViewerContent()
|
||||
private var useStaticModel = false
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -83,6 +86,12 @@ class MainActivity : Activity() {
|
||||
doubleTapDetector = GestureDetector(applicationContext, doubleTapListener)
|
||||
singleTapDetector = GestureDetector(applicationContext, singleTapListener)
|
||||
|
||||
val intent: Intent = intent
|
||||
val bundle: Bundle? = intent.extras
|
||||
bundle?.let {
|
||||
useStaticModel = it.getBoolean(STATIC_MODEL_TAG, false)
|
||||
}
|
||||
|
||||
modelViewer = ModelViewer(surfaceView)
|
||||
viewerContent.view = modelViewer.view
|
||||
viewerContent.sunlight = modelViewer.light
|
||||
@@ -141,7 +150,16 @@ class MainActivity : Activity() {
|
||||
}
|
||||
|
||||
private fun createDefaultRenderables() {
|
||||
val buffer = assets.open("models/scene.gltf").use { input ->
|
||||
// Sometimes it's useful to set to the default model to something static. You can enable
|
||||
// the static model by launching the app from adb, as in
|
||||
// `adb shell am start -n com.google.android.filament.gltf/.MainActivity --ez "use-static-model" true`
|
||||
val modelPath = if (useStaticModel) {
|
||||
"models/helmet.glb"
|
||||
} else {
|
||||
"models/scene.gltf"
|
||||
}
|
||||
|
||||
val buffer = assets.open(modelPath).use { input ->
|
||||
val bytes = ByteArray(input.available())
|
||||
input.read(bytes)
|
||||
ByteBuffer.wrap(bytes)
|
||||
|
||||
@@ -63,6 +63,9 @@ function print_help {
|
||||
echo " -b"
|
||||
echo " Enable Address and Undefined Behavior Sanitizers (asan/ubsan) for debugging."
|
||||
echo " This is only for the desktop build."
|
||||
echo " -V"
|
||||
echo " Enable LLVM code coverage for debug builds."
|
||||
echo " This is only for the desktop build."
|
||||
echo " -x value"
|
||||
echo " Define a preprocessor flag FILAMENT_BACKEND_DEBUG_FLAG with [value]. This is useful for"
|
||||
echo " enabling debug paths in the backend from the build script. For example, make a"
|
||||
@@ -208,6 +211,7 @@ MATOPT_OPTION=""
|
||||
MATOPT_GRADLE_OPTION=""
|
||||
|
||||
ASAN_UBSAN_OPTION=""
|
||||
COVERAGE_OPTION=""
|
||||
|
||||
BACKEND_DEBUG_FLAG_OPTION=""
|
||||
|
||||
@@ -275,6 +279,7 @@ function build_desktop_target {
|
||||
${MATDBG_OPTION} \
|
||||
${MATOPT_OPTION} \
|
||||
${ASAN_UBSAN_OPTION} \
|
||||
${COVERAGE_OPTION} \
|
||||
${BACKEND_DEBUG_FLAG_OPTION} \
|
||||
${STEREOSCOPIC_OPTION} \
|
||||
${OSMESA_OPTION} \
|
||||
@@ -835,7 +840,7 @@ function check_debug_release_build {
|
||||
|
||||
pushd "$(dirname "$0")" > /dev/null
|
||||
|
||||
while getopts ":hacCfgimp:q:uvWslwedtk:bx:S:X:" opt; do
|
||||
while getopts ":hacCfgimp:q:uvWslwedtk:bVx:S:X:" opt; do
|
||||
case ${opt} in
|
||||
h)
|
||||
print_help
|
||||
@@ -983,6 +988,9 @@ while getopts ":hacCfgimp:q:uvWslwedtk:bx:S:X:" opt; do
|
||||
b) ASAN_UBSAN_OPTION="-DFILAMENT_ENABLE_ASAN_UBSAN=ON"
|
||||
echo "Enabled ASAN/UBSAN"
|
||||
;;
|
||||
V) COVERAGE_OPTION="-DFILAMENT_ENABLE_COVERAGE=ON"
|
||||
echo "Enabled coverage"
|
||||
;;
|
||||
x) BACKEND_DEBUG_FLAG_OPTION="-DFILAMENT_BACKEND_DEBUG_FLAG=${OPTARG}"
|
||||
;;
|
||||
S) case $(echo "${OPTARG}" | tr '[:upper:]' '[:lower:]') in
|
||||
|
||||
@@ -77,16 +77,20 @@ if [[ "$OS_NAME" == "Linux" ]]; then
|
||||
sudo ln -s /usr/bin/clang++-${CLANG_VERSION} /usr/bin/clang++
|
||||
fi # [[ "$GITHUB_WORKFLOW" ]]
|
||||
elif [[ "$OS_NAME" == "Darwin" ]]; then
|
||||
if [[ ! "$GITHUB_WORKFLOW" ]]; then
|
||||
if [ ! command -v brew > /dev/null 2>&1 ]; then
|
||||
echo "Error: need to install homebrew to continue"
|
||||
exit 1
|
||||
fi
|
||||
if command -v brew > /dev/null 2>&1; then
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=true brew install autoconf automake libx11 libxext libxrandr \
|
||||
llvm@${LLVM_VERSION} ninja meson pkg-config libxshmfence
|
||||
# For reasons unknown, this is necessary for pkg-config to find homebrew's packages
|
||||
LOCAL_PKG_CONFIG_PATH="/opt/homebrew/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
elif command -v port > /dev/null 2>&1; then
|
||||
sudo port install autoconf automake libx11 libXext libXrandr llvm-${LLVM_VERSION} \
|
||||
ninja meson pkgconfig libxshmfence
|
||||
# For reasons unknown, this is necessary for pkg-config to find macport's packages
|
||||
LOCAL_PKG_CONFIG_PATH="/opt/local/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
else
|
||||
echo "Error: need to install homebrew or macports to continue"
|
||||
exit 1
|
||||
fi
|
||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=true brew install autoconf automake libx11 libxext libxrandr llvm@${LLVM_VERSION} ninja meson pkg-config libxshmfence
|
||||
|
||||
# For reasons unknown, this is necessary for pkg-config to find homebrew's packages
|
||||
LOCAL_PKG_CONFIG_PATH="/opt/homebrew/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
fi # [[ "$OS_NAME" == x ]]
|
||||
|
||||
LOCAL_LDFLAGS=${LDFLAGS}
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
book
|
||||
src/dup/*.md
|
||||
build/__pycache__
|
||||
src_mdbook/book
|
||||
src_mdbook/src/dup/*.md
|
||||
src_mdbook/src/main/filament.md
|
||||
src_mdbook/src/main/materials.md
|
||||
|
||||
@@ -30,21 +30,23 @@ from utils import execute, ArgParseImpl
|
||||
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
ROOT_DIR = os.path.join(CUR_DIR, '../../')
|
||||
|
||||
def get_last_commit_hash():
|
||||
res, ret = execute('git rev-parse HEAD', cwd=ROOT_DIR)
|
||||
assert res == 0, 'Failed to get the last commit hash'
|
||||
return ret.strip()
|
||||
DOCS_SRC_DIR = os.path.abspath(os.path.join(CUR_DIR, '../'))
|
||||
MARKDEEP_SRC_DIR = os.path.join(DOCS_SRC_DIR, 'src_markdeep')
|
||||
MDBOOK_SRC_DIR = os.path.join(DOCS_SRC_DIR, 'src_mdbook')
|
||||
RAW_SRC_DIR = os.path.join(DOCS_SRC_DIR, 'src_raw')
|
||||
|
||||
SRC_SRC_DIRS = [MARKDEEP_SRC_DIR, MDBOOK_SRC_DIR, RAW_SRC_DIR]
|
||||
|
||||
def get_edited_files(commit_hash):
|
||||
INSERT = '#####?????'
|
||||
res, ret = execute(f'git show --name-only --pretty=%b{INSERT} {commit_hash}')
|
||||
assert res == 0, 'Failed to get edited filed'
|
||||
assert res == 0, f'Failed to get edited filed {res}: ' + ret
|
||||
files = []
|
||||
_, after = ret.split(INSERT)
|
||||
for r in filter(lambda a: len(a) > 0, after.split('\n')):
|
||||
if r.startswith('commit'):
|
||||
break
|
||||
files.append(r)
|
||||
files.append(os.path.abspath(os.path.join(ROOT_DIR, r)))
|
||||
return files
|
||||
|
||||
# Returns True if there were no direct edits to '/docs'
|
||||
@@ -59,12 +61,19 @@ def check_has_source_edits(commit_hash, printing=True):
|
||||
config = {}
|
||||
with open(f'{CUR_DIR}/duplicates.json') as config_txt:
|
||||
config = json.loads(config_txt.read())
|
||||
source_files = set(config.keys())
|
||||
source_files = set(os.path.abspath(os.path.join(ROOT_DIR, k)) for k in config.keys())
|
||||
edited_files = set(get_edited_files(commit_hash))
|
||||
overlap = [f'\t{f}' for f in list(source_files & edited_files)]
|
||||
if printing and len(overlap) > 0:
|
||||
print(f'Found edited source files:\n' + '\n'.join(overlap))
|
||||
return len(overlap) > 0
|
||||
|
||||
# find any changes to docs_src sources
|
||||
is_docs_src_edit = lambda f: any(f.startswith(prefix) for prefix in SRC_SRC_DIRS)
|
||||
|
||||
final_edited = [f'\t{f}' for f in \
|
||||
list(source_files & edited_files) + \
|
||||
list(filter(is_docs_src_edit, edited_files))]
|
||||
|
||||
if printing and len(final_edited) > 0:
|
||||
print(f'Found edited source files:\n' + '\n'.join(final_edited))
|
||||
return len(final_edited) > 0
|
||||
|
||||
# Returns true in a given TAG is found in the commit msg
|
||||
def commit_msg_has_tag(commit_hash, tag, printing=True):
|
||||
|
||||
@@ -21,7 +21,7 @@ LINUX_ARM=4
|
||||
|
||||
function add_cargo_path() {
|
||||
local BASH_P="${HOME}/.bashrc"
|
||||
local PATH_LINE='export PATH=${PATH}:~/.cargo/bin'
|
||||
local PATH_LINE='export PATH=${PATH}:${HOME}/.cargo/bin'
|
||||
local TYPE=$1
|
||||
if [ ${TYPE} == ${DARWIN_ARM} ] || [ ${TYPE} == ${DARWIN_X86} ]; then
|
||||
BASH_P="${HOME}/.bash_profile"
|
||||
@@ -39,13 +39,13 @@ function download_mdbook() {
|
||||
fi
|
||||
|
||||
local CHECK_UNAME="
|
||||
import sys;
|
||||
parts=[a.lower() for a in sys.stdin.read().strip().split(' ')];
|
||||
import sys
|
||||
parts=[a.lower() for a in sys.stdin.read().strip().split(' ')]
|
||||
def get_type():
|
||||
if 'darwin' in parts:
|
||||
if 'x86_64' in parts:
|
||||
return ${DARWIN_X86}
|
||||
elif 'aarch' in parts:
|
||||
elif 'aarch' in parts or 'arm64' in parts:
|
||||
return ${DARWIN_ARM}
|
||||
elif 'linux' in parts:
|
||||
if 'x86_64' in parts:
|
||||
@@ -63,11 +63,12 @@ print(get_type())
|
||||
echo "*** Need to install Rust ***"
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
fi
|
||||
source "${HOME}/.cargo/env"
|
||||
if ! (command -v cargo >/dev/null 2>&1); then
|
||||
echo "*** Still cannot find `cargo` ***"
|
||||
echo "*** Still cannot find cargo ***"
|
||||
exit 1
|
||||
fi
|
||||
cargo install mdbook
|
||||
cargo install --force mdbook
|
||||
else
|
||||
# Download prebuilts from github
|
||||
mkdir -p ${HOME}/.cargo/bin
|
||||
@@ -76,10 +77,10 @@ print(get_type())
|
||||
if [ ${TYPE} == ${LINUX_X86} ]; then
|
||||
DL_URL='https://github.com/rust-lang/mdBook/releases/download/v0.4.43/mdbook-v0.4.43-x86_64-unknown-linux-gnu.tar.gz'
|
||||
fi
|
||||
curl -L -o ~/Downloads/mdbook.tar.gz ${DL_URL}
|
||||
curl -L -o /tmp/mdbook.tar.gz ${DL_URL}
|
||||
mkdir -p /tmp/mdbook
|
||||
tar -xvzf ~/Downloads/mdbook.tar.gz -C /tmp/mdbook >/dev/null 2>&1
|
||||
mv /tmp/mdbook/mdbook ~/.cargo/bin/
|
||||
tar -xvzf /tmp/mdbook.tar.gz -C /tmp/mdbook >/dev/null 2>&1
|
||||
mv /tmp/mdbook/mdbook ${HOME}/.cargo/bin/
|
||||
fi
|
||||
add_cargo_path ${TYPE}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
# Copyright (C) 2025 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.
|
||||
|
||||
FILAMENT_BOT_TOKEN=$2
|
||||
|
||||
function update_to_main() {
|
||||
python3 docs_src/build/run.py
|
||||
mkdir -p tmp
|
||||
pushd .
|
||||
cd tmp
|
||||
git clone https://x-access-token:${FILAMENT_BOT_TOKEN}@github.com/google/filament.git
|
||||
cd filament
|
||||
rm -rf docs/*
|
||||
cp -r ../../docs_src/src_mdbook/book/* docs
|
||||
git add -A docs/*
|
||||
git commit -a \
|
||||
-m "[automated] Updating /docs due to commit ${COMMIT_HASH:0:7}" \
|
||||
-m "" \
|
||||
-m "Full commit hash is ${COMMIT_HASH}" \
|
||||
-m "" \
|
||||
-m "DOCS_ALLOW_DIRECT_EDITS"
|
||||
|
||||
git push origin main
|
||||
popd
|
||||
}
|
||||
|
||||
COMMIT_HASH=$1
|
||||
HAS_EDITS=$((python3 docs_src/build/checks.py --do-or="source_edits,commit_docs_force" $COMMIT_HASH > /dev/null && echo "true") || echo "false")
|
||||
DO_BYPASS=$((python3 docs_src/build/checks.py --do-and="commit_docs_bypass" $COMMIT_HASH && echo "true") || echo "false")
|
||||
|
||||
if [[ "${HAS_EDITS}" == "true" && "${DO_BYPASS}" == "false" ]]; then
|
||||
# Run again to output the edited files:
|
||||
python3 docs_src/build/checks.py --do-or="source_edits,commit_docs_force" $COMMIT_HASH
|
||||
update_to_main
|
||||
else
|
||||
echo "has edits (to /docs_src): ${HAS_EDITS}"
|
||||
echo "bypass: ${DO_BYPASS}"
|
||||
fi
|
||||
@@ -16,12 +16,18 @@ import json
|
||||
import os
|
||||
import re
|
||||
from utils import execute, ArgParseImpl
|
||||
import shutil
|
||||
|
||||
CUR_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
DOCS_SRC_DIR = os.path.join(CUR_DIR, '../')
|
||||
ROOT_DIR = os.path.join(CUR_DIR, '../../')
|
||||
SRC_DIR = os.path.join(CUR_DIR, '../src')
|
||||
MARKDEEP_DIR = os.path.join(CUR_DIR, '../markdeep')
|
||||
|
||||
MDBOOK_DIR = os.path.join(CUR_DIR, '../src_mdbook')
|
||||
BOOK_OUPUT_DIR = os.path.join(MDBOOK_DIR, 'book')
|
||||
SRC_DIR = os.path.join(MDBOOK_DIR, 'src')
|
||||
|
||||
MARKDEEP_DIR = os.path.join(CUR_DIR, '../src_markdeep')
|
||||
RAW_COPIES_DIR = os.path.join(CUR_DIR, '../src_raw')
|
||||
DUP_DIR = os.path.join(SRC_DIR, 'dup')
|
||||
MAIN_DIR = os.path.join(SRC_DIR, 'main')
|
||||
|
||||
@@ -124,5 +130,7 @@ if __name__ == "__main__":
|
||||
pull_duplicates()
|
||||
pull_markdeep_docs()
|
||||
|
||||
res, err = execute('mdbook build', cwd=DOCS_SRC_DIR)
|
||||
res, err = execute('mdbook build', cwd=MDBOOK_DIR)
|
||||
assert res == 0, f"failed to execute `mdbook`. return-code={res} err=\"{err}\""
|
||||
|
||||
shutil.copytree(RAW_COPIES_DIR, BOOK_OUPUT_DIR, dirs_exist_ok=True)
|
||||
|
||||
@@ -13,7 +13,7 @@ This document is part of the [Filament project](https://github.com/google/filame
|
||||
## Authors
|
||||
|
||||
- [Romain Guy](https://github.com/romainguy), [@romainguy](https://twitter.com/romainguy)
|
||||
- [Mathias Agopian](https://github.com/pixelflinger), [@darthmoosious](https://twitter.com/darthmoosious)
|
||||
- [Mathias Agopian](https://github.com/pixelflinger), [@pixelflinger](https://bsky.app/profile/pixelflinger.bsky.social)
|
||||
|
||||
# Overview
|
||||
|
||||
@@ -78,26 +78,27 @@ in table [standardProperties].
|
||||
Property | Definition
|
||||
-----------------------:|:---------------------
|
||||
**baseColor** | Diffuse albedo for non-metallic surfaces, and specular color for metallic surfaces
|
||||
**metallic** | Whether a surface appears to be dielectric (0.0) or conductor (1.0). Often used as a binary value (0 or 1)
|
||||
**roughness** | Perceived smoothness (1.0) or roughness (0.0) of a surface. Smooth surfaces exhibit sharp reflections
|
||||
**metallic** | Whether a surface appears to be dielectric (0.0) or conductor (1.0). Often used as a binary value (0 or 1)
|
||||
**reflectance** | Fresnel reflectance at normal incidence for dielectric surfaces. This directly controls the strength of the reflections
|
||||
**sheenColor** | Strength of the sheen layer
|
||||
**sheenRoughness** | Perceived smoothness or roughness of the sheen layer
|
||||
**ambientOcclusion** | Defines how much of the ambient light is accessible to a surface point. It is a per-pixel shadowing factor between 0.0 and 1.0
|
||||
**clearCoat** | Strength of the clear coat layer
|
||||
**clearCoatRoughness** | Perceived smoothness or roughness of the clear coat layer
|
||||
**clearCoatNormal** | A detail normal used to perturb the clear coat layer using _bump mapping_ (_normal mapping_)
|
||||
**anisotropy** | Amount of anisotropy in either the tangent or bitangent direction
|
||||
**anisotropyDirection** | Local surface direction in tangent space
|
||||
**ambientOcclusion** | Defines how much of the ambient light is accessible to a surface point. It is a per-pixel shadowing factor between 0.0 and 1.0
|
||||
**normal** | A detail normal used to perturb the surface using _bump mapping_ (_normal mapping_)
|
||||
**bentNormal** | A normal pointing in the average unoccluded direction. Can be used to improve indirect lighting quality
|
||||
**clearCoatNormal** | A detail normal used to perturb the clear coat layer using _bump mapping_ (_normal mapping_)
|
||||
**emissive** | Additional diffuse albedo to simulate emissive surfaces (such as neons, etc.) This property is mostly useful in an HDR pipeline with a bloom pass
|
||||
**postLightingColor** | Additional color that can be blended with the result of the lighting computations. See `postLightingBlending`
|
||||
**ior** | Index of refraction, either for refractive objects or as an alternative to reflectance
|
||||
**transmission** | Defines how much of the diffuse light of a dielectric is transmitted through the object, in other words this defines how transparent an object is
|
||||
**absorption** | Absorption factor for refractive objects
|
||||
**microThickness** | Thickness of the thin layer of refractive objects
|
||||
**thickness** | Thickness of the solid volume of refractive objects
|
||||
**sheenColor** | Strength of the sheen layer
|
||||
**sheenRoughness** | Perceived smoothness or roughness of the sheen layer
|
||||
**emissive** | Additional diffuse albedo to simulate emissive surfaces (such as neons, etc.) This property is mostly useful in an HDR pipeline with a bloom pass
|
||||
**normal** | A detail normal used to perturb the surface using _bump mapping_ (_normal mapping_)
|
||||
**postLightingColor** | Additional color that can be blended with the result of the lighting computations. See `postLightingBlending`
|
||||
**absorption** | Absorption factor for refractive objects
|
||||
**transmission** | Defines how much of the diffuse light of a dielectric is transmitted through the object, in other words this defines how transparent an object is
|
||||
**ior** | Index of refraction, either for refractive objects or as an alternative to reflectance
|
||||
**microThickness** | Thickness of the thin layer of refractive objects
|
||||
**bentNormal** | A normal pointing in the average unoccluded direction. Can be used to improve indirect lighting quality
|
||||
**shadowStrength** | Strength factor between 0 and 1 for all shadows received by this material
|
||||
[Table [standardProperties]: Properties of the standard model]
|
||||
|
||||
The type and range of each property is described in table [standardPropertiesTypes].
|
||||
@@ -991,10 +992,13 @@ Type
|
||||
|
||||
Value
|
||||
: Each entry is an object with the properties `name` and `type`, both of `string` type. The
|
||||
name must be a valid GLSL identifier. Entries also have an optional `precision`, which can be
|
||||
name must be a valid GLSL identifier. Entries have an optional `precision`, which can be
|
||||
one of `default` (best precision for the platform, typically `high` on desktop, `medium` on
|
||||
mobile), `low`, `medium`, `high`. The type must be one of the types described in
|
||||
table [materialParamsTypes].
|
||||
table [materialParamsTypes]. For Android external textures, entries also have an optional
|
||||
transformName parameter to specify the name of the material parameter that will be
|
||||
used to expose the transform matrix associated with the external sampler. In iOS and Vulkan,
|
||||
this will always be identity.
|
||||
|
||||
Type | Description
|
||||
:----------------------|:---------------------------------
|
||||
@@ -1023,12 +1027,11 @@ samplerCubemap | Cubemap texture
|
||||
[Table [materialParamsTypes]: Material parameter types]
|
||||
|
||||
Samplers
|
||||
: Sampler types can specify additional options:
|
||||
: Sampler types can have the following fields:
|
||||
- `format` : which can be either `int` or `float` (defaults to `float`).
|
||||
- `multisample` : a boolean to indicate whether the sampler is meant for multisampling (defaults to `false`)
|
||||
- `unfilterable` : a boolean to indicate whether the sampling is not filtered (defaults to `false`)
|
||||
|
||||
- `format`: either `int` or `float` (defaults to `float`).
|
||||
- `stages`: array of strings containing the list of shader stages this
|
||||
sampler can be accessed from. Each entry must be either `vertex` or
|
||||
`fragment` (defaults to both).
|
||||
|
||||
Arrays
|
||||
: A parameter can define an array of values by appending `[size]` after the type name, where
|
||||
@@ -1273,6 +1276,9 @@ Description
|
||||
when selecting any shading model that is not `unlit`. See the shader sections of this document
|
||||
for more information on how to access these attributes from the shaders.
|
||||
|
||||
!!! Note: Interaction with custom variables
|
||||
When the `color` attribute is specified, only four custom variables are available instead of five.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
||||
material {
|
||||
parameters : [
|
||||
@@ -1303,7 +1309,7 @@ Type
|
||||
: array of `string`
|
||||
|
||||
Value
|
||||
: Up to 4 strings, each must be a valid GLSL identifier.
|
||||
: Up to 5 strings, each must be a valid GLSL identifier.
|
||||
|
||||
Description
|
||||
: Defines custom interpolants (or variables) that are output by the material's vertex shader.
|
||||
@@ -1319,6 +1325,10 @@ Description
|
||||
particular if `default` is specified the default precision is used is the fragment shader
|
||||
(`mediump`) and in the vertex shader (`highp`).
|
||||
|
||||
!!! Warning: Interaction with required attributes
|
||||
If the `color` attribute is specified in the `required` list, then only four variables can be used
|
||||
instead of five.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
||||
material {
|
||||
name : Skybox,
|
||||
@@ -10,8 +10,8 @@ create-missing = false
|
||||
|
||||
[output.html]
|
||||
mathjax-support = true
|
||||
default-theme = "light"
|
||||
preferred-dark-theme = "light"
|
||||
default-theme = "ayu"
|
||||
preferred-dark-theme = "ayu"
|
||||
|
||||
[output.html.print]
|
||||
enable = false
|
||||
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 236 KiB After Width: | Height: | Size: 236 KiB |
|
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 199 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 158 KiB After Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 322 KiB After Width: | Height: | Size: 322 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 110 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 101 KiB |
|
Before Width: | Height: | Size: 461 KiB After Width: | Height: | Size: 461 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 114 KiB |
|
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 320 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 186 KiB |
|
Before Width: | Height: | Size: 7.4 MiB After Width: | Height: | Size: 7.4 MiB |
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.6 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 814 B After Width: | Height: | Size: 814 B |
|
Before Width: | Height: | Size: 349 B After Width: | Height: | Size: 349 B |
|
Before Width: | Height: | Size: 170 B After Width: | Height: | Size: 170 B |
|
Before Width: | Height: | Size: 84 B After Width: | Height: | Size: 84 B |
|
Before Width: | Height: | Size: 4.9 MiB After Width: | Height: | Size: 4.9 MiB |
|
Before Width: | Height: | Size: 2.0 MiB After Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 2.0 MiB After Width: | Height: | Size: 2.0 MiB |
|
Before Width: | Height: | Size: 215 KiB After Width: | Height: | Size: 215 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 2.4 MiB After Width: | Height: | Size: 2.4 MiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |