Skip to content
Snippets Groups Projects
Commit 39bade97 authored by Mathias Paulin's avatar Mathias Paulin :speech_balloon:
Browse files

Add envmap to the visualization renderer.

parent 6f613be5
No related branches found
No related tags found
No related merge requests found
......@@ -166,16 +166,23 @@ const std::string customGeomAttrib{"in vec4 geomCustomAttrib[];\n"
* add an edition widget as in Radium app demo
*/
const std::string customFragmentColor{
"in vec4 fragCustomAttrib;\n"
"\nvec4 computeCustomColor(Material mat, vec3 lightDir, vec3 viewDir, vec3 normal_world) {\n"
"in vec4 fragCustomAttrib;"
"\nvec4 computeCustomColor(Material mat, vec3 lightDir, vec3 viewDir, vec3 normal_world) { \n"
"vec3 diffColor; \n"
"vec3 specColor; \n"
"getSeparateBSDFComponent( mat, getPerVertexTexCoord(), lightDir, viewDir,\n"
"vec3(0, 0, 1), diffColor, specColor );\n"
"vec3 col = normal_world*0.5+0.5;\n"
"col *= fragCustomAttrib.rgb;\n"
"return vec4( (specColor+col)*max(lightDir.z, 0), 1); \n"
"}\n"};
"vec3 envd;\n"
"vec3 envs;\n"
"int e = getEnvMapColors(mat, normal_world, envd, envs);"
"vec3 finalColor = normal_world*0.5+0.5;\n"
"finalColor *= fragCustomAttrib.rgb;\n"
"if (e==1) { finalColor = finalColor*envd + specColor*envs; }\n"
"else { finalColor = (finalColor + specColor) * max(lightDir.z, 0) \n"
" * lightContributionFrom(light, getWorldSpacePosition().xyz); }\n"
"return vec4( finalColor, 1); \n"
"}\n"
};
/**
* Main code to demonstrate the use of a self configured node based renderer
......
......@@ -50,6 +50,34 @@ buildControllerGui( NodeBasedRenderer* renderer, const std::function<void()>& ap
false );
controlPanel->endLayout( true );
controlPanel->beginLayout( QBoxLayout::LeftToRight );
auto envmpClbck = [&controller, appUpdateCallback]( const std::string& files ) {
controller.setEnvMap( files );
appUpdateCallback();
};
controlPanel->addFileInput(
"Environment map", envmpClbck, "../", "Images (*.png *.jpg *.pfm *.exr *hdr)" );
controlPanel->beginLayout( QBoxLayout::TopToBottom );
controlPanel->addOption(
" Show envMap ",
[&controller, appUpdateCallback]( bool b ) {
controller.showEnvMap( b );
appUpdateCallback();
},
true );
controlPanel->addSliderInput(
" Environment strength ",
[&controller, appUpdateCallback]( int v ) {
controller.setEnvStrength( v );
appUpdateCallback();
},
100 );
controlPanel->endLayout();
controlPanel->endLayout( true );
// TODO : add a double slider to get the good value. ask @dlyr for its doubleSliderClass ...
controlPanel->beginLayout( QBoxLayout::LeftToRight );
auto splatSizeCtrl = [&controller]( double v ) { controller.setSplatSize( v ); };
......
......@@ -19,6 +19,35 @@ using namespace Ra::Core::Utils; // log
namespace RadiumNBR {
using namespace gl;
// Envmap shader source
static const std::string noopEnvMapFunction{
"\nint getEnvMapColors(Material mat, vec3 normalWorld, out vec3 diffuse, out vec3 specular) {\n"
" diffuse = vec3(1); specular = vec3(1); return 0;\n"
"}\n\n"
};
static const std::string envMapFunction{
"\nuniform samplerCube envTexture;\n"
"uniform int numLod;\n"
"uniform mat4 redShCoeffs;\n"
"uniform mat4 greenShCoeffs;\n"
"uniform mat4 blueShCoeffs;\n"
"uniform float envStrength;\n"
"const float OneOverPi = 0.3183098862;\n"
"int getEnvMapColors(Material mat, vec3 normalWorld, out vec3 diffuse, out vec3 specular) {\n"
" vec3 view = normalize(in_viewVector);\n"
" vec3 rfl = reflect(-view, normalWorld.xyz);\n"
" vec4 up = vec4(normalWorld, 1);\n"
" diffuse.r = dot(up, redShCoeffs * up);\n"
" diffuse.g = dot(up, greenShCoeffs * up);\n"
" diffuse.b = dot(up, blueShCoeffs * up);\n"
" diffuse *= envStrength/OneOverPi;\n"
" float cosTi = clamp(dot(rfl, normalWorld), 0.001, 1.);\n"
" float r = getGGXRoughness(material, getPerVertexTexCoord()) * numLod;\n"
" specular = textureLod(envTexture, rfl, r).rgb * cosTi * envStrength;\n"
" return 1;\n"
"}\n\n"};
/* Test Point cloud parameter provider */
/*
* WARNING : this class is here only for testing and experimentation purpose.
......@@ -114,16 +143,23 @@ void CustomAttribToColorPass::execute(
glClearBufferfv( GL_DEPTH, 0, &clearDepth );
if ( m_envmap ) {
m_passParams.addParameter( "envStrength", m_envmap->getEnvStrength() );
}
// TODO : if an envmap is set, render with the envmap only ?
if ( m_lightmanager->count() > 0 )
{
// for ( const auto& l : m_lights )
for ( size_t i = 0; i < m_lightmanager->count(); ++i )
{
Ra::Engine::Data::RenderParameters passParams;
passParams.concatParameters( m_passParams );
const auto l = m_lightmanager->getLight( i );
l->getRenderParameters( passParams );
if (m_envmap) {
passParams.concatParameters( m_passParams );
}
for ( const auto& ro : *m_objectsToRender )
{
ro->render( passParams, viewParams, passIndex() );
......@@ -150,7 +186,7 @@ bool CustomAttribToColorPass::buildRenderTechnique(
{"CustomAtt2ClrPass::CustomColorProgram" + ro->getName()} ) )
{
rt.setConfiguration( *cfg, passIndex() );
// TODO : warning, the param provider might be erroneous
// TODO : is this really usefull ?
rt.setParametersProvider( mat, passIndex() );
}
else
......@@ -238,8 +274,14 @@ bool CustomAttribToColorPass::buildRenderTechnique(
ro->getName()};
theConfig.addShaderSource( Ra::Engine::Data::ShaderType::ShaderType_VERTEX,
vertexShaderSource + m_customVertexAttrib );
theConfig.addShaderSource( Ra::Engine::Data::ShaderType::ShaderType_FRAGMENT,
fragmentShadersource + m_customFragmentColor );
if ( m_envmap ) {
theConfig.addShaderSource( Ra::Engine::Data::ShaderType::ShaderType_FRAGMENT,
fragmentShadersource + envMapFunction + m_customFragmentColor );
} else {
theConfig.addShaderSource( Ra::Engine::Data::ShaderType::ShaderType_FRAGMENT,
fragmentShadersource + noopEnvMapFunction + m_customFragmentColor );
}
theConfig.addInclude( "\"" + mat->getMaterialName() + ".glsl\"",
Ra::Engine::Data::ShaderType::ShaderType_FRAGMENT );
......@@ -285,39 +327,39 @@ bool CustomAttribToColorPass::buildRenderTechnique(
"layout( location = 6 ) out vec3 out_lightVector;\n"
"void propagateAttributes();\n"
"void main() {\n"
"vec3 eye = -transform.view[3].xyz * mat3( transform.view );\n"
"// if no normal is provided, splats are aligned with the screen plane\n"
"vec3 normal = in_normal[0];\n"
"if ( length( normal ) < 0.1 ) { normal = normalize( eye - in_position[0] ); }\n"
"// orthonormal basis {u, v, normal}\n"
"vec3 u = vec3( 1, 0, 0 );\n"
"if ( abs( normal.x ) > 1e-3 ) { u = normalize( vec3( -normal.z / normal.x, 0, 1 ) ); }\n"
"vec3 v = normalize( cross( normal, u ) );\n"
"vec3 point[4];\n"
"point[0] = in_position[0] - pointCloudSplatRadius * ( u + v );\n"
"point[1] = point[0] + pointCloudSplatRadius * u * 2;\n"
"point[2] = point[0] + pointCloudSplatRadius * v * 2;\n"
"point[3] = point[0] + pointCloudSplatRadius * ( u + v ) * 2;\n"
"vec2 uv[4];\n"
"uv[0] = vec2( -1, -1 );\n"
"uv[1] = vec2( -1, +1 );\n"
"uv[2] = vec2( +1, -1 );\n"
"uv[3] = vec2( +1, +1 );\n"
"for ( int idx = 0; idx < 4; ++idx ) {\n"
" gl_Position = transform.proj * transform.view * vec4( point[idx], 1 );\n"
" out_position = point[idx];\n"
" out_texcoord = vec3( uv[idx], 0. );\n"
" out_normal = normal;\n"
" out_tangent = in_tangent[0];\n"
" out_viewVector = in_viewVector[0];\n"
" out_lightVector = in_lightVector[0];\n"
" out_vertexcolor = in_vertexColor[0];\n"
" propagateAttributes();"
" EmitVertex();\n"
"}\n"
"EndPrimitive();\n"
"vec3 eye = -transform.view[3].xyz * mat3( transform.view );\n"
"// if no normal is provided, splats are aligned with the screen plane\n"
"vec3 normal = in_normal[0];\n"
"if ( length( normal ) < 0.1 ) { normal = normalize( eye - in_position[0] ); }\n"
"// orthonormal basis {u, v, normal}\n"
"vec3 u = vec3( 1, 0, 0 );\n"
"if ( abs( normal.x ) > 1e-3 ) { u = normalize( vec3( -normal.z / normal.x, 0, 1 ) ); "
"}\n"
};
"vec3 v = normalize( cross( normal, u ) );\n"
"vec3 point[4];\n"
"point[0] = in_position[0] - pointCloudSplatRadius * ( u + v );\n"
"point[1] = point[0] + pointCloudSplatRadius * u * 2;\n"
"point[2] = point[0] + pointCloudSplatRadius * v * 2;\n"
"point[3] = point[0] + pointCloudSplatRadius * ( u + v ) * 2;\n"
"vec2 uv[4];\n"
"uv[0] = vec2( -1, -1 );\n"
"uv[1] = vec2( -1, +1 );\n"
"uv[2] = vec2( +1, -1 );\n"
"uv[3] = vec2( +1, +1 );\n"
"for ( int idx = 0; idx < 4; ++idx ) {\n"
" gl_Position = transform.proj * transform.view * vec4( point[idx], 1 );\n"
" out_position = point[idx];\n"
" out_texcoord = vec3( uv[idx], 0. );\n"
" out_normal = normal;\n"
" out_tangent = in_tangent[0];\n"
" out_viewVector = in_viewVector[0];\n"
" out_lightVector = in_lightVector[0];\n"
" out_vertexcolor = in_vertexColor[0];\n"
" propagateAttributes();"
" EmitVertex();\n"
"}\n"
"EndPrimitive();\n"
"}\n"};
auto pointCloudConst =
dynamic_cast<const Ra::Engine::Scene::PointCloudComponent*>( ro->getComponent() );
......@@ -328,7 +370,7 @@ bool CustomAttribToColorPass::buildRenderTechnique(
geometryShadersource + m_customGeometryAttrib );
// construct the parameter provider for the technique
paramProvider = std::make_shared<PointCloudParameterProvider>( mat, pointCloud );
pointCloud->setSplatSize(0.025);
pointCloud->setSplatSize( 0.025 );
}
// Add to the ShaderConfigManager
Ra::Engine::Data::ShaderConfigurationFactory::addConfiguration( theConfig );
......@@ -343,8 +385,8 @@ bool CustomAttribToColorPass::buildRenderTechnique(
void CustomAttribToColorPass::setAttribToColorFunc( const std::string& vertex_source,
const std::string& geometry_source,
const std::string& fragment_source ) {
m_customVertexAttrib = vertex_source;
m_customFragmentColor = fragment_source;
m_customVertexAttrib = vertex_source;
m_customFragmentColor = fragment_source;
m_customGeometryAttrib = geometry_source;
rebuildShaders();
}
......@@ -363,14 +405,32 @@ void CustomAttribToColorPass::rebuildShaders() {
m_needConfigRebuild = false;
}
void CustomAttribToColorPass::setSplatSize(float s) {
void CustomAttribToColorPass::setSplatSize( float s ) {
m_splatsSize = s;
for ( auto ro : *m_objectsToRender ) {
for ( auto ro : *m_objectsToRender )
{
auto pointCloud =
dynamic_cast<Ra::Engine::Scene::PointCloudComponent*>( ro->getComponent() );
if ( pointCloud ) {
pointCloud->setSplatSize( m_splatsSize );
}
if ( pointCloud ) { pointCloud->setSplatSize( m_splatsSize ); }
}
}
void CustomAttribToColorPass::setEnvMap( std::shared_ptr<EnvMap> envmp ) {
m_envmap = envmp;
if ( m_envmap )
{
// Set the envmap parameter once.
// Warning : there is no way to remove parameters. Might segfault if this is not consistent
// with rendering usage
m_passParams.addParameter( "redShCoeffs", m_envmap->getShMatrix( 0 ) );
m_passParams.addParameter( "greenShCoeffs", m_envmap->getShMatrix( 1 ) );
m_passParams.addParameter( "blueShCoeffs", m_envmap->getShMatrix( 2 ) );
m_passParams.addParameter( "envTexture", m_envmap->getEnvTexture() );
int numLod = std::log2(
std::min( m_envmap->getEnvTexture()->width(), m_envmap->getEnvTexture()->height() ) );
m_passParams.addParameter( "numLod", numLod );
}
rebuildShaders();
}
} // namespace RadiumNBR
#pragma once
#include <RadiumNBR/RenderPass.hpp>
#include <RadiumNBR/EnvMap.hpp>
#include <Core/Utils/Color.hpp>
......@@ -53,9 +54,24 @@ class CustomAttribToColorPass : public RenderPass
/// Set the splat size for pointclouds
inline float getSplatSize() { return m_splatsSize; }
// return the splatSize used for point clouds
/// return the splatSize used for point clouds
void setSplatSize(float s);
/// set the env map to use
void setEnvMap( std::shared_ptr<EnvMap> envmp );
/// set the strength (aka "power") of the env map
void setEnvStrength( int s ) {
if ( m_envmap )
{
m_envStrength = float( s ) / 100.f;
m_envmap->setEnvStrength( m_envStrength );
}
}
/// get the strength (aka "power") of the env map
int getEnvStrength() const { return int( m_envStrength * 100 ); }
private:
/// The framebuffer used to render this pass
std::unique_ptr<globjects::Framebuffer> m_fbo{nullptr};
......@@ -74,12 +90,21 @@ class CustomAttribToColorPass : public RenderPass
std::string m_customGeometryAttrib{"void propagateAttributes(){}\n"};
/// the custom FragmentColor shader function
/// If not changed, compute the same expression (without ao) than the light stage
/// If not changed, compute the same expression (without ao) than the envlight stage
std::string m_customFragmentColor{
"vec4 computeCustomColor(Material mat, vec3 light_dir, vec3 view_dir) {\n"
"vec3 bsdf= evaluateBSDF(material, getPerVertexTexCoord(), light_dir, view_dir);\n"
"vec3 contribution = lightContributionFrom(light, getWorldSpacePosition().xyz);\n"
"return vec4(bsdf * 3.141592 * contribution, 1.0);\n"
"\nvec4 computeCustomColor(Material mat, vec3 lightDir, vec3 viewDir, vec3 normal_world) { \n"
"vec3 diffColor; \n"
"vec3 specColor; \n"
"getSeparateBSDFComponent( mat, getPerVertexTexCoord(), lightDir, viewDir,\n"
"vec3(0, 0, 1), diffColor, specColor );\n"
"vec3 envd;\n"
"vec3 envs;\n"
"int e = getEnvMapColors(mat, normal_world, envd, envs);"
"vec3 finalColor;\n"
"if (e==1) { finalColor = diffColor*envd + specColor*envs; }\n"
"else { finalColor = (diffColor + specColor) * max(lightDir.z, 0) \n"
" * lightContributionFrom(light, getWorldSpacePosition().xyz); }\n"
"return vec4( finalColor, 1); \n"
"}\n"};
/// State indicator
......@@ -90,5 +115,11 @@ class CustomAttribToColorPass : public RenderPass
/// The splats size
float m_splatsSize{0.025};
/// The Environment to used for envmap lighting
std::shared_ptr<EnvMap> m_envmap{nullptr};
/// The strength of the envmap
float m_envStrength;
};
} // namespace RadiumNBR
......@@ -37,13 +37,15 @@ class NodeBasedRenderer_LIBRARY_API FullFeatureRenderer final : public NodeBased
void setEnvMap( const std::string& files );
void showEnvMap( bool state );
void setEnvStrength( int s );
// TODO : define a way to configure each passes without adding here specifi methods
// TODO the following might be removed in the future
Scalar getAoRadius() const;
void setAoRadius( Scalar r );
int getAoSamplingDensity() const;
void setAoSamplingDensity( int d );
void setEnvStrength( int s );
void wireframeMode( bool status );
protected:
......
......@@ -118,4 +118,38 @@ void VisualizationController::setSplatSize( float s ) {
m_customPass->setSplatSize( s );
};
void VisualizationController::setEnvMap( const std::string& files ) {
if ( files.empty() )
{
m_clearPass->setEnvMap( nullptr );
m_customPass->setEnvMap( nullptr );
m_hasEnvMap = false;
}
else
{
// Todo, add type VERTICALCROSS, HORIZONTALCROSS and differentiate between all types
// using file extension and file size
auto t = ( files.find( ';' ) != files.npos ) ? EnvMap::EnvMapType::ENVMAP_CUBE
: EnvMap::EnvMapType::ENVMAP_PFM;
if ( t == EnvMap::EnvMapType::ENVMAP_PFM )
{
auto ext = files.substr( files.size() - 3 );
if ( ext != "pfm" ) { t = EnvMap::EnvMapType::ENVMAP_LATLON; }
}
// for now, only skyboxes are managed
auto e = std::make_shared<EnvMap>( files, t, true );
m_clearPass->setEnvMap( e );
m_customPass->setEnvMap( e );
m_hasEnvMap = true;
}
}
void VisualizationController::showEnvMap( bool state ) {
m_clearPass->showEnvMap( state );
}
void VisualizationController::setEnvStrength( int s ) {
m_customPass->setEnvStrength( s );
}
} // namespace RadiumNBR
......@@ -38,25 +38,41 @@ class NodeBasedRenderer_LIBRARY_API VisualizationController
float getSplatSize();
void setSplatSize( float s );
void setEnvMap( const std::string& files );
void showEnvMap( bool state );
void setEnvStrength( int s );
private:
/// The custom pass if needed for modification
std::shared_ptr<RadiumNBR::CustomAttribToColorPass> m_customPass;
/// The clear pass for the background
std::shared_ptr<RadiumNBR::ClearPass> m_clearPass;
///
/// TODO : this default are the same as in the CustomAttribToColorPass. Use them instead of redefining here
std::string m_vertexFunction{"void outputCustomAttribs() {\n}\n"};
std::string m_geometryFunction{"void propagateAttributes(){}\n"};
std::string m_fragmentFunction{
"vec4 computeCustomColor(Material mat, vec3 light_dir, vec3 view_dir) {\n"
"vec3 bsdf= evaluateBSDF(material, getPerVertexTexCoord(), light_dir, view_dir);\n"
"vec3 contribution = lightContributionFrom(light, getWorldSpacePosition().xyz);\n"
"return vec4(bsdf * 3.141592 * contribution, 1.0);\n"
"\nvec4 computeCustomColor(Material mat, vec3 lightDir, vec3 viewDir, vec3 normal_world) { \n"
"vec3 diffColor; \n"
"vec3 specColor; \n"
"getSeparateBSDFComponent( mat, getPerVertexTexCoord(), lightDir, viewDir,\n"
"vec3(0, 0, 1), diffColor, specColor );\n"
"vec3 envd;\n"
"vec3 envs;\n"
"int e = getEnvMapColors(mat, normal_world, envd, envs);"
"vec3 finalColor;\n"
"if (e==1) { finalColor = diffColor*envd + specColor*envs; }\n"
"else { finalColor = (diffColor + specColor) * max(lightDir.z, 0) \n"
" * lightContributionFrom(light, getWorldSpacePosition().xyz); }\n"
"return vec4( finalColor, 1); \n"
"}\n"};
RadiumNBR::NodeBasedRenderer* m_renderer;
bool m_postProcess{true};
/// Is an envmap attached to the renderer
bool m_hasEnvMap{false};
};
} // namespace RadiumNBR
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment