From 1f558367a93aeb41f0a9dcbf22939526f54d3eef Mon Sep 17 00:00:00 2001 From: Samuel Felton Date: Mon, 29 Apr 2024 20:15:46 +0200 Subject: [PATCH] Fix cook torrance model, Add light contrib map example in tutorial --- .../include/visp3/ar/vpPanda3DRGBRenderer.h | 6 +- .../vpPanda3DRGBRenderer.cpp | 56 ++++++++++------- tutorial/ar/tutorial-panda3d-renderer.cpp | 62 ++++++++++++++----- 3 files changed, 85 insertions(+), 39 deletions(-) diff --git a/modules/ar/include/visp3/ar/vpPanda3DRGBRenderer.h b/modules/ar/include/visp3/ar/vpPanda3DRGBRenderer.h index e77b6c27c6..e4d9d7a983 100644 --- a/modules/ar/include/visp3/ar/vpPanda3DRGBRenderer.h +++ b/modules/ar/include/visp3/ar/vpPanda3DRGBRenderer.h @@ -43,7 +43,9 @@ class VISP_EXPORT vpPanda3DRGBRenderer : public vpPanda3DBaseRenderer, public vpPanda3DLightableScene { public: - vpPanda3DRGBRenderer() : vpPanda3DBaseRenderer("RGB") { } + vpPanda3DRGBRenderer() : vpPanda3DBaseRenderer("RGB"), m_showSpeculars(true) { } + vpPanda3DRGBRenderer(bool showSpeculars) : vpPanda3DBaseRenderer(showSpeculars ? "RGB" : "RGB-diffuse"), m_showSpeculars(showSpeculars) { } + /** * @brief Store the render resulting from calling renderFrame() into a vpImage. @@ -59,8 +61,10 @@ class VISP_EXPORT vpPanda3DRGBRenderer : public vpPanda3DBaseRenderer, public vp protected: void setupScene() vp_override; void setupRenderTarget() vp_override; + virtual std::string makeFragmentShader(bool hasTexture, bool specular); private: + bool m_showSpeculars; Texture *m_colorTexture; GraphicsOutput *m_colorBuffer; static const char *COOK_TORRANCE_VERT; diff --git a/modules/ar/src/panda3d-simulator/vpPanda3DRGBRenderer.cpp b/modules/ar/src/panda3d-simulator/vpPanda3DRGBRenderer.cpp index eeab32af1d..775e8612a4 100644 --- a/modules/ar/src/panda3d-simulator/vpPanda3DRGBRenderer.cpp +++ b/modules/ar/src/panda3d-simulator/vpPanda3DRGBRenderer.cpp @@ -82,11 +82,7 @@ void main() )shader"; const char *vpPanda3DRGBRenderer::COOK_TORRANCE_FRAG = R"shader( -#version 330 - -//#define HAS_TEXTURE 1 -//#define SPECULAR 1 - +// Version 330, specified when generating shader #define M_PI 3.1415926535897932384626433832795 @@ -146,7 +142,7 @@ float G(float hn, float nv, float nl, float vh) vec3 F(vec3 F0, float vh) { - return F0 + (1.f - F0) * pow(1.f - vh, 5); + return F0 + (vec3(1.f, 1.f, 1.f) - F0) * pow(1.f - vh, 5); } @@ -172,8 +168,8 @@ void main() vec3 aFac = p3d_LightSource[i].attenuation; float attenuation = 1.f / (aFac[0] + aFac[1] * lightDist + aFac[2] * lightDist * lightDist); - vec3 FV = clamp(F(F0, vh), 0.0, 1.0); - vec3 kd = (1.f - FV) * (1.f - p3d_Material.metallic); + vec3 FV = F(F0, vh); + vec3 kd = (1.f - p3d_Material.metallic) * (1.f - FV) * (1.f / M_PI); #ifdef HAS_TEXTURE vec4 diffuseColor = texture(p3d_Texture0, texcoords); #else @@ -181,29 +177,49 @@ void main() #endif - //diffuseColor.xyz = (1.f - FV) * (1.f - p3d_Material.metallic) * diffuseColor.xyz; #ifdef SPECULAR - float DV = D(roughness2, hn); - float GV = G(hn, nv, nl, vh); - vec3 rs = (DV * GV * FV) / (4.f * nl * nv); - vec3 specularColor = rs * p3d_Material.specular; + vec3 specularColor = vec3(0.f, 0.f, 0.f); + if(nl > 0.f && nv > 0.f) { + float DV = D(roughness2, hn); + float GV = G(hn, nv, nl, vh); + vec3 rs = (DV * GV * FV) / (4.f * nl * nv); + specularColor = rs * p3d_Material.baseColor.rgb; + } #else vec3 specularColor = vec3(0.0, 0.0, 0.0); #endif - //p3d_FragData += (p3d_LightSource[i].color * attenuation) * nl * (diffuseColor * vec4(kd, 1.f) + vec4(specularColor, 1.f)); - p3d_FragData = diffuseColor; + p3d_FragData += (p3d_LightSource[i].color * attenuation) * nl * (diffuseColor * vec4(kd, 1.f) + vec4(specularColor, 1.f)); } } )shader"; +std::string vpPanda3DRGBRenderer::makeFragmentShader(bool hasTexture, bool specular) +{ + std::stringstream ss; + ss << "#version 330" << std::endl; + if (hasTexture) { + ss << "#define HAS_TEXTURE 1" << std::endl; + } + if (specular) { + ss << "#define SPECULAR 1" << std::endl; + } + ss << vpPanda3DRGBRenderer::COOK_TORRANCE_FRAG; + std::cout << ss.str() << std::endl; + return ss.str(); +} + void vpPanda3DRGBRenderer::addNodeToScene(const NodePath &object) { NodePath objectInScene = object.copy_to(m_renderRoot); objectInScene.set_name(object.get_name()); - objectInScene.ls(); - std::cout << objectInScene.has_texture() << std::endl; + PT(Shader) shader = Shader::make(Shader::ShaderLanguage::SL_GLSL, + COOK_TORRANCE_VERT, + makeFragmentShader(false, m_showSpeculars)); + + objectInScene.set_shader(shader); + setNodePose(objectInScene, vpHomogeneousMatrix()); } @@ -226,12 +242,6 @@ void vpPanda3DRGBRenderer::setupScene() { vpPanda3DBaseRenderer::setupScene(); setLightableScene(m_renderRoot); - PT(Shader) shader; - shader = Shader::make(Shader::ShaderLanguage::SL_GLSL, - COOK_TORRANCE_VERT, - COOK_TORRANCE_FRAG); - m_renderRoot.set_shader(shader); - //m_renderRoot.set_shader_auto(); } void vpPanda3DRGBRenderer::setupRenderTarget() diff --git a/tutorial/ar/tutorial-panda3d-renderer.cpp b/tutorial/ar/tutorial-panda3d-renderer.cpp index 86a0621c2f..fc779132ca 100644 --- a/tutorial/ar/tutorial-panda3d-renderer.cpp +++ b/tutorial/ar/tutorial-panda3d-renderer.cpp @@ -44,12 +44,25 @@ void displayDepth(const vpImage &depthImage, } +void displayLightDifference(const vpImage &colorImage, const vpImage &colorDiffuseOnly, vpImage &lightDifference) +{ +#pragma omp parallel for + for (int i = 0; i < colorImage.getSize(); ++i) { + float I1 = 0.299 * colorImage.bitmap[i].R + 0.587 * colorImage.bitmap[i].G * +0.114 * colorImage.bitmap[i].B; + float I2 = 0.299 * colorDiffuseOnly.bitmap[i].R + 0.587 * colorDiffuseOnly.bitmap[i].G * +0.114 * colorDiffuseOnly.bitmap[i].B; + lightDifference.bitmap[i] = static_cast(abs(I1 - I2)); + } + vpDisplay::display(lightDifference); + vpDisplay::flush(lightDifference); +} + int main(int argc, const char **argv) { bool invertTexture = false; bool stepByStep = false; bool debug = false; + bool showLightContrib = false; char *modelPathCstr = nullptr; vpParseArgv::vpArgvInfo argTable[] = { @@ -59,6 +72,8 @@ int main(int argc, const char **argv) "Path to the model to load."}, {"-step", vpParseArgv::ARGV_CONSTANT_BOOL, (char *) nullptr, (char *)&stepByStep, "Show frames step by step."}, + {"-specular", vpParseArgv::ARGV_CONSTANT_BOOL, (char *) nullptr, (char *)&showLightContrib, + "Show frames step by step."}, {"-debug", vpParseArgv::ARGV_CONSTANT_BOOL, (char *) nullptr, (char *)&debug, "Show Opengl/Panda3D debug message."}, {"-h", vpParseArgv::ARGV_HELP, (char *) nullptr, (char *) nullptr, @@ -80,7 +95,7 @@ int main(int argc, const char **argv) else { modelPath = "data/deformed_sphere.bam"; } - vpPanda3DRenderParameters renderParams(vpCameraParameters(300, 300, 160, 120), 240, 320, 0.01, 10.0); + vpPanda3DRenderParameters renderParams(vpCameraParameters(600, 600, 320, 240), 480, 640, 0.01, 10.0); vpPanda3DRendererSet renderer(renderParams); renderer.setRenderParameters(renderParams); @@ -90,16 +105,20 @@ int main(int argc, const char **argv) std::shared_ptr cameraRenderer = std::shared_ptr(new vpPanda3DGeometryRenderer(vpPanda3DGeometryRenderer::vpRenderType::CAMERA_NORMALS)); std::shared_ptr rgbRenderer = std::shared_ptr(new vpPanda3DRGBRenderer()); + std::shared_ptr rgbDiffuseRenderer = std::shared_ptr(new vpPanda3DRGBRenderer(false)); renderer.addSubRenderer(geometryRenderer); renderer.addSubRenderer(cameraRenderer); renderer.addSubRenderer(rgbRenderer); + if (showLightContrib) { + renderer.addSubRenderer(rgbDiffuseRenderer); + } + renderer.setVerticalSyncEnabled(false); renderer.setAbortOnPandaError(true); if (debug) { renderer.enableDebugLog(); - } if (invertTexture) { renderer.setForcedInvertTextures(true); @@ -114,7 +133,7 @@ int main(int argc, const char **argv) renderer.addNodeToScene(object); - vpPanda3DAmbientLight alight("Ambient", vpRGBf(0.5)); + vpPanda3DAmbientLight alight("Ambient", vpRGBf(0.2)); renderer.addLight(alight); vpPanda3DPointLight plight("Point", vpRGBf(1.0), vpColVector({ 0.0, 0.2, -0.4 }), vpColVector({ 0.0, 0.0, 1.0 })); renderer.addLight(plight); @@ -126,12 +145,14 @@ int main(int argc, const char **argv) vpImage normalsImage; vpImage cameraNormalsImage; vpImage depthImage; + unsigned h = renderParams.getImageHeight(), w = renderParams.getImageWidth(); + vpImage colorImage(h, w); + vpImage colorDiffuseOnly(h, w); + vpImage lightDifference(h, w); - vpImage colorImage(renderParams.getImageHeight(), renderParams.getImageWidth()); - vpImage normalDisplayImage(renderParams.getImageHeight(), renderParams.getImageWidth()); - vpImage cameraNormalDisplayImage(renderParams.getImageHeight(), renderParams.getImageWidth()); - - vpImage depthDisplayImage(renderParams.getImageHeight(), renderParams.getImageWidth()); + vpImage normalDisplayImage(h, w); + vpImage cameraNormalDisplayImage(h, w); + vpImage depthDisplayImage(h, w); #if defined(VISP_HAVE_GTK) using DisplayCls = vpDisplayGTK; @@ -146,9 +167,15 @@ int main(int argc, const char **argv) #endif DisplayCls dNormals(normalDisplayImage, 0, 0, "normals in world space"); - DisplayCls dNormalsCamera(cameraNormalDisplayImage, 0, renderParams.getImageHeight() + 80, "normals in camera space"); - DisplayCls dDepth(depthDisplayImage, renderParams.getImageWidth() + 80, 0, "depth"); - DisplayCls dColor(colorImage, renderParams.getImageWidth() * 3 + 90, 0, "color"); + DisplayCls dNormalsCamera(cameraNormalDisplayImage, 0, h + 80, "normals in camera space"); + DisplayCls dDepth(depthDisplayImage, w + 80, 0, "depth"); + DisplayCls dColor(colorImage, w + 80, h + 80, "color"); + + DisplayCls dImageDiff; + if (showLightContrib) { + dImageDiff.init(lightDifference, w * 2 + 90, 0, "Specular/reflectance contribution"); + } + renderer.renderFrame(); bool end = false; bool firstFrame = true; @@ -163,17 +190,22 @@ int main(int argc, const char **argv) const double beforeRender = vpTime::measureTimeMs(); renderer.renderFrame(); - const double beforeFetch = vpTime::measureTimeMs(); renderer.getRenderer(geometryRenderer->getName())->getRender(normalsImage, depthImage); renderer.getRenderer(cameraRenderer->getName())->getRender(cameraNormalsImage); - renderer.getRenderer()->getRender(colorImage); + renderer.getRenderer(rgbRenderer->getName())->getRender(colorImage); + if (showLightContrib) { + renderer.getRenderer(rgbDiffuseRenderer->getName())->getRender(colorDiffuseOnly); + } const double beforeConvert = vpTime::measureTimeMs(); displayNormals(normalsImage, normalDisplayImage); displayNormals(cameraNormalsImage, cameraNormalDisplayImage); displayDepth(depthImage, depthDisplayImage, nearV, farV); + if (showLightContrib) { + displayLightDifference(colorImage, colorDiffuseOnly, lightDifference); + } vpDisplay::display(colorImage); vpDisplay::displayText(colorImage, 15, 15, "Click to quit", vpColor::red); @@ -199,11 +231,11 @@ int main(int argc, const char **argv) } } // if (firstFrame) { - // renderParams.setImageResolution(renderParams.getImageHeight() * 0.5, renderParams.getImageWidth() * 0.5); + // renderParams.setImageResolution(h * 0.5, w * 0.5); // vpCameraParameters orig = renderParams.getCameraIntrinsics(); // vpCameraParameters newCam(orig.get_px() * 0.5, orig.get_py() * 0.5, orig.get_u0() * 0.5, orig.get_v0() * 0.5); // renderParams.setCameraIntrinsics(newCam); - // std::cout << renderParams.getImageHeight() << std::endl; + // std::cout << h << std::endl; // //dDepth.setDownScalingFactor(0.5); // renderer.setRenderParameters(renderParams); // }