From 76ecde3d3723983921862d0535777cb31229a6aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Tue, 3 Jan 2017 00:23:18 -0800 Subject: [PATCH] Added example-32-particles. --- examples/32-particles/particles.cpp | 428 +++++++++++++++++ examples/common/ps/fs_particle.bin.h | 150 ++++++ examples/common/ps/fs_particle.sc | 19 + examples/common/ps/makefile | 9 + examples/common/ps/particle_system.cpp | 638 +++++++++++++++++++++++++ examples/common/ps/particle_system.h | 86 ++++ examples/common/ps/varying.def.sc | 6 + examples/common/ps/vs_particle.bin.h | 151 ++++++ examples/common/ps/vs_particle.sc | 16 + examples/runtime/textures/particle.ktx | Bin 0 -> 262212 bytes scripts/genie.lua | 1 + 11 files changed, 1504 insertions(+) create mode 100644 examples/32-particles/particles.cpp create mode 100644 examples/common/ps/fs_particle.bin.h create mode 100644 examples/common/ps/fs_particle.sc create mode 100644 examples/common/ps/makefile create mode 100644 examples/common/ps/particle_system.cpp create mode 100644 examples/common/ps/particle_system.h create mode 100644 examples/common/ps/varying.def.sc create mode 100644 examples/common/ps/vs_particle.bin.h create mode 100644 examples/common/ps/vs_particle.sc create mode 100644 examples/runtime/textures/particle.ktx diff --git a/examples/32-particles/particles.cpp b/examples/32-particles/particles.cpp new file mode 100644 index 000000000..8a9b375ec --- /dev/null +++ b/examples/32-particles/particles.cpp @@ -0,0 +1,428 @@ +/* + * Copyright 2011-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include "common.h" +#include "bgfx_utils.h" +#include +#include + +#include +#include +#include + +#include +#include + +#include + +static const char* s_shapeNames[] = +{ + "Sphere", + "Hemisphere", + "Circle", + "Disc", + "Rect", +}; + +static const char* s_directionName[] = +{ + "Up", + "Outward", +}; + +static const char* s_easeFuncName[] = +{ + "Linear", + "InQuad", + "OutQuad", + "InOutQuad", + "OutInQuad", + "InCubic", + "OutCubic", + "InOutCubic", + "OutInCubic", + "InQuart", + "OutQuart", + "InOutQuart", + "OutInQuart", + "InQuint", + "OutQuint", + "InOutQuint", + "OutInQuint", + "InSine", + "OutSine", + "InOutSine", + "OutInSine", + "InExpo", + "OutExpo", + "InOutExpo", + "OutInExpo", + "InCirc", + "OutCirc", + "InOutCirc", + "OutInCirc", + "InElastic", + "OutElastic", + "InOutElastic", + "OutInElastic", + "InBack", + "OutBack", + "InOutBack", + "OutInBack", + "InBounce", + "OutBounce", + "InOutBounce", + "OutInBounce", +}; +BX_STATIC_ASSERT(BX_COUNTOF(s_easeFuncName) == bx::Easing::Count); + +struct Emitter +{ + EmitterUniforms m_uniforms; + EmitterHandle m_handle; + + EmitterShape::Enum m_shape; + EmitterDirection::Enum m_direction; + + void create() + { + m_shape = EmitterShape::Sphere; + m_direction = EmitterDirection::Outward; + + m_handle = psCreateEmitter(m_shape, m_direction, 1024); + m_uniforms.reset(); + } + + void destroy() + { + psDestroyEmitter(m_handle); + } + + void update() + { + psUpdateEmitter(m_handle, &m_uniforms); + } + + void imgui(const float* _view, const float* _proj) + { +// if (ImGui::CollapsingHeader("General") ) + { + if (ImGui::Combo("Shape", (int*)&m_shape, s_shapeNames, BX_COUNTOF(s_shapeNames) ) + || ImGui::Combo("Direction", (int*)&m_direction, s_directionName, BX_COUNTOF(s_directionName) ) ) + { + psDestroyEmitter(m_handle); + m_handle = psCreateEmitter(m_shape, m_direction, 1024); + } + + ImGui::SliderInt("particles / s", (int*)&m_uniforms.m_particlesPerSecond, 0, 1024); + + ImGui::SliderFloat("Gravity scale" + , &m_uniforms.m_gravityScale + , -2.0f + , 2.0f + ); + + ImGui::RangeSliderFloat("Life span" + , &m_uniforms.m_lifeSpan[0] + , &m_uniforms.m_lifeSpan[1] + , 0.1f + , 5.0f + ); + + if (ImGui::Button("Reset") ) + { + psUpdateEmitter(m_handle); + } + } + + if (ImGui::CollapsingHeader("Position and scale") ) + { + ImGui::Combo("Position Ease", (int*)&m_uniforms.m_easePos, s_easeFuncName, BX_COUNTOF(s_easeFuncName) ); + + ImGui::RangeSliderFloat("Start offset" + , &m_uniforms.m_offsetStart[0] + , &m_uniforms.m_offsetStart[1] + , 0.0f + , 10.0f + ); + ImGui::RangeSliderFloat("End offset" + , &m_uniforms.m_offsetEnd[0] + , &m_uniforms.m_offsetEnd[1] + , 0.0f + , 10.0f + ); + + ImGui::Text("Scale:"); + + ImGui::Combo("Scale Ease", (int*)&m_uniforms.m_easeScale, s_easeFuncName, BX_COUNTOF(s_easeFuncName) ); + + ImGui::RangeSliderFloat("Scale Start" + , &m_uniforms.m_scaleStart[0] + , &m_uniforms.m_scaleStart[1] + , 0.0f + , 3.0f + ); + ImGui::RangeSliderFloat("Scale End" + , &m_uniforms.m_scaleEnd[0] + , &m_uniforms.m_scaleEnd[1] + , 0.0f + , 3.0f + ); + } + + if (ImGui::CollapsingHeader("Blending and color") ) + { + ImGui::Combo("Blend Ease", (int*)&m_uniforms.m_easeBlend, s_easeFuncName, BX_COUNTOF(s_easeFuncName) ); + ImGui::RangeSliderFloat("Blend Start" + , &m_uniforms.m_blendStart[0] + , &m_uniforms.m_blendStart[1] + , 0.0f + , 1.0f + ); + ImGui::RangeSliderFloat("Blend End" + , &m_uniforms.m_blendEnd[0] + , &m_uniforms.m_blendEnd[1] + , 0.0f + , 1.0f + ); + + ImGui::Text("Color:"); + + ImGui::Combo("RGBA Ease", (int*)&m_uniforms.m_easeRgba, s_easeFuncName, BX_COUNTOF(s_easeFuncName) ); + ImGui::ColorEdit4("RGBA0", &m_uniforms.m_rgba[0], true); + ImGui::ColorEdit4("RGBA1", &m_uniforms.m_rgba[1], true); + ImGui::ColorEdit4("RGBA2", &m_uniforms.m_rgba[2], true); + ImGui::ColorEdit4("RGBA3", &m_uniforms.m_rgba[3], true); + ImGui::ColorEdit4("RGBA4", &m_uniforms.m_rgba[4], true); + } + + ImGui::End(); + + float mtx[16]; + bx::mtxSRT(mtx + , 1.0f, 1.0f, 1.0f + , m_uniforms.m_angle[0], m_uniforms.m_angle[1], m_uniforms.m_angle[2] + , m_uniforms.m_position[0], m_uniforms.m_position[1], m_uniforms.m_position[2] + ); + + ImGuizmo::Manipulate( + _view + , _proj + , ImGuizmo::OPERATION::TRANSLATE + , ImGuizmo::MODE::LOCAL + , mtx + ); + + float scale[3]; + ImGuizmo::DecomposeMatrixToComponents(mtx, m_uniforms.m_position, m_uniforms.m_angle, scale); + } +}; + +class Particles : public entry::AppI +{ + void init(int _argc, char** _argv) BX_OVERRIDE + { + Args args(_argc, _argv); + + m_width = 1280; + m_height = 720; + m_debug = BGFX_DEBUG_TEXT; + m_reset = BGFX_RESET_VSYNC; + + bgfx::init(args.m_type, args.m_pciId); + bgfx::reset(m_width, m_height, m_reset); + + // Enable m_debug text. + bgfx::setDebug(m_debug); + + // Set view 0 clear state. + bgfx::setViewClear(0 + , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH + , 0x202020ff + , 1.0f + , 0 + ); + + ddInit(); + + psInit(); + + for (uint32_t ii = 0; ii < BX_COUNTOF(m_emitter); ++ii) + { + m_emitter[ii].create(); + } + + imguiCreate(); + + cameraCreate(); + + const float initialPos[3] = { 0.0f, 2.0f, -12.0f }; + cameraSetPosition(initialPos); + cameraSetVerticalAngle(0.0f); + + m_timeOffset = bx::getHPCounter(); + } + + virtual int shutdown() BX_OVERRIDE + { + for (uint32_t ii = 0; ii < BX_COUNTOF(m_emitter); ++ii) + { + m_emitter[ii].destroy(); + } + + psShutdown(); + + ddShutdown(); + + imguiDestroy(); + + cameraDestroy(); + + // Shutdown bgfx. + bgfx::shutdown(); + + return 0; + } + + bool update() BX_OVERRIDE + { + if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) ) + { + // Set view 0 default viewport. + bgfx::setViewRect(0, 0, 0, m_width, m_height); + + bgfx::touch(0); + + int64_t now = bx::getHPCounter() - m_timeOffset; + static int64_t last = now; + const int64_t frameTime = now - last; + last = now; + const double freq = double(bx::getHPFrequency() ); + const double toMs = 1000.0/freq; + const float deltaTime = float(frameTime/freq); + + // Use debug font to print information about this example. + bgfx::dbgTextClear(); + bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/xx-particles"); + bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Particles."); + bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs); + + // Update camera.George RR Martin + cameraUpdate(deltaTime, m_mouseState); + + float view[16]; + cameraGetViewMtx(view); + + float proj[16]; + + // Set view and projection matrix for view 0. + const bgfx::HMD* hmd = bgfx::getHMD(); + if (NULL != hmd && 0 != (hmd->flags & BGFX_HMD_RENDERING) ) + { + float eye[3]; + cameraGetPosition(eye); + bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye); + bgfx::setViewTransform(0, view, hmd->eye[0].projection, BGFX_VIEW_STEREO, hmd->eye[1].projection); + bgfx::setViewRect(0, 0, 0, hmd->width, hmd->height); + } + else + { + bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f); + + bgfx::setViewTransform(0, view, proj); + bgfx::setViewRect(0, 0, 0, m_width, m_height); + } + + imguiBeginFrame( + m_mouseState.m_mx + , m_mouseState.m_my + , (m_mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0) + | (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0) + | (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0) + , m_mouseState.m_mz + , m_width + , m_height + ); + + ImGui::Begin("Properties" + , NULL + , ImVec2(400.0f, 600.0f) + , ImGuiWindowFlags_AlwaysAutoResize + ); + + static float timeScale = 1.0f; + ImGui::SliderFloat("Time scale" + , &timeScale + , 0.0f + , 1.0f + ); + + static bool showBounds; + ImGui::Checkbox("Show bounds", &showBounds); + + ImGui::Text("Emitter:"); + static int currentEmitter = 0; + for (uint32_t ii = 0; ii < BX_COUNTOF(m_emitter); ++ii) + { + ImGui::SameLine(); + + char name[16]; + bx::snprintf(name, BX_COUNTOF(name), "%d", ii); + + ImGui::RadioButton(name, ¤tEmitter, ii); + } + + m_emitter[currentEmitter].imgui(view, proj); + + imguiEndFrame(); + + ddBegin(0); + + float center[3] = { 0.0f, 0.0f, 0.0f }; + ddDrawGrid(Axis::Y, center); + + float eye[3]; + cameraGetPosition(eye); + + m_emitter[currentEmitter].update(); + + psUpdate(deltaTime * timeScale); + psRender(0, view, eye); + + if (showBounds) + { +// Aabb aabb; +// toAabb(aabb, tvb.data, tvb.size/tvb.stride, tvb.stride); + +// ddSetColor(0xff0000ff); +// ddDraw(aabb); + } + + + ddEnd(); + + // Advance to next frame. Rendering thread will be kicked to + // process submitted rendering primitives. + bgfx::frame(); + + return true; + } + + return false; + } + + entry::MouseState m_mouseState; + + int64_t m_timeOffset; + + uint32_t m_width; + uint32_t m_height; + uint32_t m_debug; + uint32_t m_reset; + + Emitter m_emitter[4]; +}; + +ENTRY_IMPLEMENT_MAIN(Particles); diff --git a/examples/common/ps/fs_particle.bin.h b/examples/common/ps/fs_particle.bin.h new file mode 100644 index 000000000..3c96bf68a --- /dev/null +++ b/examples/common/ps/fs_particle.bin.h @@ -0,0 +1,150 @@ +static const uint8_t fs_particle_glsl[403] = +{ + 0x46, 0x53, 0x48, 0x04, 0x01, 0x83, 0xf2, 0xe1, 0x01, 0x00, 0x0a, 0x73, 0x5f, 0x74, 0x65, 0x78, // FSH........s_tex + 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x73, 0x01, 0x00, 0x00, 0x76, // Color......s...v + 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, // arying highp vec + 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, // 4 v_color0;.vary + 0x69, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, // ing highp vec4 v + 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, // _texcoord0;.unif + 0x6f, 0x72, 0x6d, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, 0x32, 0x44, 0x20, 0x73, 0x5f, // orm sampler2D s_ + 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, // texColor;.void m + 0x61, 0x69, 0x6e, 0x20, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x77, 0x70, 0x20, // ain ().{. lowp + 0x76, 0x65, 0x63, 0x34, 0x20, 0x72, 0x67, 0x62, 0x61, 0x5f, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x6c, // vec4 rgba_1;. l + 0x6f, 0x77, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, // owp vec4 tmpvar_ + 0x32, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x32, 0x20, 0x3d, 0x20, // 2;. tmpvar_2 = + 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x44, 0x20, 0x28, 0x73, 0x5f, 0x74, 0x65, 0x78, // texture2D (s_tex + 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, // Color, v_texcoor + 0x64, 0x30, 0x2e, 0x78, 0x79, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x72, 0x67, 0x62, 0x61, 0x5f, 0x31, // d0.xy);. rgba_1 + 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x3d, 0x20, 0x28, 0x28, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, // .xyz = ((tmpvar_ + 0x32, 0x2e, 0x78, 0x78, 0x78, 0x20, 0x2a, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, // 2.xxx * v_color0 + 0x2e, 0x78, 0x79, 0x7a, 0x29, 0x20, 0x2a, 0x20, 0x28, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, // .xyz) * (tmpvar_ + 0x32, 0x2e, 0x78, 0x20, 0x2a, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x2e, 0x77, // 2.x * v_color0.w + 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x72, 0x67, 0x62, 0x61, 0x5f, 0x31, 0x2e, 0x77, 0x20, 0x3d, // ));. rgba_1.w = + 0x20, 0x28, 0x28, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x32, 0x2e, 0x78, 0x20, 0x2a, 0x20, // ((tmpvar_2.x * + 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x2e, 0x77, 0x29, 0x20, 0x2a, 0x20, 0x28, 0x31, // v_color0.w) * (1 + 0x2e, 0x30, 0x20, 0x2d, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, // .0 - v_texcoord0 + 0x2e, 0x7a, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, // .z));. gl_FragC + 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x5f, 0x31, 0x3b, 0x0a, 0x7d, // olor = rgba_1;.} + 0x0a, 0x0a, 0x00, // ... +}; +static const uint8_t fs_particle_dx9[326] = +{ + 0x46, 0x53, 0x48, 0x04, 0x01, 0x83, 0xf2, 0xe1, 0x01, 0x00, 0x0a, 0x73, 0x5f, 0x74, 0x65, 0x78, // FSH........s_tex + 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x01, 0x00, 0x00, 0x01, 0x00, 0x28, 0x01, 0x00, 0x03, 0xff, // Color0.....(.... + 0xff, 0xfe, 0xff, 0x20, 0x00, 0x43, 0x54, 0x41, 0x42, 0x1c, 0x00, 0x00, 0x00, 0x53, 0x00, 0x00, // ... .CTAB....S.. + 0x00, 0x00, 0x03, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x91, 0x00, // ................ + 0x00, 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, // .L...0.......... + 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, // .<.......s_texCo + 0x6c, 0x6f, 0x72, 0x00, 0xab, 0x04, 0x00, 0x0c, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, // lor............. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x73, 0x5f, 0x33, 0x5f, 0x30, 0x00, 0x4d, 0x69, 0x63, 0x72, // .....ps_3_0.Micr + 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, // osoft (R) HLSL S + 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x31, // hader Compiler 1 + 0x30, 0x2e, 0x31, 0x00, 0xab, 0x51, 0x00, 0x00, 0x05, 0x00, 0x00, 0x0f, 0xa0, 0x00, 0x00, 0x80, // 0.1..Q.......... + 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, // ?............... + 0x02, 0x0a, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, // ................ + 0x80, 0x01, 0x00, 0x07, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x90, 0x00, 0x08, 0x0f, // ................ + 0xa0, 0x42, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80, 0x01, 0x00, 0xe4, 0x90, 0x00, 0x08, 0xe4, // .B.............. + 0xa0, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, // ................ + 0x80, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x54, 0x80, 0x00, 0x00, 0x93, // ...........T.... + 0x90, 0x05, 0x00, 0x00, 0x03, 0x00, 0x08, 0x07, 0x80, 0x00, 0x00, 0xf9, 0x80, 0x00, 0x00, 0xff, // ................ + 0x90, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x00, 0xaa, // ................ + 0x91, 0x05, 0x00, 0x00, 0x03, 0x00, 0x08, 0x08, 0x80, 0x00, 0x00, 0x55, 0x80, 0x00, 0x00, 0x00, // ...........U.... + 0x80, 0xff, 0xff, 0x00, 0x00, 0x00, // ...... +}; +static const uint8_t fs_particle_dx11[517] = +{ + 0x46, 0x53, 0x48, 0x04, 0x01, 0x83, 0xf2, 0xe1, 0x01, 0x00, 0x0a, 0x73, 0x5f, 0x74, 0x65, 0x78, // FSH........s_tex + 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x01, 0x00, 0x00, 0x01, 0x00, 0xe4, 0x01, 0x44, 0x58, 0x42, // Color0.......DXB + 0x43, 0xdd, 0x04, 0xf1, 0x4a, 0xaa, 0xb0, 0xdf, 0xe0, 0xf5, 0x18, 0x2f, 0x3b, 0x6e, 0xa9, 0x0e, // C...J....../;n.. + 0x0a, 0x01, 0x00, 0x00, 0x00, 0xe4, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, // .............,.. + 0x00, 0xa0, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x49, 0x53, 0x47, 0x4e, 0x6c, 0x00, 0x00, // .........ISGNl.. + 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .........P...... + 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, // ................ + 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, // ................ + 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // .........b...... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x0f, 0x07, 0x00, // ................ + 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x43, 0x4f, 0x4c, // .SV_POSITION.COL + 0x4f, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0xab, 0x4f, 0x53, 0x47, // OR.TEXCOORD..OSG + 0x4e, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, // N,........... .. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x0f, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x54, 0x41, 0x52, 0x47, 0x45, 0x54, 0x00, 0xab, // .....SV_TARGET.. + 0xab, 0x53, 0x48, 0x44, 0x52, 0x08, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x42, 0x00, 0x00, // .SHDR....@...B.. + 0x00, 0x5a, 0x00, 0x00, 0x03, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x18, 0x00, // .Z....`......X.. + 0x04, 0x00, 0x70, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x62, 0x10, 0x00, // ..p......UU..b.. + 0x03, 0xf2, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x03, 0x72, 0x10, 0x10, // .........b...r.. + 0x00, 0x02, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, // .....e.... ..... + 0x00, 0x68, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x45, 0x00, 0x00, 0x09, 0xf2, 0x00, 0x10, // .h.......E...... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x10, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x7e, 0x10, // .....F.......F~. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, // ......`......8.. + 0x07, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, // .".............. + 0x00, 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, 0xf2, 0x00, 0x10, // .........8...... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x05, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x19, 0x10, // .....F.......6.. + 0x00, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x07, 0x72, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, // .....8...r ..... + 0x00, 0x96, 0x07, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6, 0x1f, 0x10, 0x00, 0x01, 0x00, 0x00, // ................ + 0x00, 0x00, 0x00, 0x00, 0x08, 0x22, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x10, 0x10, // .....".......*.. + 0x80, 0x41, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x80, // .A........@..... + 0x3f, 0x38, 0x00, 0x00, 0x07, 0x82, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x10, // ?8.... ......... + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, // .............>.. + 0x01, 0x00, 0x00, 0x00, 0x00, // ..... +}; +static const uint8_t fs_particle_mtl[882] = +{ + 0x46, 0x53, 0x48, 0x04, 0x01, 0x83, 0xf2, 0xe1, 0x00, 0x00, 0x63, 0x03, 0x00, 0x00, 0x75, 0x73, // FSH.......c...us + 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x20, 0x6d, 0x65, // ing namespace me + 0x74, 0x61, 0x6c, 0x3b, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x78, 0x6c, 0x61, 0x74, // tal;.struct xlat + 0x4d, 0x74, 0x6c, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x7b, // MtlShaderInput { + 0x0a, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, // . float4 v_colo + 0x72, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, 0x5f, 0x74, // r0;. float4 v_t + 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x73, 0x74, 0x72, // excoord0;.};.str + 0x75, 0x63, 0x74, 0x20, 0x78, 0x6c, 0x61, 0x74, 0x4d, 0x74, 0x6c, 0x53, 0x68, 0x61, 0x64, 0x65, // uct xlatMtlShade + 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x68, 0x61, 0x6c, 0x66, // rOutput {. half + 0x34, 0x20, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x3b, 0x0a, // 4 gl_FragColor;. + 0x7d, 0x3b, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x78, 0x6c, 0x61, 0x74, 0x4d, 0x74, // };.struct xlatMt + 0x6c, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x7b, // lShaderUniform { + 0x0a, 0x7d, 0x3b, 0x0a, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x78, 0x6c, 0x61, // .};.fragment xla + 0x74, 0x4d, 0x74, 0x6c, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, // tMtlShaderOutput + 0x20, 0x78, 0x6c, 0x61, 0x74, 0x4d, 0x74, 0x6c, 0x4d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x78, 0x6c, // xlatMtlMain (xl + 0x61, 0x74, 0x4d, 0x74, 0x6c, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, // atMtlShaderInput + 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x69, 0x20, 0x5b, 0x5b, 0x73, 0x74, 0x61, 0x67, 0x65, 0x5f, // _mtl_i [[stage_ + 0x69, 0x6e, 0x5d, 0x5d, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x78, // in]], constant x + 0x6c, 0x61, 0x74, 0x4d, 0x74, 0x6c, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x55, 0x6e, 0x69, 0x66, // latMtlShaderUnif + 0x6f, 0x72, 0x6d, 0x26, 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x75, 0x20, 0x5b, 0x5b, 0x62, 0x75, // orm& _mtl_u [[bu + 0x66, 0x66, 0x65, 0x72, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x0a, 0x20, 0x20, 0x2c, 0x20, 0x20, 0x20, // ffer(0)]]. , + 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x32, 0x64, 0x3c, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x3e, // texture2d + 0x20, 0x73, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x5b, 0x5b, 0x74, 0x65, // s_texColor [[te + 0x78, 0x74, 0x75, 0x72, 0x65, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x2c, 0x20, 0x73, 0x61, 0x6d, 0x70, // xture(0)]], samp + 0x6c, 0x65, 0x72, 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x73, 0x6d, 0x70, 0x5f, 0x73, 0x5f, 0x74, 0x65, // ler _mtlsmp_s_te + 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x5b, 0x5b, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x72, // xColor [[sampler + 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x78, 0x6c, 0x61, 0x74, 0x4d, // (0)]]).{. xlatM + 0x74, 0x6c, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x5f, // tlShaderOutput _ + 0x6d, 0x74, 0x6c, 0x5f, 0x6f, 0x3b, 0x0a, 0x20, 0x20, 0x68, 0x61, 0x6c, 0x66, 0x34, 0x20, 0x72, // mtl_o;. half4 r + 0x67, 0x62, 0x61, 0x5f, 0x31, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x68, 0x61, 0x6c, // gba_1 = 0;. hal + 0x66, 0x34, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x32, 0x20, 0x3d, 0x20, 0x30, 0x3b, // f4 tmpvar_2 = 0; + 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x32, 0x20, 0x3d, 0x20, 0x68, 0x61, // . tmpvar_2 = ha + 0x6c, 0x66, 0x34, 0x28, 0x73, 0x5f, 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2e, 0x73, // lf4(s_texColor.s + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x28, 0x5f, 0x6d, 0x74, 0x6c, 0x73, 0x6d, 0x70, 0x5f, 0x73, 0x5f, // ample(_mtlsmp_s_ + 0x74, 0x65, 0x78, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x2c, 0x20, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, // texColor, (float + 0x32, 0x29, 0x28, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x69, 0x2e, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, // 2)(_mtl_i.v_texc + 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x2e, 0x78, 0x79, 0x29, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x72, // oord0.xy)));. r + 0x67, 0x62, 0x61, 0x5f, 0x31, 0x2e, 0x78, 0x79, 0x7a, 0x20, 0x3d, 0x20, 0x28, 0x28, 0x28, 0x68, // gba_1.xyz = (((h + 0x61, 0x6c, 0x66, 0x33, 0x29, 0x28, 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x33, 0x29, 0x28, 0x74, // alf3)((float3)(t + 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x32, 0x2e, 0x78, 0x78, 0x78, 0x29, 0x20, 0x2a, 0x20, 0x5f, // mpvar_2.xxx) * _ + 0x6d, 0x74, 0x6c, 0x5f, 0x69, 0x2e, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x2e, 0x78, // mtl_i.v_color0.x + 0x79, 0x7a, 0x29, 0x29, 0x20, 0x2a, 0x20, 0x28, 0x28, 0x68, 0x61, 0x6c, 0x66, 0x29, 0x28, 0x28, // yz)) * ((half)(( + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x28, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x32, 0x2e, // float)(tmpvar_2. + 0x78, 0x29, 0x20, 0x2a, 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x69, 0x2e, 0x76, 0x5f, 0x63, 0x6f, // x) * _mtl_i.v_co + 0x6c, 0x6f, 0x72, 0x30, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x72, 0x67, 0x62, // lor0.w)));. rgb + 0x61, 0x5f, 0x31, 0x2e, 0x77, 0x20, 0x3d, 0x20, 0x28, 0x28, 0x68, 0x61, 0x6c, 0x66, 0x29, 0x28, // a_1.w = ((half)( + 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x28, 0x28, 0x28, 0x68, 0x61, 0x6c, 0x66, 0x29, 0x28, // (float)(((half)( + 0x28, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x29, 0x28, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x32, // (float)(tmpvar_2 + 0x2e, 0x78, 0x29, 0x20, 0x2a, 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x69, 0x2e, 0x76, 0x5f, 0x63, // .x) * _mtl_i.v_c + 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x2e, 0x77, 0x29, 0x29, 0x29, 0x20, 0x2a, 0x20, 0x28, 0x31, 0x2e, // olor0.w))) * (1. + 0x30, 0x20, 0x2d, 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x69, 0x2e, 0x76, 0x5f, 0x74, 0x65, 0x78, // 0 - _mtl_i.v_tex + 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x2e, 0x7a, 0x29, 0x29, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x5f, // coord0.z)));. _ + 0x6d, 0x74, 0x6c, 0x5f, 0x6f, 0x2e, 0x67, 0x6c, 0x5f, 0x46, 0x72, 0x61, 0x67, 0x43, 0x6f, 0x6c, // mtl_o.gl_FragCol + 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x72, 0x67, 0x62, 0x61, 0x5f, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x72, // or = rgba_1;. r + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x6f, 0x3b, 0x0a, 0x7d, 0x0a, // eturn _mtl_o;.}. + 0x0a, 0x00, // .. +}; +extern const uint8_t* fs_particle_pssl; +extern const uint32_t fs_particle_pssl_size; diff --git a/examples/common/ps/fs_particle.sc b/examples/common/ps/fs_particle.sc new file mode 100644 index 000000000..f0b4f569f --- /dev/null +++ b/examples/common/ps/fs_particle.sc @@ -0,0 +1,19 @@ +$input v_color0, v_texcoord0 + +/* + * Copyright 2011-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include + +SAMPLER2D(s_texColor, 0); + +void main() +{ + vec4 rgba = texture2D(s_texColor, v_texcoord0.xy).xxxx; + + rgba.xyz = rgba.xyz * v_color0.xyz * rgba.w * v_color0.w; + rgba.w = rgba.w * v_color0.w * (1.0f - v_texcoord0.z); + gl_FragColor = rgba; +} diff --git a/examples/common/ps/makefile b/examples/common/ps/makefile new file mode 100644 index 000000000..ab2bae2d5 --- /dev/null +++ b/examples/common/ps/makefile @@ -0,0 +1,9 @@ +# +# Copyright 2011-2016 Branimir Karadzic. All rights reserved. +# License: http://www.opensource.org/licenses/BSD-2-Clause +# + +include ../../../../bgfx/scripts/shader-embeded.mk + +rebuild: + @make -s --no-print-directory clean all diff --git a/examples/common/ps/particle_system.cpp b/examples/common/ps/particle_system.cpp new file mode 100644 index 000000000..93a0b615c --- /dev/null +++ b/examples/common/ps/particle_system.cpp @@ -0,0 +1,638 @@ +/* + * Copyright 2011-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include +#include + +#include "particle_system.h" +#include "../bgfx_utils.h" + +#include +#include +#include + +#include "vs_particle.bin.h" +#include "fs_particle.bin.h" + +static const bgfx::EmbeddedShader s_embeddedShaders[] = +{ + BGFX_EMBEDDED_SHADER(vs_particle), + BGFX_EMBEDDED_SHADER(fs_particle), + + BGFX_EMBEDDED_SHADER_END() +}; + +static const bx::EaseFn s_easeFunc[] = +{ + bx::easeLinear, + bx::easeInQuad, + bx::easeOutQuad, + bx::easeInOutQuad, + bx::easeOutInQuad, + bx::easeInCubic, + bx::easeOutCubic, + bx::easeInOutCubic, + bx::easeOutInCubic, + bx::easeInQuart, + bx::easeOutQuart, + bx::easeInOutQuart, + bx::easeOutInQuart, + bx::easeInQuint, + bx::easeOutQuint, + bx::easeInOutQuint, + bx::easeOutInQuint, + bx::easeInSine, + bx::easeOutSine, + bx::easeInOutSine, + bx::easeOutInSine, + bx::easeInExpo, + bx::easeOutExpo, + bx::easeInOutExpo, + bx::easeOutInExpo, + bx::easeInCirc, + bx::easeOutCirc, + bx::easeInOutCirc, + bx::easeOutInCirc, + bx::easeInElastic, + bx::easeOutElastic, + bx::easeInOutElastic, + bx::easeOutInElastic, + bx::easeInBack, + bx::easeOutBack, + bx::easeInOutBack, + bx::easeOutInBack, + bx::easeInBounce, + bx::easeOutBounce, + bx::easeInOutBounce, + bx::easeOutInBounce, +}; +BX_STATIC_ASSERT(BX_COUNTOF(s_easeFunc) == bx::Easing::Count); + +struct PosColorTexCoord0Vertex +{ + float m_x; + float m_y; + float m_z; + uint32_t m_abgr; + float m_u; + float m_v; + float m_blend; + float m_angle; + + static void init() + { + ms_decl + .begin() + .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) + .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true) + .add(bgfx::Attrib::TexCoord0, 4, bgfx::AttribType::Float) + .end(); + } + + static bgfx::VertexDecl ms_decl; +}; + +bgfx::VertexDecl PosColorTexCoord0Vertex::ms_decl; + +struct Particle +{ + float start[3]; + float end[2][3]; + float blendStart; + float blendEnd; + float scaleStart; + float scaleEnd; + + uint32_t rgba[5]; + + float life; + float lifeSpan; +}; + +struct ParticleSort +{ + float dist; + uint32_t idx; +}; + +inline uint32_t toAbgr(const float* _rgba) +{ + return 0 + | (uint8_t(_rgba[0]*255.0f)<< 0) + | (uint8_t(_rgba[1]*255.0f)<< 8) + | (uint8_t(_rgba[2]*255.0f)<<16) + | (uint8_t(_rgba[3]*255.0f)<<24) + ; +} + +inline uint32_t toAbgr(float _rr, float _gg, float _bb, float _aa) +{ + return 0 + | (uint8_t(_rr*255.0f)<< 0) + | (uint8_t(_gg*255.0f)<< 8) + | (uint8_t(_bb*255.0f)<<16) + | (uint8_t(_aa*255.0f)<<24) + ; +} + +struct Emitter +{ + void create(EmitterShape::Enum _shape, EmitterDirection::Enum _direction, uint32_t _maxParticles); + void destroy(); + + void reset() + { + m_num = 0; + } + + void update(float _dt) + { + uint32_t num = m_num; + for (uint32_t ii = 0; ii < num; ++ii) + { + Particle& particle = m_particles[ii]; + particle.life += _dt * 1.0f/particle.lifeSpan; + + if (particle.life > 1.0f) + { + if (ii != num-1) + { + memcpy(&particle, &m_particles[num-1], sizeof(Particle) ); + --ii; + } + + --num; + } + } + + m_num = num; + + if (0 < m_uniforms.m_particlesPerSecond) + { + spawn(_dt); + } + } + + void spawn(float _dt) + { + float mtx[16]; + bx::mtxSRT(mtx + , 1.0f, 1.0f, 1.0f + , m_uniforms.m_angle[0], m_uniforms.m_angle[1], m_uniforms.m_angle[2] + , m_uniforms.m_position[0], m_uniforms.m_position[1], m_uniforms.m_position[2] + ); + + const float timePerParticle = 1.0f/m_uniforms.m_particlesPerSecond; + m_dt += _dt; + const uint32_t numParticles = uint32_t(m_dt / timePerParticle); + m_dt -= numParticles * timePerParticle; + + float time = 0.0f; + for (uint32_t ii = 0 + ; ii < numParticles && m_num < m_max + ; ++ii + ) + { + Particle& particle = m_particles[m_num]; + m_num++; + + const float up[3] = { 0.0f, 1.0f, 0.0f }; + + float pos[3]; + switch (m_shape) + { + default: + case EmitterShape::Sphere: + bx::randUnitSphere(pos, &m_rng); + break; + + case EmitterShape::Hemisphere: + bx::randUnitHemisphere(pos, &m_rng, up); + break; + + case EmitterShape::Circle: + bx::randUnitCircle(pos, &m_rng); + break; + + case EmitterShape::Disc: + { + float tmp[3]; + bx::randUnitCircle(tmp, &m_rng); + bx::vec3Mul(pos, tmp, bx::frnd(&m_rng) ); + } + break; + + case EmitterShape::Rect: + pos[0] = bx::frndh(&m_rng); + pos[1] = 0.0f; + pos[2] = bx::frndh(&m_rng); + break; + } + + float dir[3]; + switch (m_direction) + { + default: + case EmitterDirection::Up: + bx::vec3Move(dir, up); + break; + + case EmitterDirection::Outward: + bx::vec3Norm(dir, pos); + break; + } + + float start[3]; + float end[3]; + const float startOffset = bx::flerp(m_uniforms.m_offsetStart[0], m_uniforms.m_offsetStart[1], bx::frnd(&m_rng) ); + bx::vec3Mul(start, pos, startOffset); + + const float endOffset = bx::flerp(m_uniforms.m_offsetEnd[0], m_uniforms.m_offsetEnd[1], bx::frnd(&m_rng) ); + float tmp1[3]; + bx::vec3Mul(tmp1, dir, endOffset); + bx::vec3Add(end, tmp1, start); + + particle.life = time; + particle.lifeSpan = bx::flerp(m_uniforms.m_lifeSpan[0], m_uniforms.m_lifeSpan[1], bx::frnd(&m_rng) ); + + float gravity[3] = { 0.0f, -9.81f * m_uniforms.m_gravityScale * bx::fsq(particle.lifeSpan), 0.0f }; + + bx::vec3MulMtx(particle.start, start, mtx); + bx::vec3MulMtx(particle.end[0], end, mtx); + bx::vec3Add(particle.end[1], particle.end[0], gravity); + + memcpy(particle.rgba, m_uniforms.m_rgba, BX_COUNTOF(m_uniforms.m_rgba)*sizeof(uint32_t) ); + + particle.blendStart = bx::flerp(m_uniforms.m_blendStart[0], m_uniforms.m_blendStart[1], bx::frnd(&m_rng) ); + particle.blendStart = bx::flerp(m_uniforms.m_blendEnd[0], m_uniforms.m_blendEnd[1], bx::frnd(&m_rng) ); + + particle.scaleStart = bx::flerp(m_uniforms.m_scaleStart[0], m_uniforms.m_scaleStart[1], bx::frnd(&m_rng) ); + particle.scaleEnd = bx::flerp(m_uniforms.m_scaleEnd[0], m_uniforms.m_scaleEnd[1], bx::frnd(&m_rng) ); + + time += timePerParticle; + } + } + + uint32_t render(const float* _mtxView, const float* _eye, uint32_t _first, ParticleSort* _outSort, PosColorTexCoord0Vertex* _outVertices) const + { + bx::EaseFn easeRgba = s_easeFunc[m_uniforms.m_easeRgba]; + bx::EaseFn easePos = s_easeFunc[m_uniforms.m_easePos]; + bx::EaseFn easeBlend = s_easeFunc[m_uniforms.m_easeBlend]; + bx::EaseFn easeScale = s_easeFunc[m_uniforms.m_easeScale]; + + for (uint32_t jj = 0, num = m_num; jj < num; ++jj) + { + const Particle& particle = m_particles[jj]; + + const float ttPos = easePos(particle.life); + const float ttScale = easeScale(particle.life); + const float ttBlend = bx::fsaturate(easeBlend(particle.life) ); + const float ttRgba = bx::fsaturate(easeRgba(particle.life) ); + + float p0[3]; + bx::vec3Lerp(p0, particle.start, particle.end[0], ttPos); + + float p1[3]; + bx::vec3Lerp(p1, particle.end[0], particle.end[1], ttPos); + + float pos[3]; + bx::vec3Lerp(pos, p0, p1, ttPos); + + const uint32_t current = _first + jj; + ParticleSort& sort = _outSort[current]; + float tmp[3]; + bx::vec3Sub(tmp, _eye, pos); + sort.dist = bx::fsqrt(bx::vec3Dot(tmp, tmp) ); + sort.idx = current; + + uint32_t idx = uint32_t(ttRgba*4); + float ttmod = bx::fmod(ttRgba, 0.25f)/0.25f; + uint32_t rgbaStart = particle.rgba[idx]; + uint32_t rgbaEnd = particle.rgba[idx+1]; + + float rr = bx::flerp( ( (uint8_t*)&rgbaStart)[0], ( (uint8_t*)&rgbaEnd)[0], ttmod)/255.0f; + float gg = bx::flerp( ( (uint8_t*)&rgbaStart)[1], ( (uint8_t*)&rgbaEnd)[1], ttmod)/255.0f; + float bb = bx::flerp( ( (uint8_t*)&rgbaStart)[2], ( (uint8_t*)&rgbaEnd)[2], ttmod)/255.0f; + float aa = bx::flerp( ( (uint8_t*)&rgbaStart)[3], ( (uint8_t*)&rgbaEnd)[3], ttmod)/255.0f; + + float blend = bx::flerp(particle.blendStart, particle.blendEnd, ttBlend); + float scale = bx::flerp(particle.scaleStart, particle.scaleEnd, ttScale); + + uint32_t abgr = toAbgr(rr, gg, bb, aa); + + float udir[3] = { _mtxView[0]*scale, _mtxView[4]*scale, _mtxView[8]*scale }; + float vdir[3] = { _mtxView[1]*scale, _mtxView[5]*scale, _mtxView[9]*scale }; + + PosColorTexCoord0Vertex* vertex = &_outVertices[current*4]; + bx::vec3Sub(tmp, pos, udir); + bx::vec3Sub(&vertex->m_x, tmp, vdir); + vertex->m_abgr = abgr; + vertex->m_u = 0.0f; + vertex->m_v = 0.0f; + vertex->m_blend = blend; + ++vertex; + + bx::vec3Add(tmp, pos, udir); + bx::vec3Sub(&vertex->m_x, tmp, vdir); + vertex->m_abgr = abgr; + vertex->m_u = 1.0f; + vertex->m_v = 0.0f; + vertex->m_blend = blend; + ++vertex; + + bx::vec3Add(tmp, pos, udir); + bx::vec3Add(&vertex->m_x, tmp, vdir); + vertex->m_abgr = abgr; + vertex->m_u = 1.0f; + vertex->m_v = 1.0f; + vertex->m_blend = blend; + ++vertex; + + bx::vec3Sub(tmp, pos, udir); + bx::vec3Add(&vertex->m_x, tmp, vdir); + vertex->m_abgr = abgr; + vertex->m_u = 0.0f; + vertex->m_v = 1.0f; + vertex->m_blend = blend; + ++vertex; + } + + return m_num; + } + + EmitterShape::Enum m_shape; + EmitterDirection::Enum m_direction; + + float m_dt; + bx::RngMwc m_rng; + EmitterUniforms m_uniforms; + + Particle* m_particles; + uint32_t m_num; + uint32_t m_max; +}; + +void EmitterUniforms::reset() +{ + m_position[0] = 0.0f; + m_position[1] = 0.0f; + m_position[2] = 0.0f; + + m_angle[0] = 0.0f; + m_angle[1] = 0.0f; + m_angle[2] = 0.0f; + + m_particlesPerSecond = 0; + + m_offsetStart[0] = 0.0f; + m_offsetStart[1] = 1.0f; + m_offsetEnd[0] = 2.0f; + m_offsetEnd[1] = 3.0f; + + m_rgba[0] = 0x00ffffff; + m_rgba[1] = UINT32_MAX; + m_rgba[2] = UINT32_MAX; + m_rgba[3] = UINT32_MAX; + m_rgba[4] = 0x00ffffff; + + m_blendStart[0] = 0.8f; + m_blendStart[1] = 1.0f; + m_blendEnd[0] = 0.0f; + m_blendEnd[1] = 0.2f; + + m_scaleStart[0] = 0.1f; + m_scaleStart[1] = 0.2f; + m_scaleEnd[0] = 0.3f; + m_scaleEnd[1] = 0.4f; + + m_lifeSpan[0] = 1.0f; + m_lifeSpan[1] = 2.0f; + + m_gravityScale = 0.0f; + + m_easePos = bx::Easing::Linear; + m_easeRgba = bx::Easing::Linear; + m_easeBlend = bx::Easing::Linear; + m_easeScale = bx::Easing::Linear; +} + +static int32_t particleSortFn(const void* _lhs, const void* _rhs) +{ + const ParticleSort& lhs = *(const ParticleSort*)_lhs; + const ParticleSort& rhs = *(const ParticleSort*)_rhs; + return lhs.dist > rhs.dist ? -1 : 1; +} + +struct ParticleSystem +{ + void init(bx::AllocatorI* _allocator) + { + m_allocator = _allocator; + +#if BX_CONFIG_ALLOCATOR_CRT + if (NULL == _allocator) + { + static bx::CrtAllocator allocator; + m_allocator = &allocator; + } +#endif // BX_CONFIG_ALLOCATOR_CRT + + PosColorTexCoord0Vertex::init(); + + m_num = 0; + + s_texColor = bgfx::createUniform("s_texColor", bgfx::UniformType::Int1); + m_particleTexture = loadTexture("textures/particle.ktx"); + + bgfx::RendererType::Enum type = bgfx::getRendererType(); + m_particleProgram = bgfx::createProgram( + bgfx::createEmbeddedShader(s_embeddedShaders, type, "vs_particle") + , bgfx::createEmbeddedShader(s_embeddedShaders, type, "fs_particle") + , true + ); + } + + void shutdown() + { + bgfx::destroyProgram(m_particleProgram); + bgfx::destroyTexture(m_particleTexture); + bgfx::destroyUniform(s_texColor); + + m_allocator = NULL; + } + + void update(float _dt) + { + uint32_t numParticles = 0; + for (uint16_t ii = 0, num = m_emitterAlloc.getNumHandles(); ii < num; ++ii) + { + const uint16_t idx = m_emitterAlloc.getHandleAt(ii); + Emitter& emitter = m_emitter[idx]; + emitter.update(_dt); + numParticles += emitter.m_num; + } + + m_num = numParticles; + } + + void render(uint8_t _view, const float* _mtxView, const float* _eye) + { + if (0 != m_num) + { + bgfx::TransientVertexBuffer tvb; + bgfx::TransientIndexBuffer tib; + bgfx::allocTransientBuffers(&tvb + , PosColorTexCoord0Vertex::ms_decl + , m_num*4 + , &tib + , m_num*6 + ); + PosColorTexCoord0Vertex* vertices = (PosColorTexCoord0Vertex*)tvb.data; + + ParticleSort* particleSort = (ParticleSort*)BX_ALLOC(m_allocator, m_num*sizeof(ParticleSort) ); + + uint32_t pos = 0; + for (uint16_t ii = 0, num = m_emitterAlloc.getNumHandles(); ii < num; ++ii) + { + const uint16_t idx = m_emitterAlloc.getHandleAt(ii); + const Emitter& emitter = m_emitter[idx]; + pos += emitter.render(_mtxView, _eye, pos, particleSort, vertices); + } + + qsort(particleSort + , m_num + , sizeof(ParticleSort) + , particleSortFn + ); + + uint16_t* indices = (uint16_t*)tib.data; + for (uint32_t ii = 0; ii < m_num; ++ii) + { + const ParticleSort& sort = particleSort[ii]; + uint16_t* index = &indices[ii*6]; + uint16_t idx = (uint16_t)sort.idx; + index[0] = idx*4+0; + index[1] = idx*4+1; + index[2] = idx*4+2; + index[3] = idx*4+2; + index[4] = idx*4+3; + index[5] = idx*4+0; + } + + BX_FREE(m_allocator, particleSort); + + bgfx::setState(0 + | BGFX_STATE_RGB_WRITE + | BGFX_STATE_ALPHA_WRITE + | BGFX_STATE_DEPTH_TEST_LESS + | BGFX_STATE_CULL_CW + | BGFX_STATE_BLEND_NORMAL + ); + bgfx::setVertexBuffer(&tvb); + bgfx::setIndexBuffer(&tib); + bgfx::setTexture(0, s_texColor, m_particleTexture); + bgfx::submit(_view, m_particleProgram); + } + } + + EmitterHandle createEmitter(EmitterShape::Enum _shape, EmitterDirection::Enum _direction, uint32_t _maxParticles) + { + EmitterHandle handle = { m_emitterAlloc.alloc() }; + + if (UINT16_MAX != handle.idx) + { + m_emitter[handle.idx].create(_shape, _direction, _maxParticles); + } + + return handle; + } + + void updateEmitter(EmitterHandle _handle, const EmitterUniforms* _uniforms) + { + Emitter& emitter = m_emitter[_handle.idx]; + + if (NULL == _uniforms) + { + emitter.reset(); + } + else + { + memcpy(&emitter.m_uniforms, _uniforms, sizeof(EmitterUniforms) ); + } + } + + void destroyEmitter(EmitterHandle _handle) + { + m_emitter[_handle.idx].destroy(); + m_emitterAlloc.free(_handle.idx); + } + + bx::AllocatorI* m_allocator; + +#define MAX_EMITTERS 64 + bx::HandleAllocT m_emitterAlloc; + Emitter m_emitter[MAX_EMITTERS]; + + bgfx::UniformHandle s_texColor; + bgfx::TextureHandle m_particleTexture; + bgfx::ProgramHandle m_particleProgram; + + uint32_t m_num; +}; + +static ParticleSystem s_ps; + +void Emitter::create(EmitterShape::Enum _shape, EmitterDirection::Enum _direction, uint32_t _maxParticles) +{ + m_dt = 0.0f; + m_uniforms.reset(); + m_shape = _shape; + m_direction = _direction; + + m_num = 0; + m_max = _maxParticles; + m_particles = (Particle*)BX_ALLOC(s_ps.m_allocator, m_max*sizeof(Particle) ); +} + +void Emitter::destroy() +{ + BX_FREE(s_ps.m_allocator, m_particles); + m_particles = NULL; +} + +void psInit(bx::AllocatorI* _allocator) +{ + s_ps.init(_allocator); +} + +void psShutdown() +{ + s_ps.shutdown(); +} + +EmitterHandle psCreateEmitter(EmitterShape::Enum _shape, EmitterDirection::Enum _direction, uint32_t _maxParticles) +{ + return s_ps.createEmitter(_shape, _direction, _maxParticles); +} + +void psUpdateEmitter(EmitterHandle _handle, const EmitterUniforms* _uniforms) +{ + s_ps.updateEmitter(_handle, _uniforms); +} + +void psDestroyEmitter(EmitterHandle _handle) +{ + s_ps.destroyEmitter(_handle); +} + +void psUpdate(float _dt) +{ + s_ps.update(_dt); +} + +void psRender(uint8_t _view, const float* _mtxView, const float* _eye) +{ + s_ps.render(_view, _mtxView, _eye); +} diff --git a/examples/common/ps/particle_system.h b/examples/common/ps/particle_system.h new file mode 100644 index 000000000..c2366ac52 --- /dev/null +++ b/examples/common/ps/particle_system.h @@ -0,0 +1,86 @@ +/* + * Copyright 2011-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#ifndef PARTICLE_SYSTEM_H_HEADER_GUARD +#define PARTICLE_SYSTEM_H_HEADER_GUARD + +#include +#include +#include + +struct EmitterShape +{ + enum Enum + { + Sphere, + Hemisphere, + Circle, + Disc, + Rect, + + Count + }; +}; + +struct EmitterDirection +{ + enum Enum + { + Up, + Outward, + + Count + }; +}; + +struct EmitterUniforms +{ + void reset(); + + float m_position[3]; + float m_angle[3]; + + float m_blendStart[2]; + float m_blendEnd[2]; + float m_offsetStart[2]; + float m_offsetEnd[2]; + float m_scaleStart[2]; + float m_scaleEnd[2]; + float m_lifeSpan[2]; + float m_gravityScale; + + uint32_t m_rgba[5]; + uint32_t m_particlesPerSecond; + + bx::Easing::Enum m_easePos; + bx::Easing::Enum m_easeRgba; + bx::Easing::Enum m_easeBlend; + bx::Easing::Enum m_easeScale; +}; + +struct EmitterHandle { uint16_t idx; }; + +/// +void psInit(bx::AllocatorI* _allocator = NULL); + +/// +void psShutdown(); + +/// +EmitterHandle psCreateEmitter(EmitterShape::Enum _shape, EmitterDirection::Enum _direction, uint32_t _maxParticles); + +/// +void psUpdateEmitter(EmitterHandle _handle, const EmitterUniforms* _uniforms = NULL); + +/// +void psDestroyEmitter(EmitterHandle _handle); + +/// +void psUpdate(float _dt); + +/// +void psRender(uint8_t _view, const float* _mtxView, const float* _eye); + +#endif // PARTICLE_SYSTEM_H_HEADER_GUARD diff --git a/examples/common/ps/varying.def.sc b/examples/common/ps/varying.def.sc new file mode 100644 index 000000000..2218c4b47 --- /dev/null +++ b/examples/common/ps/varying.def.sc @@ -0,0 +1,6 @@ +vec4 v_color0 : COLOR0 = vec4(1.0, 0.0, 0.0, 1.0); +vec4 v_texcoord0 : TEXCOORD0 = vec4(0.0, 0.0, 0.0, 0.0); + +vec3 a_position : POSITION; +vec4 a_color0 : COLOR0; +vec4 a_texcoord0 : TEXCOORD0; diff --git a/examples/common/ps/vs_particle.bin.h b/examples/common/ps/vs_particle.bin.h new file mode 100644 index 000000000..49af4f00f --- /dev/null +++ b/examples/common/ps/vs_particle.bin.h @@ -0,0 +1,151 @@ +static const uint8_t vs_particle_glsl[420] = +{ + 0x56, 0x53, 0x48, 0x04, 0x01, 0x83, 0xf2, 0xe1, 0x01, 0x00, 0x0f, 0x75, 0x5f, 0x6d, 0x6f, 0x64, // VSH........u_mod + 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x04, 0x01, 0x00, 0x00, 0x01, 0x00, // elViewProj...... + 0x7f, 0x01, 0x00, 0x00, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x68, 0x69, // ....attribute hi + 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, // ghp vec4 a_color + 0x30, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x68, 0x69, 0x67, // 0;.attribute hig + 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x33, 0x20, 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, // hp vec3 a_positi + 0x6f, 0x6e, 0x3b, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x68, 0x69, // on;.attribute hi + 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x61, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, // ghp vec4 a_texco + 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x69, // ord0;.varying hi + 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, // ghp vec4 v_color + 0x30, 0x3b, 0x0a, 0x76, 0x61, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, // 0;.varying highp + 0x20, 0x76, 0x65, 0x63, 0x34, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, // vec4 v_texcoord + 0x30, 0x3b, 0x0a, 0x75, 0x6e, 0x69, 0x66, 0x6f, 0x72, 0x6d, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, // 0;.uniform highp + 0x20, 0x6d, 0x61, 0x74, 0x34, 0x20, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, // mat4 u_modelVie + 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x3b, 0x0a, 0x76, 0x6f, 0x69, 0x64, 0x20, 0x6d, 0x61, 0x69, 0x6e, // wProj;.void main + 0x20, 0x28, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x68, 0x69, 0x67, 0x68, 0x70, 0x20, 0x76, 0x65, // ().{. highp ve + 0x63, 0x34, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x3b, 0x0a, 0x20, 0x20, 0x74, // c4 tmpvar_1;. t + 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x77, 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x3b, // mpvar_1.w = 1.0; + 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x78, 0x79, 0x7a, 0x20, // . tmpvar_1.xyz + 0x3d, 0x20, 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x20, 0x20, // = a_position;. + 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x28, 0x75, // gl_Position = (u + 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x20, 0x2a, // _modelViewProj * + 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x76, 0x5f, // tmpvar_1);. v_ + 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, // color0 = a_color + 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, // 0;. v_texcoord0 + 0x20, 0x3d, 0x20, 0x61, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x3b, 0x0a, // = a_texcoord0;. + 0x7d, 0x0a, 0x0a, 0x00, // }... +}; +static const uint8_t vs_particle_dx9[347] = +{ + 0x56, 0x53, 0x48, 0x04, 0x01, 0x83, 0xf2, 0xe1, 0x01, 0x00, 0x0f, 0x75, 0x5f, 0x6d, 0x6f, 0x64, // VSH........u_mod + 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x04, 0x01, 0x00, 0x00, 0x04, 0x00, // elViewProj...... + 0x38, 0x01, 0x00, 0x03, 0xfe, 0xff, 0xfe, 0xff, 0x21, 0x00, 0x43, 0x54, 0x41, 0x42, 0x1c, 0x00, // 8.......!.CTAB.. + 0x00, 0x00, 0x57, 0x00, 0x00, 0x00, 0x00, 0x03, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x1c, 0x00, // ..W............. + 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, // ......P...0..... + 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0x5f, // ......@.......u_ + 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x00, 0x03, 0x00, // modelViewProj... + 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x73, // ..............vs + 0x5f, 0x33, 0x5f, 0x30, 0x00, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x28, // _3_0.Microsoft ( + 0x52, 0x29, 0x20, 0x48, 0x4c, 0x53, 0x4c, 0x20, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x20, 0x43, // R) HLSL Shader C + 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x31, 0x30, 0x2e, 0x31, 0x00, 0xab, 0x1f, 0x00, // ompiler 10.1.... + 0x00, 0x02, 0x0a, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, // ................ + 0x00, 0x80, 0x01, 0x00, 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x05, 0x00, 0x00, 0x80, 0x02, 0x00, // ................ + 0x0f, 0x90, 0x1f, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x0f, 0xe0, 0x1f, 0x00, // ................ + 0x00, 0x02, 0x0a, 0x00, 0x00, 0x80, 0x01, 0x00, 0x0f, 0xe0, 0x1f, 0x00, 0x00, 0x02, 0x05, 0x00, // ................ + 0x00, 0x80, 0x02, 0x00, 0x0f, 0xe0, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x80, 0x01, 0x00, // ................ + 0xe4, 0xa0, 0x01, 0x00, 0x55, 0x90, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, // ....U........... + 0xe4, 0xa0, 0x01, 0x00, 0x00, 0x90, 0x00, 0x00, 0xe4, 0x80, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, // ................ + 0x0f, 0x80, 0x02, 0x00, 0xe4, 0xa0, 0x01, 0x00, 0xaa, 0x90, 0x00, 0x00, 0xe4, 0x80, 0x02, 0x00, // ................ + 0x00, 0x03, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0xe4, 0x80, 0x03, 0x00, 0xe4, 0xa0, 0x01, 0x00, // ................ + 0x00, 0x02, 0x01, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0xe4, 0x90, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, // ................ + 0x0f, 0xe0, 0x02, 0x00, 0xe4, 0x90, 0xff, 0xff, 0x00, 0x00, 0x00, // ........... +}; +static const uint8_t vs_particle_dx11[620] = +{ + 0x56, 0x53, 0x48, 0x04, 0x01, 0x83, 0xf2, 0xe1, 0x01, 0x00, 0x0f, 0x75, 0x5f, 0x6d, 0x6f, 0x64, // VSH........u_mod + 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, // elViewProj...... + 0x40, 0x02, 0x44, 0x58, 0x42, 0x43, 0x94, 0x83, 0x4e, 0xd2, 0x28, 0xd5, 0xeb, 0x87, 0x3e, 0xf5, // @.DXBC..N.(...>. + 0xa1, 0x65, 0x63, 0x87, 0x0e, 0xf7, 0x01, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x03, 0x00, // .ec.......@..... + 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x9c, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x49, 0x53, // ..,...........IS + 0x47, 0x4e, 0x68, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, // GNh...........P. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x56, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ......V......... + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x00, 0x5f, 0x00, // .............._. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, // ................ + 0x00, 0x00, 0x0f, 0x0f, 0x00, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x50, 0x4f, 0x53, 0x49, // ......COLOR.POSI + 0x54, 0x49, 0x4f, 0x4e, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, 0x00, 0x4f, 0x53, // TION.TEXCOORD.OS + 0x47, 0x4e, 0x6c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x50, 0x00, // GNl...........P. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ................ + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x62, 0x00, // ..............b. + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, // ................ + 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x53, 0x56, 0x5f, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, 0x4f, // ......SV_POSITIO + 0x4e, 0x00, 0x43, 0x4f, 0x4c, 0x4f, 0x52, 0x00, 0x54, 0x45, 0x58, 0x43, 0x4f, 0x4f, 0x52, 0x44, // N.COLOR.TEXCOORD + 0x00, 0xab, 0x53, 0x48, 0x44, 0x52, 0x28, 0x01, 0x00, 0x00, 0x40, 0x00, 0x01, 0x00, 0x4a, 0x00, // ..SHDR(...@...J. + 0x00, 0x00, 0x59, 0x00, 0x00, 0x04, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, // ..Y...F. ....... + 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0xf2, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, 0x00, // .._..........._. + 0x00, 0x03, 0x72, 0x10, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x03, 0xf2, 0x10, // ..r......._..... + 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x67, 0x00, 0x00, 0x04, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, // ......g.... .... + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, 0x01, 0x00, // ......e.... .... + 0x00, 0x00, 0x65, 0x00, 0x00, 0x03, 0xf2, 0x20, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x68, 0x00, // ..e.... ......h. + 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x08, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, // ......8......... + 0x00, 0x00, 0x56, 0x15, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, // ..V.......F. ... + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, // ......2......... + 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, // ..F. ........... + 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0x00, // ......F.......2. + 0x00, 0x0a, 0xf2, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, // ..........F. ... + 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xa6, 0x1a, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x46, 0x0e, // ..............F. + 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf2, 0x20, 0x10, 0x00, 0x00, 0x00, // ........... .... + 0x00, 0x00, 0x46, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x8e, 0x20, 0x00, 0x00, 0x00, // ..F.......F. ... + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0xf2, 0x20, 0x10, 0x00, 0x01, 0x00, // ......6.... .... + 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x05, 0xf2, 0x20, // ..F.......6.... + 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x46, 0x1e, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x3e, 0x00, // ......F.......>. + 0x00, 0x01, 0x00, 0x03, 0x05, 0x00, 0x01, 0x00, 0x10, 0x00, 0x40, 0x00, // ..........@. +}; +static const uint8_t vs_particle_mtl[777] = +{ + 0x56, 0x53, 0x48, 0x04, 0x01, 0x83, 0xf2, 0xe1, 0x01, 0x00, 0x0f, 0x75, 0x5f, 0x6d, 0x6f, 0x64, // VSH........u_mod + 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x04, 0x01, 0x00, 0x00, 0x01, 0x00, // elViewProj...... + 0xe4, 0x02, 0x00, 0x00, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, // ....using namesp + 0x61, 0x63, 0x65, 0x20, 0x6d, 0x65, 0x74, 0x61, 0x6c, 0x3b, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, // ace metal;.struc + 0x74, 0x20, 0x78, 0x6c, 0x61, 0x74, 0x4d, 0x74, 0x6c, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x49, // t xlatMtlShaderI + 0x6e, 0x70, 0x75, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, // nput {. float4 + 0x61, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x20, 0x5b, 0x5b, 0x61, 0x74, 0x74, 0x72, 0x69, // a_color0 [[attri + 0x62, 0x75, 0x74, 0x65, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x66, 0x6c, 0x6f, // bute(0)]];. flo + 0x61, 0x74, 0x33, 0x20, 0x61, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x5b, // at3 a_position [ + 0x5b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x28, 0x31, 0x29, 0x5d, 0x5d, 0x3b, // [attribute(1)]]; + 0x0a, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x61, 0x5f, 0x74, 0x65, 0x78, 0x63, // . float4 a_texc + 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x20, 0x5b, 0x5b, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, // oord0 [[attribut + 0x65, 0x28, 0x32, 0x29, 0x5d, 0x5d, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, // e(2)]];.};.struc + 0x74, 0x20, 0x78, 0x6c, 0x61, 0x74, 0x4d, 0x74, 0x6c, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x4f, // t xlatMtlShaderO + 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, // utput {. float4 + 0x20, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x5b, 0x5b, 0x70, // gl_Position [[p + 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5d, 0x5d, 0x3b, 0x0a, 0x20, 0x20, 0x66, 0x6c, 0x6f, // osition]];. flo + 0x61, 0x74, 0x34, 0x20, 0x76, 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x20, 0x20, // at4 v_color0;. + 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x20, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, // float4 v_texcoor + 0x64, 0x30, 0x3b, 0x0a, 0x7d, 0x3b, 0x0a, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x20, 0x78, 0x6c, // d0;.};.struct xl + 0x61, 0x74, 0x4d, 0x74, 0x6c, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x55, 0x6e, 0x69, 0x66, 0x6f, // atMtlShaderUnifo + 0x72, 0x6d, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x34, 0x78, 0x34, 0x20, // rm {. float4x4 + 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x3b, // u_modelViewProj; + 0x0a, 0x7d, 0x3b, 0x0a, 0x76, 0x65, 0x72, 0x74, 0x65, 0x78, 0x20, 0x78, 0x6c, 0x61, 0x74, 0x4d, // .};.vertex xlatM + 0x74, 0x6c, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x78, // tlShaderOutput x + 0x6c, 0x61, 0x74, 0x4d, 0x74, 0x6c, 0x4d, 0x61, 0x69, 0x6e, 0x20, 0x28, 0x78, 0x6c, 0x61, 0x74, // latMtlMain (xlat + 0x4d, 0x74, 0x6c, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x20, 0x5f, // MtlShaderInput _ + 0x6d, 0x74, 0x6c, 0x5f, 0x69, 0x20, 0x5b, 0x5b, 0x73, 0x74, 0x61, 0x67, 0x65, 0x5f, 0x69, 0x6e, // mtl_i [[stage_in + 0x5d, 0x5d, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x74, 0x20, 0x78, 0x6c, 0x61, // ]], constant xla + 0x74, 0x4d, 0x74, 0x6c, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x55, 0x6e, 0x69, 0x66, 0x6f, 0x72, // tMtlShaderUnifor + 0x6d, 0x26, 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x75, 0x20, 0x5b, 0x5b, 0x62, 0x75, 0x66, 0x66, // m& _mtl_u [[buff + 0x65, 0x72, 0x28, 0x30, 0x29, 0x5d, 0x5d, 0x29, 0x0a, 0x7b, 0x0a, 0x20, 0x20, 0x78, 0x6c, 0x61, // er(0)]]).{. xla + 0x74, 0x4d, 0x74, 0x6c, 0x53, 0x68, 0x61, 0x64, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, // tMtlShaderOutput + 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x6f, 0x3b, 0x0a, 0x20, 0x20, 0x66, 0x6c, 0x6f, 0x61, 0x74, // _mtl_o;. float + 0x34, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x20, 0x3d, 0x20, 0x30, 0x3b, 0x0a, // 4 tmpvar_1 = 0;. + 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x77, 0x20, 0x3d, 0x20, 0x31, // tmpvar_1.w = 1 + 0x2e, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, 0x31, 0x2e, 0x78, // .0;. tmpvar_1.x + 0x79, 0x7a, 0x20, 0x3d, 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x69, 0x2e, 0x61, 0x5f, 0x70, 0x6f, // yz = _mtl_i.a_po + 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x3b, 0x0a, 0x20, 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x6f, // sition;. _mtl_o + 0x2e, 0x67, 0x6c, 0x5f, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x28, // .gl_Position = ( + 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x75, 0x2e, 0x75, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x56, 0x69, // _mtl_u.u_modelVi + 0x65, 0x77, 0x50, 0x72, 0x6f, 0x6a, 0x20, 0x2a, 0x20, 0x74, 0x6d, 0x70, 0x76, 0x61, 0x72, 0x5f, // ewProj * tmpvar_ + 0x31, 0x29, 0x3b, 0x0a, 0x20, 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x6f, 0x2e, 0x76, 0x5f, 0x63, // 1);. _mtl_o.v_c + 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x20, 0x3d, 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x69, 0x2e, 0x61, // olor0 = _mtl_i.a + 0x5f, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x5f, 0x6d, 0x74, 0x6c, 0x5f, // _color0;. _mtl_ + 0x6f, 0x2e, 0x76, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, 0x64, 0x30, 0x20, 0x3d, 0x20, // o.v_texcoord0 = + 0x5f, 0x6d, 0x74, 0x6c, 0x5f, 0x69, 0x2e, 0x61, 0x5f, 0x74, 0x65, 0x78, 0x63, 0x6f, 0x6f, 0x72, // _mtl_i.a_texcoor + 0x64, 0x30, 0x3b, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x5f, 0x6d, 0x74, // d0;. return _mt + 0x6c, 0x5f, 0x6f, 0x3b, 0x0a, 0x7d, 0x0a, 0x0a, 0x00, // l_o;.}... +}; +extern const uint8_t* vs_particle_pssl; +extern const uint32_t vs_particle_pssl_size; diff --git a/examples/common/ps/vs_particle.sc b/examples/common/ps/vs_particle.sc new file mode 100644 index 000000000..33a2a4639 --- /dev/null +++ b/examples/common/ps/vs_particle.sc @@ -0,0 +1,16 @@ +$input a_position, a_color0, a_texcoord0 +$output v_color0, v_texcoord0 + +/* + * Copyright 2011-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause + */ + +#include + +void main() +{ + gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) ); + v_color0 = a_color0; + v_texcoord0 = a_texcoord0; +} diff --git a/examples/runtime/textures/particle.ktx b/examples/runtime/textures/particle.ktx new file mode 100644 index 0000000000000000000000000000000000000000..affe202662d270bcc46dd082df99ce2f24f2c14c GIT binary patch literal 262212 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 WYz}M=Yz}-52X_DeoIF3p=l=m2YS)_p literal 0 HcmV?d00001 diff --git a/scripts/genie.lua b/scripts/genie.lua index c5d5d1d81..c8e48417b 100644 --- a/scripts/genie.lua +++ b/scripts/genie.lua @@ -401,6 +401,7 @@ if _OPTIONS["with-examples"] then exampleProject("29-debugdraw") exampleProject("30-picking") exampleProject("31-rsm") + exampleProject("32-particles") -- C99 source doesn't compile under WinRT settings if not premake.vstudio.iswinrt() then