Пример #1
0
void OpenGLRenderer::drawBatched(const RenderList& list) {
    RW_PROFILE_SCOPE(__func__);
#if 0  // Needs shader changes
	// Determine how many batches we need to process the entire list
	auto entries = list.size();
	glBindBuffer(GL_UNIFORM_BUFFER, UBOObject);
	for (int b = 0; b < entries; b += maxObjectEntries)
	{
		auto toConsume = std::min((GLuint)entries, b + maxObjectEntries) - b;
		std::vector<ObjectUniformData> uploadBuffer;
		uploadBuffer.resize(toConsume);
		for (int d = 0; d < toConsume; ++d)
		{
			auto& draw = list[b+d];
			uploadBuffer[d] = {
				draw.model,
				glm::vec4(draw.drawInfo.colour.r/255.f,
				draw.drawInfo.colour.g/255.f,
				draw.drawInfo.colour.b/255.f, 1.f),
				1.f,
				1.f,
				draw.drawInfo.colour.a/255.f
			};
		}
		glBufferData(GL_UNIFORM_BUFFER,
					 toConsume * sizeof(ObjectUniformData),
					 uploadBuffer.data(),
					 GL_STREAM_DRAW);

		// Dispatch individual draws
		for (int d = 0; d < toConsume; ++d)
		{
			auto& draw = list[b+d];
			useDrawBuffer(draw.dbuff);

			for( GLuint u = 0; u < draw.drawInfo.textures.size(); ++u )
			{
				useTexture(u, draw.drawInfo.textures[u]);
			}

			glDrawElements(draw.dbuff->getFaceType(), draw.drawInfo.count, GL_UNSIGNED_INT,
                           reinterpret_cast<void*>(sizeof(RenderIndex) * draw.drawInfo.start));
		}
	}
#else
    for (auto& ri : list) {
        draw(ri.model, ri.dbuff, ri.drawInfo);
    }
#endif
}
Пример #2
0
void LayerCache::update(Camera::Transform transform, RenderList& renderlist) {
    const double OVERDRAW = 2.5;
    renderlist.clear();
    m_needupdate = false;
    if(!m_layer->areInstancesVisible()) {
        FL_DBG(_log, "Layer instances hidden");
        return;
    }
    bool isWarped = transform == Camera::WarpedTransform;
    if( isWarped ) {
        fullUpdate();
    }

    Rect viewport = m_camera->getViewPort();
    Rect screen_viewport = viewport;
    double zoom = m_camera->getZoom();
    DoublePoint3D viewport_a = m_camera->screenToVirtualScreen(Point3D(viewport.x, viewport.y));
    DoublePoint3D viewport_b = m_camera->screenToVirtualScreen(Point3D(viewport.right(), viewport.bottom()));
    viewport.x = static_cast<int32_t>(std::min(viewport_a.x, viewport_b.x));
    viewport.y = static_cast<int32_t>(std::min(viewport_a.y, viewport_b.y));
    viewport.w = static_cast<int32_t>(std::max(viewport_a.x, viewport_b.x) - viewport.x);
    viewport.h = static_cast<int32_t>(std::max(viewport_a.y, viewport_b.y) - viewport.y);
    uint8_t layer_trans = m_layer->getLayerTransparency();

    double zmin = 0.0, zmax = 0.0;

    // FL_LOG(_log, LMsg("camera-update viewport") << viewport);
    std::vector<int32_t> index_list;
    collect(viewport, index_list);
    for(unsigned i=0; i!=index_list.size(); ++i) {
        Entry& entry = m_entries[index_list[i]];
        // NOTE
        // An update is forced if the item has an animation/action.
        // This update only happens if it is _already_ included in the viewport
        // Nevertheless: Moving instances - which might move into the viewport will be updated
        // By the layer change listener.
        if(entry.force_update || !isWarped) {
            updateEntry(entry);
        }

        RenderItem& item = m_instances[entry.instance_index];
        InstanceVisual* visual = item.instance->getVisual<InstanceVisual>();
        bool visible = (visual->isVisible() != 0);
        uint8_t instance_trans = visual->getTransparency();
        if(!item.image || !visible || (instance_trans == 255 && layer_trans == 0)
                || (instance_trans == 0 && layer_trans == 255)) {
            continue;
        }

        if(layer_trans != 0) {
            if(instance_trans != 0) {
                uint8_t calc_trans = layer_trans - instance_trans;
                if(calc_trans >= 0) {
                    instance_trans = calc_trans;
                } else {
                    instance_trans = 0;
                }
            } else {
                instance_trans = layer_trans;
            }
        }

        Point3D screen_point = m_camera->virtualScreenToScreen(item.screenpoint);
        // NOTE:
        // One would expect this to be necessary here,
        // however it works the same without, sofar
        // m_camera->calculateZValue(screen_point);
        // item.screenpoint.z = -screen_point.z;

        item.dimensions.x = screen_point.x;
        item.dimensions.y = screen_point.y;
        item.dimensions.w = item.bbox.w;
        item.dimensions.h = item.bbox.h;

        item.transparency = 255 - instance_trans;

        if (zoom != 1.0) {
            // NOTE: Due to image alignment, there is additional additions on image dimensions
            //       There's probabaly some better solution for this, but works "good enough" for now.
            //       In case additions are removed, gaps appear between tiles.
            item.dimensions.w = unsigned(double(item.bbox.w) * zoom + OVERDRAW);
            item.dimensions.h = unsigned(double(item.bbox.h) * zoom + OVERDRAW);
        }

        if (!m_need_sorting) {
            zmin = std::min(zmin, item.screenpoint.z);
            zmax = std::max(zmax, item.screenpoint.z);
        }

        if(item.dimensions.intersects(screen_viewport)) {
            renderlist.push_back(&item);
        }
    }

    if (m_need_sorting) {
        InstanceDistanceSort ids;
        std::stable_sort(renderlist.begin(), renderlist.end(), ids);
    } else {
        zmin -= 0.5;
        zmax += 0.5;

        // We want to put every z value in [-10,10] range.
        // To do it, we simply solve
        // { y1 = a*x1 + b
        // { y2 = a*x2 + b
        // where [y1,y2]' = [-10,10]' is required z range,
        // and [x1,x2]' is expected min,max z coords.
        double det = zmin - zmax;
        if (fabs(det) > FLT_EPSILON) {
            double det_a = -10.0 - 10.0;
            double det_b = 10.0 * zmin - (-10.0) * zmax;
            double a = static_cast<float>(det_a / det);
            double b = static_cast<float>(det_b / det);
            float estimate = sqrtf(static_cast<float>(renderlist.size()));
            float stack_delta = fabs(-10.0f - 10.0f) / estimate * 0.1f;

            RenderList::iterator it = renderlist.begin();
            for ( ; it != renderlist.end(); ++it) {
                double& z = (*it)->screenpoint.z;
                z = a * z + b;
                InstanceVisual* vis = (*it)->instance->getVisual<InstanceVisual>();
                z += vis->getStackPosition() * stack_delta;
            }
        }
    }
    //  FL_LOG(_log, LMsg("camera-update ") << " N=" <<renderlist.size() << "/" << m_instances.size() << "/" << index_list.size());
}