/* * Copyright (c) 2020 Samsung Electronics Co., Ltd. * * 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 "shared/utility.h" #include "shared/view.h" using namespace Dali; using Dali::Toolkit::Control; using Dali::Toolkit::TextLabel; using Dali::Toolkit::ToolBar; const char* BACKGROUND_IMAGE(""); const char* TOOLBAR_IMAGE(DEMO_IMAGE_DIR "top-bar.png"); const char* APPLICATION_TITLE("Ray Marching"); const char* SHADER_NAME("raymarch_sphere_shaded"); /** * @brief LoadShaderCode * @param filename * @param output * @return */ bool LoadShaderCode(const char* path, const char* filename, std::vector& output) { std::string fullpath(path); fullpath += filename; Dali::FileStream fileStream(fullpath, Dali::FileStream::READ | Dali::FileStream::BINARY); FILE* file = fileStream.GetFile(); if(!file) { return false; } bool retValue = false; if(!fseek(file, 0, SEEK_END)) { long int size = ftell(file); if((size != -1L) && (!fseek(file, 0, SEEK_SET))) { output.resize(size + 1); std::fill(output.begin(), output.end(), 0); ssize_t result = fread(output.data(), size, 1, file); retValue = (result >= 0); } } return retValue; } /** * @brief LoadShaders * @param shaderName * @return */ Shader LoadShaders(const std::string& shaderName) { std::vector bufV, bufF; std::string shaderVSH(shaderName); std::string shaderFSH(shaderName); shaderVSH += ".vsh"; shaderFSH += ".fsh"; Shader shader; if(LoadShaderCode(DEMO_SHADER_DIR, shaderVSH.c_str(), bufV) && LoadShaderCode(DEMO_SHADER_DIR, shaderFSH.c_str(), bufF)) { shader = Shader::New(bufV.data(), bufF.data()); } return shader; } // This example shows how to create a Ray Marching using a shader // class RayMarchingExample : public ConnectionTracker { public: RayMarchingExample(Application& application) : mApplication(application) { // Connect to the Application's Init signal mApplication.InitSignal().Connect(this, &RayMarchingExample::Create); } ~RayMarchingExample() { // Nothing to do here; } // The Init signal is received once (only) during the Application lifetime void Create(Application& application) { // Get a handle to the window Window window = application.GetWindow(); window.GetRootLayer().TouchedSignal().Connect(this, &RayMarchingExample::OnTouch); window.KeyEventSignal().Connect(this, &RayMarchingExample::OnKeyEvent); window.SetBackgroundColor(Color::YELLOW); // Creates a default view with a default tool bar. // The view is added to the window. mContentLayer = DemoHelper::CreateView(application, mView, mToolBar, BACKGROUND_IMAGE, TOOLBAR_IMAGE, APPLICATION_TITLE); // Add an extra space on the right to center the title text. mToolBar.AddControl(Actor::New(), DemoHelper::DEFAULT_VIEW_STYLE.mToolBarButtonPercentage, Toolkit::Alignment::HORIZONTAL_RIGHT); AddContentLayer(); } bool OnTouch(Actor actor, const TouchEvent& touch) { // quit the application mApplication.Quit(); return true; } /** * Main key event handler */ void OnKeyEvent(const KeyEvent& event) { if(event.GetState() == KeyEvent::DOWN) { if(IsKey(event, Dali::DALI_KEY_ESCAPE) || IsKey(event, Dali::DALI_KEY_BACK)) { mApplication.Quit(); } } } /** * Creates quad renderer */ Renderer CreateQuadRenderer() { // Create shader & geometry needed by Renderer Shader shader = LoadShaders(SHADER_NAME); Property::Map vertexFormat; vertexFormat["aPosition"] = Property::VECTOR2; VertexBuffer vertexBuffer = VertexBuffer::New(vertexFormat); const float P(0.5f); const Vector2 vertices[] = { Vector2(-P, -P), Vector2(+P, -P), Vector2(-P, +P), Vector2(+P, +P)}; vertexBuffer.SetData(vertices, 4); // Instantiate quad geometry Geometry geometry = Geometry::New(); geometry.AddVertexBuffer(vertexBuffer); geometry.SetType(Geometry::TRIANGLE_STRIP); // Create renderer Renderer renderer = Renderer::New(geometry, shader); renderer.RegisterProperty("uRadius", 0.0f); renderer.RegisterProperty("uAdjuster", -4.0f); // Animate the sphere radius uniform and a generic uAdjust uniform currently used to move the light around Animation animation = Animation::New(8.0f); animation.AnimateTo(Property(renderer, "uRadius"), 1.2f, AlphaFunction::BOUNCE); animation.AnimateTo(Property(renderer, "uAdjuster"), 4.0f, AlphaFunction::BOUNCE); animation.SetLooping(true); animation.Play(); return renderer; } void AddContentLayer() { Window window = mApplication.GetWindow(); //Create all the renderers Renderer renderer = CreateQuadRenderer(); Actor actor = Actor::New(); actor.AddRenderer(renderer); actor.SetProperty(Actor::Property::ANCHOR_POINT, Dali::AnchorPoint::CENTER); actor.SetProperty(Actor::Property::PARENT_ORIGIN, Dali::ParentOrigin::CENTER); actor.SetResizePolicy(Dali::ResizePolicy::FILL_TO_PARENT, Dali::Dimension::ALL_DIMENSIONS); mContentLayer.Add(actor); } private: Application& mApplication; Control mView; Layer mContentLayer; ToolBar mToolBar; }; int DALI_EXPORT_API main(int argc, char** argv) { Application application = Application::New(&argc, &argv); RayMarchingExample test(application); application.MainLoop(); return 0; }