Index baseVertex = 0; for (uint32_t i = 2; i < N; i++) { solidIndices.push_back(baseVertex + 0); solidIndices.push_back(baseVertex + i); solidIndices.push_back(baseVertex + i - 1); solidIndices.push_back(baseVertex + N); solidIndices.push_back(baseVertex + i + N - 1); solidIndices.push_back(baseVertex + i + N); } for (uint32_t i = 1; i <= N; i++) { wireIndices.push_back(baseVertex + (i % N)); wireIndices.push_back(baseVertex + i - 1); wireIndices.push_back(baseVertex + (i % N) + N); wireIndices.push_back(baseVertex + (i - 1) + N); } // Now do the sides baseVertex += 2 * N; for (uint32_t i = 0; i < N; i++) { vec3 left = shape[i]; vec3 right = shape[(i + 1) % N]; vec3 normal = glm::normalize(left + right); vec3 topLeft = (isConical ? vec3(0.0f, 0.5f, 0.0f) : vec3(left.x, 0.5f, left.z)); vec3 topRight = (isConical ? vec3(0.0f, 0.5f, 0.0f) : vec3(right.x, 0.5f, right.z)); vec3 bottomLeft = vec3(left.x, -0.5f, left.z); vec3 bottomRight = vec3(right.x, -0.5f, right.z); vec3 tangent = glm::normalize(bottomLeft - bottomRight); // Our tex coords go in the opposite direction as our vertices float u = 1.0f - (float)i / (float)N; float u2 = 1.0f - (float)(i + 1) / (float)N; vertices.emplace_back(topLeft, normal, vec2(u, 0.0f), tangent); vertices.emplace_back(bottomLeft, normal, vec2(u, 1.0f), tangent); vertices.emplace_back(topRight, normal, vec2(u2, 0.0f), tangent); vertices.emplace_back(bottomRight, normal, vec2(u2, 1.0f), tangent); solidIndices.push_back(baseVertex + 0); solidIndices.push_back(baseVertex + 2); solidIndices.push_back(baseVertex + 1); solidIndices.push_back(baseVertex + 1); solidIndices.push_back(baseVertex + 2); solidIndices.push_back(baseVertex + 3); wireIndices.push_back(baseVertex + 0); wireIndices.push_back(baseVertex + 1); wireIndices.push_back(baseVertex + 3); wireIndices.push_back(baseVertex + 2); baseVertex += 4; } shapeData.setupVertices(vertexBuffer, vertices); shapeData.setupIndices(indexBuffer, solidIndices, wireIndices);} // FIXME solids need per-face vertices, but smooth shaded// components do not. Find a way to support using draw elements// or draw arrays as appropriate// Maybe special case cone and cylinder since they combine flat// and smooth shadingvoid GeometryCache::buildShapes() { using namespace geometry; auto vertexBuffer = std::make_shared<gpu::Buffer>(); auto indexBuffer = std::make_shared<gpu::Buffer>(); // Cube setupFlatShape(_shapes[Cube], geometry::cube(), _shapeVertices, _shapeIndices); //Quad renders as flat Cube setupFlatShape(_shapes[Quad], geometry::cube(), _shapeVertices, _shapeIndices); // Tetrahedron setupFlatShape(_shapes[Tetrahedron], geometry::tetrahedron(), _shapeVertices, _shapeIndices); // Icosahedron setupFlatShape(_shapes[Icosahedron], geometry::icosahedron(), _shapeVertices, _shapeIndices); // Octahedron setupFlatShape(_shapes[Octahedron], geometry::octahedron(), _shapeVertices, _shapeIndices); // Dodecahedron setupFlatShape(_shapes[Dodecahedron], geometry::dodecahedron(), _shapeVertices, _shapeIndices); // Sphere // FIXME this uses way more vertices than required. Should find a way to calculate the indices // using shared vertices for better vertex caching auto sphere = geometry::tesselate(geometry::icosahedron(), ICOSAHEDRON_TO_SPHERE_TESSELATION_COUNT); sphere.fitDimension(1.0f); setupSmoothShape(_shapes[Sphere], sphere, _shapeVertices, _shapeIndices); // Line { ShapeData& shapeData = _shapes[Line]; shapeData.setupVertices(_shapeVertices, std::vector<ShapeVertex> { ShapeVertex(vec3(-0.5f, 0.0f, 0.0f), vec3(-0.5f, 0.0f, 0.0f), vec2(0.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f)), ShapeVertex(vec3(0.5f, 0.0f, 0.0f), vec3(0.5f, 0.0f, 0.0f), vec2(0.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f)) }); IndexVector wireIndices; // Only two indices wireIndices.push_back(0); wireIndices.push_back(1); shapeData.setupIndices(_shapeIndices, IndexVector(), wireIndices); } //Triangle, extrudePolygon<3>(_shapes[Triangle], _shapeVertices, _shapeIndices); //Hexagon, extrudePolygon<6>(_shapes[Hexagon], _shapeVertices, _shapeIndices); //Octagon, extrudePolygon<8>(_shapes[Octagon], _shapeVertices, _shapeIndices); //Cylinder, extrudePolygon<64>(_shapes[Cylinder], _shapeVertices, _shapeIndices); //Cone, extrudePolygon<64>(_shapes[Cone], _shapeVertices, _shapeIndices, true); // Circle renders as flat Cylinder extrudePolygon<64>(_shapes[Circle], _shapeVertices, _shapeIndices); // Not implemented yet: //Torus,} const GeometryCache::ShapeData * GeometryCache::getShapeData(const Shape shape) const { if (((int)shape < 0) || ((int)shape >= (int)_shapes.size())) { qCWarning(renderutils) << "GeometryCache::getShapeData - Invalid shape " << shape << " specified. Returning default fallback."; //--EARLY EXIT--( No valid shape data for shape ) return nullptr; } return &_shapes[shape];} GeometryCache::Shape GeometryCache::getShapeForEntityShape(int entityShape) { if ((entityShape < 0) || (entityShape >= (int)MAPPING.size())) { qCWarning(renderutils) << "GeometryCache::getShapeForEntityShape - Invalid shape " << entityShape << " specified. Returning default fallback."; //--EARLY EXIT--( fall back to default assumption ) return GeometryCache::Sphere; } return MAPPING[entityShape];} QString GeometryCache::stringFromShape(GeometryCache::Shape geoShape){ if (((int)geoShape < 0) || ((int)geoShape >= (int)GeometryCache::NUM_SHAPES)) { qCWarning(renderutils) << "GeometryCache::stringFromShape - Invalid shape " << geoShape << " specified."; //--EARLY EXIT-- return "INVALID_GEOCACHE_SHAPE"; } return GEOCACHE_SHAPE_STRINGS[geoShape];} gpu::Stream::FormatPointer& getSolidStreamFormat() { if (!SOLID_STREAM_FORMAT) { SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD0, gpu::Stream::TEXCOORD0, TEXCOORD0_ELEMENT); SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TANGENT, gpu::Stream::TANGENT, TANGENT_ELEMENT); } return SOLID_STREAM_FORMAT;} gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() { if (!INSTANCED_SOLID_STREAM_FORMAT) { INSTANCED_SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD0, gpu::Stream::TEXCOORD0, TEXCOORD0_ELEMENT); INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TANGENT, gpu::Stream::TANGENT, TANGENT_ELEMENT); INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); } return INSTANCED_SOLID_STREAM_FORMAT;} gpu::Stream::FormatPointer& getInstancedSolidFadeStreamFormat() { if (!INSTANCED_SOLID_FADE_STREAM_FORMAT) { INSTANCED_SOLID_FADE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD0, gpu::Stream::TEXCOORD0, TEXCOORD0_ELEMENT); INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TANGENT, gpu::Stream::TANGENT, TANGENT_ELEMENT); INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD2, gpu::Stream::TEXCOORD2, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD3, gpu::Stream::TEXCOORD3, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD4, gpu::Stream::TEXCOORD4, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); } return INSTANCED_SOLID_FADE_STREAM_FORMAT;} gpu::Stream::FormatPointer& getWireStreamFormat() { if (!WIRE_STREAM_FORMAT) { WIRE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); } return WIRE_STREAM_FORMAT;} gpu::Stream::FormatPointer& getInstancedWireStreamFormat() { if (!INSTANCED_WIRE_STREAM_FORMAT) { INSTANCED_WIRE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); } return INSTANCED_WIRE_STREAM_FORMAT;} gpu::Stream::FormatPointer& getInstancedWireFadeStreamFormat() { if (!INSTANCED_WIRE_FADE_STREAM_FORMAT) { INSTANCED_WIRE_FADE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD2, gpu::Stream::TEXCOORD2, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD3, gpu::Stream::TEXCOORD3, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD4, gpu::Stream::TEXCOORD4, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); } return INSTANCED_WIRE_FADE_STREAM_FORMAT;} QHash<SimpleProgramKey, gpu::PipelinePointer> GeometryCache::_simplePrograms; gpu::ShaderPointer GeometryCache::_simpleShader;gpu::ShaderPointer GeometryCache::_transparentShader;gpu::ShaderPointer GeometryCache::_unlitShader;gpu::ShaderPointer GeometryCache::_simpleFadeShader;gpu::ShaderPointer GeometryCache::_unlitFadeShader; render::ShapePipelinePointer GeometryCache::_simpleOpaquePipeline;render::ShapePipelinePointer GeometryCache::_simpleTransparentPipeline;render::ShapePipelinePointer GeometryCache::_simpleOpaqueFadePipeline;render::ShapePipelinePointer GeometryCache::_simpleTransparentFadePipeline;render::ShapePipelinePointer GeometryCache::_simpleWirePipeline; uint8_t GeometryCache::CUSTOM_PIPELINE_NUMBER = 0; render::ShapePipelinePointer GeometryCache::shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key, gpu::Batch& batch) { initializeShapePipelines(); if (key.isWireframe()) { return _simpleWirePipeline; } if (key.isFaded()) { if (key.isTranslucent()) { return _simpleTransparentFadePipeline; } else { return _simpleOpaqueFadePipeline; } } else { if (key.isTranslucent()) { return _simpleTransparentPipeline; } else { return _simpleOpaquePipeline; } }} GeometryCache::GeometryCache() :_nextID(0) { // Let's register its special shapePipeline factory: registerShapePipeline(); buildShapes();} GeometryCache::~GeometryCache() {#ifdef WANT_DEBUG qCDebug(renderutils) << "GeometryCache::~GeometryCache()... "; qCDebug(renderutils) << " _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size(); qCDebug(renderutils) << " _line3DVBOs.size():" << _line3DVBOs.size(); qCDebug(renderutils) << " BatchItemDetails... population:" << GeometryCache::BatchItemDetails::population;#endif //def WANT_DEBUG} void GeometryCache::releaseID(int id) { _registeredQuad3DTextures.remove(id); _lastRegisteredQuad2DTexture.remove(id); _registeredQuad2DTextures.remove(id); _lastRegisteredQuad3D.remove(id); _registeredQuad3D.remove(id); _lastRegisteredQuad2D.remove(id); _registeredQuad2D.remove(id); _lastRegisteredBevelRects.remove(id); _registeredBevelRects.remove(id); _lastRegisteredLine3D.remove(id); _registeredLine3DVBOs.remove(id); _lastRegisteredLine2D.remove(id); _registeredLine2DVBOs.remove(id); _registeredVertices.remove(id); _lastRegisteredDashedLines.remove(id); _registeredDashedLines.remove(id); _lastRegisteredGridBuffer.remove(id); _registeredGridBuffers.remove(id);} void GeometryCache::initializeShapePipelines() { if (!_simpleOpaquePipeline) { _simpleOpaquePipeline = getShapePipeline(false, false, true, false); _simpleTransparentPipeline = getShapePipeline(false, true, true, false); _simpleOpaqueFadePipeline = getFadingShapePipeline(false, false, false, false, false); _simpleTransparentFadePipeline = getFadingShapePipeline(false, true, false, false, false); _simpleWirePipeline = getShapePipeline(false, false, true, true); }} render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBias) { return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, false, true), nullptr, [](const render::ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) { batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get<TextureCache>()->getWhiteTexture()); DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch); } );} render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBias) { auto fadeEffect = DependencyManager::get<FadeEffect>(); auto fadeBatchSetter = fadeEffect->getBatchSetter(); auto fadeItemSetter = fadeEffect->getItemStoredSetter(); return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, true), nullptr, [fadeBatchSetter, fadeItemSetter](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args* args) { batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get<TextureCache>()->getWhiteTexture()); fadeBatchSetter(shapePipeline, batch, args); }, fadeItemSetter );} render::ShapePipelinePointer GeometryCache::getOpaqueShapePipeline(bool isFading) { return isFading ? _simpleOpaqueFadePipeline : _simpleOpaquePipeline;} render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) { return isFading ? _simpleTransparentFadePipeline : _simpleTransparentPipeline;} void GeometryCache::renderShape(gpu::Batch& batch, Shape shape) { batch.setInputFormat(getSolidStreamFormat()); _shapes[shape].draw(batch);} void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape) { batch.setInputFormat(getWireStreamFormat()); _shapes[shape].drawWire(batch);} void GeometryCache::renderShape(gpu::Batch& batch, Shape shape, const glm::vec4& color) { batch.setInputFormat(getSolidStreamFormat()); // Color must be set after input format batch._glColor4f(color.r, color.g, color.b, color.a); _shapes[shape].draw(batch);} void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape, const glm::vec4& color) { batch.setInputFormat(getWireStreamFormat()); // Color must be set after input format batch._glColor4f(color.r, color.g, color.b, color.a); _shapes[shape].drawWire(batch);} void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) { gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); batch.setInputBuffer(gpu::Stream::COLOR, colorView);} void GeometryCache::renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer) { batch.setInputFormat(getInstancedSolidStreamFormat()); setupBatchInstance(batch, colorBuffer); _shapes[shape].drawInstances(batch, count);} void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer) { batch.setInputFormat(getInstancedWireStreamFormat()); setupBatchInstance(batch, colorBuffer); _shapes[shape].drawWireInstances(batch, count);} void setupBatchFadeInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer, gpu::BufferPointer fadeBuffer1, gpu::BufferPointer fadeBuffer2, gpu::BufferPointer fadeBuffer3) { gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); gpu::BufferView texCoord2View(fadeBuffer1, TEXCOORD4_ELEMENT); gpu::BufferView texCoord3View(fadeBuffer2, TEXCOORD4_ELEMENT); gpu::BufferView texCoord4View(fadeBuffer3, TEXCOORD4_ELEMENT); batch.setInputBuffer(gpu::Stream::COLOR, colorView); batch.setInputBuffer(gpu::Stream::TEXCOORD2, texCoord2View); batch.setInputBuffer(gpu::Stream::TEXCOORD3, texCoord3View); batch.setInputBuffer(gpu::Stream::TEXCOORD4, texCoord4View);} void GeometryCache::renderFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer, gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3) { batch.setInputFormat(getInstancedSolidFadeStreamFormat()); setupBatchFadeInstance(batch, colorBuffer, fadeBuffer1, fadeBuffer2, fadeBuffer3); _shapes[shape].drawInstances(batch, count);} void GeometryCache::renderWireFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer, gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3) { batch.setInputFormat(getInstancedWireFadeStreamFormat()); setupBatchFadeInstance(batch, colorBuffer, fadeBuffer1, fadeBuffer2, fadeBuffer3); _shapes[shape].drawWireInstances(batch, count);} void GeometryCache::renderCube(gpu::Batch& batch) { renderShape(batch, Cube);} void GeometryCache::renderWireCube(gpu::Batch& batch) { renderWireShape(batch, Cube);} void GeometryCache::renderCube(gpu::Batch& batch, const glm::vec4& color) { renderShape(batch, Cube, color);} void GeometryCache::renderWireCube(gpu::Batch& batch, const glm::vec4& color) { renderWireShape(batch, Cube, color);} void GeometryCache::renderSphere(gpu::Batch& batch) { renderShape(batch, Sphere);} void GeometryCache::renderWireSphere(gpu::Batch& batch) { renderWireShape(batch, Sphere);} void GeometryCache::renderSphere(gpu::Batch& batch, const glm::vec4& color) { renderShape(batch, Sphere, color);} void GeometryCache::renderWireSphere(gpu::Batch& batch, const glm::vec4& color) { renderWireShape(batch, Sphere, color);} void GeometryCache::renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, int majorRows, int majorCols, float majorEdge, int minorRows, int minorCols, float minorEdge, const glm::vec4& color, bool isLayered, int id) { static const glm::vec2 MIN_TEX_COORD(0.0f, 0.0f); static const glm::vec2 MAX_TEX_COORD(1.0f, 1.0f); bool registered = (id != UNKNOWN_ID); Vec2FloatPair majorKey(glm::vec2(majorRows, majorCols), majorEdge); Vec2FloatPair minorKey(glm::vec2(minorRows, minorCols), minorEdge); Vec2FloatPairPair key(majorKey, minorKey); // Make the gridbuffer if (registered && (!_registeredGridBuffers.contains(id) || _lastRegisteredGridBuffer[id] != key)) { GridSchema gridSchema; GridBuffer gridBuffer = std::make_shared<gpu::Buffer>(sizeof(GridSchema), (const gpu::Byte*) &gridSchema); if (registered && _registeredGridBuffers.contains(id)) { gridBuffer = _registeredGridBuffers[id]; } _registeredGridBuffers[id] = gridBuffer; _lastRegisteredGridBuffer[id] = key; gridBuffer.edit<GridSchema>().period = glm::vec4(majorRows, majorCols, minorRows, minorCols); gridBuffer.edit<GridSchema>().offset.x = -(majorEdge / majorRows) / 2; gridBuffer.edit<GridSchema>().offset.y = -(majorEdge / majorCols) / 2; gridBuffer.edit<GridSchema>().offset.z = -(minorEdge / minorRows) / 2; gridBuffer.edit<GridSchema>().offset.w = -(minorEdge / minorCols) / 2; gridBuffer.edit<GridSchema>().edge = glm::vec4(glm::vec2(majorEdge), // If rows or columns are not set, do not draw minor gridlines glm::vec2((minorRows != 0 && minorCols != 0) ? minorEdge : 0.0f)); } // Set the grid pipeline useGridPipeline(batch, _registeredGridBuffers[id], isLayered); renderQuad(batch, minCorner, maxCorner, MIN_TEX_COORD, MAX_TEX_COORD, color, id);} void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, const QVector<glm::vec4>& colors) { BatchItemDetails& details = _registeredVertices[id]; if (details.isCreated) { details.clear();#ifdef WANT_DEBUG qCDebug(renderutils) << "updateVertices()... RELEASING REGISTERED";#endif // def WANT_DEBUG } const int FLOATS_PER_VERTEX = 2 + 3; // vertices + normals const int NUM_POS_COORDS = 2; const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float); details.isCreated = true; details.vertices = points.size();Lines 501–1000 of 2501. Previous lines Load more
Index baseVertex = 0; for (uint32_t i = 2; i < N; i++) { solidIndices.push_back(baseVertex + 0); solidIndices.push_back(baseVertex + i); solidIndices.push_back(baseVertex + i - 1); solidIndices.push_back(baseVertex + N); solidIndices.push_back(baseVertex + i + N - 1); solidIndices.push_back(baseVertex + i + N); } for (uint32_t i = 1; i <= N; i++) { wireIndices.push_back(baseVertex + (i % N)); wireIndices.push_back(baseVertex + i - 1); wireIndices.push_back(baseVertex + (i % N) + N); wireIndices.push_back(baseVertex + (i - 1) + N); } // Now do the sides baseVertex += 2 * N; for (uint32_t i = 0; i < N; i++) { vec3 left = shape[i]; vec3 right = shape[(i + 1) % N]; vec3 normal = glm::normalize(left + right); vec3 topLeft = (isConical ? vec3(0.0f, 0.5f, 0.0f) : vec3(left.x, 0.5f, left.z)); vec3 topRight = (isConical ? vec3(0.0f, 0.5f, 0.0f) : vec3(right.x, 0.5f, right.z)); vec3 bottomLeft = vec3(left.x, -0.5f, left.z); vec3 bottomRight = vec3(right.x, -0.5f, right.z); vec3 tangent = glm::normalize(bottomLeft - bottomRight); // Our tex coords go in the opposite direction as our vertices float u = 1.0f - (float)i / (float)N; float u2 = 1.0f - (float)(i + 1) / (float)N; vertices.emplace_back(topLeft, normal, vec2(u, 0.0f), tangent); vertices.emplace_back(bottomLeft, normal, vec2(u, 1.0f), tangent); vertices.emplace_back(topRight, normal, vec2(u2, 0.0f), tangent); vertices.emplace_back(bottomRight, normal, vec2(u2, 1.0f), tangent); solidIndices.push_back(baseVertex + 0); solidIndices.push_back(baseVertex + 2); solidIndices.push_back(baseVertex + 1); solidIndices.push_back(baseVertex + 1); solidIndices.push_back(baseVertex + 2); solidIndices.push_back(baseVertex + 3); wireIndices.push_back(baseVertex + 0); wireIndices.push_back(baseVertex + 1); wireIndices.push_back(baseVertex + 3); wireIndices.push_back(baseVertex + 2); baseVertex += 4; } shapeData.setupVertices(vertexBuffer, vertices); shapeData.setupIndices(indexBuffer, solidIndices, wireIndices); } // FIXME solids need per-face vertices, but smooth shaded // components do not. Find a way to support using draw elements // or draw arrays as appropriate // Maybe special case cone and cylinder since they combine flat // and smooth shading void GeometryCache::buildShapes() { using namespace geometry; auto vertexBuffer = std::make_shared<gpu::Buffer>(); auto indexBuffer = std::make_shared<gpu::Buffer>(); // Cube setupFlatShape(_shapes[Cube], geometry::cube(), _shapeVertices, _shapeIndices); //Quad renders as flat Cube setupFlatShape(_shapes[Quad], geometry::cube(), _shapeVertices, _shapeIndices); // Tetrahedron setupFlatShape(_shapes[Tetrahedron], geometry::tetrahedron(), _shapeVertices, _shapeIndices); // Icosahedron setupFlatShape(_shapes[Icosahedron], geometry::icosahedron(), _shapeVertices, _shapeIndices); // Octahedron setupFlatShape(_shapes[Octahedron], geometry::octahedron(), _shapeVertices, _shapeIndices); // Dodecahedron setupFlatShape(_shapes[Dodecahedron], geometry::dodecahedron(), _shapeVertices, _shapeIndices); // Sphere // FIXME this uses way more vertices than required. Should find a way to calculate the indices // using shared vertices for better vertex caching auto sphere = geometry::tesselate(geometry::icosahedron(), ICOSAHEDRON_TO_SPHERE_TESSELATION_COUNT); sphere.fitDimension(1.0f); setupSmoothShape(_shapes[Sphere], sphere, _shapeVertices, _shapeIndices); // Line { ShapeData& shapeData = _shapes[Line]; shapeData.setupVertices(_shapeVertices, std::vector<ShapeVertex> { ShapeVertex(vec3(-0.5f, 0.0f, 0.0f), vec3(-0.5f, 0.0f, 0.0f), vec2(0.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f)), ShapeVertex(vec3(0.5f, 0.0f, 0.0f), vec3(0.5f, 0.0f, 0.0f), vec2(0.0f, 0.0f), vec3(0.0f, 0.0f, 0.0f)) }); IndexVector wireIndices; // Only two indices wireIndices.push_back(0); wireIndices.push_back(1); shapeData.setupIndices(_shapeIndices, IndexVector(), wireIndices); } //Triangle, extrudePolygon<3>(_shapes[Triangle], _shapeVertices, _shapeIndices); //Hexagon, extrudePolygon<6>(_shapes[Hexagon], _shapeVertices, _shapeIndices); //Octagon, extrudePolygon<8>(_shapes[Octagon], _shapeVertices, _shapeIndices); //Cylinder, extrudePolygon<64>(_shapes[Cylinder], _shapeVertices, _shapeIndices); //Cone, extrudePolygon<64>(_shapes[Cone], _shapeVertices, _shapeIndices, true); // Circle renders as flat Cylinder extrudePolygon<64>(_shapes[Circle], _shapeVertices, _shapeIndices); // Not implemented yet: //Torus, } const GeometryCache::ShapeData * GeometryCache::getShapeData(const Shape shape) const { if (((int)shape < 0) || ((int)shape >= (int)_shapes.size())) { qCWarning(renderutils) << "GeometryCache::getShapeData - Invalid shape " << shape << " specified. Returning default fallback."; //--EARLY EXIT--( No valid shape data for shape ) return nullptr; } return &_shapes[shape]; } GeometryCache::Shape GeometryCache::getShapeForEntityShape(int entityShape) { if ((entityShape < 0) || (entityShape >= (int)MAPPING.size())) { qCWarning(renderutils) << "GeometryCache::getShapeForEntityShape - Invalid shape " << entityShape << " specified. Returning default fallback."; //--EARLY EXIT--( fall back to default assumption ) return GeometryCache::Sphere; } return MAPPING[entityShape]; } QString GeometryCache::stringFromShape(GeometryCache::Shape geoShape) { if (((int)geoShape < 0) || ((int)geoShape >= (int)GeometryCache::NUM_SHAPES)) { qCWarning(renderutils) << "GeometryCache::stringFromShape - Invalid shape " << geoShape << " specified."; //--EARLY EXIT-- return "INVALID_GEOCACHE_SHAPE"; } return GEOCACHE_SHAPE_STRINGS[geoShape]; } gpu::Stream::FormatPointer& getSolidStreamFormat() { if (!SOLID_STREAM_FORMAT) { SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD0, gpu::Stream::TEXCOORD0, TEXCOORD0_ELEMENT); SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TANGENT, gpu::Stream::TANGENT, TANGENT_ELEMENT); } return SOLID_STREAM_FORMAT; } gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() { if (!INSTANCED_SOLID_STREAM_FORMAT) { INSTANCED_SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD0, gpu::Stream::TEXCOORD0, TEXCOORD0_ELEMENT); INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::TANGENT, gpu::Stream::TANGENT, TANGENT_ELEMENT); INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); } return INSTANCED_SOLID_STREAM_FORMAT; } gpu::Stream::FormatPointer& getInstancedSolidFadeStreamFormat() { if (!INSTANCED_SOLID_FADE_STREAM_FORMAT) { INSTANCED_SOLID_FADE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD0, gpu::Stream::TEXCOORD0, TEXCOORD0_ELEMENT); INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TANGENT, gpu::Stream::TANGENT, TANGENT_ELEMENT); INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD2, gpu::Stream::TEXCOORD2, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD3, gpu::Stream::TEXCOORD3, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD4, gpu::Stream::TEXCOORD4, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); } return INSTANCED_SOLID_FADE_STREAM_FORMAT; } gpu::Stream::FormatPointer& getWireStreamFormat() { if (!WIRE_STREAM_FORMAT) { WIRE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); } return WIRE_STREAM_FORMAT; } gpu::Stream::FormatPointer& getInstancedWireStreamFormat() { if (!INSTANCED_WIRE_STREAM_FORMAT) { INSTANCED_WIRE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); } return INSTANCED_WIRE_STREAM_FORMAT; } gpu::Stream::FormatPointer& getInstancedWireFadeStreamFormat() { if (!INSTANCED_WIRE_FADE_STREAM_FORMAT) { INSTANCED_WIRE_FADE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD2, gpu::Stream::TEXCOORD2, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD3, gpu::Stream::TEXCOORD3, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD4, gpu::Stream::TEXCOORD4, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); } return INSTANCED_WIRE_FADE_STREAM_FORMAT; } QHash<SimpleProgramKey, gpu::PipelinePointer> GeometryCache::_simplePrograms; gpu::ShaderPointer GeometryCache::_simpleShader; gpu::ShaderPointer GeometryCache::_transparentShader; gpu::ShaderPointer GeometryCache::_unlitShader; gpu::ShaderPointer GeometryCache::_simpleFadeShader; gpu::ShaderPointer GeometryCache::_unlitFadeShader; render::ShapePipelinePointer GeometryCache::_simpleOpaquePipeline; render::ShapePipelinePointer GeometryCache::_simpleTransparentPipeline; render::ShapePipelinePointer GeometryCache::_simpleOpaqueFadePipeline; render::ShapePipelinePointer GeometryCache::_simpleTransparentFadePipeline; render::ShapePipelinePointer GeometryCache::_simpleWirePipeline; uint8_t GeometryCache::CUSTOM_PIPELINE_NUMBER = 0; render::ShapePipelinePointer GeometryCache::shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key, gpu::Batch& batch) { initializeShapePipelines(); if (key.isWireframe()) { return _simpleWirePipeline; } if (key.isFaded()) { if (key.isTranslucent()) { return _simpleTransparentFadePipeline; } else { return _simpleOpaqueFadePipeline; } } else { if (key.isTranslucent()) { return _simpleTransparentPipeline; } else { return _simpleOpaquePipeline; } } } GeometryCache::GeometryCache() : _nextID(0) { // Let's register its special shapePipeline factory: registerShapePipeline(); buildShapes(); } GeometryCache::~GeometryCache() { #ifdef WANT_DEBUG qCDebug(renderutils) << "GeometryCache::~GeometryCache()... "; qCDebug(renderutils) << " _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size(); qCDebug(renderutils) << " _line3DVBOs.size():" << _line3DVBOs.size(); qCDebug(renderutils) << " BatchItemDetails... population:" << GeometryCache::BatchItemDetails::population; #endif //def WANT_DEBUG } void GeometryCache::releaseID(int id) { _registeredQuad3DTextures.remove(id); _lastRegisteredQuad2DTexture.remove(id); _registeredQuad2DTextures.remove(id); _lastRegisteredQuad3D.remove(id); _registeredQuad3D.remove(id); _lastRegisteredQuad2D.remove(id); _registeredQuad2D.remove(id); _lastRegisteredBevelRects.remove(id); _registeredBevelRects.remove(id); _lastRegisteredLine3D.remove(id); _registeredLine3DVBOs.remove(id); _lastRegisteredLine2D.remove(id); _registeredLine2DVBOs.remove(id); _registeredVertices.remove(id); _lastRegisteredDashedLines.remove(id); _registeredDashedLines.remove(id); _lastRegisteredGridBuffer.remove(id); _registeredGridBuffers.remove(id); } void GeometryCache::initializeShapePipelines() { if (!_simpleOpaquePipeline) { _simpleOpaquePipeline = getShapePipeline(false, false, true, false); _simpleTransparentPipeline = getShapePipeline(false, true, true, false); _simpleOpaqueFadePipeline = getFadingShapePipeline(false, false, false, false, false); _simpleTransparentFadePipeline = getFadingShapePipeline(false, true, false, false, false); _simpleWirePipeline = getShapePipeline(false, false, true, true); } } render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBias) { return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, false, true), nullptr, [](const render::ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) { batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get<TextureCache>()->getWhiteTexture()); DependencyManager::get<DeferredLightingEffect>()->setupKeyLightBatch(args, batch); } ); } render::ShapePipelinePointer GeometryCache::getFadingShapePipeline(bool textured, bool transparent, bool culled, bool unlit, bool depthBias) { auto fadeEffect = DependencyManager::get<FadeEffect>(); auto fadeBatchSetter = fadeEffect->getBatchSetter(); auto fadeItemSetter = fadeEffect->getItemStoredSetter(); return std::make_shared<render::ShapePipeline>(getSimplePipeline(textured, transparent, culled, unlit, depthBias, true), nullptr, [fadeBatchSetter, fadeItemSetter](const render::ShapePipeline& shapePipeline, gpu::Batch& batch, render::Args* args) { batch.setResourceTexture(gr::Texture::MaterialAlbedo, DependencyManager::get<TextureCache>()->getWhiteTexture()); fadeBatchSetter(shapePipeline, batch, args); }, fadeItemSetter ); } render::ShapePipelinePointer GeometryCache::getOpaqueShapePipeline(bool isFading) { return isFading ? _simpleOpaqueFadePipeline : _simpleOpaquePipeline; } render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) { return isFading ? _simpleTransparentFadePipeline : _simpleTransparentPipeline; } void GeometryCache::renderShape(gpu::Batch& batch, Shape shape) { batch.setInputFormat(getSolidStreamFormat()); _shapes[shape].draw(batch); } void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape) { batch.setInputFormat(getWireStreamFormat()); _shapes[shape].drawWire(batch); } void GeometryCache::renderShape(gpu::Batch& batch, Shape shape, const glm::vec4& color) { batch.setInputFormat(getSolidStreamFormat()); // Color must be set after input format batch._glColor4f(color.r, color.g, color.b, color.a); _shapes[shape].draw(batch); } void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape, const glm::vec4& color) { batch.setInputFormat(getWireStreamFormat()); // Color must be set after input format batch._glColor4f(color.r, color.g, color.b, color.a); _shapes[shape].drawWire(batch); } void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) { gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); batch.setInputBuffer(gpu::Stream::COLOR, colorView); } void GeometryCache::renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer) { batch.setInputFormat(getInstancedSolidStreamFormat()); setupBatchInstance(batch, colorBuffer); _shapes[shape].drawInstances(batch, count); } void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer) { batch.setInputFormat(getInstancedWireStreamFormat()); setupBatchInstance(batch, colorBuffer); _shapes[shape].drawWireInstances(batch, count); } void setupBatchFadeInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer, gpu::BufferPointer fadeBuffer1, gpu::BufferPointer fadeBuffer2, gpu::BufferPointer fadeBuffer3) { gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); gpu::BufferView texCoord2View(fadeBuffer1, TEXCOORD4_ELEMENT); gpu::BufferView texCoord3View(fadeBuffer2, TEXCOORD4_ELEMENT); gpu::BufferView texCoord4View(fadeBuffer3, TEXCOORD4_ELEMENT); batch.setInputBuffer(gpu::Stream::COLOR, colorView); batch.setInputBuffer(gpu::Stream::TEXCOORD2, texCoord2View); batch.setInputBuffer(gpu::Stream::TEXCOORD3, texCoord3View); batch.setInputBuffer(gpu::Stream::TEXCOORD4, texCoord4View); } void GeometryCache::renderFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer, gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3) { batch.setInputFormat(getInstancedSolidFadeStreamFormat()); setupBatchFadeInstance(batch, colorBuffer, fadeBuffer1, fadeBuffer2, fadeBuffer3); _shapes[shape].drawInstances(batch, count); } void GeometryCache::renderWireFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer, gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3) { batch.setInputFormat(getInstancedWireFadeStreamFormat()); setupBatchFadeInstance(batch, colorBuffer, fadeBuffer1, fadeBuffer2, fadeBuffer3); _shapes[shape].drawWireInstances(batch, count); } void GeometryCache::renderCube(gpu::Batch& batch) { renderShape(batch, Cube); } void GeometryCache::renderWireCube(gpu::Batch& batch) { renderWireShape(batch, Cube); } void GeometryCache::renderCube(gpu::Batch& batch, const glm::vec4& color) { renderShape(batch, Cube, color); } void GeometryCache::renderWireCube(gpu::Batch& batch, const glm::vec4& color) { renderWireShape(batch, Cube, color); } void GeometryCache::renderSphere(gpu::Batch& batch) { renderShape(batch, Sphere); } void GeometryCache::renderWireSphere(gpu::Batch& batch) { renderWireShape(batch, Sphere); } void GeometryCache::renderSphere(gpu::Batch& batch, const glm::vec4& color) { renderShape(batch, Sphere, color); } void GeometryCache::renderWireSphere(gpu::Batch& batch, const glm::vec4& color) { renderWireShape(batch, Sphere, color); } void GeometryCache::renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, int majorRows, int majorCols, float majorEdge, int minorRows, int minorCols, float minorEdge, const glm::vec4& color, bool isLayered, int id) { static const glm::vec2 MIN_TEX_COORD(0.0f, 0.0f); static const glm::vec2 MAX_TEX_COORD(1.0f, 1.0f); bool registered = (id != UNKNOWN_ID); Vec2FloatPair majorKey(glm::vec2(majorRows, majorCols), majorEdge); Vec2FloatPair minorKey(glm::vec2(minorRows, minorCols), minorEdge); Vec2FloatPairPair key(majorKey, minorKey); // Make the gridbuffer if (registered && (!_registeredGridBuffers.contains(id) || _lastRegisteredGridBuffer[id] != key)) { GridSchema gridSchema; GridBuffer gridBuffer = std::make_shared<gpu::Buffer>(sizeof(GridSchema), (const gpu::Byte*) &gridSchema); if (registered && _registeredGridBuffers.contains(id)) { gridBuffer = _registeredGridBuffers[id]; } _registeredGridBuffers[id] = gridBuffer; _lastRegisteredGridBuffer[id] = key; gridBuffer.edit<GridSchema>().period = glm::vec4(majorRows, majorCols, minorRows, minorCols); gridBuffer.edit<GridSchema>().offset.x = -(majorEdge / majorRows) / 2; gridBuffer.edit<GridSchema>().offset.y = -(majorEdge / majorCols) / 2; gridBuffer.edit<GridSchema>().offset.z = -(minorEdge / minorRows) / 2; gridBuffer.edit<GridSchema>().offset.w = -(minorEdge / minorCols) / 2; gridBuffer.edit<GridSchema>().edge = glm::vec4(glm::vec2(majorEdge), // If rows or columns are not set, do not draw minor gridlines glm::vec2((minorRows != 0 && minorCols != 0) ? minorEdge : 0.0f)); } // Set the grid pipeline useGridPipeline(batch, _registeredGridBuffers[id], isLayered); renderQuad(batch, minCorner, maxCorner, MIN_TEX_COORD, MAX_TEX_COORD, color, id); } void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, const QVector<glm::vec4>& colors) { BatchItemDetails& details = _registeredVertices[id]; if (details.isCreated) { details.clear(); #ifdef WANT_DEBUG qCDebug(renderutils) << "updateVertices()... RELEASING REGISTERED"; #endif // def WANT_DEBUG } const int FLOATS_PER_VERTEX = 2 + 3; // vertices + normals const int NUM_POS_COORDS = 2; const int VERTEX_NORMAL_OFFSET = NUM_POS_COORDS * sizeof(float); details.isCreated = true; details.vertices = points.size();