diff --git a/examples/DecodeOnGPU/decode.vert b/examples/DecodeOnGPU/decode.vert index 94d35f44..de61bc42 100644 --- a/examples/DecodeOnGPU/decode.vert +++ b/examples/DecodeOnGPU/decode.vert @@ -1,6 +1,6 @@ #version 140 -in vec4 position; // This will be the position of the vertex in model-space +in uvec4 position; // This will be the position of the vertex in model-space // The usual matrices are provided uniform mat4 cameraToClipMatrix; @@ -13,8 +13,11 @@ out vec4 worldPosition; void main() { + vec4 decodedPosition = position; + decodedPosition.xyz = decodedPosition.xyz * (1.0 / 256.0); + // Standard sequence of OpenGL transformations. - worldPosition = modelToWorldMatrix * position; + worldPosition = modelToWorldMatrix * decodedPosition; vec4 cameraPosition = worldToCameraMatrix * worldPosition; gl_Position = cameraToClipMatrix * cameraPosition; } diff --git a/examples/DecodeOnGPU/main.cpp b/examples/DecodeOnGPU/main.cpp index 3a36fd48..fd1e0b16 100644 --- a/examples/DecodeOnGPU/main.cpp +++ b/examples/DecodeOnGPU/main.cpp @@ -66,7 +66,7 @@ void createSphereInVolume(SimpleVolume& volData, float fRadius) } } -OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::Vertex< uint8_t > >& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f) +OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::MarchingCubesVertex< uint8_t > >& surfaceMesh, const PolyVox::Vector3DInt32& translation = PolyVox::Vector3DInt32(0, 0, 0), float scale = 1.0f) { // Convienient access to the vertices and indices const auto& vecIndices = surfaceMesh.getIndices(); @@ -83,7 +83,7 @@ OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::Vertex< uint8_t // The GL_ARRAY_BUFFER will contain the list of vertex positions glGenBuffers(1, &(meshData.vertexBuffer)); glBindBuffer(GL_ARRAY_BUFFER, meshData.vertexBuffer); - glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(Vertex< uint8_t >), vecVertices.data(), GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(MarchingCubesVertex< uint8_t >), vecVertices.data(), GL_STATIC_DRAW); // and GL_ELEMENT_ARRAY_BUFFER will contain the indices glGenBuffers(1, &(meshData.indexBuffer)); @@ -92,20 +92,20 @@ OpenGLMeshData buildOpenGLMeshData(const PolyVox::Mesh< PolyVox::Vertex< uint8_t // Every surface extractor outputs valid positions for the vertices, so tell OpenGL how these are laid out glEnableVertexAttribArray(0); // Attrib '0' is the vertex positions - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex< uint8_t >), (GLvoid*)(offsetof(Vertex< uint8_t >, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) + glVertexAttribIPointer(0, 3, GL_UNSIGNED_SHORT, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, position))); //take the first 3 floats from every sizeof(decltype(vecVertices)::value_type) // Some surface extractors also generate normals, so tell OpenGL how these are laid out. If a surface extractor // does not generate normals then nonsense values are written into the buffer here and sghould be ignored by the // shader. This is mostly just to simplify this example code - in a real application you will know whether your // chosen surface extractor generates normals and can skip uploading them if not. glEnableVertexAttribArray(1); // Attrib '1' is the vertex normals. - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex< uint8_t >), (GLvoid*)(offsetof(Vertex< uint8_t >, normal))); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, normal))); // Finally a surface extractor will probably output additional data. This is highly application dependant. For this example code // we're just uploading it as a set of bytes which we can read individually, but real code will want to do something specialised here. glEnableVertexAttribArray(2); //We're talking about shader attribute '2' GLint size = (std::min)(sizeof(uint8_t), size_t(4)); // Can't upload more that 4 components (vec4 is GLSL's biggest type) - glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(Vertex< uint8_t >), (GLvoid*)(offsetof(Vertex< uint8_t >, data))); + glVertexAttribIPointer(2, size, GL_UNSIGNED_BYTE, sizeof(MarchingCubesVertex< uint8_t >), (GLvoid*)(offsetof(MarchingCubesVertex< uint8_t >, data))); // We're done uploading and can now unbind. glBindVertexArray(0); @@ -133,12 +133,16 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } + std::cout << shader->log().toStdString() << std::endl; + if (!shader->addShaderFromSourceFile(QGLShader::Fragment, ":/decode.frag")) { std::cerr << shader->log().toStdString() << std::endl; exit(EXIT_FAILURE); } + std::cout << shader->log().toStdString() << std::endl; + openGLWidget.setShader(shader); //Create an empty volume and then place a sphere in it @@ -146,15 +150,15 @@ int main(int argc, char *argv[]) createSphereInVolume(volData, 30); // Extract the surface for the specified region of the volume. Uncomment the line for the kind of surface extraction you want to see. - auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion()); - //auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion()); + //auto mesh = extractCubicMesh(&volData, volData.getEnclosingRegion()); + auto mesh = extractMarchingCubesMesh(&volData, volData.getEnclosingRegion()); // The surface extractor outputs the mesh in an efficient compressed format which is not directly suitable for rendering. The easiest approach is to // decode this on the CPU as shown below, though more advanced applications can upload the compressed mesh to the GPU and decompress in shader code. - auto decodedMesh = decode(mesh); + //auto decodedMesh = decode(mesh); //Pass the surface to the OpenGL window - OpenGLMeshData meshData = buildOpenGLMeshData(decodedMesh); + OpenGLMeshData meshData = buildOpenGLMeshData(mesh); openGLWidget.addMeshData(meshData); openGLWidget.setViewableRegion(volData.getEnclosingRegion()); diff --git a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl index 1b50431e..3fedba49 100644 --- a/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl +++ b/library/PolyVoxCore/include/PolyVoxCore/MarchingCubesSurfaceExtractor.inl @@ -446,7 +446,7 @@ namespace PolyVox const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v100) - m_controller.convertToDensity(v000)); const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()) + fInterp, static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()), static_cast(iZVolSpace - m_regSizeInCells.getLowerZ())); - const Vector3DUint16 v3dPositionAsUint(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); + const Vector3DUint16 v3dScaledPosition(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); Vector3DFloat v3dNormal = (n100*fInterp) + (n000*(1-fInterp)); @@ -461,7 +461,7 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v100, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dPositionAsUint; + surfaceVertex.position = v3dScaledPosition; surfaceVertex.normal = v3dNormal; surfaceVertex.data = uMaterial; @@ -480,7 +480,7 @@ namespace PolyVox const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v010) - m_controller.convertToDensity(v000)); const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()), static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()) + fInterp, static_cast(iZVolSpace - m_regSizeInVoxels.getLowerZ())); - const Vector3DUint16 v3dPositionAsUint(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); + const Vector3DUint16 v3dScaledPosition(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); Vector3DFloat v3dNormal = (n010*fInterp) + (n000*(1-fInterp)); @@ -495,7 +495,7 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v010, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dPositionAsUint; + surfaceVertex.position = v3dScaledPosition; surfaceVertex.normal = v3dNormal; surfaceVertex.data = uMaterial; @@ -514,7 +514,7 @@ namespace PolyVox const float fInterp = static_cast(m_tThreshold - m_controller.convertToDensity(v000)) / static_cast(m_controller.convertToDensity(v001) - m_controller.convertToDensity(v000)); const Vector3DFloat v3dPosition(static_cast(iXVolSpace - m_regSizeInVoxels.getLowerX()), static_cast(iYVolSpace - m_regSizeInVoxels.getLowerY()), static_cast(iZVolSpace - m_regSizeInVoxels.getLowerZ()) + fInterp); - const Vector3DUint16 v3dPositionAsUint(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); + const Vector3DUint16 v3dScaledPosition(static_cast(v3dPosition.getX() * 256.0f), static_cast(v3dPosition.getY() * 256.0f), static_cast(v3dPosition.getZ() * 256.0f)); Vector3DFloat v3dNormal = (n001*fInterp) + (n000*(1-fInterp)); // The gradient for a voxel can be zero (e.g. solid voxel surrounded by empty ones) and so @@ -528,7 +528,7 @@ namespace PolyVox const typename VolumeType::VoxelType uMaterial = m_controller.blendMaterials(v000, v001, fInterp); MarchingCubesVertex surfaceVertex; - surfaceVertex.position = v3dPositionAsUint; + surfaceVertex.position = v3dScaledPosition; surfaceVertex.normal = v3dNormal; surfaceVertex.data = uMaterial;