188 lines
6.5 KiB
C++
188 lines
6.5 KiB
C++
/*
|
|
* Copyright (C) 2018 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.
|
|
*/
|
|
|
|
#include <filament/Engine.h>
|
|
#include <filament/IndexBuffer.h>
|
|
#include <filament/LightManager.h>
|
|
#include <filament/Material.h>
|
|
#include <filament/RenderableManager.h>
|
|
#include <filament/Scene.h>
|
|
#include <filament/Skybox.h>
|
|
#include <filament/TextureSampler.h>
|
|
#include <filament/TransformManager.h>
|
|
#include <filament/VertexBuffer.h>
|
|
#include <filament/View.h>
|
|
|
|
#include <math/norm.h>
|
|
|
|
#include <filamentapp/Config.h>
|
|
#include <filamentapp/FilamentApp.h>
|
|
#include <filamentapp/MeshAssimp.h>
|
|
|
|
#include "generated/resources/resources.h"
|
|
|
|
using namespace filament;
|
|
using namespace filament::math;
|
|
using Backend = Engine::Backend;
|
|
|
|
struct GroundPlane {
|
|
VertexBuffer* vb;
|
|
IndexBuffer* ib;
|
|
Material* mat;
|
|
utils::Entity renderable;
|
|
};
|
|
|
|
struct App {
|
|
utils::Entity light;
|
|
std::map<std::string, MaterialInstance*> materials;
|
|
MeshAssimp* meshes;
|
|
mat4f transform;
|
|
GroundPlane plane;
|
|
};
|
|
|
|
static const char* MODEL_FILE = "assets/models/monkey/monkey.obj";
|
|
static const char* IBL_FOLDER = "envs/pillars";
|
|
|
|
static constexpr bool ENABLE_SHADOWS = true;
|
|
|
|
static GroundPlane createGroundPlane(Engine* engine);
|
|
|
|
static const Config config {
|
|
.title = "shadowtest",
|
|
.iblDirectory = FilamentApp::getRootAssetsPath() + IBL_FOLDER,
|
|
.scale = 1,
|
|
.splitView = false,
|
|
.backend = Backend::VULKAN,
|
|
};
|
|
|
|
int main(int argc, char** argv) {
|
|
App app;
|
|
|
|
auto setup = [&app](Engine* engine, View* view, Scene* scene) {
|
|
auto& tcm = engine->getTransformManager();
|
|
auto& rcm = engine->getRenderableManager();
|
|
auto& em = utils::EntityManager::get();
|
|
|
|
// Add geometry into the scene.
|
|
app.meshes = new MeshAssimp(*engine);
|
|
app.meshes->addFromFile(FilamentApp::getRootAssetsPath() + MODEL_FILE, app.materials);
|
|
auto ti = tcm.getInstance(app.meshes->getRenderables()[0]);
|
|
app.transform = mat4f{ mat3f(1), float3(0, 0, -4) } * tcm.getWorldTransform(ti);
|
|
for (auto renderable : app.meshes->getRenderables()) {
|
|
auto instance = rcm.getInstance(renderable);
|
|
if (rcm.hasComponent(renderable)) {
|
|
rcm.setCastShadows(instance, ENABLE_SHADOWS);
|
|
rcm.setReceiveShadows(instance, false);
|
|
scene->addEntity(renderable);
|
|
}
|
|
}
|
|
|
|
// Add light sources into the scene.
|
|
app.light = em.create();
|
|
LightManager::Builder(LightManager::Type::SUN)
|
|
.color(Color::toLinear<ACCURATE>(sRGBColor(0.98f, 0.92f, 0.89f)))
|
|
.intensity(110000)
|
|
.direction({ 0.7, -1, -0.8 })
|
|
.sunAngularRadius(1.9f)
|
|
.castShadows(ENABLE_SHADOWS)
|
|
.build(*engine, app.light);
|
|
scene->addEntity(app.light);
|
|
|
|
// Hide skybox and add ground plane.
|
|
scene->setSkybox(nullptr);
|
|
view->setClearColor({0.5f,0.75f,1.0f,1.0f});
|
|
app.plane = createGroundPlane(engine);
|
|
scene->addEntity(app.plane.renderable);
|
|
};
|
|
|
|
auto cleanup = [&app](Engine* engine, View*, Scene*) {
|
|
engine->destroy(app.plane.renderable);
|
|
engine->destroy(app.plane.mat);
|
|
engine->destroy(app.plane.vb);
|
|
engine->destroy(app.plane.ib);
|
|
engine->destroy(app.light);
|
|
for (auto& item : app.materials) {
|
|
engine->destroy(item.second);
|
|
}
|
|
delete app.meshes;
|
|
};
|
|
|
|
FilamentApp::get().animate([&app](Engine* engine, View* view, double now) {
|
|
auto& tcm = engine->getTransformManager();
|
|
auto ti = tcm.getInstance(app.meshes->getRenderables()[0]);
|
|
tcm.setTransform(ti, app.transform * mat4f::rotation(now, float3{ 0, 1, 0 }));
|
|
});
|
|
|
|
FilamentApp::get().run(config, setup, cleanup);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static GroundPlane createGroundPlane(Engine* engine) {
|
|
Material* shadowMaterial = Material::Builder()
|
|
.package(RESOURCES_GROUNDSHADOW_DATA, RESOURCES_GROUNDSHADOW_SIZE)
|
|
.build(*engine);
|
|
shadowMaterial->setDefaultParameter("strength", 0.7f);
|
|
|
|
const static uint32_t indices[] {
|
|
0, 1, 2, 2, 3, 0
|
|
};
|
|
const static float3 vertices[] {
|
|
{ -10, 0, -10 },
|
|
{ -10, 0, 10 },
|
|
{ 10, 0, 10 },
|
|
{ 10, 0, -10 },
|
|
};
|
|
short4 tbn = packSnorm16(normalize(positive(mat3f{
|
|
float3{1.0f, 0.0f, 0.0f}, float3{0.0f, 0.0f, 1.0f}, float3{0.0f, 1.0f, 0.0f}
|
|
}.toQuaternion())).xyzw);
|
|
const static short4 normals[] { tbn, tbn, tbn, tbn };
|
|
VertexBuffer* vertexBuffer = VertexBuffer::Builder()
|
|
.vertexCount(4)
|
|
.bufferCount(2)
|
|
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
|
|
.attribute(VertexAttribute::TANGENTS, 1, VertexBuffer::AttributeType::SHORT4)
|
|
.normalized(VertexAttribute::TANGENTS)
|
|
.build(*engine);
|
|
vertexBuffer->setBufferAt(*engine, 0, VertexBuffer::BufferDescriptor(
|
|
vertices, vertexBuffer->getVertexCount() * sizeof(vertices[0])));
|
|
vertexBuffer->setBufferAt(*engine, 1, VertexBuffer::BufferDescriptor(
|
|
normals, vertexBuffer->getVertexCount() * sizeof(normals[0])));
|
|
IndexBuffer* indexBuffer = IndexBuffer::Builder().indexCount(6).build(*engine);
|
|
indexBuffer->setBuffer(*engine, IndexBuffer::BufferDescriptor(
|
|
indices, indexBuffer->getIndexCount() * sizeof(uint32_t)));
|
|
|
|
auto& em = utils::EntityManager::get();
|
|
utils::Entity renderable = em.create();
|
|
RenderableManager::Builder(1)
|
|
.boundingBox({{ 0, 0, 0 }, { 10, 1e-4f, 10 }})
|
|
.material(0, shadowMaterial->getDefaultInstance())
|
|
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, vertexBuffer, indexBuffer, 0, 6)
|
|
.culling(false)
|
|
.receiveShadows(ENABLE_SHADOWS)
|
|
.castShadows(false)
|
|
.build(*engine, renderable);
|
|
|
|
auto& tcm = engine->getTransformManager();
|
|
tcm.setTransform(tcm.getInstance(renderable), mat4f::translation(float3{ 0, -1, -4 }));
|
|
return {
|
|
.vb = vertexBuffer,
|
|
.ib = indexBuffer,
|
|
.mat = shadowMaterial,
|
|
.renderable = renderable,
|
|
};
|
|
}
|