Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft Material in core #4

Draft
wants to merge 56 commits into
base: material-in-core
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
2afb65d
[core] add sample,pdf, bsdf methods for lambertian model
grandch Jun 13, 2023
efd38e9
[core] add bsdf, sample and pdf implementation for blinnphong model
grandch Jun 15, 2023
15719a5
[core] change randomEngine for a static member
grandch Jun 19, 2023
ec36b7a
[core] first review fix
grandch Jun 20, 2023
0e3ac21
[core] Vector3f to Vector3
grandch Jun 20, 2023
055f30b
[core] fix blinnphong sampling, add roughness conv
grandch Jun 20, 2023
f2b9bcf
[ocre] doc evalBSDF
grandch Jun 20, 2023
8f320af
[core] clang format
grandch Jun 20, 2023
862a60b
[core] return reference to random generator
grandch Jun 21, 2023
151309f
[core] move math methods to LinearAlgebra
grandch Jun 21, 2023
4672268
first uniformgenerator and importancesampler
grandch Jun 27, 2023
1df63e3
wip
grandch Jun 27, 2023
4979046
add blinnphongSphereSampler
grandch Jun 28, 2023
e6b2d5f
wip random module
grandch Jun 29, 2023
937a575
add pdf methods
grandch Jun 29, 2023
f377311
add local frame to sample parameters
grandch Jun 29, 2023
4af8670
remove sampling, pdf methods in linearalgebra
grandch Jun 29, 2023
f0d5661
remove ImportanceSampler class
grandch Jul 3, 2023
a3f48e8
add UniformGenerator as optionnal parameter of material
grandch Jul 3, 2023
a5a6bf4
make samplers CRTP for static methods
grandch Jul 3, 2023
f206a5d
fix include
grandch Jul 4, 2023
1c4efe6
fix crtp
grandch Jul 5, 2023
4d77fbb
example
grandch Jul 5, 2023
b03287c
fix samplers
grandch Jul 7, 2023
1c976db
add plot.py
grandch Jul 7, 2023
5101d68
use blinn-phong exponent instead of roughness
grandch Jul 11, 2023
2ceef6c
fix operators precedence
grandch Jul 11, 2023
0c0195b
fix plot samples path
grandch Jul 11, 2023
9af5643
fix evalbsdf
grandch Jul 19, 2023
f2e323c
fix blinnphong sampling
grandch Jul 24, 2023
f73e500
plot sample
grandch Jul 24, 2023
1f6aca9
remove getRoughness method
grandch Jul 25, 2023
714e748
remove redundant field from blinnphongmaterialmodel
grandch Jul 25, 2023
670adaa
precomputed luminance
grandch Jul 25, 2023
443bd9b
private and protected fields
grandch Jul 25, 2023
7f90533
modify constructors*
grandch Jul 25, 2023
5cec94a
store random generator with shared_ptr
grandch Jul 25, 2023
d20b9f2
remove spherical coordinate based methods
grandch Jul 26, 2023
6b79b65
modify names of methods
grandch Jul 26, 2023
6798fd3
add computeLuminance method
grandch Jul 26, 2023
84fe1c8
fix frame usage in blinnphong specular sampling
grandch Jul 26, 2023
bfb19b7
remove unused u parameter for sampling
grandch Jul 26, 2023
5919435
first doc
grandch Jul 26, 2023
8c3ff9f
quick doc for example app
grandch Jul 26, 2023
09fd139
doc
grandch Jul 27, 2023
86a561d
wip unittests
grandch Jul 31, 2023
bc363ab
fix blinnphong pdf
grandch Jul 31, 2023
b1de2ba
fix reflect method
grandch Jul 31, 2023
326b312
wip unittests
grandch Jul 31, 2023
ecdedef
refix reflect method
grandch Jul 31, 2023
c3a0886
forgot (
grandch Jul 31, 2023
decdc5d
rewrite specular sampling methods
grandch Aug 3, 2023
f1fb47d
first step refactoring
grandch Aug 3, 2023
90eac6d
wip unit tests
grandch Aug 3, 2023
c385d8a
tests
grandch Aug 25, 2023
3f80c49
virtual destructor uniform generator
grandch Aug 25, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/developer.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ Radium offers several cmake functions to configure and build your extension.

- \subpage develmeshes
- \subpage develanimation
- \subpage develcorematerials
- \subpage develcorerandom

\page engine Engine

Expand Down
24 changes: 24 additions & 0 deletions doc/developer/corematerials.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
\page develcorematerials Core Materials
[TOC]

A Ra::Core::Material::MaterialModel is a way to control the appearance of an object when rendering.

For now, a Ra::Core::Material::MaterialModel only provides the _Bidirectional Scattering Distribution function (BSDF)_ to be applied on an object.

This _BSDF_ is composed of three methods.

# Methods of the Ra::Core::Material

## Evaluate BSDF

This method, wich is defined as the operator `()` by the interface in Ra::Core::Material::MaterialModel gives the color value of the object for given ingoing, outgoing and surface normal directions.

## Sample BSDF

This method, named `sample()` by the interface in Ra::Core::Material::MaterialModel gives the outgoing direction according to the choosen reflectance model for a given ingoing and surface normal direction.

A Ra::Core::Material::MaterialModel use a Ra::Core::Random::SphereSampler fed with a Ra::Core::Random::UniformGenerator in order to sample. To learn more about samplers and generators, please read the [Random](@ref develcorerandom) section.

## Probability density function corresponding to BSDF

This method, named `pdf()` by the interface in Ra::Core::Material::MaterialModel gives the probability for a pair of ingoing and outgoing direction to exist.
19 changes: 19 additions & 0 deletions doc/developer/corerandom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
\page develcorerandom Core Random
[TOC]

The `Ra::Core::Random` namespace contain two interfaces, Ra::Core::Random::UniformGenerator and Ra::Core::Random::SphereSampler.

# Generators

A generator is an implementation of the interface Ra::Core::Random::UniformGenerator. It provides an uniform random distribution between 0 and 1. The interface provides four methods to get a random scalar or a 2D, 3D or nD vector. By default, the vectors are built by calling n times the `get1D()` method.

# Samplers

A sampler follow the interface Ra::Core::Random::SphereSampler. A sphere sampler generate a direction from the center of the sphere to a point on the surface of the sphere according to a probability distribution. To achieve this, it has two methods. A method `getDir()` that maps an uniform generator into the probability distribution to generate a direction in the canonical frame and a method `pdf()` that compute the probability density function value of a direction with a given normal direction (both directions are in world frame).

There is an example app called PlotImportanceSampler that can write samples from several samplers in a json file. The json file can then be read by a python script called plot-samples.py.
To launch this script do

~~~{.bash}
python3 /path/to/plot-samples.py /path/to/jsonfile.json
~~~
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ foreach(
MaterialEdition
ParameterEdition
Picking
PlotImportanceSampler
RawShaderMaterial
SimpleAnimation
SimpleSimulation
Expand Down
61 changes: 61 additions & 0 deletions examples/PlotImportanceSampler/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
cmake_minimum_required(VERSION 3.16)
cmake_policy(SET CMP0042 NEW)

project(PlotImportanceSampler)

# ------------------------------------------------------------------------------
# set wanted application defaults for cmake settings
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
# Set default install location to installed-<Compiler_ID> folder in build dir we do not want to
# install to /usr by default
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX
"${CMAKE_CURRENT_BINARY_DIR}/installed-${CMAKE_CXX_COMPILER_ID}-${CMAKE_BUILD_TYPE}"
CACHE PATH "Install path prefix, prepended onto install directories." FORCE
)
message("Set install prefix to ${CMAKE_INSTALL_PREFIX}")
endif()
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)

