1698 lines · 70.2 KB · C++
RawDownload
        IS_CULLED_FLAG,        IS_UNLIT_FLAG,        HAS_DEPTH_BIAS_FLAG,         NUM_FLAGS,    };     enum Flag {        IS_TEXTURED = (1 << IS_TEXTURED_FLAG),        IS_CULLED = (1 << IS_CULLED_FLAG),        IS_UNLIT = (1 << IS_UNLIT_FLAG),        HAS_DEPTH_BIAS = (1 << HAS_DEPTH_BIAS_FLAG),    };    typedef unsigned short Flags;     bool isFlag(short flagNum) const { return bool((_flags & flagNum) != 0); }     bool isTextured() const { return isFlag(IS_TEXTURED); }    bool isCulled() const { return isFlag(IS_CULLED); }    bool isUnlit() const { return isFlag(IS_UNLIT); }    bool hasDepthBias() const { return isFlag(HAS_DEPTH_BIAS); }     Flags _flags = 0;    short _spare = 0;     int getRaw() const { return *reinterpret_cast<const int*>(this); }      SimpleProgramKey(bool textured = false, bool culled = true,                     bool unlit = false, bool depthBias = false) {        _flags = (textured ? IS_TEXTURED : 0) | (culled ? IS_CULLED : 0) |            (unlit ? IS_UNLIT : 0) | (depthBias ? HAS_DEPTH_BIAS : 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();} void GeometryCache::bindSimpleProgram(gpu::Batch& batch, bool textured, bool culled, bool unlit, bool depthBiased) {    batch.setPipeline(getSimplePipeline(textured, culled, unlit, depthBiased));     // If not textured, set a default albedo map    if (!textured) {        batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO,            DependencyManager::get<TextureCache>()->getWhiteTexture());    }    // Set a default normal map    batch.setResourceTexture(render::ShapePipeline::Slot::MAP::NORMAL_FITTING,        DependencyManager::get<TextureCache>()->getNormalFittingTexture());} gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool culled, bool unlit, bool depthBiased) {    SimpleProgramKey config{ textured, culled, unlit, depthBiased };     // Compile the shaders    static std::once_flag once;    std::call_once(once, [&]() {        auto VS = gpu::Shader::createVertex(std::string(simple_vert));        auto PS = gpu::Shader::createPixel(std::string(simple_textured_frag));        auto PSUnlit = gpu::Shader::createPixel(std::string(simple_textured_unlit_frag));                _simpleShader = gpu::Shader::createProgram(VS, PS);        _unlitShader = gpu::Shader::createProgram(VS, PSUnlit);                gpu::Shader::BindingSet slotBindings;        slotBindings.insert(gpu::Shader::Binding(std::string("normalFittingMap"), render::ShapePipeline::Slot::MAP::NORMAL_FITTING));        gpu::Shader::makeProgram(*_simpleShader, slotBindings);        gpu::Shader::makeProgram(*_unlitShader, slotBindings);    });     // If the pipeline already exists, return it    auto it = _simplePrograms.find(config);    if (it != _simplePrograms.end()) {        return it.value();    }     // 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(false,        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);     gpu::ShaderPointer program = (config.isUnlit()) ? _unlitShader : _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(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, [isWire, pipeline, shape](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {        batch.setPipeline(pipeline->pipeline);        pipeline->prepare(batch);         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]);        }    });} void GeometryCache::renderSolidShapeInstance(gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {    renderInstances(batch, color, false, pipeline, shape);} void GeometryCache::renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {    renderInstances(batch, color, false, pipeline, GeometryCache::Sphere);} void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {    renderInstances(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(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {#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(batch, color, false, pipeline, GeometryCache::Cube);#endif} void GeometryCache::renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {    static const std::string INSTANCE_NAME = __FUNCTION__;    renderInstances(batch, color, true, pipeline, GeometryCache::Cube);}

Lines 1501–1698 of 1698. Previous lines