2501 lines · 103.5 KB · C++
RawDownload
        details.verticesBuffer->append(sizeof(vertexBuffer), (gpu::Byte*) vertexBuffer);        details.colorBuffer->append(sizeof(colors), (gpu::Byte*) colors); #ifdef WANT_DEBUG        if (id == UNKNOWN_ID) {            qCDebug(renderutils) << "new renderLine() 2D VBO made -- _line3DVBOs.size():" << _line2DVBOs.size();        } else {            qCDebug(renderutils) << "new registered renderLine() 2D VBO made -- _registeredLine2DVBOs.size():" << _registeredLine2DVBOs.size();        }#endif    }     // this is what it takes to render a quad    batch.setInputFormat(details.streamFormat);    batch.setInputStream(0, *details.stream);    batch.draw(gpu::LINES, 2, 0);}  void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,    const glm::vec4& color, float glowIntensity, float glowWidth, int id) {     // Disable glow lines on OSX#ifndef Q_OS_WIN    glowIntensity = 0.0f;#endif     if (glowIntensity <= 0.0f) {        if (color.a >= 1.0f) {            bindSimpleProgram(batch, false, false, false, true, true);        } else {            bindSimpleProgram(batch, false, true, false, true, true);        }        renderLine(batch, p1, p2, color, id);        return;    }     // Compile the shaders    static std::once_flag once;    std::call_once(once, [&] {        auto state = std::make_shared<gpu::State>();        auto program = gpu::Shader::createProgram(shader::render_utils::program::glowLine);        state->setCullMode(gpu::State::CULL_NONE);        state->setDepthTest(true, false, gpu::LESS_EQUAL);        state->setBlendFunction(true,            gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,            gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);         PrepareStencil::testMask(*state);        _glowLinePipeline = gpu::Pipeline::create(program, state);    });     batch.setPipeline(_glowLinePipeline);     Vec3Pair key(p1, p2);    bool registered = (id != UNKNOWN_ID);    BatchItemDetails& details = _registeredLine3DVBOs[id];     // if this is a registered quad, and we have buffers, then check to see if the geometry changed and rebuild if needed    if (registered && details.isCreated) {        Vec3Pair& lastKey = _lastRegisteredLine3D[id];        if (lastKey != key) {            details.clear();            _lastRegisteredLine3D[id] = key;        }    }     const int NUM_VERTICES = 4;    if (!details.isCreated) {        details.isCreated = true;        details.uniformBuffer = std::make_shared<gpu::Buffer>();         struct LineData {            vec4 p1;            vec4 p2;            vec4 color;            float width;        };         LineData lineData { vec4(p1, 1.0f), vec4(p2, 1.0f), color, glowWidth };        details.uniformBuffer->resize(sizeof(LineData));        details.uniformBuffer->setSubData(0, lineData);    }     // The shader requires no vertices, only uniforms.    batch.setUniformBuffer(0, details.uniformBuffer);    batch.draw(gpu::TRIANGLE_STRIP, NUM_VERTICES, 0);} void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) {    static std::once_flag once;    std::call_once(once, [&]() {        auto program = gpu::Shader::createProgram(shader::render_utils::program::standardDrawTexture);         auto state = std::make_shared<gpu::State>();         // enable decal blend        state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);        PrepareStencil::testMask(*state);         _standardDrawPipeline = gpu::Pipeline::create(program, state);          auto stateNoBlend = std::make_shared<gpu::State>();        PrepareStencil::testMaskDrawShape(*stateNoBlend);         auto programNoBlend = gpu::Shader::createProgram(shader::render_utils::program::standardDrawTextureNoBlend);        _standardDrawPipelineNoBlend = gpu::Pipeline::create(programNoBlend, stateNoBlend);    });     if (noBlend) {        batch.setPipeline(_standardDrawPipelineNoBlend);    } else {        batch.setPipeline(_standardDrawPipeline);    }} void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bool isLayered) {    if (!_gridPipeline) {        auto program = gpu::Shader::createProgram(shader::render_utils::program::grid);        _gridSlot = 0;        auto stateLayered = std::make_shared<gpu::State>();        stateLayered->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);        PrepareStencil::testMask(*stateLayered);        _gridPipelineLayered = gpu::Pipeline::create(program, stateLayered);         auto state = std::make_shared<gpu::State>(stateLayered->getValues());        const float DEPTH_BIAS = 0.001f;        state->setDepthBias(DEPTH_BIAS);        state->setDepthTest(true, false, gpu::LESS_EQUAL);        PrepareStencil::testMaskDrawShape(*state);        _gridPipeline = gpu::Pipeline::create(program, state);    }     gpu::PipelinePointer pipeline = isLayered ? _gridPipelineLayered : _gridPipeline;    batch.setPipeline(pipeline);    batch.setUniformBuffer(_gridSlot, gridBuffer);}   class SimpleProgramKey {public:    enum FlagBit {        IS_TEXTURED_FLAG = 0,        IS_TRANSPARENT_FLAG,        IS_CULLED_FLAG,        IS_UNLIT_FLAG,        HAS_DEPTH_BIAS_FLAG,        IS_FADING_FLAG,        IS_ANTIALIASED_FLAG,         NUM_FLAGS,    };     enum Flag {        IS_TEXTURED = (1 << IS_TEXTURED_FLAG),        IS_TRANSPARENT = (1 << IS_TRANSPARENT_FLAG),        IS_CULLED = (1 << IS_CULLED_FLAG),        IS_UNLIT = (1 << IS_UNLIT_FLAG),        HAS_DEPTH_BIAS = (1 << HAS_DEPTH_BIAS_FLAG),        IS_FADING = (1 << IS_FADING_FLAG),        IS_ANTIALIASED = (1 << IS_ANTIALIASED_FLAG),    };    typedef unsigned short Flags;     bool isFlag(short flagNum) const { return bool((_flags & flagNum) != 0); }     bool isTextured() const { return isFlag(IS_TEXTURED); }    bool isTransparent() const { return isFlag(IS_TRANSPARENT); }    bool isCulled() const { return isFlag(IS_CULLED); }    bool isUnlit() const { return isFlag(IS_UNLIT); }    bool hasDepthBias() const { return isFlag(HAS_DEPTH_BIAS); }    bool isFading() const { return isFlag(IS_FADING); }    bool isAntiAliased() const { return isFlag(IS_ANTIALIASED); }     Flags _flags = 0;    short _spare = 0;     int getRaw() const { return *reinterpret_cast<const int*>(this); }      SimpleProgramKey(bool textured = false, bool transparent = false, bool culled = true,        bool unlit = false, bool depthBias = false, bool fading = false, bool isAntiAliased = true) {        _flags = (textured ? IS_TEXTURED : 0) | (transparent ? IS_TRANSPARENT : 0) | (culled ? IS_CULLED : 0) |            (unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 0) | (fading ? IS_FADING : 0) | (isAntiAliased ? IS_ANTIALIASED : 0);    }     SimpleProgramKey(int bitmask) : _flags(bitmask) {}}; inline uint qHash(const SimpleProgramKey& key, uint seed) {    return qHash(key.getRaw(), seed);} inline bool operator==(const SimpleProgramKey& a, const SimpleProgramKey& b) {    return a.getRaw() == b.getRaw();} static void buildWebShader(int programId, bool blendEnable,                           gpu::ShaderPointer& shaderPointerOut, gpu::PipelinePointer& pipelinePointerOut) {    shaderPointerOut = gpu::Shader::createProgram(programId);    auto state = std::make_shared<gpu::State>();    state->setCullMode(gpu::State::CULL_NONE);    state->setDepthTest(true, true, gpu::LESS_EQUAL);    state->setBlendFunction(blendEnable,                            gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,                            gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);     PrepareStencil::testMaskDrawShapeNoAA(*state);     pipelinePointerOut = gpu::Pipeline::create(shaderPointerOut, state);} void GeometryCache::bindWebBrowserProgram(gpu::Batch& batch, bool transparent) {    batch.setPipeline(getWebBrowserProgram(transparent));} gpu::PipelinePointer GeometryCache::getWebBrowserProgram(bool transparent) {    static std::once_flag once;    std::call_once(once, [&]() {        buildWebShader(shader::render_utils::program::simple_opaque_web_browser, false, _simpleOpaqueWebBrowserShader, _simpleOpaqueWebBrowserPipeline);        buildWebShader(shader::render_utils::program::simple_transparent_web_browser, true, _simpleTransparentWebBrowserShader, _simpleTransparentWebBrowserPipeline);    });     return transparent ? _simpleTransparentWebBrowserPipeline : _simpleOpaqueWebBrowserPipeline;} void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool isAntiAliased) {    batch.setPipeline(getSimplePipeline(textured, transparent, culled, unlit, depthBiased, false, isAntiAliased));     // If not textured, set a default albedo map    if (!textured) {        batch.setResourceTexture(gr::Texture::MaterialAlbedo,            DependencyManager::get<TextureCache>()->getWhiteTexture());    }} gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBiased, bool fading, bool isAntiAliased) {    SimpleProgramKey config { textured, transparent, culled, unlit, depthBiased, fading, isAntiAliased };     // If the pipeline already exists, return it    auto it = _simplePrograms.find(config);    if (it != _simplePrograms.end()) {        return it.value();    }     // Compile the shaders    if (!fading) {        static std::once_flag once;        std::call_once(once, [&]() {            using namespace shader::render_utils::program;            auto PS = DISABLE_DEFERRED ? forward_simple_textured : simple_textured;            // Use the forward pipeline for both here, otherwise transparents will be unlit            auto PSTransparent = DISABLE_DEFERRED ? forward_simple_textured_transparent : forward_simple_textured_transparent;            auto PSUnlit = DISABLE_DEFERRED ? forward_simple_textured_unlit : simple_textured_unlit;            _simpleShader = gpu::Shader::createProgram(PS);            _transparentShader = gpu::Shader::createProgram(PSTransparent);            _unlitShader = gpu::Shader::createProgram(PSUnlit);        });    } else {        static std::once_flag once;        std::call_once(once, [&]() {            using namespace shader::render_utils::program;            _simpleFadeShader = gpu::Shader::createProgram(DISABLE_DEFERRED ? forward_simple_textured : simple_textured_fade);            _unlitFadeShader = gpu::Shader::createProgram(DISABLE_DEFERRED ? forward_simple_textured_unlit : simple_textured_unlit_fade);        });    }     // If the pipeline did not exist, make it    auto state = std::make_shared<gpu::State>();    if (config.isCulled()) {        state->setCullMode(gpu::State::CULL_BACK);    } else {        state->setCullMode(gpu::State::CULL_NONE);    }    state->setDepthTest(true, true, gpu::LESS_EQUAL);    if (config.hasDepthBias()) {        state->setDepthBias(1.0f);        state->setDepthBiasSlopeScale(1.0f);    }    state->setBlendFunction(config.isTransparent(),        gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,        gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);     if (config.isAntiAliased()) {        config.isTransparent() ? PrepareStencil::testMask(*state) : PrepareStencil::testMaskDrawShape(*state);    } else {        PrepareStencil::testMaskDrawShapeNoAA(*state);    }     gpu::ShaderPointer program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _unlitShader) :                                                      (config.isFading() ? _simpleFadeShader : (config.isTransparent() ? _transparentShader : _simpleShader));    gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state);    _simplePrograms.insert(config, pipeline);    return pipeline;} uint32_t toCompactColor(const glm::vec4& color) {    uint32_t compactColor = ((int(color.x * 255.0f) & 0xFF)) |        ((int(color.y * 255.0f) & 0xFF) << 8) |        ((int(color.z * 255.0f) & 0xFF) << 16) |        ((int(color.w * 255.0f) & 0xFF) << 24);    return compactColor;} static const size_t INSTANCE_COLOR_BUFFER = 0; void renderInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, bool isWire,    const render::ShapePipelinePointer& pipeline, GeometryCache::Shape shape) {    // Add pipeline to name    std::string instanceName = (isWire ? "wire_shapes_" : "solid_shapes_") + std::to_string(shape) + "_" + std::to_string(std::hash<render::ShapePipelinePointer>()(pipeline));     // Add color to named buffer    {        gpu::BufferPointer instanceColorBuffer = batch.getNamedBuffer(instanceName, INSTANCE_COLOR_BUFFER);        auto compactColor = toCompactColor(color);        instanceColorBuffer->append(compactColor);    }     // Add call to named buffer    batch.setupNamedCalls(instanceName, [args, isWire, pipeline, shape](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {        batch.setPipeline(pipeline->pipeline);        pipeline->prepare(batch, args);         if (isWire) {            DependencyManager::get<GeometryCache>()->renderWireShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]);        }        else {            DependencyManager::get<GeometryCache>()->renderShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]);        }    });} static const size_t INSTANCE_FADE_BUFFER1 = 1;static const size_t INSTANCE_FADE_BUFFER2 = 2;static const size_t INSTANCE_FADE_BUFFER3 = 3; void renderFadeInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, int fadeCategory, float fadeThreshold,    const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, bool isWire,    const render::ShapePipelinePointer& pipeline, GeometryCache::Shape shape) {    // Add pipeline to name    std::string instanceName = (isWire ? "wire_shapes_" : "solid_shapes_") + std::to_string(shape) + "_" + std::to_string(std::hash<render::ShapePipelinePointer>()(pipeline));     // Add color to named buffer    {        gpu::BufferPointer instanceColorBuffer = batch.getNamedBuffer(instanceName, INSTANCE_COLOR_BUFFER);        auto compactColor = toCompactColor(color);        instanceColorBuffer->append(compactColor);    }    // Add fade parameters to named buffers    {        gpu::BufferPointer fadeBuffer1 = batch.getNamedBuffer(instanceName, INSTANCE_FADE_BUFFER1);        gpu::BufferPointer fadeBuffer2 = batch.getNamedBuffer(instanceName, INSTANCE_FADE_BUFFER2);        gpu::BufferPointer fadeBuffer3 = batch.getNamedBuffer(instanceName, INSTANCE_FADE_BUFFER3);        // Pack parameters in 3 vec4s        glm::vec4 fadeData1;        glm::vec4 fadeData2;        glm::vec4 fadeData3;        FadeEffect::packToAttributes(fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize,            fadeData1, fadeData2, fadeData3);        fadeBuffer1->append(fadeData1);        fadeBuffer2->append(fadeData2);        fadeBuffer3->append(fadeData3);    }     // Add call to named buffer    batch.setupNamedCalls(instanceName, [args, isWire, pipeline, shape](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {        auto& buffers = data.buffers;        batch.setPipeline(pipeline->pipeline);        pipeline->prepare(batch, args);         if (isWire) {            DependencyManager::get<GeometryCache>()->renderWireFadeShapeInstances(batch, shape, data.count(),                buffers[INSTANCE_COLOR_BUFFER], buffers[INSTANCE_FADE_BUFFER1], buffers[INSTANCE_FADE_BUFFER2], buffers[INSTANCE_FADE_BUFFER3]);        }        else {            DependencyManager::get<GeometryCache>()->renderFadeShapeInstances(batch, shape, data.count(),                buffers[INSTANCE_COLOR_BUFFER], buffers[INSTANCE_FADE_BUFFER1], buffers[INSTANCE_FADE_BUFFER2], buffers[INSTANCE_FADE_BUFFER3]);        }    });} void GeometryCache::renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {    assert(pipeline != nullptr);    renderInstances(args, batch, color, false, pipeline, shape);} void GeometryCache::renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {    assert(pipeline != nullptr);    renderInstances(args, batch, color, true, pipeline, shape);} void GeometryCache::renderSolidFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color,    int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize,    const render::ShapePipelinePointer& pipeline) {    assert(pipeline != nullptr);    renderFadeInstances(args, batch, color, fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, false, pipeline, shape);} void GeometryCache::renderWireFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color,    int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize,    const render::ShapePipelinePointer& pipeline) {    assert(pipeline != nullptr);    renderFadeInstances(args, batch, color, fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, true, pipeline, shape);} void GeometryCache::renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {    assert(pipeline != nullptr);    renderInstances(args, batch, color, false, pipeline, GeometryCache::Sphere);} void GeometryCache::renderWireSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {    assert(pipeline != nullptr);    renderInstances(args, batch, color, true, pipeline, GeometryCache::Sphere);} // Enable this in a debug build to cause 'box' entities to iterate through all the// available shape types, both solid and wireframes//#define DEBUG_SHAPES  void GeometryCache::renderSolidCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {    assert(pipeline != nullptr);#ifdef DEBUG_SHAPES    static auto startTime = usecTimestampNow();    renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {         auto usecs = usecTimestampNow();        usecs -= startTime;        auto msecs = usecs / USECS_PER_MSEC;        float seconds = msecs;        seconds /= MSECS_PER_SECOND;        float fractionalSeconds = seconds - floor(seconds);        int shapeIndex = (int)seconds;         // Every second we flip to the next shape.        static const int SHAPE_COUNT = 5;        GeometryCache::Shape shapes[SHAPE_COUNT] = {            GeometryCache::Cube,            GeometryCache::Tetrahedron,            GeometryCache::Sphere,            GeometryCache::Icosahedron,            GeometryCache::Line,        };         shapeIndex %= SHAPE_COUNT;        GeometryCache::Shape shape = shapes[shapeIndex];         // For the first half second for a given shape, show the wireframe, for the second half, show the solid.        if (fractionalSeconds > 0.5f) {            renderInstances(INSTANCE_NAME, batch, color, true, pipeline, shape);        } else {            renderInstances(INSTANCE_NAME, batch, color, false, pipeline, shape);        }    });#else    renderInstances(args, batch, color, false, pipeline, GeometryCache::Cube);#endif} void GeometryCache::renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {    static const std::string INSTANCE_NAME = __FUNCTION__;    assert(pipeline != nullptr);    renderInstances(args, batch, color, true, pipeline, GeometryCache::Cube);} graphics::MeshPointer GeometryCache::meshFromShape(Shape geometryShape, glm::vec3 color) {    auto shapeData = getShapeData(geometryShape);     qDebug() << "GeometryCache::getMeshProxyListFromShape" << shapeData << stringFromShape(geometryShape);     auto positionsBufferView = buffer_helpers::clone(shapeData->_positionView);    auto normalsBufferView = buffer_helpers::clone(shapeData->_normalView);    auto indexBufferView = buffer_helpers::clone(shapeData->_indicesView);     gpu::BufferView::Size numVertices = positionsBufferView.getNumElements();    Q_ASSERT(numVertices == normalsBufferView.getNumElements());     // apply input color across all vertices    auto colorsBufferView = buffer_helpers::clone(shapeData->_normalView);    for (gpu::BufferView::Size i = 0; i < numVertices; i++) {        colorsBufferView.edit<glm::vec3>((gpu::BufferView::Index)i) = color;    }     graphics::MeshPointer mesh(new graphics::Mesh());    mesh->setVertexBuffer(positionsBufferView);    mesh->setIndexBuffer(indexBufferView);    mesh->addAttribute(gpu::Stream::NORMAL, normalsBufferView);    mesh->addAttribute(gpu::Stream::COLOR, colorsBufferView);     const auto startIndex = 0, baseVertex = 0;    graphics::Mesh::Part part(startIndex, (graphics::Index)indexBufferView.getNumElements(), baseVertex, graphics::Mesh::TRIANGLES);    auto partBuffer = new gpu::Buffer(sizeof(graphics::Mesh::Part), (gpu::Byte*)&part);    mesh->setPartBuffer(gpu::BufferView(partBuffer, gpu::Element::PART_DRAWCALL));     mesh->modelName = GeometryCache::stringFromShape(geometryShape).toStdString();    mesh->displayName = QString("GeometryCache/shape::%1").arg(GeometryCache::stringFromShape(geometryShape)).toStdString();     return mesh;

Lines 2001–2500 of 2501. Previous lines

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t