# ------------------------------------------------------------------------------

find_package(Radium REQUIRED Core)

# ------------------------------------------------------------------------------

set(app_sources main.cpp)
set(app_headers)
set(app_resources)

# to install the app as a redistribuable bundle on macos, add MACOSX_BUNDLE when calling
# add_executable
add_executable(${PROJECT_NAME} ${app_sources} ${app_headers} ${app_uis} ${app_resources})

if("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC")
target_compile_options(
${PROJECT_NAME}
PRIVATE /MP
/W4
/wd4251
/wd4592
/wd4127
/Zm200
$<$<CONFIG:Release>:
/Gw
/GS-
/GL
/GF
>
PUBLIC
)
endif()

target_link_libraries(${PROJECT_NAME} PUBLIC Radium::Core)

# configure the application
configure_radium_app(NAME ${PROJECT_NAME})
51 changes: 51 additions & 0 deletions examples/PlotImportanceSampler/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Include the samplers and a random generator
#include <Core/Random/BlinnPhongSphereSampler.hpp>
#include <Core/Random/CosineWeightedSphereSampler.hpp>
#include <Core/Random/MersenneTwisterGenerator.hpp>
#include <Core/Random/UniformSphereSampler.hpp>

#include <fstream>
#include <iostream>
#include <nlohmann/json.hpp>
#include <vector>

