From 19e4fb2355f6948ddadf4ee19a09652c3a3e842d Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 7 Mar 2018 12:22:17 -0800 Subject: [PATCH 1/3] materials on primitives --- .../src/RenderableMaterialEntityItem.cpp | 144 +----------- .../src/RenderableMaterialEntityItem.h | 14 -- .../src/RenderableShapeEntityItem.cpp | 95 +++++++- .../src/RenderableShapeEntityItem.h | 6 + libraries/render-utils/src/GeometryCache.cpp | 216 +++++++++++++++--- libraries/render-utils/src/GeometryCache.h | 4 +- .../render-utils/src/MaterialTextures.slh | 14 +- .../src/forward_model_normal_map.slf | 2 +- .../src/model_lightmap_normal_map.slf | 6 +- .../src/model_lightmap_normal_map_fade.slf | 6 +- .../render-utils/src/model_normal_map.slf | 6 +- .../src/model_normal_map_fade.slf | 6 +- .../src/model_translucent_normal_map.slf | 2 +- .../src/model_translucent_normal_map_fade.slf | 2 +- libraries/shared/src/shared/Shapes.cpp | 111 ++++++++- libraries/shared/src/shared/Shapes.h | 2 + 16 files changed, 418 insertions(+), 218 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 119a46b68f..8566b9bae8 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -9,6 +9,7 @@ #include "RenderableMaterialEntityItem.h" #include "RenderPipelines.h" +#include "GeometryCache.h" using namespace render; using namespace render::entities; @@ -90,138 +91,6 @@ ShapeKey MaterialEntityRenderer::getShapeKey() { return builder.build(); } -glm::vec3 MaterialEntityRenderer::getVertexPos(float phi, float theta) { - return glm::vec3(glm::sin(theta) * glm::cos(phi), glm::cos(theta), glm::sin(theta) * glm::sin(phi)); -} - -glm::vec3 MaterialEntityRenderer::getTangent(float phi, float theta) { - return glm::vec3(-glm::cos(theta) * glm::cos(phi), glm::sin(theta), -glm::cos(theta) * glm::sin(phi)); -} - -void MaterialEntityRenderer::addVertex(std::vector& buffer, const glm::vec3& pos, const glm::vec3& tan, const glm::vec2 uv) { - buffer.push_back(pos.x); buffer.push_back(pos.y); buffer.push_back(pos.z); - buffer.push_back(tan.x); buffer.push_back(tan.y); buffer.push_back(tan.z); - buffer.push_back(uv.x); buffer.push_back(uv.y); -} - -void MaterialEntityRenderer::addTriangleFan(std::vector& buffer, int stack, int step) { - float v1 = ((float)stack) / STACKS; - float theta1 = v1 * (float)M_PI; - glm::vec3 tip = getVertexPos(0, theta1); - float v2 = ((float)(stack + step)) / STACKS; - float theta2 = v2 * (float)M_PI; - for (int i = 0; i < SLICES; i++) { - float u1 = ((float)i) / SLICES; - float u2 = ((float)(i + step)) / SLICES; - float phi1 = u1 * M_PI_TIMES_2; - float phi2 = u2 * M_PI_TIMES_2; - /* (flipped for negative step) - p1 - / \ - / \ - / \ - p3 ------ p2 - */ - - glm::vec3 pos2 = getVertexPos(phi2, theta2); - glm::vec3 pos3 = getVertexPos(phi1, theta2); - - glm::vec3 tan1 = getTangent(0, theta1); - glm::vec3 tan2 = getTangent(phi2, theta2); - glm::vec3 tan3 = getTangent(phi1, theta2); - - glm::vec2 uv1 = glm::vec2((u1 + u2) / 2.0f, v1); - glm::vec2 uv2 = glm::vec2(u2, v2); - glm::vec2 uv3 = glm::vec2(u1, v2); - - addVertex(buffer, tip, tan1, uv1); - addVertex(buffer, pos2, tan2, uv2); - addVertex(buffer, pos3, tan3, uv3); - - _numVertices += 3; - } -} - -int MaterialEntityRenderer::_numVertices = 0; -std::shared_ptr MaterialEntityRenderer::_streamFormat = nullptr; -std::shared_ptr MaterialEntityRenderer::_stream = nullptr; -std::shared_ptr MaterialEntityRenderer::_verticesBuffer = nullptr; - -void MaterialEntityRenderer::generateMesh() { - _streamFormat = std::make_shared(); - _stream = std::make_shared(); - _verticesBuffer = std::make_shared(); - - const int NUM_POS_COORDS = 3; - const int NUM_TANGENT_COORDS = 3; - const int VERTEX_TANGENT_OFFSET = NUM_POS_COORDS * sizeof(float); - const int VERTEX_TEXCOORD_OFFSET = VERTEX_TANGENT_OFFSET + NUM_TANGENT_COORDS * sizeof(float); - - _streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - _streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); - _streamFormat->setAttribute(gpu::Stream::TANGENT, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_TANGENT_OFFSET); - _streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET); - - _stream->addBuffer(_verticesBuffer, 0, _streamFormat->getChannels().at(0)._stride); - - std::vector vertexBuffer; - - // Top - addTriangleFan(vertexBuffer, 0, 1); - - // Middle section - for (int j = 1; j < STACKS - 1; j++) { - float v1 = ((float)j) / STACKS; - float v2 = ((float)(j + 1)) / STACKS; - float theta1 = v1 * (float)M_PI; - float theta2 = v2 * (float)M_PI; - for (int i = 0; i < SLICES; i++) { - float u1 = ((float)i) / SLICES; - float u2 = ((float)(i + 1)) / SLICES; - float phi1 = u1 * M_PI_TIMES_2; - float phi2 = u2 * M_PI_TIMES_2; - - /* - p2 ---- p3 - | / | - | / | - | / | - p1 ---- p4 - */ - - glm::vec3 pos1 = getVertexPos(phi1, theta2); - glm::vec3 pos2 = getVertexPos(phi1, theta1); - glm::vec3 pos3 = getVertexPos(phi2, theta1); - glm::vec3 pos4 = getVertexPos(phi2, theta2); - - glm::vec3 tan1 = getTangent(phi1, theta2); - glm::vec3 tan2 = getTangent(phi1, theta1); - glm::vec3 tan3 = getTangent(phi2, theta1); - glm::vec3 tan4 = getTangent(phi2, theta2); - - glm::vec2 uv1 = glm::vec2(u1, v2); - glm::vec2 uv2 = glm::vec2(u1, v1); - glm::vec2 uv3 = glm::vec2(u2, v1); - glm::vec2 uv4 = glm::vec2(u2, v2); - - addVertex(vertexBuffer, pos1, tan1, uv1); - addVertex(vertexBuffer, pos2, tan2, uv2); - addVertex(vertexBuffer, pos3, tan3, uv3); - - addVertex(vertexBuffer, pos3, tan3, uv3); - addVertex(vertexBuffer, pos4, tan4, uv4); - addVertex(vertexBuffer, pos1, tan1, uv1); - - _numVertices += 6; - } - } - - // Bottom - addTriangleFan(vertexBuffer, STACKS, -1); - - _verticesBuffer->append(vertexBuffer.size() * sizeof(float), (gpu::Byte*) vertexBuffer.data()); -} - void MaterialEntityRenderer::doRender(RenderArgs* args) { PerformanceTimer perfTimer("RenderableMaterialEntityItem::render"); Q_ASSERT(args->_batch); @@ -252,14 +121,7 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { args->_details._materialSwitches++; // Draw! - if (_numVertices == 0) { - generateMesh(); - } + DependencyManager::get()->renderSphere(batch); - batch.setInputFormat(_streamFormat); - batch.setInputStream(0, *_stream); - batch.draw(gpu::TRIANGLES, _numVertices, 0); - - const int NUM_VERTICES_PER_TRIANGLE = 3; - args->_details._trianglesRendered += _numVertices / NUM_VERTICES_PER_TRIANGLE; + args->_details._trianglesRendered += DependencyManager::get()->getSphereTriangleCount(); } diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h index fef1a41138..8de2190a0c 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h @@ -40,20 +40,6 @@ private: Transform _renderTransform; std::shared_ptr _drawMaterial; - - static int _numVertices; - static std::shared_ptr _streamFormat; - static std::shared_ptr _stream; - static std::shared_ptr _verticesBuffer; - - void generateMesh(); - void addTriangleFan(std::vector& buffer, int stack, int step); - static glm::vec3 getVertexPos(float phi, float theta); - static glm::vec3 getTangent(float phi, float theta); - static void addVertex(std::vector& buffer, const glm::vec3& pos, const glm::vec3& tan, const glm::vec2 uv); - const int SLICES = 15; - const int STACKS = 9; - const float M_PI_TIMES_2 = 2.0f * (float)M_PI; }; } } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 22cd98b08a..b14e201366 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -19,6 +19,8 @@ #include "render-utils/simple_vert.h" #include "render-utils/simple_frag.h" +#include "RenderPipelines.h" + //#define SHAPE_ENTITY_USE_FADE_EFFECT #ifdef SHAPE_ENTITY_USE_FADE_EFFECT #include @@ -108,11 +110,93 @@ bool ShapeEntityRenderer::isTransparent() const { if (_procedural.isEnabled() && _procedural.isFading()) { return Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) < 1.0f; } - - // return _entity->getLocalRenderAlpha() < 1.0f || Parent::isTransparent(); + + auto mat = _materials.find("0"); + if (mat != _materials.end()) { + if (mat->second.top().material) { + auto matKey = mat->second.top().material->getKey(); + if (matKey.isTranslucent()) { + return true; + } + } + } + return Parent::isTransparent(); } +ItemKey ShapeEntityRenderer::getKey() { + ItemKey::Builder builder; + builder.withTypeShape().withTypeMeta().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); + + withReadLock([&] { + if (isTransparent()) { + builder.withTransparent(); + } + }); + + return builder.build(); +} + +bool ShapeEntityRenderer::useMaterialPipeline() const { + withReadLock([&] { + if (_procedural.isReady()) { + return false; + } + }); + + graphics::MaterialKey drawMaterialKey; + auto mat = _materials.find("0"); + if (mat != _materials.end() && mat->second.top().material) { + drawMaterialKey = mat->second.top().material->getKey(); + } + + if (drawMaterialKey.isEmissive() || drawMaterialKey.isUnlit() || drawMaterialKey.isMetallic() || drawMaterialKey.isScattering()) { + return true; + } + + // If the material is using any map, we need to use a material ShapeKey + for (int i = 0; i < graphics::Material::MapChannel::NUM_MAP_CHANNELS; i++) { + if (drawMaterialKey.isMapChannel(graphics::Material::MapChannel(i))) { + return true; + } + } + return false; +} + +ShapeKey ShapeEntityRenderer::getShapeKey() { + if (useMaterialPipeline()) { + graphics::MaterialKey drawMaterialKey; + if (_materials["0"].top().material) { + drawMaterialKey = _materials["0"].top().material->getKey(); + } + + bool isTranslucent = drawMaterialKey.isTranslucent(); + bool hasTangents = drawMaterialKey.isNormalMap(); + bool hasLightmap = drawMaterialKey.isLightmapMap(); + bool isUnlit = drawMaterialKey.isUnlit(); + + ShapeKey::Builder builder; + builder.withMaterial(); + + if (isTranslucent) { + builder.withTranslucent(); + } + if (hasTangents) { + builder.withTangents(); + } + if (hasLightmap) { + builder.withLightmap(); + } + if (isUnlit) { + builder.withUnlit(); + } + + return builder.build(); + } else { + return Parent::getShapeKey(); + } +} + void ShapeEntityRenderer::doRender(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); Q_ASSERT(args->_batch); @@ -149,7 +233,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { } else { geometryCache->renderShape(batch, geometryShape, outColor); } - } else { + } else if (!useMaterialPipeline()) { // FIXME, support instanced multi-shape rendering using multidraw indirect outColor.a *= _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; auto pipeline = outColor.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); @@ -158,6 +242,11 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { } else { geometryCache->renderSolidShapeInstance(args, batch, geometryShape, outColor, pipeline); } + } else { + RenderPipelines::bindMaterial(mat, batch, args->_enableTexturing); + args->_details._materialSwitches++; + + geometryCache->renderShape(batch, geometryShape); } const auto triCount = geometryCache->getShapeTriangleCount(geometryShape); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index de855ce0c6..463ef187fc 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -24,6 +24,10 @@ public: virtual scriptable::ScriptableModelBase getScriptableModel() override; +protected: + ItemKey getKey() override; + ShapeKey getShapeKey() override; + private: virtual bool needsRenderUpdate() const override; virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; @@ -32,6 +36,8 @@ private: virtual void doRender(RenderArgs* args) override; virtual bool isTransparent() const override; + bool useMaterialPipeline() const; + Procedural _procedural; QString _lastUserData; Transform _renderTransform; diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 7455da13b6..61fcdafd39 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -126,6 +126,8 @@ static const int VERTICES_PER_TRIANGLE = 3; 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 TEXCOORD0_ELEMENT { gpu::VEC2, gpu::FLOAT, gpu::UV }; +static const gpu::Element TANGENT_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ }; static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA }; static const gpu::Element TEXCOORD4_ELEMENT { gpu::VEC4, gpu::FLOAT, gpu::XYZW }; @@ -133,8 +135,10 @@ static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT; static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT; static gpu::Stream::FormatPointer INSTANCED_SOLID_FADE_STREAM_FORMAT; -static const uint SHAPE_VERTEX_STRIDE = sizeof(glm::vec3) * 2; // vertices and normals +static const uint SHAPE_VERTEX_STRIDE = sizeof(glm::vec3) * 3 + sizeof(glm::vec2); // position, normal, texcoords, tangent static const uint SHAPE_NORMALS_OFFSET = sizeof(glm::vec3); +static const uint SHAPE_TEXCOORD0_OFFSET = sizeof(glm::vec3) * 2; +static const uint SHAPE_TANGENT_OFFSET = sizeof(glm::vec3) * 2 + sizeof(glm::vec2); void GeometryCache::computeSimpleHullPointListForShape(const int entityShape, const glm::vec3 &entityExtents, QVector &outPointList) { @@ -193,7 +197,18 @@ std::vector polygon() { return result; } -void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, const geometry::VertexVector& vertices) { +void addVec3ToVector(std::vector& vertices, glm::vec3 vec) { + vertices.push_back(vec.x); + vertices.push_back(vec.y); + vertices.push_back(vec.z); +} + +void addVec2ToVector(std::vector& vertices, glm::vec2 vec) { + vertices.push_back(vec.x); + vertices.push_back(vec.y); +} + +void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, const std::vector& vertices) { gpu::Buffer::Size offset = vertexBuffer->getSize(); vertexBuffer->append(vertices); @@ -203,6 +218,10 @@ void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, c viewSize, SHAPE_VERTEX_STRIDE, POSITION_ELEMENT); _normalView = gpu::BufferView(vertexBuffer, offset + SHAPE_NORMALS_OFFSET, viewSize, SHAPE_VERTEX_STRIDE, NORMAL_ELEMENT); + _texCoordView = gpu::BufferView(vertexBuffer, offset + SHAPE_TEXCOORD0_OFFSET, + viewSize, SHAPE_VERTEX_STRIDE, TEXCOORD0_ELEMENT); + _tangentView = gpu::BufferView(vertexBuffer, offset + SHAPE_TANGENT_OFFSET, + viewSize, SHAPE_VERTEX_STRIDE, TANGENT_ELEMENT); } void GeometryCache::ShapeData::setupIndices(gpu::BufferPointer& indexBuffer, const geometry::IndexVector& indices, const geometry::IndexVector& wireIndices) { @@ -228,6 +247,8 @@ void GeometryCache::ShapeData::setupIndices(gpu::BufferPointer& indexBuffer, con void GeometryCache::ShapeData::setupBatch(gpu::Batch& batch) const { batch.setInputBuffer(gpu::Stream::POSITION, _positionView); batch.setInputBuffer(gpu::Stream::NORMAL, _normalView); + batch.setInputBuffer(gpu::Stream::TEXCOORD, _texCoordView); + batch.setInputBuffer(gpu::Stream::TANGENT, _tangentView); batch.setIndexBuffer(_indicesView); } @@ -294,7 +315,7 @@ static IndexPair indexToken(geometry::Index a, geometry::Index b) { template void setupFlatShape(GeometryCache::ShapeData& shapeData, const geometry::Solid& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) { using namespace geometry; - VertexVector vertices; + std::vector vertices; IndexVector solidIndices, wireIndices; IndexPairs wireSeenIndices; @@ -310,11 +331,38 @@ void setupFlatShape(GeometryCache::ShapeData& shapeData, const geometry::Solid void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) { using namespace geometry; - VertexVector vertices; - vertices.reserve(shape.vertices.size() * 2); + std::vector vertices; + vertices.reserve(shape.vertices.size() * SHAPE_VERTEX_STRIDE / sizeof(float)); for (const auto& vertex : shape.vertices) { - vertices.push_back(vertex); - vertices.push_back(vertex); + addVec3ToVector(vertices, vertex); + addVec3ToVector(vertices, vertex); + vec2 uv = calculateSphereTexCoord(vertex); + addVec2ToVector(vertices, calculateSphereTexCoord(vertex)); + // We'll fill in the correct tangents later, once we correct the UVs + addVec3ToVector(vertices, vec3(0.0f)); + } + + // We need to fix up the sphere's UVs because it's actually a tesselated icosahedron. See http://mft-dev.dk/uv-mapping-sphere/ + size_t faceCount = shape.faces.size(); + for (size_t f = 0; f < faceCount; f++) { + // Fix zipper + { + float& u1 = vertices[shape.faces[f][0] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TEXCOORD0_OFFSET / sizeof(float)]; + float& u2 = vertices[shape.faces[f][1] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TEXCOORD0_OFFSET / sizeof(float)]; + float& u3 = vertices[shape.faces[f][2] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TEXCOORD0_OFFSET / sizeof(float)]; + + if (glm::isnan(u1)) { + u1 = (u2 + u3) / 2.0f; + } + if (glm::isnan(u2)) { + u2 = (u1 + u3) / 2.0f; + } + if (glm::isnan(u3)) { + u3 = (u1 + u2) / 2.0f; + } + + const float U_THRESHOLD = 0.25f; + float max = glm::max(u1, glm::max(u2, u3)); + float min = glm::min(u1, glm::min(u2, u3)); + + if (max - min > U_THRESHOLD) { + if (u1 < U_THRESHOLD) { + u1 += 1.0f; + } + if (u2 < U_THRESHOLD) { + u2 += 1.0f; + } + if (u3 < U_THRESHOLD) { + u3 += 1.0f; + } + } + } + + // Fix swirling at poles + for (Index i = 0; i < N; i++) { + Index originalIndex = shape.faces[f][i]; + if (shape.vertices[originalIndex].y == 1.0f || shape.vertices[originalIndex].y == -1.0f) { + float uSum = 0.0f; + for (Index i2 = 1; i2 <= N - 1; i2++) { + float u = vertices[shape.faces[f][(i + i2) % N] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TEXCOORD0_OFFSET / sizeof(float)]; + uSum += u; + } + uSum /= (float)(N - 1); + vertices[originalIndex * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TEXCOORD0_OFFSET / sizeof(float)] = uSum; + break; + } + } + + // Fill in tangents + for (Index i = 0; i < N; i++) { + vec3 tangent = calculateSphereTangent(vertices[shape.faces[f][i] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TEXCOORD0_OFFSET / sizeof(float)]); + vertices[shape.faces[f][i] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TANGENT_OFFSET / sizeof(float)] = tangent.x; + vertices[shape.faces[f][i] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TANGENT_OFFSET / sizeof(float) + 1] = tangent.y; + vertices[shape.faces[f][i] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TANGENT_OFFSET / sizeof(float) + 2] = tangent.z; + } } IndexVector solidIndices, wireIndices; IndexPairs wireSeenIndices; - size_t faceCount = shape.faces.size(); size_t faceIndexCount = triangulatedFaceIndexCount(); solidIndices.reserve(faceIndexCount * faceCount); @@ -391,25 +517,31 @@ void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid template void extrudePolygon(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer, bool isConical = false) { using namespace geometry; - VertexVector vertices; + std::vector vertices; IndexVector solidIndices, wireIndices; // Top (if not conical) and bottom faces std::vector shape = polygon(); if (isConical) { for (uint32_t i = 0; i < N; i++) { - vertices.push_back(vec3(0.0f, 0.5f, 0.0f)); - vertices.push_back(vec3(0.0f, 1.0f, 0.0f)); + addVec3ToVector(vertices, vec3(0.0f, 0.5f, 0.0f)); + addVec3ToVector(vertices, vec3(0.0f, 1.0f, 0.0f)); + addVec2ToVector(vertices, vec2(i / (float)N, 1.0f)); + addVec3ToVector(vertices, vec3(0.0f)); } } else { for (const vec3& v : shape) { - vertices.push_back(vec3(v.x, 0.5f, v.z)); - vertices.push_back(vec3(0.0f, 1.0f, 0.0f)); + addVec3ToVector(vertices, vec3(v.x, 0.5f, v.z)); + addVec3ToVector(vertices, vec3(0.0f, 1.0f, 0.0f)); + addVec2ToVector(vertices, vec2(v.x, v.z) + vec2(0.5f)); + addVec3ToVector(vertices, vec3(1.0f, 0.0f, 0.0f)); } } for (const vec3& v : shape) { - vertices.push_back(vec3(v.x, -0.5f, v.z)); - vertices.push_back(vec3(0.0f, -1.0f, 0.0f)); + addVec3ToVector(vertices, vec3(v.x, -0.5f, v.z)); + addVec3ToVector(vertices, vec3(0.0f, -1.0f, 0.0f)); + addVec2ToVector(vertices, vec2(-v.x, v.z) + vec2(0.5f)); + addVec3ToVector(vertices, vec3(-1.0f, 0.0f, 0.0f)); } Index baseVertex = 0; for (uint32_t i = 2; i < N; i++) { @@ -438,15 +570,28 @@ void extrudePolygon(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& ver 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); - vertices.push_back(topLeft); - vertices.push_back(normal); - vertices.push_back(bottomLeft); - vertices.push_back(normal); - vertices.push_back(topRight); - vertices.push_back(normal); - vertices.push_back(bottomRight); - vertices.push_back(normal); + // Our tex coords go in the opposite direction as our vertices + float u = 1.0f - i / (float)N; + float u2 = 1.0f - (i + 1) / (float)N; + + addVec3ToVector(vertices, topLeft); + addVec3ToVector(vertices, normal); + addVec2ToVector(vertices, vec2(u, 0.0f)); + addVec3ToVector(vertices, tangent); + addVec3ToVector(vertices, bottomLeft); + addVec3ToVector(vertices, normal); + addVec2ToVector(vertices, vec2(u, 1.0f)); + addVec3ToVector(vertices, tangent); + addVec3ToVector(vertices, topRight); + addVec3ToVector(vertices, normal); + addVec2ToVector(vertices, vec2(u2, 0.0f)); + addVec3ToVector(vertices, tangent); + addVec3ToVector(vertices, bottomRight); + addVec3ToVector(vertices, normal); + addVec2ToVector(vertices, vec2(u2, 1.0f)); + addVec3ToVector(vertices, tangent); solidIndices.push_back(baseVertex + 0); solidIndices.push_back(baseVertex + 2); @@ -469,14 +614,16 @@ void drawCircle(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& vertexB // Draw a circle with radius 1/4th the size of the bounding box using namespace geometry; - VertexVector vertices; + std::vector vertices; IndexVector solidIndices, wireIndices; const int NUM_CIRCLE_VERTICES = 64; std::vector shape = polygon(); for (const vec3& v : shape) { - vertices.push_back(vec3(v.x, 0.0f, v.z)); - vertices.push_back(vec3(0.0f, 0.0f, 0.0f)); + addVec3ToVector(vertices, vec3(v.x, 0.0f, v.z)); + addVec3ToVector(vertices, vec3(0.0f, 0.0f, 0.0f)); + addVec2ToVector(vertices, vec2(v.x, v.z) + vec2(0.5f)); + addVec3ToVector(vertices, vec3(1.0f, 0.0f, 0.0f)); } Index baseVertex = 0; @@ -532,9 +679,9 @@ void GeometryCache::buildShapes() { // Line { ShapeData& shapeData = _shapes[Line]; - shapeData.setupVertices(_shapeVertices, VertexVector { - vec3(-0.5f, 0.0f, 0.0f), vec3(-0.5f, 0.0f, 0.0f), - vec3(0.5f, 0.0f, 0.0f), vec3(0.5f, 0.0f, 0.0f) + shapeData.setupVertices(_shapeVertices, std::vector { + -0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, + 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f }); IndexVector wireIndices; // Only two indices @@ -598,6 +745,8 @@ gpu::Stream::FormatPointer& getSolidStreamFormat() { SOLID_STREAM_FORMAT = std::make_shared(); // 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; } @@ -607,6 +756,8 @@ gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() { INSTANCED_SOLID_STREAM_FORMAT = std::make_shared(); // 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; @@ -617,6 +768,8 @@ gpu::Stream::FormatPointer& getInstancedSolidFadeStreamFormat() { INSTANCED_SOLID_FADE_STREAM_FORMAT = std::make_shared(); // 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); @@ -919,6 +1072,7 @@ void GeometryCache::updateVertices(int id, const QVector& points, con details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_NORMAL_OFFSET); + // TODO: circle3D overlays use this to define their vertices, so they need tex coords details.streamFormat->setAttribute(gpu::Stream::COLOR, 1, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA)); details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride); diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 998043b80e..b0caaf113c 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -357,10 +357,12 @@ public: struct ShapeData { gpu::BufferView _positionView; gpu::BufferView _normalView; + gpu::BufferView _texCoordView; + gpu::BufferView _tangentView; gpu::BufferView _indicesView; gpu::BufferView _wireIndicesView; - void setupVertices(gpu::BufferPointer& vertexBuffer, const geometry::VertexVector& vertices); + void setupVertices(gpu::BufferPointer& vertexBuffer, const std::vector& vertices); void setupIndices(gpu::BufferPointer& indexBuffer, const geometry::IndexVector& indices, const geometry::IndexVector& wireIndices); void setupBatch(gpu::Batch& batch) const; void draw(gpu::Batch& batch) const; diff --git a/libraries/render-utils/src/MaterialTextures.slh b/libraries/render-utils/src/MaterialTextures.slh index b3662385b0..26bb85a853 100644 --- a/libraries/render-utils/src/MaterialTextures.slh +++ b/libraries/render-utils/src/MaterialTextures.slh @@ -148,25 +148,25 @@ vec3 fetchLightmapMap(vec2 uv) { } <@endfunc@> -<@func tangentToViewSpace(fetchedNormal, interpolatedNormal, interpolatedTangent, normal)@> +<@func evalMaterialNormal(fetchedNormal, interpolatedNormal, interpolatedTangent, normal)@> { vec3 normalizedNormal = normalize(<$interpolatedNormal$>.xyz); vec3 normalizedTangent = normalize(<$interpolatedTangent$>.xyz); - vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); + vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent); vec3 localNormal = <$fetchedNormal$>; - <$normal$> = vec3(normalizedTangent * localNormal.x + normalizedNormal * localNormal.y + normalizedBitangent * localNormal.z); + <$normal$> = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z); } <@endfunc@> -<@func tangentToViewSpaceLOD(fragPos, fetchedNormal, interpolatedNormal, interpolatedTangent, normal)@> +<@func evalMaterialNormalLOD(fragPos, fetchedNormal, interpolatedNormal, interpolatedTangent, normal)@> { vec3 normalizedNormal = normalize(<$interpolatedNormal$>.xyz); vec3 normalizedTangent = normalize(<$interpolatedTangent$>.xyz); - vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); + vec3 normalizedBitangent = cross(normalizedNormal, normalizedTangent); // attenuate the normal map divergence from the mesh normal based on distance - // THe attenuation range [20,100] meters from the eye is arbitrary for now + // The attenuation range [20,100] meters from the eye is arbitrary for now vec3 localNormal = mix(<$fetchedNormal$>, vec3(0.0, 1.0, 0.0), smoothstep(20.0, 100.0, (-<$fragPos$>).z)); - <$normal$> = vec3(normalizedTangent * localNormal.x + normalizedNormal * localNormal.y + normalizedBitangent * localNormal.z); + <$normal$> = vec3(normalizedBitangent * localNormal.x + normalizedNormal * localNormal.y + normalizedTangent * localNormal.z); } <@endfunc@> diff --git a/libraries/render-utils/src/forward_model_normal_map.slf b/libraries/render-utils/src/forward_model_normal_map.slf index b32ed862d6..0ba464d3f0 100644 --- a/libraries/render-utils/src/forward_model_normal_map.slf +++ b/libraries/render-utils/src/forward_model_normal_map.slf @@ -58,7 +58,7 @@ void main(void) { vec3 fragPosition = _position.xyz; vec3 fragNormal; - <$tangentToViewSpace(normalTex, _normal, _tangent, fragNormal)$> + <$evalMaterialNormal(normalTex, _normal, _tangent, fragNormal)$> TransformCamera cam = getTransformCamera(); diff --git a/libraries/render-utils/src/model_lightmap_normal_map.slf b/libraries/render-utils/src/model_lightmap_normal_map.slf index 8734ea74b8..eecde59e54 100644 --- a/libraries/render-utils/src/model_lightmap_normal_map.slf +++ b/libraries/render-utils/src/model_lightmap_normal_map.slf @@ -33,11 +33,11 @@ void main(void) { <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> - vec3 viewNormal; - <$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$> + vec3 fragNormal; + <$evalMaterialNormalLOD(_position, normalTexel, _normal, _tangent, fragNormal)$> packDeferredFragmentLightmap( - normalize(viewNormal.xyz), + normalize(fragNormal.xyz), evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), getMaterialAlbedo(mat) * albedo.rgb * _color, getMaterialRoughness(mat) * roughness, diff --git a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf index e6cb35ec4f..af497f90c6 100644 --- a/libraries/render-utils/src/model_lightmap_normal_map_fade.slf +++ b/libraries/render-utils/src/model_lightmap_normal_map_fade.slf @@ -43,11 +43,11 @@ void main(void) { <$fetchMaterialTexturesCoord0(matKey, _texCoord0, albedo, roughness, normalTexel, metallicTex)$> <$fetchMaterialTexturesCoord1(matKey, _texCoord1, _SCRIBE_NULL, lightmapVal)$> - vec3 viewNormal; - <$tangentToViewSpaceLOD(_position, normalTexel, _normal, _tangent, viewNormal)$> + vec3 fragNormal; + <$evalMaterialNormalLOD(_position, normalTexel, _normal, _tangent, fragNormal)$> packDeferredFragmentLightmap( - normalize(viewNormal.xyz), + normalize(fragNormal.xyz), evalOpaqueFinalAlpha(getMaterialOpacity(mat), albedo.a), getMaterialAlbedo(mat) * albedo.rgb * _color, getMaterialRoughness(mat) * roughness, diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf index 82f667bf73..49613eca6a 100644 --- a/libraries/render-utils/src/model_normal_map.slf +++ b/libraries/render-utils/src/model_normal_map.slf @@ -46,8 +46,8 @@ void main(void) { vec3 emissive = getMaterialEmissive(mat); <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - vec3 viewNormal; - <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$> + vec3 fragNormal; + <$evalMaterialNormalLOD(_position, normalTex, _normal, _tangent, fragNormal)$> float metallic = getMaterialMetallic(mat); <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; @@ -56,7 +56,7 @@ void main(void) { <$evalMaterialScattering(scatteringTex, scattering, matKey, scattering)$>; packDeferredFragment( - normalize(viewNormal.xyz), + normalize(fragNormal.xyz), opacity, albedo, roughness, diff --git a/libraries/render-utils/src/model_normal_map_fade.slf b/libraries/render-utils/src/model_normal_map_fade.slf index 67bea98cf0..bf6222652c 100644 --- a/libraries/render-utils/src/model_normal_map_fade.slf +++ b/libraries/render-utils/src/model_normal_map_fade.slf @@ -56,8 +56,8 @@ void main(void) { vec3 emissive = getMaterialEmissive(mat); <$evalMaterialEmissive(emissiveTex, emissive, matKey, emissive)$>; - vec3 viewNormal; - <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, viewNormal)$> + vec3 fragNormal; + <$evalMaterialNormalLOD(_position, normalTex, _normal, _tangent, fragNormal)$> float metallic = getMaterialMetallic(mat); <$evalMaterialMetallic(metallicTex, metallic, matKey, metallic)$>; @@ -65,7 +65,7 @@ void main(void) { float scattering = getMaterialScattering(mat); packDeferredFragment( - normalize(viewNormal.xyz), + normalize(fragNormal.xyz), opacity, albedo, roughness, diff --git a/libraries/render-utils/src/model_translucent_normal_map.slf b/libraries/render-utils/src/model_translucent_normal_map.slf index 759007d93e..52015660c6 100644 --- a/libraries/render-utils/src/model_translucent_normal_map.slf +++ b/libraries/render-utils/src/model_translucent_normal_map.slf @@ -61,7 +61,7 @@ void main(void) { vec3 fragPosition = _position.xyz; vec3 fragNormal; - <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, fragNormal)$> + <$evalMaterialNormalLOD(_position, normalTex, _normal, _tangent, fragNormal)$> TransformCamera cam = getTransformCamera(); vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0)); diff --git a/libraries/render-utils/src/model_translucent_normal_map_fade.slf b/libraries/render-utils/src/model_translucent_normal_map_fade.slf index 204b5ac56b..c6c0e16812 100644 --- a/libraries/render-utils/src/model_translucent_normal_map_fade.slf +++ b/libraries/render-utils/src/model_translucent_normal_map_fade.slf @@ -71,7 +71,7 @@ void main(void) { vec3 fragPosition = _position.xyz; // Lighting is done in world space vec3 fragNormal; - <$tangentToViewSpaceLOD(_position, normalTex, _normal, _tangent, fragNormal)$> + <$evalMaterialNormalLOD(_position, normalTex, _normal, _tangent, fragNormal)$> TransformCamera cam = getTransformCamera(); vec3 fragEyeVector = vec3(cam._viewInverse * vec4(-fragPosition, 0.0)); diff --git a/libraries/shared/src/shared/Shapes.cpp b/libraries/shared/src/shared/Shapes.cpp index dabdf21202..277154d6b6 100644 --- a/libraries/shared/src/shared/Shapes.cpp +++ b/libraries/shared/src/shared/Shapes.cpp @@ -8,8 +8,11 @@ #include "Shapes.h" +#include "qmath.h" + namespace geometry { +using glm::vec2; using glm::vec3; // The golden ratio @@ -20,7 +23,7 @@ Solid<3> tesselate(const Solid<3>& solid_, int count) { float length = glm::length(solid.vertices[0]); for (int i = 0; i < count; ++i) { Solid<3> result { solid.vertices, {} }; - result.vertices.reserve(solid.vertices.size() + solid.faces.size() * 3); + result.vertices.reserve(solid.vertices.size() + solid.faces.size() * 6); for (size_t f = 0; f < solid.faces.size(); ++f) { Index baseVertex = (Index)result.vertices.size(); const Face<3>& oldFace = solid.faces[f]; @@ -30,13 +33,26 @@ Solid<3> tesselate(const Solid<3>& solid_, int count) { vec3 ab = glm::normalize(a + b) * length; vec3 bc = glm::normalize(b + c) * length; vec3 ca = glm::normalize(c + a) * length; + + result.vertices.push_back(a); + result.vertices.push_back(ab); + result.vertices.push_back(ca); + result.faces.push_back(Face<3>{ { baseVertex, baseVertex + 1, baseVertex + 2 } }); + + result.vertices.push_back(ab); + result.vertices.push_back(b); + result.vertices.push_back(bc); + result.faces.push_back(Face<3>{ { baseVertex + 3, baseVertex + 4, baseVertex + 5 } }); + + result.vertices.push_back(bc); + result.vertices.push_back(c); + result.vertices.push_back(ca); + result.faces.push_back(Face<3>{ { baseVertex + 6, baseVertex + 7, baseVertex + 8 } }); + result.vertices.push_back(ab); result.vertices.push_back(bc); result.vertices.push_back(ca); - result.faces.push_back(Face<3>{ { oldFace[0], baseVertex, baseVertex + 2 } }); - result.faces.push_back(Face<3>{ { baseVertex, oldFace[1], baseVertex + 1 } }); - result.faces.push_back(Face<3>{ { baseVertex + 1, oldFace[2], baseVertex + 2 } }); - result.faces.push_back(Face<3>{ { baseVertex, baseVertex + 1, baseVertex + 2 } }); + result.faces.push_back(Face<3>{ { baseVertex + 9, baseVertex + 10, baseVertex + 11 } }); } solid = result; } @@ -50,6 +66,10 @@ const Solid<3>& tetrahedron() { static const auto D = vec3(-1, -1, 1); static const Solid<3> TETRAHEDRON = Solid<3>{ { A, B, C, D }, + { vec2(0.75f, 0.5f), vec2(0.5f, 0.0f), vec2(0.25f, 0.5f), + vec2(0.5f, 1.0f), vec2(1.0f, 1.0f), vec2(0.75f, 0.5f), + vec2(0.25f, 0.5f), vec2(0.5f, 1.0f), vec2(0.75f, 0.5f), + vec2(0.25f, 0.5f), vec2(0.0f, 1.0f), vec2(0.5f, 1.0f) }, FaceVector<3>{ Face<3> { { 0, 1, 2 } }, Face<3> { { 3, 1, 0 } }, @@ -65,8 +85,15 @@ const Solid<4>& cube() { static const auto B = vec3(-1, 1, 1); static const auto C = vec3(-1, 1, -1); static const auto D = vec3(1, 1, -1); + static const float THIRD = 1.0f / 3.0f; static const Solid<4> CUBE = Solid<4>{ { A, B, C, D, -A, -B, -C, -D }, + { vec2(0.5f, 0.0f), vec2(0.25f, 0.0f), vec2(0.25f, THIRD), vec2(0.5f, THIRD), + vec2(0.5f, THIRD), vec2(0.25f, THIRD), vec2(0.25f, 2.0f * THIRD), vec2(0.5f, 2.0f * THIRD), + vec2(0.25f, THIRD), vec2(0.0f, THIRD), vec2(0.0f, 2.0f * THIRD), vec2(0.25f, 2.0f * THIRD), + vec2(1.0f, THIRD), vec2(0.75f, THIRD), vec2(0.75f, 2.0f * THIRD), vec2(1.0f, 2.0f * THIRD), + vec2(0.75f, THIRD), vec2(0.5f, THIRD), vec2(0.5f, 2.0f * THIRD), vec2(0.75f, 2.0f * THIRD), + vec2(0.25f, 1.0f), vec2(0.5f, 1.0f), vec2(0.5f, 2.0f * THIRD), vec2(0.25f, 2.0f * THIRD) }, FaceVector<4>{ Face<4> { { 3, 2, 1, 0 } }, Face<4> { { 0, 1, 7, 6 } }, @@ -86,8 +113,18 @@ const Solid<3>& octahedron() { static const auto D = vec3(0, 0, -1); static const auto E = vec3(1, 0, 0); static const auto F = vec3(-1, 0, 0); + static const float THIRD = 1.0f / 3.0f; + static const float SEVENTH = 1.0f / 7.0f; static const Solid<3> OCTAHEDRON = Solid<3>{ { A, B, C, D, E, F}, + { vec2(2.0f * SEVENTH, THIRD), vec2(SEVENTH, 2.0f * THIRD), vec2(3.0f * SEVENTH, 2.0f * THIRD), + vec2(2.0f * SEVENTH, THIRD), vec2(3.0f * SEVENTH, 2.0f * THIRD), vec2(4.0f * SEVENTH, THIRD), + vec2(5.0f * SEVENTH, 0.0f), vec2(4.0f * SEVENTH, THIRD), vec2(6.0f * SEVENTH, THIRD), + vec2(2.0f * SEVENTH, THIRD), vec2(0.0f, THIRD), vec2(1.0f * SEVENTH, 2.0f * THIRD), + vec2(2.0f * SEVENTH, 1.0f), vec2(3.0f * SEVENTH, 2.0f * THIRD), vec2(1.0f * SEVENTH, 2.0f * THIRD), + vec2(5.0f * SEVENTH, 2.0f * THIRD), vec2(4.0f * SEVENTH, THIRD), vec2(3.0f * SEVENTH, 2.0f * THIRD), + vec2(5.0f * SEVENTH, 2.0f * THIRD), vec2(6.0f * SEVENTH, THIRD), vec2(4.0f * SEVENTH, THIRD), + vec2(5.0f * SEVENTH, 2.0f * THIRD), vec2(1.0f, 2.0f * THIRD), vec2(6.0f * SEVENTH, THIRD) }, FaceVector<3> { Face<3> { { 0, 2, 4, } }, Face<3> { { 0, 4, 3, } }, @@ -116,11 +153,52 @@ const Solid<5>& dodecahedron() { static const vec3 I = vec3(0, -IP, P); static const vec3 J = vec3(P, 0, IP); + + /* _ + / \ | + / \ y2 + / \ | + / \ _ + \ / | + \ / y1 + \ / | + ___________ _ + |x3|- - x1 - -||x3| + |- - - - x2- - - -| + */ + + // x1, x2, and x3 are the solutions to the following system of equations: + // 1 = 3 * x1 + 3 * x2 + x3 + // x1 + 2 * x3 = (golden ratio) * x1 + // x2 = x1 + 2 * x3 + static const float x1 = 4.0f / (17.0f + 7.0f * sqrt(5.0f)); + static const float x2 = (1.0f / 11.0f) * (5.0f * sqrt(5.0f) - 9.0f); + static const float x2_2 = x2 / 2.0f; + static const float x3 = (1.0f / 11.0f) * (6.0f * sqrt(5.0f) - 13.0f); + // y1 and y2 are the solutions to the following system of equations (x is the sidelength, but is different than x1 because the scale in the y direction is different): + // 1 = 3 * y1 + 2 * y2 + // y1 = sin(108 deg) * x + // y1 + y2 = x * sqrt(5 + 2 * sqrt(5)) / 2 + static const float y1 = sqrt(2.0f * (5.0f + sqrt(5.0f))) / (sqrt(2.0f * (5.0f + sqrt(5.0f))) + 4.0f * sqrt(5.0f + 2.0f * sqrt(5.0f))); + static const float y2 = -(sqrt(2.0f * (5.0f + sqrt(5.0f))) - 2.0f * sqrt(5.0f + 2.0f * sqrt(5.0f))) / (sqrt(2.0f * (5.0f + sqrt(5.0f))) + 4.0f * sqrt(5.0f + 2.0f * sqrt(5.0f))); + static const Solid<5> DODECAHEDRON = Solid<5>{ { A, B, C, D, E, F, G, H, I, J, -A, -B, -C, -D, -E, -F, -G, -H, -I, -J, }, + { vec2(x1 + x2_2, 0.0f), vec2(x2_2, 0.0f), vec2(x2_2 - x3, y1), vec2(x3 + x1, y1 + y2), vec2(x3 + x1 + x2_2, y1), + vec2(1.0f - (x2 - x3 + x2_2), 0.0f), vec2(1.0f - (x2 + x1 + x3), y2), vec2(1.0f - (x2 + x1), y1 + y2), vec2(1.0f - x2, y1 + y2), vec2(1.0f - (x2 - x3), y2), + vec2(1.0f - x2_2, y1), vec2(1.0f - x2, y1 + y2), vec2(1.0f - (x3 + x1), y1 + y2 + y1), vec2(1.0f - x3, y1 + y2 + y1), vec2(1.0f, y1 + y2), + vec2(x3, y1 + y2), vec2(0.0f, y1 + y2 + y1), vec2(x2_2, y1 + y2 + y1 + y2), vec2(x2, y1 + y2 + y1), vec2(x1 + x3, y1 + y2), + vec2(x3 + x1, y1 + y2), vec2(x2, y1 + y2 + y1), vec2(x2 + x1, y1 + y2 + y1), vec2(x3 + x1 + x2, y1 + y2), vec2(x3 + x1 + x2_2, y1), + vec2(x3 + x1 + x2_2, y1), vec2(x3 + x1 + x2, y1 + y2), vec2(x3 + x1 + x2 + x2_2, y1), vec2(x1 + x2 + x2_2, 0.0f), vec2(x3 + x1 + x2_2 + x3, 0.0f), + vec2(1.0f - (x3 + x1 + x2_2), 1.0f - y1), vec2(1.0f - (x3 + x1 + x2), 1.0f - (y1 + y2)), vec2(1.0f - (x3 + x1 + x2 + x2_2), 1.0f - y1), vec2(1.0f - (x1 + x2 + x2_2), 1.0f), vec2(1.0f - (x3 + x1 + x2_2 + x3), 1.0f), + vec2(x2 + x1 + x3, 1.0f - y2), vec2(x2 + x1, 1.0f - (y1 + y2)), vec2(x2, 1.0f - (y1 + y2)), vec2(x2 - x3, 1.0f - y2), vec2(x2 - x3 + x2_2, 1.0f), + vec2(x2 + x1 + x2, y1 + y2 + y1), vec2(x3 + x1 + x2 + x1, y1 + y2), vec2(x3 + x1 + x2, y1 + y2), vec2(x2 + x1, y1 + y2 + y1), vec2(x2 + x1 + x2_2, y1 + y2 + y1 + y2), + vec2(1.0f - (x3 + x1 + x2), y1 + y2 + y1), vec2(1.0f - (x2 + x1), y1 + y2), vec2(1.0f - (x2 + x1 + x2_2), y1), vec2(1.0f - (x2 + x1 + x2), y1 + y2), vec2(1.0f - (x3 + x1 + x2 + x1), y1 + y2 + y1), + vec2(1.0f - (x3 + x1 + x2_2), y1 + y2 + y1 + y2), vec2(1.0f - (x3 + x1), y1 + y2 + y1), vec2(1.0f - x2, y1 + y2), vec2(1.0f - (x2 + x1), y2 + y1), vec2(1.0f - (x3 + x1 + x2), y1 + y2 + y1), + vec2(1.0f - (x1 + x2_2), 1.0f), vec2(1.0f - x2_2, 1.0f), vec2(1.0f - (x2_2 - x3), 1.0f - y1), vec2(1.0f - (x1 + x3), 1.0f - (y1 + y2)), vec2(1.0f - (x3 + x1 + x2_2), 1.0f - y1) }, FaceVector<5> { Face<5> { { 0, 1, 2, 3, 4 } }, Face<5> { { 0, 5, 18, 6, 1 } }, @@ -148,12 +226,33 @@ const Solid<3>& icosahedron() { static const auto D = vec3(P, 0, N); static const auto E = vec3(P, 0, -N); static const auto F = vec3(0, N, -P); - + static const float THIRD = 1.0f / 3.0f; + static const float ELEVENTH = 1.0f / 11.0f; static const Solid<3> ICOSAHEDRON = Solid<3> { { A, B, C, D, E, F, -A, -B, -C, -D, -E, -F, }, + { vec2(3.0f * ELEVENTH, 0.0f), vec2(2.0f * ELEVENTH, THIRD), vec2(4.0f * ELEVENTH, THIRD), + vec2(2.0f * ELEVENTH, THIRD), vec2(3.0f * ELEVENTH, 2.0f * THIRD), vec2(4.0f * ELEVENTH, THIRD), + vec2(3.0f * ELEVENTH, 2.0f * THIRD), vec2(5.0f * ELEVENTH, 2.0f * THIRD), vec2(4.0f * ELEVENTH, THIRD), + vec2(5.0f * ELEVENTH, 2.0f * THIRD), vec2(6.0f * ELEVENTH, THIRD), vec2(4.0f * ELEVENTH, THIRD), + vec2(6.0f * ELEVENTH, THIRD), vec2(5.0f * ELEVENTH, 0.0f), vec2(4.0f * ELEVENTH, THIRD), + vec2(1.0f * ELEVENTH, 0.0f), vec2(0.0f, THIRD), vec2(2.0f * ELEVENTH, THIRD), + vec2(1.0f * ELEVENTH, 2.0f * THIRD), vec2(2.0f * ELEVENTH, THIRD), vec2(0.0f, THIRD), + vec2(2.0f * ELEVENTH, THIRD), vec2(1.0f * ELEVENTH, 2.0f * THIRD), vec2(3.0f * ELEVENTH, 2.0f * THIRD), + vec2(2.0f * ELEVENTH, 1.0f), vec2(3.0f * ELEVENTH, 2.0f * THIRD), vec2(1.0f * ELEVENTH, 2.0f * THIRD), + vec2(3.0f * ELEVENTH, 2.0f * THIRD), vec2(4.0f * ELEVENTH, 1.0f), vec2(5.0f * ELEVENTH, 2.0f * THIRD), + vec2(7.0f * ELEVENTH, 2.0f * THIRD), vec2(5.0f * ELEVENTH, 2.0f * THIRD), vec2(6.0f * ELEVENTH, 1.0f), + vec2(5.0f * ELEVENTH, 2.0f * THIRD), vec2(7.0f * ELEVENTH, 2.0f * THIRD), vec2(6.0f * ELEVENTH, THIRD), + vec2(8.0f * ELEVENTH, THIRD), vec2(6.0f * ELEVENTH, THIRD), vec2(7.0f * ELEVENTH, 2.0f * THIRD), + vec2(6.0f * ELEVENTH, THIRD), vec2(8.0f * ELEVENTH, THIRD), vec2(7.0f * ELEVENTH, 0.0f), + vec2(10.0f * ELEVENTH, THIRD), vec2(9.0f * ELEVENTH, 0.0f), vec2(8.0f * ELEVENTH, THIRD), + vec2(7.0f * ELEVENTH, 2.0f * THIRD), vec2(8.0f * ELEVENTH, 1.0f), vec2(9.0f * ELEVENTH, 2.0f * THIRD), + vec2(8.0f * ELEVENTH, THIRD), vec2(7.0f * ELEVENTH, 2.0f * THIRD), vec2(9.0f * ELEVENTH, 2.0f * THIRD), + vec2(10.0f * ELEVENTH, THIRD), vec2(8.0f * ELEVENTH, THIRD), vec2(9.0f * ELEVENTH, 2.0f * THIRD), + vec2(1.0f, 2.0f * THIRD), vec2(10.0f * ELEVENTH, THIRD), vec2(9.0f * ELEVENTH, 2.0f * THIRD), + vec2(10.0f * ELEVENTH, 1.0f), vec2(1.0f, 2.0f * THIRD), vec2(9.0f * ELEVENTH, 2.0f * THIRD) }, FaceVector<3> { Face<3> { { 1, 2, 0 } }, Face<3> { { 2, 3, 0 } }, diff --git a/libraries/shared/src/shared/Shapes.h b/libraries/shared/src/shared/Shapes.h index 3486a0a663..6bd2eab199 100644 --- a/libraries/shared/src/shared/Shapes.h +++ b/libraries/shared/src/shared/Shapes.h @@ -22,6 +22,7 @@ namespace geometry { using Index = uint32_t; using Vec = glm::vec3; using VertexVector = std::vector; + using TexCoordVector = std::vector; using IndexVector = std::vector; template @@ -33,6 +34,7 @@ namespace geometry { template struct Solid { VertexVector vertices; + TexCoordVector texCoords; FaceVector faces; Solid& fitDimension(float newMaxDimension) { From 96e48a01621d45093b05da7aa597429878e2d928 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 7 Mar 2018 13:16:13 -0800 Subject: [PATCH 2/3] warnings --- .../src/RenderableMaterialEntityItem.cpp | 2 +- .../src/RenderableShapeEntityItem.cpp | 9 +++++---- libraries/render-utils/src/GeometryCache.cpp | 3 +-- libraries/shared/src/shared/Shapes.cpp | 14 +++++++------- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 8566b9bae8..ea8edb8a08 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -123,5 +123,5 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { // Draw! DependencyManager::get()->renderSphere(batch); - args->_details._trianglesRendered += DependencyManager::get()->getSphereTriangleCount(); + args->_details._trianglesRendered += (int)DependencyManager::get()->getSphereTriangleCount(); } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index b14e201366..0e04ae3418 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -138,11 +138,12 @@ ItemKey ShapeEntityRenderer::getKey() { } bool ShapeEntityRenderer::useMaterialPipeline() const { - withReadLock([&] { - if (_procedural.isReady()) { - return false; - } + bool proceduralReady = resultWithReadLock([&] { + return _procedural.isReady(); }); + if (proceduralReady) { + return false; + } graphics::MaterialKey drawMaterialKey; auto mat = _materials.find("0"); diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 61fcdafd39..edd68603cb 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -401,7 +401,7 @@ vec2 calculateSphereTexCoord(const vec3& vertex) { } vec3 calculateSphereTangent(float u) { - float phi = u * M_PI * 2.0f; + float phi = u * (float)M_PI * 2.0f; return -glm::normalize(glm::vec3(glm::sin(phi), 0.0f, glm::cos(phi))); } @@ -414,7 +414,6 @@ void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid for (const auto& vertex : shape.vertices) { addVec3ToVector(vertices, vertex); addVec3ToVector(vertices, vertex); - vec2 uv = calculateSphereTexCoord(vertex); addVec2ToVector(vertices, calculateSphereTexCoord(vertex)); // We'll fill in the correct tangents later, once we correct the UVs addVec3ToVector(vertices, vec3(0.0f)); diff --git a/libraries/shared/src/shared/Shapes.cpp b/libraries/shared/src/shared/Shapes.cpp index 277154d6b6..afcf956165 100644 --- a/libraries/shared/src/shared/Shapes.cpp +++ b/libraries/shared/src/shared/Shapes.cpp @@ -22,7 +22,7 @@ Solid<3> tesselate(const Solid<3>& solid_, int count) { Solid<3> solid = solid_; float length = glm::length(solid.vertices[0]); for (int i = 0; i < count; ++i) { - Solid<3> result { solid.vertices, {} }; + Solid<3> result { solid.vertices, {}, {} }; result.vertices.reserve(solid.vertices.size() + solid.faces.size() * 6); for (size_t f = 0; f < solid.faces.size(); ++f) { Index baseVertex = (Index)result.vertices.size(); @@ -171,16 +171,16 @@ const Solid<5>& dodecahedron() { // 1 = 3 * x1 + 3 * x2 + x3 // x1 + 2 * x3 = (golden ratio) * x1 // x2 = x1 + 2 * x3 - static const float x1 = 4.0f / (17.0f + 7.0f * sqrt(5.0f)); - static const float x2 = (1.0f / 11.0f) * (5.0f * sqrt(5.0f) - 9.0f); + static const float x1 = 4.0f / (17.0f + 7.0f * sqrtf(5.0f)); + static const float x2 = (1.0f / 11.0f) * (5.0f * sqrtf(5.0f) - 9.0f); static const float x2_2 = x2 / 2.0f; - static const float x3 = (1.0f / 11.0f) * (6.0f * sqrt(5.0f) - 13.0f); + static const float x3 = (1.0f / 11.0f) * (6.0f * sqrtf(5.0f) - 13.0f); // y1 and y2 are the solutions to the following system of equations (x is the sidelength, but is different than x1 because the scale in the y direction is different): // 1 = 3 * y1 + 2 * y2 // y1 = sin(108 deg) * x - // y1 + y2 = x * sqrt(5 + 2 * sqrt(5)) / 2 - static const float y1 = sqrt(2.0f * (5.0f + sqrt(5.0f))) / (sqrt(2.0f * (5.0f + sqrt(5.0f))) + 4.0f * sqrt(5.0f + 2.0f * sqrt(5.0f))); - static const float y2 = -(sqrt(2.0f * (5.0f + sqrt(5.0f))) - 2.0f * sqrt(5.0f + 2.0f * sqrt(5.0f))) / (sqrt(2.0f * (5.0f + sqrt(5.0f))) + 4.0f * sqrt(5.0f + 2.0f * sqrt(5.0f))); + // y1 + y2 = x * sqrtf(5 + 2 * sqrtf(5)) / 2 + static const float y1 = sqrtf(2.0f * (5.0f + sqrtf(5.0f))) / (sqrtf(2.0f * (5.0f + sqrtf(5.0f))) + 4.0f * sqrtf(5.0f + 2.0f * sqrtf(5.0f))); + static const float y2 = -(sqrtf(2.0f * (5.0f + sqrtf(5.0f))) - 2.0f * sqrtf(5.0f + 2.0f * sqrtf(5.0f))) / (sqrtf(2.0f * (5.0f + sqrtf(5.0f))) + 4.0f * sqrtf(5.0f + 2.0f * sqrtf(5.0f))); static const Solid<5> DODECAHEDRON = Solid<5>{ { From 984a48316d742b8bbcfd182c69dc1f4ccdb0813b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 16 Mar 2018 10:56:56 -0700 Subject: [PATCH 3/3] CR --- libraries/render-utils/src/GeometryCache.cpp | 145 +++++-------------- libraries/render-utils/src/GeometryCache.h | 11 +- 2 files changed, 45 insertions(+), 111 deletions(-) diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index edd68603cb..693e288d5d 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -135,10 +135,10 @@ static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT; static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT; static gpu::Stream::FormatPointer INSTANCED_SOLID_FADE_STREAM_FORMAT; -static const uint SHAPE_VERTEX_STRIDE = sizeof(glm::vec3) * 3 + sizeof(glm::vec2); // position, normal, texcoords, tangent -static const uint SHAPE_NORMALS_OFFSET = sizeof(glm::vec3); -static const uint SHAPE_TEXCOORD0_OFFSET = sizeof(glm::vec3) * 2; -static const uint SHAPE_TANGENT_OFFSET = sizeof(glm::vec3) * 2 + sizeof(glm::vec2); +static const uint SHAPE_VERTEX_STRIDE = sizeof(GeometryCache::ShapeVertex); // position, normal, texcoords, tangent +static const uint SHAPE_NORMALS_OFFSET = offsetof(GeometryCache::ShapeVertex, normal); +static const uint SHAPE_TEXCOORD0_OFFSET = offsetof(GeometryCache::ShapeVertex, uv); +static const uint SHAPE_TANGENT_OFFSET = offsetof(GeometryCache::ShapeVertex, tangent); void GeometryCache::computeSimpleHullPointListForShape(const int entityShape, const glm::vec3 &entityExtents, QVector &outPointList) { @@ -197,22 +197,11 @@ std::vector polygon() { return result; } -void addVec3ToVector(std::vector& vertices, glm::vec3 vec) { - vertices.push_back(vec.x); - vertices.push_back(vec.y); - vertices.push_back(vec.z); -} - -void addVec2ToVector(std::vector& vertices, glm::vec2 vec) { - vertices.push_back(vec.x); - vertices.push_back(vec.y); -} - -void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, const std::vector& vertices) { +void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, const std::vector& vertices) { gpu::Buffer::Size offset = vertexBuffer->getSize(); vertexBuffer->append(vertices); - gpu::Buffer::Size viewSize = vertices.size() * sizeof(glm::vec3); + gpu::Buffer::Size viewSize = vertices.size() * sizeof(ShapeVertex); _positionView = gpu::BufferView(vertexBuffer, offset, viewSize, SHAPE_VERTEX_STRIDE, POSITION_ELEMENT); @@ -315,14 +304,14 @@ static IndexPair indexToken(geometry::Index a, geometry::Index b) { template void setupFlatShape(GeometryCache::ShapeData& shapeData, const geometry::Solid& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) { using namespace geometry; - std::vector vertices; + std::vector vertices; IndexVector solidIndices, wireIndices; IndexPairs wireSeenIndices; size_t faceCount = shape.faces.size(); size_t faceIndexCount = triangulatedFaceIndexCount(); - vertices.reserve(N * faceCount * 2); + vertices.reserve(N * faceCount); solidIndices.reserve(faceIndexCount * faceCount); Index baseVertex = 0; @@ -359,10 +348,7 @@ void setupFlatShape(GeometryCache::ShapeData& shapeData, const geometry::Solid void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) { using namespace geometry; - std::vector vertices; - vertices.reserve(shape.vertices.size() * SHAPE_VERTEX_STRIDE / sizeof(float)); + std::vector vertices; + vertices.reserve(shape.vertices.size()); for (const auto& vertex : shape.vertices) { - addVec3ToVector(vertices, vertex); - addVec3ToVector(vertices, vertex); - addVec2ToVector(vertices, calculateSphereTexCoord(vertex)); // We'll fill in the correct tangents later, once we correct the UVs - addVec3ToVector(vertices, vec3(0.0f)); + vertices.emplace_back(vertex, vertex, calculateSphereTexCoord(vertex), vec3(0.0f)); } // We need to fix up the sphere's UVs because it's actually a tesselated icosahedron. See http://mft-dev.dk/uv-mapping-sphere/ @@ -424,9 +409,9 @@ void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid for (size_t f = 0; f < faceCount; f++) { // Fix zipper { - float& u1 = vertices[shape.faces[f][0] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TEXCOORD0_OFFSET / sizeof(float)]; - float& u2 = vertices[shape.faces[f][1] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TEXCOORD0_OFFSET / sizeof(float)]; - float& u3 = vertices[shape.faces[f][2] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TEXCOORD0_OFFSET / sizeof(float)]; + float& u1 = vertices[shape.faces[f][0]].uv.x; + float& u2 = vertices[shape.faces[f][1]].uv.x; + float& u3 = vertices[shape.faces[f][2]].uv.x; if (glm::isnan(u1)) { u1 = (u2 + u3) / 2.0f; @@ -461,21 +446,19 @@ void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid if (shape.vertices[originalIndex].y == 1.0f || shape.vertices[originalIndex].y == -1.0f) { float uSum = 0.0f; for (Index i2 = 1; i2 <= N - 1; i2++) { - float u = vertices[shape.faces[f][(i + i2) % N] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TEXCOORD0_OFFSET / sizeof(float)]; + float u = vertices[shape.faces[f][(i + i2) % N]].uv.x; uSum += u; } uSum /= (float)(N - 1); - vertices[originalIndex * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TEXCOORD0_OFFSET / sizeof(float)] = uSum; + vertices[originalIndex].uv.x = uSum; break; } } // Fill in tangents for (Index i = 0; i < N; i++) { - vec3 tangent = calculateSphereTangent(vertices[shape.faces[f][i] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TEXCOORD0_OFFSET / sizeof(float)]); - vertices[shape.faces[f][i] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TANGENT_OFFSET / sizeof(float)] = tangent.x; - vertices[shape.faces[f][i] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TANGENT_OFFSET / sizeof(float) + 1] = tangent.y; - vertices[shape.faces[f][i] * SHAPE_VERTEX_STRIDE / sizeof(float) + SHAPE_TANGENT_OFFSET / sizeof(float) + 2] = tangent.z; + vec3 tangent = calculateSphereTangent(vertices[shape.faces[f][i]].uv.x); + vertices[shape.faces[f][i]].tangent = tangent; } } @@ -516,31 +499,22 @@ void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid template void extrudePolygon(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer, bool isConical = false) { using namespace geometry; - std::vector vertices; + std::vector vertices; IndexVector solidIndices, wireIndices; // Top (if not conical) and bottom faces std::vector shape = polygon(); if (isConical) { for (uint32_t i = 0; i < N; i++) { - addVec3ToVector(vertices, vec3(0.0f, 0.5f, 0.0f)); - addVec3ToVector(vertices, vec3(0.0f, 1.0f, 0.0f)); - addVec2ToVector(vertices, vec2(i / (float)N, 1.0f)); - addVec3ToVector(vertices, vec3(0.0f)); + vertices.emplace_back(vec3(0.0f, 0.5f, 0.0f), vec3(0.0f, 1.0f, 0.0f), vec2((float)i / (float)N, 1.0f), vec3(0.0f)); } } else { for (const vec3& v : shape) { - addVec3ToVector(vertices, vec3(v.x, 0.5f, v.z)); - addVec3ToVector(vertices, vec3(0.0f, 1.0f, 0.0f)); - addVec2ToVector(vertices, vec2(v.x, v.z) + vec2(0.5f)); - addVec3ToVector(vertices, vec3(1.0f, 0.0f, 0.0f)); + vertices.emplace_back(vec3(v.x, 0.5f, v.z), vec3(0.0f, 1.0f, 0.0f), vec2(v.x, v.z) + vec2(0.5f), vec3(1.0f, 0.0f, 0.0f)); } } for (const vec3& v : shape) { - addVec3ToVector(vertices, vec3(v.x, -0.5f, v.z)); - addVec3ToVector(vertices, vec3(0.0f, -1.0f, 0.0f)); - addVec2ToVector(vertices, vec2(-v.x, v.z) + vec2(0.5f)); - addVec3ToVector(vertices, vec3(-1.0f, 0.0f, 0.0f)); + vertices.emplace_back(vec3(v.x, -0.5f, v.z), vec3(0.0f, -1.0f, 0.0f), vec2(-v.x, v.z) + vec2(0.5f), vec3(-1.0f, 0.0f, 0.0f)); } Index baseVertex = 0; for (uint32_t i = 2; i < N; i++) { @@ -572,25 +546,13 @@ void extrudePolygon(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& ver vec3 tangent = glm::normalize(bottomLeft - bottomRight); // Our tex coords go in the opposite direction as our vertices - float u = 1.0f - i / (float)N; - float u2 = 1.0f - (i + 1) / (float)N; + float u = 1.0f - (float)i / (float)N; + float u2 = 1.0f - (float)(i + 1) / (float)N; - addVec3ToVector(vertices, topLeft); - addVec3ToVector(vertices, normal); - addVec2ToVector(vertices, vec2(u, 0.0f)); - addVec3ToVector(vertices, tangent); - addVec3ToVector(vertices, bottomLeft); - addVec3ToVector(vertices, normal); - addVec2ToVector(vertices, vec2(u, 1.0f)); - addVec3ToVector(vertices, tangent); - addVec3ToVector(vertices, topRight); - addVec3ToVector(vertices, normal); - addVec2ToVector(vertices, vec2(u2, 0.0f)); - addVec3ToVector(vertices, tangent); - addVec3ToVector(vertices, bottomRight); - addVec3ToVector(vertices, normal); - addVec2ToVector(vertices, vec2(u2, 1.0f)); - addVec3ToVector(vertices, tangent); + 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); @@ -609,43 +571,6 @@ void extrudePolygon(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& ver shapeData.setupIndices(indexBuffer, solidIndices, wireIndices); } -void drawCircle(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) { - // Draw a circle with radius 1/4th the size of the bounding box - using namespace geometry; - - std::vector vertices; - IndexVector solidIndices, wireIndices; - const int NUM_CIRCLE_VERTICES = 64; - - std::vector shape = polygon(); - for (const vec3& v : shape) { - addVec3ToVector(vertices, vec3(v.x, 0.0f, v.z)); - addVec3ToVector(vertices, vec3(0.0f, 0.0f, 0.0f)); - addVec2ToVector(vertices, vec2(v.x, v.z) + vec2(0.5f)); - addVec3ToVector(vertices, vec3(1.0f, 0.0f, 0.0f)); - } - - Index baseVertex = 0; - for (uint32_t i = 2; i < NUM_CIRCLE_VERTICES; i++) { - solidIndices.push_back(baseVertex + 0); - solidIndices.push_back(baseVertex + i); - solidIndices.push_back(baseVertex + i - 1); - solidIndices.push_back(baseVertex + NUM_CIRCLE_VERTICES); - solidIndices.push_back(baseVertex + i + NUM_CIRCLE_VERTICES - 1); - solidIndices.push_back(baseVertex + i + NUM_CIRCLE_VERTICES); - } - - for (uint32_t i = 1; i <= NUM_CIRCLE_VERTICES; i++) { - wireIndices.push_back(baseVertex + (i % NUM_CIRCLE_VERTICES)); - wireIndices.push_back(baseVertex + i - 1); - wireIndices.push_back(baseVertex + (i % NUM_CIRCLE_VERTICES) + NUM_CIRCLE_VERTICES); - wireIndices.push_back(baseVertex + (i - 1) + NUM_CIRCLE_VERTICES); - } - - 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 @@ -678,9 +603,9 @@ void GeometryCache::buildShapes() { // Line { ShapeData& shapeData = _shapes[Line]; - shapeData.setupVertices(_shapeVertices, std::vector { - -0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, - 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f + shapeData.setupVertices(_shapeVertices, std::vector { + 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 diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index b0caaf113c..63154398a4 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -354,6 +354,15 @@ public: /// Set a batch to the simple pipeline, returning the previous pipeline void useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend = false); + struct ShapeVertex { + ShapeVertex(const vec3& pos, const vec3& normal, const vec2& uv, const vec3& tangent) : pos(pos), normal(normal), uv(uv), tangent(tangent) {} + + vec3 pos; + vec3 normal; + vec2 uv; + vec3 tangent; + }; + struct ShapeData { gpu::BufferView _positionView; gpu::BufferView _normalView; @@ -362,7 +371,7 @@ public: gpu::BufferView _indicesView; gpu::BufferView _wireIndicesView; - void setupVertices(gpu::BufferPointer& vertexBuffer, const std::vector& vertices); + void setupVertices(gpu::BufferPointer& vertexBuffer, const std::vector& vertices); void setupIndices(gpu::BufferPointer& indexBuffer, const geometry::IndexVector& indices, const geometry::IndexVector& wireIndices); void setupBatch(gpu::Batch& batch) const; void draw(gpu::Batch& batch) const;