Commit df326e74 authored by Nicholas Milef's avatar Nicholas Milef

ENH: Added custom mapper class and restructured light classes

parent 29ba2ab1
......@@ -154,7 +154,8 @@ Mesh::setVertexDisplacements(const Vectord& u)
m_transformApplied = false;
}
void Mesh::translateVertices(const Vec3d& t)
void
Mesh::translateVertices(const Vec3d& t)
{
for (size_t i = 0; i < m_vertexPositions.size(); ++i)
{
......@@ -200,7 +201,7 @@ Mesh::getPointDataArray(const std::string& arrayName) const
return &(it->second);
}
const size_t
size_t
Mesh::getNumVertices() const
{
return m_initialVertexPositions.size();
......
......@@ -136,7 +136,7 @@ public:
///
/// \brief Returns the number of total vertices in the mesh
///
const size_t getNumVertices() const;
size_t getNumVertices() const;
///
/// \brief Set the topologyChanged flag
......
......@@ -116,7 +116,7 @@ AssimpMeshIO::readMeshData(const std::string& filePath)
}
}
if (importedMesh->HasTangentsAndBitangents())
if (importedMesh->HasTangentsAndBitangents() && importedMesh->HasTextureCoords(0))
{
for (unsigned int i = 0; i < numVertices; i++)
{
......@@ -136,7 +136,7 @@ AssimpMeshIO::readMeshData(const std::string& filePath)
mesh->setVertexTangents(tangents);
mesh->setVertexBitangents(bitangents);
// UV coordinates normals
// UV coordinates
StdVectorOfVectorf UVs(numVertices);
if (importedMesh->HasTextureCoords(0))
{
......
......@@ -32,7 +32,7 @@ RenderMaterial::RenderMaterial()
}
}
const RenderMaterial::DisplayMode
RenderMaterial::DisplayMode
RenderMaterial::getDisplayMode() const
{
return m_displayMode;
......@@ -50,7 +50,7 @@ RenderMaterial::setDisplayMode(const DisplayMode displayMode)
m_modified = true;
}
const float
float
RenderMaterial::getLineWidth() const
{
return m_lineWidth;
......@@ -68,7 +68,7 @@ RenderMaterial::setLineWidth(const float width)
m_modified = true;
}
const float
float
RenderMaterial::getPointSize() const
{
return m_pointSize;
......@@ -86,7 +86,7 @@ RenderMaterial::setPointSize(const float size)
m_modified = true;
}
const bool
bool
RenderMaterial::getBackFaceCulling() const
{
return m_backfaceCulling;
......@@ -129,29 +129,28 @@ RenderMaterial::setDiffuseColor(const Color color)
m_modified = true;
}
const Color&
RenderMaterial::getSpecularColor() const
const float&
RenderMaterial::getMetalness() const
{
return m_specularColor;
return m_metalness;
}
void
RenderMaterial::setSpecularColor(const Color color)
RenderMaterial::setMetalness(const float metalness)
{
m_specularColor = color;
m_modified = true;
m_metalness = metalness;
}
const float&
RenderMaterial::getSpecularity() const
RenderMaterial::getRoughness() const
{
return m_specularity;
return m_roughness;
}
void
RenderMaterial::setSpecularity(const float specularity)
RenderMaterial::setRoughness(const float roughness)
{
m_specularity = specularity;
m_roughness = roughness;
}
std::shared_ptr<Texture>
......
......@@ -52,25 +52,25 @@ public:
///
/// \brief Get/Set display mode
///
const DisplayMode getDisplayMode() const;
DisplayMode getDisplayMode() const;
void setDisplayMode(const DisplayMode displayMode);
///
/// \brief Get/Set line width or the wireframe
///
const float getLineWidth() const;
float getLineWidth() const;
void setLineWidth(const float width);
///
/// \brief Get/Set point size
///
const float getPointSize() const;
float getPointSize() const;
void setPointSize(const float size);
///
/// \brief Backface culling on/off
///
const bool getBackFaceCulling() const;
bool getBackFaceCulling() const;
void setBackFaceCulling(const bool culling);
void backfaceCullingOn();
void backfaceCullingOff();
......@@ -82,16 +82,16 @@ public:
void setDiffuseColor(const Color color);
///
/// \brief Get/Set the specular color (only set for metals)
/// \brief Get/Set the metalness
///
const Color& getSpecularColor() const;
void setSpecularColor(const Color color);
const float& getMetalness() const;
void setMetalness(const float metalness);
///
/// \brief Get/Set the specularity
/// \brief Get/Set the roughness
///
const float& getSpecularity() const;
void setSpecularity(const float specularity);
const float& getRoughness() const;
void setRoughness(const float roughness);
///
/// \brief Add/Get texture
......@@ -123,10 +123,10 @@ protected:
// Colors
Color m_diffuseColor = Color::White;
Color m_specularColor = Color::Black;
// Classical values
float m_specularity = 0.0; ///< Not shiny by default
float m_metalness = 0.0; ///< Value for metalness with range: [0.0, 1.0]
float m_roughness = 0.0; ///< Value for roughness with range: [0.0, 1.0]
// Textures
std::vector<std::shared_ptr<Texture>> m_textures; ///< Ordered by Texture::Type
......
......@@ -29,7 +29,7 @@ Texture::Texture(std::string path, Type type)
m_type = type;
}
const Texture::Type
Texture::Type
Texture::getType() const
{
return m_type;
......
......@@ -67,7 +67,7 @@ public:
///
/// \brief Get type
///
const Type getType() const;
Type getType() const;
///
/// \brief Get path
......
......@@ -6,6 +6,7 @@ imstk_add_library( Rendering
H_FILES
imstkVTKRenderer.h
imstkVTKTextureDelegate.h
imstkVTKCustomPolyDataMapper.h
RenderDelegate/imstkVTKCubeRenderDelegate.h
RenderDelegate/imstkVTKLineMeshRenderDelegate.h
RenderDelegate/imstkVTKPlaneRenderDelegate.h
......@@ -21,6 +22,7 @@ imstk_add_library( Rendering
CPP_FILES
imstkVTKRenderer.cpp
imstkVTKTextureDelegate.cpp
imstkVTKCustomPolyDataMapper.cpp
RenderDelegate/imstkVTKCubeRenderDelegate.cpp
RenderDelegate/imstkVTKLineMeshRenderDelegate.cpp
RenderDelegate/imstkVTKPlaneRenderDelegate.cpp
......
......@@ -41,7 +41,7 @@ VTKCapsuleRenderDelegate::VTKCapsuleRenderDelegate(std::shared_ptr<Capsule> caps
m_transformFilter->SetTransform(vtkSmartPointer<vtkTransform>::New());
this->update();
this->setUpMapper(m_transformFilter->GetOutputPort(), true);
this->setUpMapper(m_transformFilter->GetOutputPort(), true, m_geometry);
}
void
......
......@@ -39,7 +39,7 @@ VTKCubeRenderDelegate::VTKCubeRenderDelegate(std::shared_ptr<Cube> cube) :
m_transformFilter->SetTransform(vtkSmartPointer<vtkTransform>::New());
this->update();
this->setUpMapper(m_transformFilter->GetOutputPort(), true);
this->setUpMapper(m_transformFilter->GetOutputPort(), true, m_geometry);
}
void
......
......@@ -38,7 +38,7 @@ VTKCylinderRenderDelegate::VTKCylinderRenderDelegate(std::shared_ptr<Cylinder> c
m_transformFilter->SetTransform(vtkSmartPointer<vtkTransform>::New());
this->update();
this->setUpMapper(m_transformFilter->GetOutputPort(), true);
this->setUpMapper(m_transformFilter->GetOutputPort(), true, m_geometry);
}
void
......
......@@ -51,7 +51,7 @@ VTKLineMeshRenderDelegate::VTKLineMeshRenderDelegate(std::shared_ptr<LineMesh> l
m_geometry->m_dataModified = false;
// Setup Mapper & Actor
this->setUpMapper(lines->GetOutputPort(), true);
this->setUpMapper(lines->GetOutputPort(), true, m_geometry);
// Update Transform, Render Properties
this->update();
......
......@@ -37,7 +37,7 @@ VTKPlaneRenderDelegate::VTKPlaneRenderDelegate(std::shared_ptr<Plane>plane) :
m_transformFilter->SetTransform(vtkSmartPointer<vtkTransform>::New());
this->update();
this->setUpMapper(m_transformFilter->GetOutputPort(), true);
this->setUpMapper(m_transformFilter->GetOutputPort(), true, m_geometry);
}
void
......
......@@ -111,7 +111,9 @@ VTKRenderDelegate::make_delegate(std::shared_ptr<Geometry> geom)
}
void
VTKRenderDelegate::setUpMapper(vtkAlgorithmOutput *source, const bool rigid)
VTKRenderDelegate::setUpMapper(vtkAlgorithmOutput *source,
const bool rigid,
std::shared_ptr<Geometry> geometry)
{
// Add normals
vtkSmartPointer<vtkPolyDataAlgorithm> normalGen;
......@@ -130,9 +132,16 @@ VTKRenderDelegate::setUpMapper(vtkAlgorithmOutput *source, const bool rigid)
// Disable auto Shift & Scale which is slow for deformable objects
// as it needs to compute a bounding box at every frame
if(auto mapper = vtkOpenGLPolyDataMapper::SafeDownCast(m_mapper.GetPointer()))
if(auto mapper = VTKCustomPolyDataMapper::SafeDownCast(m_mapper.GetPointer()))
{
mapper->SetVBOShiftScaleMethod(vtkOpenGLVertexBufferObject::DISABLE_SHIFT_SCALE);
if (!geometry->getRenderMaterial())
{
geometry->setRenderMaterial(std::make_shared<RenderMaterial>());
}
mapper->setGeometry(geometry);
}
}
......@@ -179,12 +188,7 @@ VTKRenderDelegate::updateActorProperties()
// Colors & Light
auto diffuseColor = material->m_diffuseColor;
auto specularColor = material->m_specularColor;
auto specularity = material->m_specularity;
actorProperty->SetDiffuseColor(diffuseColor.r, diffuseColor.g, diffuseColor.b);
actorProperty->SetSpecularColor(specularColor.r, specularColor.g, specularColor.b);
actorProperty->SetSpecularPower(specularity);
actorProperty->SetSpecular(1.0);
// Material state is now up to date
material->m_modified = false;
......
......@@ -28,6 +28,7 @@
#include "imstkRenderMaterial.h"
#include "imstkVTKTextureDelegate.h"
#include "imstkTextureManager.h"
#include "imstkVTKCustomPolyDataMapper.h"
#include "vtkSmartPointer.h"
#include "vtkAlgorithmOutput.h"
......@@ -60,7 +61,9 @@ public:
///
/// \brief Set up normals and mapper
///
void setUpMapper(vtkAlgorithmOutput *source, const bool rigid);
void setUpMapper(vtkAlgorithmOutput *source,
const bool rigid,
std::shared_ptr<Geometry> geometry);
///
/// \brief Return geometry to render
......@@ -99,14 +102,14 @@ protected:
VTKRenderDelegate()
{
m_actor = vtkSmartPointer<vtkActor>::New();
m_mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
m_mapper = vtkSmartPointer<VTKCustomPolyDataMapper>::New();
m_transform = vtkSmartPointer<vtkTransform>::New();
m_actor->SetMapper(m_mapper);
m_actor->SetUserTransform(m_transform);
}
vtkSmartPointer<vtkActor> m_actor;
vtkSmartPointer<vtkPolyDataMapper> m_mapper;
vtkSmartPointer<VTKCustomPolyDataMapper> m_mapper;
vtkSmartPointer<vtkTransform> m_transform;
};
}
......
......@@ -39,7 +39,7 @@ VTKSphereRenderDelegate::VTKSphereRenderDelegate(std::shared_ptr<Sphere>sphere)
m_transformFilter->SetTransform(vtkSmartPointer<vtkTransform>::New());
this->update();
this->setUpMapper(m_transformFilter->GetOutputPort(), true);
this->setUpMapper(m_transformFilter->GetOutputPort(), true, m_geometry);
}
void
......
......@@ -109,9 +109,26 @@ VTKSurfaceMeshRenderDelegate::VTKSurfaceMeshRenderDelegate(std::shared_ptr<Surfa
}
}
// Update tangents
if (m_geometry->getVertexTangents().size() > 0)
{
auto tangents = vtkSmartPointer<vtkFloatArray>::New();
tangents->SetName("tangents");
tangents->SetNumberOfComponents(3);
for (auto const tangent : m_geometry->getVertexTangents())
{
float tempTangent[3] = {(float)tangent[0],
(float)tangent[1],
(float)tangent[2]};
tangents->InsertNextTuple(tempTangent);
}
polydata->GetPointData()->AddArray(tangents);
}
// Update Transform, Render Properties
this->update();
this->setUpMapper(source->GetOutputPort(), false);
this->setUpMapper(source->GetOutputPort(), false, m_geometry);
}
void
......@@ -136,6 +153,8 @@ VTKSurfaceMeshRenderDelegate::initializeTextures(TextureManager<VTKTextureDelega
return;
}
unsigned int currentUnit = 0;
// Go through all of the textures
for (int unit = 0; unit < Texture::Type::NONE; unit++)
{
......@@ -165,7 +184,8 @@ VTKSurfaceMeshRenderDelegate::initializeTextures(TextureManager<VTKTextureDelega
*/
// Set texture
m_actor->GetProperty()->SetTexture(unit, textureDelegate->getTexture());
m_actor->GetProperty()->SetTexture(currentUnit, textureDelegate->getTexture());
currentUnit++;
}
}
......
out vec4 gl_FragData[0];
uniform vec3 cameraPosition = vec3(0, 0, 1);
uniform int numLights = 0;
in Vertex
{
vec3 position;
vec3 normal;
vec2 uv;
} vertex;
// Lights
uniform vec3 lightPosition[16];
uniform int lightType[16];
uniform vec4 lightColor[16];
uniform vec4 lightDirection[16];
// Textures
#ifdef SHADED
uniform sampler2D diffuseTexture;
uniform samplerCube cubemapTexture;
#endif
// Material properties
uniform float metalness = 0;
uniform float roughness = 1.0;
// Colors
vec3 diffuseColor = vec3(1);
vec3 reflectionColor = vec3(1);
vec3 specularColor = vec3(0);
vec3 finalSpecular = vec3(0);
vec3 finalDiffuse = vec3(0);
vec3 finalColor = vec3(0);
// Other information
vec3 normal = vec3(0, 0, 1);
vec3 cameraDirection = vec3(0, 0, 1);
void calculateClassicalLighting(vec3 lightDirection, vec3 color, float intensity);
vec3 toneMap(vec3 color);
void main()
{
#ifdef SHADED
normal = normalize(vertex.normal);
cameraDirection = normalize(vertex.position - cameraPosition);
#ifdef DIFFUSE_TEXTURE
diffuseColor = pow(texture(diffuseTexture, vertex.uv).rgb, vec3(2.2));
#endif
#ifdef CUBEMAP_TEXTURE
reflectionColor = pow(texture(cubemapTexture, reflect(cameraDirection, normal)).rgb, vec3(2.2));
#endif
specularColor = mix(vec3(1), diffuseColor, metalness);
diffuseColor = mix(diffuseColor, reflectionColor * diffuseColor, metalness);
float lightIntensity = 0;
vec3 lightDir = vec3(0);
for (int i = 0; i < numLights; i++)
{
if (lightType[i] > 1)
{
lightDir = vertex.position.xyz - lightPosition[i];
float distance_squared = dot(lightDir, lightDir);
lightIntensity = lightColor[i].a / distance_squared;
if (lightType[i] == 3)
{
if (lightDirection[i].a > dot(normalize(lightDir), normalize(lightDirection[i].xyz)))
{
lightIntensity = 0;
}
}
}
else
{
lightDir = lightDirection[i].xyz;
lightIntensity = lightColor[i].a;
}
calculateClassicalLighting(normalize(lightDir),
lightColor[i].rgb, lightIntensity);
}
// Sum components and apply gamma correction
finalColor = mix(0.5, 1.0, roughness) * finalDiffuse + mix(0.5, 0.0, roughness) * finalSpecular;
// Apply tone mapping
finalColor = toneMap(finalColor);
gl_FragData[0] = vec4(pow(finalColor, vec3(1.0 / 2.2)), 1);
#else
gl_FragData[0] = vec4(0, 0, 0, 1);
#endif
}
void calculateClassicalLighting(vec3 lightDirection, vec3 lightColor, float lightIntensity)
{
float diffusePow = max(dot(normal, -lightDirection), 0.0);
finalDiffuse += max(lightColor * lightIntensity * diffuseColor * diffusePow, 0.0);
vec3 halfway = normalize(-cameraDirection - lightDirection);
float specularPow = max(dot(normal, halfway), 0.0);
finalSpecular += specularColor * lightColor * lightIntensity * vec3(pow(specularPow, (1.0 - roughness) * 100.0));
}
// Reinhard tonemapping
vec3 toneMap(vec3 color)
{
float luminance = dot(color, vec3(.21, .72, .07));
return (luminance / (luminance + vec3(1.0))) * color;
}
\ No newline at end of file
// Matrices
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
uniform mat3 normalMatrix;
in vec3 inputPosition;
in vec3 inputNormal;
in vec3 inputTangent;
in vec2 inputUV;
out Vertex
{
vec3 position;
vec3 normal;
vec2 uv;
} vertex;
void main()
{
mat3 rotationMatrix = mat3(normalMatrix);
vertex.normal = normalize(rotationMatrix * normalize(inputNormal));
vec3 position = vec3(modelMatrix * vec4(inputPosition, 1));
vertex.uv = inputUV;
vertex.position = position;
gl_Position = projectionMatrix * viewMatrix * vec4(position, 1);
}
\ No newline at end of file
/*=========================================================================
Library: iMSTK
Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
& Imaging in Medicine, Rensselaer Polytechnic Institute.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=========================================================================*/
#include "imstkVTKCustomPolyDataMapper.h"
namespace imstk
{
vtkStandardNewMacro(VTKCustomPolyDataMapper);
void
VTKCustomPolyDataMapper::BuildBufferObjects(vtkRenderer * renderer, vtkActor * actor)
{
auto polyData = this->GetInput();
auto renderWindow = (vtkOpenGLRenderWindow*)renderer->GetRenderWindow();
auto VBOCache = renderWindow->GetVBOCache();
this->VBOs->CacheDataArray("inputPosition", polyData->GetPoints()->GetData(), VBOCache, VTK_FLOAT);
this->VBOs->CacheDataArray("inputNormal", polyData->GetPointData()->GetNormals(), VBOCache, VTK_FLOAT);
this->VBOs->CacheDataArray("inputUV", polyData->GetPointData()->GetTCoords(), VBOCache, VTK_FLOAT);
if (polyData->GetPointData()->GetArray("tangents"))
{
this->VBOs->CacheDataArray("inputTangent", polyData->GetPointData()->GetArray("tangents"), VBOCache, VTK_FLOAT);
}
this->VBOs->BuildAllVBOs(VBOCache);
this->BuildIBO(renderer, actor, polyData);
this->VBOBuildTime.Modified();
}
void
VTKCustomPolyDataMapper::ReplaceShaderValues(
std::map<vtkShader::Type, vtkShader*> vtkNotUsed(shaders),
vtkRenderer * vtkNotUsed(renderer),
vtkActor * vtkNotUsed(actor))
{
}
void
VTKCustomPolyDataMapper::GetShaderTemplate(
std::map<vtkShader::Type, vtkShader*> shaders,
vtkRenderer * vtkNotUsed(renderer),
vtkActor * actor)
{
this->loadShader("./Shaders/VTKShaders/mesh.vert", m_vertexShaderSource);
this->loadShader("./Shaders/VTKShaders/mesh.frag", m_fragmentShaderSource);
auto renderMaterial = m_geometry->getRenderMaterial();
auto diffuseTexture = renderMaterial->getTexture(Texture::DIFFUSE);
auto cubemapTexture = renderMaterial->getTexture(Texture::CUBEMAP);
auto surfaceMesh = std::dynamic_pointer_cast<SurfaceMesh>(m_geometry);
if (this->GetOpenGLMode(actor->GetProperty()->GetRepresentation(), this->LastBoundBO->PrimitiveType) == GL_TRIANGLES)
{
m_fragmentShaderSource = "#define SHADED\n" + m_fragmentShaderSource;
}
if (diffuseTexture->getPath() != "" && surfaceMesh)
{
m_fragmentShaderSource = "#define DIFFUSE_TEXTURE\n" + m_fragmentShaderSource;
}
if (cubemapTexture->getPath() != "" && surfaceMesh)
{
m_fragmentShaderSource = "#define CUBEMAP_TEXTURE\n" + m_fragmentShaderSource;
}
m_vertexShaderSource = "#version 330\n" + m_vertexShaderSource;
m_fragmentShaderSource = "#version 330\n" + m_fragmentShaderSource;
shaders[vtkShader::Vertex]->SetSource(m_vertexShaderSource.c_str());
shaders[vtkShader::Fragment]->SetSource(m_fragmentShaderSource.c_str());
}
void
VTKCustomPolyDataMapper::SetMapperShaderParameters(
vtkOpenGLHelper& helper,
vtkRenderer * renderer,
vtkActor * actor)
{
auto textures = this->GetTextures(actor);
helper.VAO->Bind();
this->VBOs->AddAllAttributesToVAO(helper.Program, helper.VAO);
auto camera = renderer->GetActiveCamera();
vtkMatrix4x4 * viewMatrix;
vtkMatrix4x4 * projectionMatrix;
vtkMatrix3x3 * rotationMatrix;
vtkMatrix4x4 * viewProjectionMatrix;
vtkMatrix3x3 * modelRotationMatrix;
vtkMatrix4x4 * modelMatrix;
((vtkOpenGLCamera*)camera)->GetKeyMatrices(renderer, viewMatrix, rotationMatrix, projectionMatrix, viewProjectionMatrix);
((vtkOpenGLActor*)actor)->GetKeyMatrices(modelMatrix, modelRotationMatrix);
// Per renderer: 16 light limit for iMSTK, VTK supports 6
float lightPosition[16][3]; // 3 float position
int lightType[16]; // 1 bool directional vs. point light
float lightColor[16][4]; // 3 float color, 1 float intensity
float lightDirection[16][4]; // 3 float direction, 1 float angle
auto lights = renderer->GetLights();
lights->InitTraversal();
for (unsigned int i = 0; i < 16; i++)
{
auto light = lights->GetNextItem();
if (light)
{
lightPosition[i][0] = light->GetPosition()[0];
lightPosition[i][1] = light->GetPosition()[1];
lightPosition[i][2] = light->GetPosition()[2];
if (light->GetPositional())
{
lightType[i] = 2;
if (light->GetConeAngle() < 178.0)
{
lightType[i] = 3;
}
}
else
{
lightType[i] = 1;
}
lightColor[i][0] = light->GetDiffuseColor()[0];
lightColor[i][1] = light->GetDiffuseColor()[1];
lightColor[i][2] = light->GetDiffuseColor()[2];
lightColor[i][3] = light->GetIntensity();