diff --git a/filament/backend/src/vulkan/VulkanConstants.h b/filament/backend/src/vulkan/VulkanConstants.h index 16bff009d6..1f5257ed5e 100644 --- a/filament/backend/src/vulkan/VulkanConstants.h +++ b/filament/backend/src/vulkan/VulkanConstants.h @@ -165,14 +165,14 @@ constexpr static const int FVK_REQUIRED_VERSION_MINOR = 1; // buffers that have been submitted but have not yet finished rendering. Note that Filament can // issue multiple commit calls in a single frame, and that we use a triple buffered swap chain on // some platforms. -constexpr static const int FVK_MAX_COMMAND_BUFFERS = 10; +constexpr static const int FVK_MAX_COMMAND_BUFFERS = 3; // Number of command buffer submissions that should occur before an unused pipeline is removed // from the cache. // // If this number is low, VkPipeline construction will occur frequently, which can // be extremely slow. If this number is high, the memory footprint will be large. -constexpr static const int FVK_MAX_PIPELINE_AGE = 10; +constexpr static const int FVK_MAX_PIPELINE_AGE = 3; // VulkanPipelineCache does not track which command buffers contain references to which pipelines, // instead it simply waits for at least FVK_MAX_COMMAND_BUFFERS submissions to occur before diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index 0855102dd9..21fd2b57e7 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -530,6 +530,8 @@ void VulkanDriver::createTextureR(Handle th, SamplerType target, uint auto vktexture = mResourceAllocator.construct(th, mPlatform->getDevice(), mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, target, levels, format, samples, w, h, depth, usage, mStagePool); +// FVK_LOGE <<"created texture: " << vktexture->getVkImage() << " dim=" << +// vktexture->width << "x" << vktexture->height << utils::io::endl; mResourceManager.acquire(vktexture); } diff --git a/filament/src/details/RenderTarget.cpp b/filament/src/details/RenderTarget.cpp index dad0af4d63..9dcee1997b 100644 --- a/filament/src/details/RenderTarget.cpp +++ b/filament/src/details/RenderTarget.cpp @@ -34,7 +34,7 @@ struct RenderTarget::BuilderDetails { uint32_t mWidth{}; uint32_t mHeight{}; uint8_t mSamples = 1; // currently not settable in the public facing API - uint8_t mLayerCount = 0;// currently not settable in the public facing API + uint8_t mLayerCount = 1;// currently not settable in the public facing API }; using BuilderType = RenderTarget; diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt index 7cd8ce6b9e..9ad1eb9554 100644 --- a/samples/CMakeLists.txt +++ b/samples/CMakeLists.txt @@ -39,6 +39,7 @@ set(MATERIAL_SRCS materials/sandboxSubsurface.mat materials/sandboxUnlit.mat materials/texturedLit.mat + materials/iconTest.mat ) if (CMAKE_CROSSCOMPILING) @@ -270,6 +271,7 @@ if (NOT ANDROID) add_demo(viewtest) # Sample app specific + target_link_libraries(hellotriangle PRIVATE gltf-demo-resources uberarchive gltfio) target_link_libraries(frame_generator PRIVATE imageio) target_link_libraries(gltf_viewer PRIVATE gltf-demo-resources uberarchive gltfio viewer) target_link_libraries(gltf_instances PRIVATE gltf-demo-resources uberarchive gltfio viewer) diff --git a/samples/hellotriangle.cpp b/samples/hellotriangle.cpp index 4477429dd6..5ce7669c63 100644 --- a/samples/hellotriangle.cpp +++ b/samples/hellotriangle.cpp @@ -1,192 +1,490 @@ -/* - * 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 +#include #include #include #include -#include -#include +#include #include +#include #include #include -#include -#include #include +#include +#include +#include +#include +#include + +#include #include +#include -#include -#include +#include -#include +#include +#include -#include -#include +#include +#include +#include +#include #include "generated/resources/resources.h" +#include "materials/uberarchive.h" + +#include using namespace filament; -using utils::Entity; -using utils::EntityManager; +using namespace math; +using namespace utils; -struct App { - Config config; - VertexBuffer* vb; - IndexBuffer* ib; - Material* mat; - Camera* cam; - Entity camera; - Skybox* skybox; - Entity renderable; +namespace { + +const static uint32_t gIndices[] = {0, 1, 2, 2, 3, 0}; + +float const QUAD_WIDTH = .5; + +const static math::float3 gVertices[] = { + float3 {0, 0, 0} * QUAD_WIDTH, + float3 {0, 1, 0} * QUAD_WIDTH, + float3 {1, 1, 0} * QUAD_WIDTH, + float3 {1, 0, 0} * QUAD_WIDTH, }; -struct Vertex { - filament::math::float2 position; - uint32_t color; +const static math::float2 gUVs[] = { + {0, 0}, + {0, 1}, + {1, 1}, + {1, 0}, }; -static const Vertex TRIANGLE_VERTICES[3] = { - {{1, 0}, 0xffff0000u}, - {{cos(M_PI * 2 / 3), sin(M_PI * 2 / 3)}, 0xff00ff00u}, - {{cos(M_PI * 4 / 3), sin(M_PI * 4 / 3)}, 0xff0000ffu}, -}; +const static short4 tbn = math::packSnorm16(mat3f::packTangentFrame( + math::mat3f{float3{1.0f, 0.0f, 0.0f}, float3{0.0f, 0.0f, 1.0f}, + float3{0.0f, 1.0f, 0.0f}}).xyzw); -static constexpr uint16_t TRIANGLE_INDICES[3] = { 0, 1, 2 }; +const static math::short4 gNormals[]{tbn, tbn, tbn, tbn}; -static void printUsage(char* name) { - std::string exec_name(utils::Path(name).getName()); - std::string usage( - "HELLOTRIANGLE renders a spinning colored triangle\n" - "Usage:\n" - " HELLOTRIANGLE [options]\n" - "Options:\n" - " --help, -h\n" - " Prints this message\n\n" - " --api, -a\n" - " Specify the backend API: opengl, vulkan, or metal\n" - ); - const std::string from("HELLOTRIANGLE"); - for (size_t pos = usage.find(from); pos != std::string::npos; pos = usage.find(from, pos)) { - usage.replace(pos, from.length(), exec_name); +struct TestPrimitive { + TestPrimitive(Engine* engine) { + vertexBuffer = + VertexBuffer::Builder() + .vertexCount(4) + .bufferCount(3) + .attribute(VertexAttribute::POSITION, 0, + VertexBuffer::AttributeType::FLOAT3) + .attribute(VertexAttribute::UV0, 1, VertexBuffer::AttributeType::FLOAT2) + .attribute(VertexAttribute::TANGENTS, 2, VertexBuffer::AttributeType::FLOAT4) + .build(*engine); + vertexBuffer->setBufferAt(*engine, 0, + VertexBuffer::BufferDescriptor(gVertices, + vertexBuffer->getVertexCount() * sizeof(gVertices[0]))); + vertexBuffer->setBufferAt(*engine, 1, + VertexBuffer::BufferDescriptor(gUVs, + vertexBuffer->getVertexCount() * sizeof(gUVs[0]))); + vertexBuffer->setBufferAt(*engine, 2, + VertexBuffer::BufferDescriptor(gNormals, + vertexBuffer->getVertexCount() * sizeof(gNormals[0]))); + + indexBuffer = IndexBuffer::Builder().indexCount(6).build(*engine); + + indexBuffer->setBuffer(*engine, IndexBuffer::BufferDescriptor(gIndices, + indexBuffer->getIndexCount() * sizeof(uint32_t))); } - std::cout << usage; + + VertexBuffer* verts() const { return vertexBuffer; } + IndexBuffer* inds() const { return indexBuffer; } + +private: + VertexBuffer* vertexBuffer; + IndexBuffer* indexBuffer; +}; + +struct TestMaterial { + TestMaterial(Engine* engine) { + material = Material::Builder() + .package(RESOURCES_ICONTEST_DATA, RESOURCES_ICONTEST_SIZE) + .build(*engine); + } + + MaterialInstance* instance() { + auto inst = material->createInstance(); + instances.push_back(inst); + return inst; + } + +private: + Material* material; + std::vector instances; +}; + +struct TestTexture { + TestTexture(Engine* engine, size_t width, size_t height, bool attachment=false) { + auto usage = Texture::Usage::DEFAULT; + if (attachment) { + usage = usage | Texture::Usage::COLOR_ATTACHMENT; + } + texture = Texture::Builder() + .width(width).height(height).levels(1) + .usage(usage) + .format(Texture::InternalFormat::RGBA8).build(*engine); + uint8_t* data = (uint8_t*) malloc(width * height * 4); + std::memset(data, 0xFF, width * height * 4); + Texture::PixelBufferDescriptor buffer(data, size_t(width * height * 4), + Texture::Format::RGBA, Texture::Type::UBYTE, + [](void* buf, size_t size, void* user) { + free(buf); + }); + texture->setImage(*engine, 0, 0, 0, 0, width, height, 1, std::move(buffer)); + } + Texture* get() const { return texture; } +private: + Texture* texture; +}; + +std::pair createSDLwindow() { + const uint32_t windowFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI; + SDL_Window* win = SDL_CreateWindow("Hello World!", 0, 100, 800, 800, windowFlags); + if (win == nullptr) { + std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl; + SDL_Quit(); + return {NULL, NULL}; + } + + void* nativeWindow = getNativeWindow(win); +#if defined(__APPLE__) + prepareNativeWindow(win); + setUpMetalLayer(nativeWindow); +#endif + + return {win, nativeWindow}; } -static int handleCommandLineArguments(int argc, char* argv[], App* app) { - static constexpr const char* OPTSTR = "ha:"; - static const struct option OPTIONS[] = { - { "help", no_argument, nullptr, 'h' }, - { "api", required_argument, nullptr, 'a' }, - { nullptr, 0, nullptr, 0 } +struct IconScene { + + struct Option { + float border=1.4; + bool postProcessing=true; + bool useSkybox=false; }; - int opt; - int option_index = 0; - while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) { - std::string arg(optarg ? optarg : ""); - switch (opt) { - default: - case 'h': - printUsage(argv[0]); - exit(0); - case 'a': - if (arg == "opengl") { - app->config.backend = Engine::Backend::OPENGL; - } else if (arg == "vulkan") { - app->config.backend = Engine::Backend::VULKAN; - } else if (arg == "metal") { - app->config.backend = Engine::Backend::METAL; - } else { - std::cerr << "Unrecognized backend. Must be 'opengl'|'vulkan'|'metal'.\n"; - exit(1); - } - break; + + IconScene(Engine* engine, Renderer* renderer, uint32_t w, uint32_t h, Option option) + : engine(engine), + renderer(renderer), + material(engine), + primitives(engine) { + cameraEntity = EntityManager::get().create(); + camera = engine->createCamera(cameraEntity); + camera->lookAt(float3(0, 0, -10.f), float3(0, 0, 0), float3(0, 1.0f, 0)); + float halfWidth = (QUAD_WIDTH / 2) * option.border; + camera->setProjection(Camera::Projection::ORTHO, + -halfWidth , halfWidth, -halfWidth, halfWidth, -50, 50); + + scene = engine->createScene(); + + view = engine->createView(); + view->setViewport({0, 0, w, h}); + view->setScene(scene); + view->setCamera(camera); + view->setPostProcessingEnabled(false); + + Entity renderable = EntityManager::get().create(); + matInstance = material.instance(); + RenderableManager::Builder(1) + .boundingBox({{-10, -10, -10}, {10, 10, 10}}) + .material(0, matInstance) + .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, + primitives.verts(), primitives.inds(), 0, 6) + .culling(false) + .build(*engine, renderable); + + scene->addEntity(renderable); + + auto& tcm = engine->getTransformManager(); + tcm.create(renderable); + auto inst = tcm.getInstance(renderable); + mat4f xlate = mat4f::translation(float3(QUAD_WIDTH / -2.0, QUAD_WIDTH / -2.0, 0)); + tcm.setTransform(inst, xlate); + } + + void render(Texture* texture, Texture* renderTargetTexture, float3 const& multiplier) { + TextureSampler sampler{TextureSampler::MinFilter::NEAREST, + TextureSampler::MagFilter::NEAREST}; + + matInstance->setParameter("tex", texture, sampler); + matInstance->setParameter("multiplier", multiplier); + + RenderTarget* target; + if (auto itr = targets.find(renderTargetTexture); itr != targets.end()) { + target = itr->second; + } else { + target = RenderTarget::Builder() + .texture(RenderTarget::AttachmentPoint::COLOR, renderTargetTexture) + .build(*engine); + targets[renderTargetTexture] = target; + } + + view->setRenderTarget(target); + renderer->renderStandaloneView(view); + } + + void renderToSwapChain(SwapChain* swapChain, Texture* texture) { + TextureSampler sampler{TextureSampler::MinFilter::NEAREST, + TextureSampler::MagFilter::NEAREST}; + matInstance->setParameter("tex", texture, sampler); + matInstance->setParameter("multiplier", float3 {1}); + + if (renderer->beginFrame(swapChain)) { + // for each View + renderer->render(view); + renderer->endFrame(); } } - return optind; + + +private: + Engine* engine; + Renderer* renderer; + View* view; + Scene* scene; + Camera* camera; + TestMaterial material; + TestPrimitive primitives; + Entity cameraEntity; + Skybox* skybox; + MaterialInstance* matInstance; + std::unordered_map targets; +}; + +struct MainScene { + using TextureMatrix = std::vector>; + + MainScene(Engine* engine, Renderer* renderer, uint32_t w, uint32_t h, uint32_t nrows, + uint32_t ncols) + : renderer(renderer), + primitives{engine}, + material(engine), + engine(engine) { + cameraEntity = EntityManager::get().create(); + + camera = engine->createCamera(cameraEntity); + camera->lookAt(float3(0, 0, -10.f), float3(0, 0, 0), float3(0, 1.0f, 0)); + camera->setProjection(45.0, double(w) / h, 0.1, 50, Camera::Fov::VERTICAL); + + scene = engine->createScene(); + +// skybox = Skybox::Builder().color({0.2, 0.2, 0.2, 1.0}).build(*engine); +// scene->setSkybox(skybox); + + view = engine->createView(); + view->setViewport({0, 0, w, h}); + view->setScene(scene); + view->setCamera(camera); + view->setPostProcessingEnabled(false); + + root = EntityManager::get().create(); + auto& tcm = engine->getTransformManager(); + tcm.create(root); + auto rootInst = tcm.getInstance(root); + mat4f xlate = mat4f::translation(float3(-QUAD_WIDTH / 2 * nrows , -QUAD_WIDTH / 2 * ncols, 0)); + tcm.setTransform(rootInst, xlate); + + matInst = material.instance(); + + renderable = EntityManager::get().create(); + scene->addEntity(renderable); + RenderableManager::Builder(1) + .boundingBox({{-10, -10, -10}, {10, 10, 10}}) + .material(0, matInst) + .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, + primitives.verts(), primitives.inds(), 0, 6) + .culling(false) + .build(*engine, renderable); + + auto transformInst = tcm.getInstance(renderable); + tcm.setParent(transformInst, rootInst); + } + + void render(Texture* texture, RenderTarget* target, uint32_t r, uint32_t c) { + auto& tcm = engine->getTransformManager(); + TextureSampler sampler{TextureSampler::MinFilter::NEAREST, + TextureSampler::MagFilter::NEAREST}; + matInst->setParameter("tex", texture, sampler); + matInst->setParameter("multiplier", float3 {1}); + + auto transformInst = tcm.getInstance(renderable); + mat4f xlate = mat4f::translation(float3(QUAD_WIDTH * r, QUAD_WIDTH * c, 0)); + tcm.setTransform(transformInst, xlate); + + view->setRenderTarget(target); + renderer->renderStandaloneView(view); + } + + void renderToSwapChain(SwapChain* swapChain, Texture* texture, uint32_t r, uint32_t c){ + auto& tcm = engine->getTransformManager(); + TextureSampler sampler{TextureSampler::MinFilter::NEAREST, + TextureSampler::MagFilter::NEAREST}; + matInst->setParameter("tex", texture, sampler); + matInst->setParameter("multiplier", float3 {1}); + + auto transformInst = tcm.getInstance(renderable); + mat4f xlate = mat4f::translation(float3(QUAD_WIDTH * r, QUAD_WIDTH * c, 0)); + tcm.setTransform(transformInst, xlate); + + if (renderer->beginFrame(swapChain)) { + // for each View + renderer->render(view); + renderer->endFrame(); + } + } + + + Scene* get() const { return scene; } + Camera* getCamera() const { return camera; } + View* getView() const { return view; } + +private: + Renderer* renderer; + TestMaterial material; + MaterialInstance* matInst; + TestPrimitive primitives; + TextureMatrix textures; + Scene* scene; + Entity light; + Entity root; + Entity renderable; + Camera* camera; + Entity cameraEntity; + Skybox* skybox; + View* view; + std::vector renderables; + Engine* engine; +}; + } -int main(int argc, char** argv) { - App app{}; - app.config.title = "hellotriangle"; - app.config.featureLevel = backend::FeatureLevel::FEATURE_LEVEL_0; - handleCommandLineArguments(argc, argv, &app); +int main() { + SDL_Init(SDL_INIT_EVERYTHING); + auto const [window, nativeWindow] = createSDLwindow(); - auto setup = [&app](Engine* engine, View* view, Scene* scene) { - app.skybox = Skybox::Builder().color({0.1, 0.125, 0.25, 1.0}).build(*engine); - scene->setSkybox(app.skybox); - view->setPostProcessingEnabled(false); - static_assert(sizeof(Vertex) == 12, "Strange vertex size."); - app.vb = VertexBuffer::Builder() - .vertexCount(3) - .bufferCount(1) - .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT2, 0, 12) - .attribute(VertexAttribute::COLOR, 0, VertexBuffer::AttributeType::UBYTE4, 8, 12) - .normalized(VertexAttribute::COLOR) - .build(*engine); - app.vb->setBufferAt(*engine, 0, - VertexBuffer::BufferDescriptor(TRIANGLE_VERTICES, 36, nullptr)); - app.ib = IndexBuffer::Builder() - .indexCount(3) - .bufferType(IndexBuffer::IndexType::USHORT) - .build(*engine); - app.ib->setBuffer(*engine, - IndexBuffer::BufferDescriptor(TRIANGLE_INDICES, 6, nullptr)); - app.mat = Material::Builder() - .package(RESOURCES_BAKEDCOLOR_DATA, RESOURCES_BAKEDCOLOR_SIZE) - .build(*engine); - app.renderable = EntityManager::get().create(); - RenderableManager::Builder(1) - .boundingBox({{ -1, -1, -1 }, { 1, 1, 1 }}) - .material(0, app.mat->getDefaultInstance()) - .geometry(0, RenderableManager::PrimitiveType::TRIANGLES, app.vb, app.ib, 0, 3) - .culling(false) - .receiveShadows(false) - .castShadows(false) - .build(*engine, app.renderable); - scene->addEntity(app.renderable); - app.camera = utils::EntityManager::get().create(); - app.cam = engine->createCamera(app.camera); - view->setCamera(app.cam); + Engine* engine = Engine::create(filament::backend::Backend::VULKAN); + SwapChain* swapChain = + engine->createSwapChain(nativeWindow, filament::SwapChain::CONFIG_HAS_STENCIL_BUFFER); + Renderer* renderer = engine->createRenderer(); + + // Determine the current size of the window in physical pixels. + uint32_t w, h; + SDL_GL_GetDrawableSize(window, (int*) &w, (int*) &h); + + filamat::MaterialBuilder::init(); + + TestTexture matTexture {engine, 27, 27}; + + size_t const nrow = 10, ncol = 10; + + uint32_t const iconWidth = 50; + uint32_t const iconHeight = 50; + + IconScene iconScene {engine, renderer, iconWidth, iconHeight, {.useSkybox=false} }; + + auto buildTargets = [nrow, ncol, engine]() { + std::vector> targets; + for (size_t r = 0; r < nrow; r++) { + std::vector row; + for (size_t c = 0; c < ncol; c++) { + TestTexture ttex {engine, iconWidth, iconHeight, true }; + row.push_back(ttex.get()); + } + targets.push_back(row); + } + return targets; }; - auto cleanup = [&app](Engine* engine, View*, Scene*) { - engine->destroy(app.skybox); - engine->destroy(app.renderable); - engine->destroy(app.mat); - engine->destroy(app.vb); - engine->destroy(app.ib); - engine->destroyCameraComponent(app.camera); - utils::EntityManager::get().destroy(app.camera); - }; + std::vector> targets0 = buildTargets(); + std::vector> targets1 = buildTargets(); + std::vector> targets2 = buildTargets(); - FilamentApp::get().animate([&app](Engine* engine, View* view, double now) { - constexpr float ZOOM = 1.5f; - const uint32_t w = view->getViewport().width; - const uint32_t h = view->getViewport().height; - const float aspect = (float) w / h; - app.cam->setProjection(Camera::Projection::ORTHO, - -aspect * ZOOM, aspect * ZOOM, - -ZOOM, ZOOM, 0, 1); - auto& tcm = engine->getTransformManager(); - tcm.setTransform(tcm.getInstance(app.renderable), - filament::math::mat4f::rotation(now, filament::math::float3{ 0, 0, 1 })); - }); + MainScene scene(engine, renderer, w, h, nrow, ncol); - FilamentApp::get().run(app.config, setup, cleanup); + renderer->setClearOptions({.clear = false}); + float3 const a {.7, .3, .3}; + float3 const b {.3, .7, .3}; + std::vector> coords; + for (size_t r = 0; r < nrow; r++) { + for (size_t c = 0; c < ncol; c++) { + coords.push_back({r, c}); + } + } + IconScene swapChainScene{engine, renderer, w, h, { + .border = 1.0f, .postProcessing = false}}; + + TestTexture mainTex{engine, w, h, true}; + auto mainRT = RenderTarget::Builder() + .texture(RenderTarget::AttachmentPoint::COLOR, mainTex.get()) + .build(*engine); + + bool closeWindow = false; + size_t count = 0; + while (!closeWindow && ++count) { + constexpr int kMaxEvents = 16; + SDL_Event events[kMaxEvents]; + int nevents = 0; + while (nevents < kMaxEvents && SDL_PollEvent(&events[nevents]) != 0) { + nevents++; + } + + // Now, loop over the events a second time for app-side processing. + for (int i = 0; i < nevents; i++) { + const SDL_Event& event = events[i]; + switch (event.type) { + case SDL_QUIT: + closeWindow = true; + break; + case SDL_WINDOWEVENT: + switch (event.window.event) { + case SDL_WINDOWEVENT_RESIZED: + break; + default: + break; + } + break; + default: + break; + } + } + auto [r, c] = coords[count % coords.size()]; + float3 color0 = (r + c) % 2 == 0 ? a : b; + float3 color1 = (r + c) % 2 == 0 ? b : a; + auto rt0 = targets0[r][c]; + auto rt1 = targets1[r][c]; + auto rt2 = targets2[r][c]; + iconScene.render(matTexture.get(), rt0, color0); + iconScene.render(rt0, rt1, color1); + iconScene.render(rt1, rt2, float3 {.8}); +// engine->flushAndWait(); + scene.render(rt2, mainRT, r, c); +// engine->flushAndWait(); +// engine->flush(); +// scene.renderToSwapChain(swapChain, rt1, r, c); + + + if (count % 27 == 0) { + swapChainScene.renderToSwapChain(swapChain, mainTex.get()); + } + SDL_Delay(16); + + // if (renderer->beginFrame(swapChain)) { + // // for each View + // renderer->render(scene.getView()); + // renderer->endFrame(); + // } + + +// SDL_Delay(16); + + } return 0; } diff --git a/samples/materials/iconTest.mat b/samples/materials/iconTest.mat new file mode 100644 index 0000000000..5d247e5000 --- /dev/null +++ b/samples/materials/iconTest.mat @@ -0,0 +1,26 @@ +material { + name : Icon, + shadingModel : unlit, + requires : [ + uv0 + ], + parameters : [ + { + type : sampler2d, + name : tex + }, + { + type : float3, + name : multiplier + } + ], +} + +fragment { + void material(inout MaterialInputs material) { + prepareMaterial(material); + vec3 m = materialParams.multiplier; + vec3 rgb = texture(materialParams_tex, getUV0()).rgb * m; + material.baseColor = vec4(rgb, 1.0); + } +}