From d96c97cdb4f2cd883ceee91f45b94dd1a9b3f96f Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 15 Apr 2016 13:04:19 -0700 Subject: [PATCH] Cleanup stars to persist BufferView --- interface/src/Stars.cpp | 142 +++++++++++++++++++--------------------- interface/src/Stars.h | 26 ++++++-- 2 files changed, 87 insertions(+), 81 deletions(-) diff --git a/interface/src/Stars.cpp b/interface/src/Stars.cpp index a0283f0efd..7e2deef494 100644 --- a/interface/src/Stars.cpp +++ b/interface/src/Stars.cpp @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -42,26 +41,11 @@ static const float TAU = 6.28318530717958f; //static const float MILKY_WAY_RATIO = 0.4f; static const char* UNIFORM_TIME_NAME = "iGlobalTime"; - - -Stars::Stars() { -} - -Stars::~Stars() { -} - // Produce a random float value between 0 and 1 static float frand() { return (float)rand() / (float)RAND_MAX; } -// Produce a random radian value between 0 and 2 PI (TAU) -/* -static float rrand() { - return frand() * TAU; -} - */ - // http://mathworld.wolfram.com/SpherePointPicking.html static vec2 randPolar() { vec2 result(frand(), frand()); @@ -115,59 +99,56 @@ struct StarVertex { vec4 colorAndSize; }; -// FIXME star colors -void Stars::render(RenderArgs* renderArgs, float alpha) { - static gpu::BufferPointer vertexBuffer; - static gpu::Stream::FormatPointer streamFormat; - static gpu::Element positionElement, colorElement; - static gpu::PipelinePointer _gridPipeline; - static gpu::PipelinePointer _starsPipeline; - static int32_t _timeSlot{ -1 }; - static std::once_flag once; +static const int STARS_VERTICES_SLOT{ 0 }; +static const int STARS_COLOR_SLOT{ 1 }; - const int VERTICES_SLOT = 0; - const int COLOR_SLOT = 1; +gpu::PipelinePointer Stars::_gridPipeline{}; +gpu::PipelinePointer Stars::_starsPipeline{}; +int32_t Stars::_timeSlot{ -1 }; - std::call_once(once, [&] { - { - auto vs = gpu::Shader::createVertex(std::string(standardTransformPNTC_vert)); - auto ps = gpu::Shader::createPixel(std::string(starsGrid_frag)); - auto program = gpu::Shader::createProgram(vs, ps); - gpu::Shader::makeProgram((*program)); - _timeSlot = program->getBuffers().findLocation(UNIFORM_TIME_NAME); - if (_timeSlot == gpu::Shader::INVALID_LOCATION) { - _timeSlot = program->getUniforms().findLocation(UNIFORM_TIME_NAME); - } - auto state = gpu::StatePointer(new gpu::State()); - // enable decal blend - state->setDepthTest(gpu::State::DepthTest(false)); - state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); - _gridPipeline = gpu::Pipeline::create(program, state); - } - { - auto vs = gpu::Shader::createVertex(std::string(stars_vert)); - auto ps = gpu::Shader::createPixel(std::string(stars_frag)); - auto program = gpu::Shader::createProgram(vs, ps); - gpu::Shader::makeProgram((*program)); - auto state = gpu::StatePointer(new gpu::State()); - // enable decal blend - state->setDepthTest(gpu::State::DepthTest(false)); - state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); - state->setAntialiasedLineEnable(true); // line smoothing also smooth points - state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); - _starsPipeline = gpu::Pipeline::create(program, state); - +void Stars::init() { + if (!_gridPipeline) { + auto vs = gpu::Shader::createVertex(std::string(standardTransformPNTC_vert)); + auto ps = gpu::Shader::createPixel(std::string(starsGrid_frag)); + auto program = gpu::Shader::createProgram(vs, ps); + gpu::Shader::makeProgram((*program)); + _timeSlot = program->getBuffers().findLocation(UNIFORM_TIME_NAME); + if (_timeSlot == gpu::Shader::INVALID_LOCATION) { + _timeSlot = program->getUniforms().findLocation(UNIFORM_TIME_NAME); } + auto state = gpu::StatePointer(new gpu::State()); + // enable decal blend + state->setDepthTest(gpu::State::DepthTest(false)); + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + _gridPipeline = gpu::Pipeline::create(program, state); + } + if (!_starsPipeline) { + auto vs = gpu::Shader::createVertex(std::string(stars_vert)); + auto ps = gpu::Shader::createPixel(std::string(stars_frag)); + auto program = gpu::Shader::createProgram(vs, ps); + gpu::Shader::makeProgram((*program)); + auto state = gpu::StatePointer(new gpu::State()); + // enable decal blend + state->setDepthTest(gpu::State::DepthTest(false)); + state->setStencilTest(true, 0xFF, gpu::State::StencilTest(0, 0xFF, gpu::EQUAL, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP, gpu::State::STENCIL_OP_KEEP)); + state->setAntialiasedLineEnable(true); // line smoothing also smooth points + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA); + _starsPipeline = gpu::Pipeline::create(program, state); + } + + unsigned limit = STARFIELD_NUM_STARS; + std::vector points; + points.resize(limit); + + { // generate stars QElapsedTimer startTime; startTime.start(); + vertexBuffer.reset(new gpu::Buffer); srand(STARFIELD_SEED); - unsigned limit = STARFIELD_NUM_STARS; - std::vector points; - points.resize(limit); for (size_t star = 0; star < limit; ++star) { points[star].position = vec4(fromPolar(randPolar()), 1); float size = frand() * 2.5f + 0.5f; @@ -179,16 +160,32 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { points[star].colorAndSize = vec4(color, size); } } + double timeDiff = (double)startTime.nsecsElapsed() / 1000000.0; // ns to ms qDebug() << "Total time to generate stars: " << timeDiff << " msec"; + } + + gpu::Element positionElement, colorElement; + const size_t VERTEX_STRIDE = sizeof(StarVertex); + + vertexBuffer->append(VERTEX_STRIDE * limit, (const gpu::Byte*)&points[0]); + streamFormat.reset(new gpu::Stream::Format()); // 1 for everyone + streamFormat->setAttribute(gpu::Stream::POSITION, STARS_VERTICES_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::XYZW), 0); + streamFormat->setAttribute(gpu::Stream::COLOR, STARS_COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::RGBA)); + positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element; + colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element; + + size_t offset = offsetof(StarVertex, position); + positionView = gpu::BufferView(vertexBuffer, offset, vertexBuffer->getSize(), VERTEX_STRIDE, positionElement); + + offset = offsetof(StarVertex, colorAndSize); + colorView = gpu::BufferView(vertexBuffer, offset, vertexBuffer->getSize(), VERTEX_STRIDE, colorElement); +} + +// FIXME star colors +void Stars::render(RenderArgs* renderArgs, float alpha) { + std::call_once(once, [&]{ init(); }); - vertexBuffer->append(sizeof(StarVertex) * limit, (const gpu::Byte*)&points[0]); - streamFormat.reset(new gpu::Stream::Format()); // 1 for everyone - streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::XYZW), 0); - streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::FLOAT, gpu::RGBA)); - positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element; - colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element; - }); auto modelCache = DependencyManager::get(); auto textureCache = DependencyManager::get(); @@ -210,17 +207,10 @@ void Stars::render(RenderArgs* renderArgs, float alpha) { batch._glUniform1f(_timeSlot, secs); geometryCache->renderCube(batch); - static const size_t VERTEX_STRIDE = sizeof(StarVertex); - size_t offset = offsetof(StarVertex, position); - gpu::BufferView posView(vertexBuffer, offset, vertexBuffer->getSize(), VERTEX_STRIDE, positionElement); - offset = offsetof(StarVertex, colorAndSize); - gpu::BufferView colView(vertexBuffer, offset, vertexBuffer->getSize(), VERTEX_STRIDE, colorElement); - // Render the stars batch.setPipeline(_starsPipeline); - batch.setInputFormat(streamFormat); - batch.setInputBuffer(VERTICES_SLOT, posView); - batch.setInputBuffer(COLOR_SLOT, colView); + batch.setInputBuffer(STARS_VERTICES_SLOT, positionView); + batch.setInputBuffer(STARS_COLOR_SLOT, colorView); batch.draw(gpu::Primitive::POINTS, STARFIELD_NUM_STARS); } diff --git a/interface/src/Stars.h b/interface/src/Stars.h index 73f04755ab..f07caff770 100644 --- a/interface/src/Stars.h +++ b/interface/src/Stars.h @@ -12,21 +12,37 @@ #ifndef hifi_Stars_h #define hifi_Stars_h +#include + class RenderArgs; // Starfield rendering component. class Stars { public: - Stars(); - ~Stars(); + Stars() = default; + ~Stars() = default; + + Stars(Stars const&) = delete; + Stars& operator=(Stars const&) = delete; // Renders the starfield from a local viewer's perspective. // The parameters specifiy the field of view. void render(RenderArgs* args, float alpha); + private: - // don't copy/assign - Stars(Stars const&); // = delete; - Stars& operator=(Stars const&); // delete; + // Pipelines + static gpu::PipelinePointer _gridPipeline; + static gpu::PipelinePointer _starsPipeline; + static int32_t _timeSlot; + + // Buffers + gpu::BufferPointer vertexBuffer; + gpu::Stream::FormatPointer streamFormat; + gpu::BufferView positionView; + gpu::BufferView colorView; + std::once_flag once; + + void init(); };