int main( int /*argc*/, char** /*argv*/ ) {
using namespace Ra::Core;
using json = nlohmann::json;

//! [Creating the random generator to feed the samplers]
Random::MersenneTwisterGenerator generator = Random::MersenneTwisterGenerator();

//! [Creating the samplers]
std::vector<Vector3> uSamplesDir, cSamplesDir, bSamplesDir4, bSamplesDir16, bSamplesDir64,
bSamplesDir128;

//! [Sampling (here 500 times) with each sampler]
for ( int i = 0; i < 500; i++ ) {
uSamplesDir.push_back( Random::UniformSphereSampler::getDir( &generator ).first );
cSamplesDir.push_back( Random::CosineWeightedSphereSampler::getDir( &generator ).first );
bSamplesDir4.push_back( Random::BlinnPhongSphereSampler::getDir( &generator, 4 ).first );
bSamplesDir16.push_back( Random::BlinnPhongSphereSampler::getDir( &generator, 16 ).first );
bSamplesDir64.push_back( Random::BlinnPhongSphereSampler::getDir( &generator, 64 ).first );
bSamplesDir128.push_back(
Random::BlinnPhongSphereSampler::getDir( &generator, 128 ).first );
}

//! [Creating a json format to write the samples in and write to a file named "samples.json"]
json j = { { "UniformSamples", uSamplesDir },
{ "CosineWeightedSamples", cSamplesDir },
{ "BlinnPhongSamples 4", bSamplesDir4 },
{ "BlinnPhongSamples 16", bSamplesDir16 },
{ "BlinnPhongSamples 64", bSamplesDir64 },
{ "BlinnPhongSamples 128", bSamplesDir128 } };

std::ofstream o( "samples.json" );

o << std::setw( 4 ) << j << std::endl;

o.close();

//! [Samples can now be displayed with the python script named "plot-samples.py"]

return 0;
}
36 changes: 36 additions & 0 deletions examples/PlotImportanceSampler/plot-samples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import json
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import numpy as np
import math
import sys

"""
This python script is used to plot the samples writted to a json file by the main.cpp Radium example app in the PlotImportanceSampler folder.

To launch this script use the command
python3 plot-samples.py /path/to/jsonfile.json
"""

def plotDir(array, ax):
for p in array:
ax.scatter(p[0], p[1], p[2], c='#1f77b4', s=1)

with open(sys.argv[1], 'r') as f:
data = json.load(f)

size = len(data)

fig = plt.figure(figsize=plt.figaspect(1/3))
gs = gridspec.GridSpec(math.ceil(size/3), 3)

