예제 #1
0
void ApplicationCompositor::buildHemiVertices(
    const float fov, const float aspectRatio, const int slices, const int stacks) {
    static float textureFOV = 0.0f, textureAspectRatio = 1.0f;
    if (textureFOV == fov && textureAspectRatio == aspectRatio) {
        return;
    }

    textureFOV = fov;
    textureAspectRatio = aspectRatio;

    auto geometryCache = DependencyManager::get<GeometryCache>();

    _hemiVertices = gpu::BufferPointer(new gpu::Buffer());
    _hemiIndices = gpu::BufferPointer(new gpu::Buffer());


    if (fov >= PI) {
        qDebug() << "TexturedHemisphere::buildVBO(): FOV greater or equal than Pi will create issues";
    }

    //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm
    
    vec3 pos; 
    vec2 uv;
    // Compute vertices positions and texture UV coordinate
    // Create and write to buffer
    for (int i = 0; i < stacks; i++) {
        uv.y = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f
        // abs(theta) <= fov / 2.0f
        float pitch = -fov * (uv.y - 0.5f);
        for (int j = 0; j < slices; j++) {
            uv.x = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f
            // abs(phi) <= fov * aspectRatio / 2.0f
            float yaw = -fov * aspectRatio * (uv.x - 0.5f);
            pos = getPoint(yaw, pitch);
            static const vec4 color(1);
            _hemiVertices->append(sizeof(pos), (gpu::Byte*)&pos);
            _hemiVertices->append(sizeof(vec2), (gpu::Byte*)&uv);
            _hemiVertices->append(sizeof(vec4), (gpu::Byte*)&color);
        }
    }
    
    // Compute number of indices needed
    static const int VERTEX_PER_TRANGLE = 3;
    static const int TRIANGLE_PER_RECTANGLE = 2;
    int numberOfRectangles = (slices - 1) * (stacks - 1);
    _hemiIndexCount = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE;
    
    // Compute indices order
    std::vector<GLushort> indices;
    for (int i = 0; i < stacks - 1; i++) {
        for (int j = 0; j < slices - 1; j++) {
            GLushort bottomLeftIndex = i * slices + j;
            GLushort bottomRightIndex = bottomLeftIndex + 1;
            GLushort topLeftIndex = bottomLeftIndex + slices;
            GLushort topRightIndex = topLeftIndex + 1;
            // FIXME make a z-order curve for better vertex cache locality
            indices.push_back(topLeftIndex);
            indices.push_back(bottomLeftIndex);
            indices.push_back(topRightIndex);

            indices.push_back(topRightIndex);
            indices.push_back(bottomLeftIndex);
            indices.push_back(bottomRightIndex);
        }
    }
    _hemiIndices->append(sizeof(GLushort) * indices.size(), (gpu::Byte*)&indices[0]);
}
예제 #2
0
파일: main.cpp 프로젝트: JamesLinus/hifi
    void draw() {
        // Attempting to draw before we're visible and have a valid size will
        // produce GL errors.
        if (!isVisible() || _size.width() <= 0 || _size.height() <= 0) {
            return;
        }
        makeCurrent();
        
        gpu::Batch batch;
        batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLORS, { 0.0f, 0.0f, 0.0f, 1.0f });
        batch.clearDepthFramebuffer(1e4);
        batch.setViewportTransform({ 0, 0, _size.width() * devicePixelRatio(), _size.height() * devicePixelRatio() });
        batch.setProjectionTransform(_projectionMatrix);
        
        float t = _time.elapsed() * 1e-3f;
        glm::vec3 unitscale { 1.0f };
        glm::vec3 up { 0.0f, 1.0f, 0.0f };

        float distance = 3.0f;
        glm::vec3 camera_position{ distance * sinf(t), 0.0f, distance * cosf(t) };

        static const vec3 camera_focus(0);
        static const vec3 camera_up(0, 1, 0);
        glm::mat4 camera = glm::inverse(glm::lookAt(camera_position, camera_focus, up));
        batch.setViewTransform(camera);
        batch.setPipeline(_pipeline);
        batch.setModelTransform(Transform());

        auto geometryCache = DependencyManager::get<GeometryCache>();

        // Render grid on xz plane (not the optimal way to do things, but w/e)
        // Note: GeometryCache::renderGrid will *not* work, as it is apparenly unaffected by batch rotations and renders xy only
        {
            static const std::string GRID_INSTANCE = "Grid";
            static auto compactColor1 = toCompactColor(vec4{ 0.35f, 0.25f, 0.15f, 1.0f });
            static auto compactColor2 = toCompactColor(vec4{ 0.15f, 0.25f, 0.35f, 1.0f });
            static std::vector<glm::mat4> transforms;
            static gpu::BufferPointer colorBuffer;
            if (!transforms.empty()) {
                transforms.reserve(200);
                colorBuffer = std::make_shared<gpu::Buffer>();
                for (int i = 0; i < 100; ++i) {
                    {
                        glm::mat4 transform = glm::translate(mat4(), vec3(0, -1, -50 + i));
                        transform = glm::scale(transform, vec3(100, 1, 1));
                        transforms.push_back(transform);
                        colorBuffer->append(compactColor1);
                    }

                    {
                        glm::mat4 transform = glm::mat4_cast(quat(vec3(0, PI / 2.0f, 0)));
                        transform = glm::translate(transform, vec3(0, -1, -50 + i));
                        transform = glm::scale(transform, vec3(100, 1, 1));
                        transforms.push_back(transform);
                        colorBuffer->append(compactColor2);
                    }
                }
            }

            auto pipeline = geometryCache->getSimplePipeline();
            for (auto& transform : transforms) {
                batch.setModelTransform(transform);
                batch.setupNamedCalls(GRID_INSTANCE, [=](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
                    batch.setViewTransform(camera);
                    batch.setPipeline(_pipeline);
                    geometryCache->renderWireShapeInstances(batch, GeometryCache::Line, data.count(), colorBuffer);
                });
            }
        }

        {
            static const size_t ITEM_COUNT = 1000;
            static const float SHAPE_INTERVAL = (PI * 2.0f) / ITEM_COUNT;
            static const float ITEM_INTERVAL = SHAPE_INTERVAL / TYPE_COUNT;

            static const gpu::Element POSITION_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
            static const gpu::Element NORMAL_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
            static const gpu::Element COLOR_ELEMENT{ gpu::VEC4, gpu::NUINT8, gpu::RGBA };
            static const gpu::Element TRANSFORM_ELEMENT{ gpu::MAT4, gpu::FLOAT, gpu::XYZW };


            static std::vector<Transform> transforms;
            static std::vector<vec4> colors;
            static gpu::BufferPointer indirectBuffer;
            static gpu::BufferPointer transformBuffer;
            static gpu::BufferPointer colorBuffer;
            static gpu::BufferView colorView; 
            static gpu::BufferView instanceXfmView; 

            if (!transformBuffer) {
                transformBuffer = std::make_shared<gpu::Buffer>();
                colorBuffer = std::make_shared<gpu::Buffer>();
                indirectBuffer = std::make_shared<gpu::Buffer>();

                static const float ITEM_RADIUS = 20;
                static const vec3 ITEM_TRANSLATION{ 0, 0, -ITEM_RADIUS };
                for (size_t i = 0; i < TYPE_COUNT; ++i) {
                    GeometryCache::Shape shape = SHAPE[i];
                    GeometryCache::ShapeData shapeData = geometryCache->_shapes[shape];
                    {
                        gpu::Batch::DrawIndexedIndirectCommand indirectCommand;
                        indirectCommand._count = (uint)shapeData._indexCount;
                        indirectCommand._instanceCount = ITEM_COUNT;
                        indirectCommand._baseInstance = (uint)(i * ITEM_COUNT);
                        indirectCommand._firstIndex = (uint)shapeData._indexOffset / 2;
                        indirectCommand._baseVertex = 0;
                        indirectBuffer->append(indirectCommand);
                    }

                    //indirectCommand._count
                    float startingInterval = ITEM_INTERVAL * i;
                    for (size_t j = 0; j < ITEM_COUNT; ++j) {
                        float theta = j * SHAPE_INTERVAL + startingInterval;
                        auto transform = glm::rotate(mat4(), theta, Vectors::UP);
                        transform = glm::rotate(transform, (randFloat() - 0.5f) * PI / 4.0f, Vectors::UNIT_X);
                        transform = glm::translate(transform, ITEM_TRANSLATION);
                        transform = glm::scale(transform, vec3(randFloat() / 2.0f + 0.5f));
                        transformBuffer->append(transform);
                        transforms.push_back(transform);
                        auto color = vec4{ randomColorValue(64), randomColorValue(64), randomColorValue(64), 255 };
                        color /= 255.0f;
                        colors.push_back(color);
                        colorBuffer->append(toCompactColor(color));
                    }
                }
                colorView = gpu::BufferView(colorBuffer, COLOR_ELEMENT);
                instanceXfmView = gpu::BufferView(transformBuffer, TRANSFORM_ELEMENT);
            }

#if 1
            GeometryCache::ShapeData shapeData = geometryCache->_shapes[GeometryCache::Icosahedron];
            {
                batch.setViewTransform(camera);
                batch.setModelTransform(Transform());
                batch.setPipeline(_pipeline);
                batch.setInputFormat(getInstancedSolidStreamFormat());
                batch.setInputBuffer(gpu::Stream::COLOR, colorView);
                batch.setIndirectBuffer(indirectBuffer);
                shapeData.setupBatch(batch);
                batch.multiDrawIndexedIndirect(TYPE_COUNT, gpu::TRIANGLES);
            }
#else
            batch.setViewTransform(camera);
            batch.setPipeline(_pipeline);
            for (size_t i = 0; i < TYPE_COUNT; ++i) {
                GeometryCache::Shape shape = SHAPE[i];
                for (size_t j = 0; j < ITEM_COUNT; ++j) {
                    int index = i * ITEM_COUNT + j;
                    batch.setModelTransform(transforms[index]);
                    const vec4& color = colors[index];
                    batch._glColor4f(color.r, color.g, color.b, 1.0);
                    geometryCache->renderShape(batch, shape);
                }
            }
#endif
        }

        // Render unlit cube + sphere
        static auto startUsecs = usecTimestampNow(); 
        float seconds = getSeconds(startUsecs);

        seconds /= 4.0f;
        int shapeIndex = ((int)seconds) % TYPE_COUNT;
        bool wire = (seconds - floorf(seconds) > 0.5f);
        batch.setModelTransform(Transform());
        batch._glColor4f(0.8f, 0.25f, 0.25f, 1.0f);

        if (wire) {
            geometryCache->renderWireShape(batch, SHAPE[shapeIndex]);
        } else {
            geometryCache->renderShape(batch, SHAPE[shapeIndex]);
        }
        
        batch.setModelTransform(Transform().setScale(2.05f));
        batch._glColor4f(1, 1, 1, 1);
        geometryCache->renderWireCube(batch);

        _context->render(batch);
        _qGlContext.swapBuffers(this);
        
        fps.increment();
        if (fps.elapsed() >= 0.5f) {
            qDebug() << "FPS: " << fps.rate();
            fps.reset();
        }
    }