i = 0
for l in data:
ax = fig.add_subplot(gs[math.floor(i/3), i%3], projection='3d')
ax.set_title(l)
ax.set_zlim(0, 1)
arr = np.array(data[l])
plotDir(arr, ax)
i += 1

plt.show()
77 changes: 76 additions & 1 deletion src/Core/Material/BlinnPhongMaterialModel.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#include <Core/Material/BlinnPhongMaterialModel.hpp>

#include <Core/Utils/Log.hpp>

#include <algorithm>

namespace Ra {
namespace Core {
namespace Material {
Expand All @@ -24,6 +25,80 @@ void BlinnPhongMaterialModel::displayInfo() const {
print( hasNormalTexture(), " Normal Texture : ", m_texNormal );
print( hasOpacityTexture(), " Alpha Texture : ", m_texOpacity );
}

Utils::Color Material::BlinnPhongMaterialModel::operator()( Vector3 w_i,
Vector3 w_o,
Vector3 normal,
Vector2 uv ) {
// diffuse lambertien component
Utils::Color diffuse = m_kd / M_PI;

// Blinn-Phong specular component
Vector3 halfway = w_i + w_o;
halfway.normalize();
Scalar specularIntensity =
( m_ns + 2.0f ) / ( 2.0f * M_PI ) * std::pow( normal.dot( halfway ), m_ns );
Utils::Color specular = m_ks * specularIntensity;

// Combine the diffuse and specular components
Utils::Color bsdf = diffuse + specular;

return bsdf;
}

std::optional<std::pair<Vector3, Scalar>>
BlinnPhongMaterialModel::sample( Vector3 w_i, Vector3 normal, Vector3 tangent, Vector3 bitangent ) {
Vector3 halfway;

Scalar distrib = m_generator.get()->get1D();

// diffuse part
if ( distrib < m_diffuseLuminance ) {
std::pair<Vector3, Scalar> smpl =
Core::Random::CosineWeightedSphereSampler::getDir( m_generator.get() );
Vector3 wo(
smpl.first.dot( tangent ), smpl.first.dot( bitangent ), smpl.first.dot( normal ) );
std::pair<Vector3, Scalar> result { wo, smpl.second };

return result;
}
// specular part
else if ( distrib < m_diffuseLuminance + m_specularLuminance ) {
std::pair<Vector3, Scalar> smpl =
Core::Random::BlinnPhongSphereSampler::getDir( m_generator.get(), m_ns );
Vector3 localMicroFacetNormal = smpl.first;
Vector3 microFacetNormal( localMicroFacetNormal.dot( tangent ),
localMicroFacetNormal.dot( bitangent ),
localMicroFacetNormal.dot( normal ) );
Vector3 reflected = Core::Random::BlinnPhongSphereSampler::reflect( w_i, microFacetNormal );
std::pair<Vector3, Scalar> result { reflected, smpl.second };

return result;
}
else { // no next dir
return {};
}
}

Scalar BlinnPhongMaterialModel::pdf( Vector3 w_i, Vector3 w_o, Vector3 normal ) {
return std::clamp( m_diffuseLuminance *
Core::Random::CosineWeightedSphereSampler::pdf( w_o, normal ) +
m_specularLuminance *
Core::Random::BlinnPhongSphereSampler::pdf( w_i, w_o, normal, m_ns ),
0_ra,
1_ra );
}

void BlinnPhongMaterialModel::computeLuminance() {
Vector3 rgbToLuminance { 0.2126_ra, 0.7152_ra, 0.0722_ra };
Scalar dIntensity = m_kd.rgb().dot( rgbToLuminance );
Scalar sIntensity = m_ks.rgb().dot( rgbToLuminance );
Scalar diffSpecNorm = std::max( 1_ra, dIntensity + sIntensity );

m_diffuseLuminance = dIntensity / diffSpecNorm;
m_specularLuminance = sIntensity / diffSpecNorm;
}

} // namespace Material
} // namespace Core
} // namespace Ra
Loading