From b212a52215b1bd388a29bbc13b9ccac6cb03b589 Mon Sep 17 00:00:00 2001 From: kmkolasinski Date: Tue, 21 Apr 2015 21:33:10 +0200 Subject: [PATCH] Commit to 3.14 == Pi Version Some fixes and improevemnts: 1) Glossiness texture 2) Selecting camera position ... --- Bin/Configs/40_pistol.ini | 62 ++- Sources/CommonObjects.h | 50 +- Sources/camera.cpp | 47 +- Sources/camera.h | 4 +- Sources/content.qrc | 4 + Sources/dialogshortcuts.ui | 69 ++- Sources/formimageprop.cpp | 91 +++- Sources/formimageprop.h | 10 +- Sources/formimageprop.ui | 700 ++++++++++++++++++------- Sources/formmaterialindicesmanager.cpp | 6 +- Sources/formmaterialindicesmanager.ui | 109 +++- Sources/glimageeditor.cpp | 41 +- Sources/glimageeditor.h | 5 + Sources/glwidget.cpp | 240 +++++++-- Sources/glwidget.h | 8 +- Sources/glwidgetbase.cpp | 39 +- Sources/glwidgetbase.h | 4 +- Sources/mainwindow.cpp | 34 +- Sources/mainwindow.h | 3 + Sources/mainwindow.ui | 152 ++++-- Sources/resources/centerCamCursor.png | Bin 0 -> 963 bytes Sources/resources/centerCamCursor.svg | 296 +++++++++++ Sources/resources/filters.frag | 56 +- Sources/resources/filters_3d.frag | 215 ++------ Sources/resources/plane.frag | 36 +- Sources/resources/plane.geom | 12 +- Sources/resources/plane.tes.vert | 4 + Sources/resources/resetCamera.png | Bin 0 -> 1948 bytes Sources/resources/resetCamera.svg | 171 ++++++ Sources/resources/showMaterials.png | Bin 0 -> 7999 bytes Sources/resources/showMaterials.svg | 129 +++++ Sources/resources/showSettings.png | Bin 4695 -> 7480 bytes Sources/resources/showSettings.svg | 222 ++++++++ Sources/resources/showUVs.png | Bin 0 -> 7669 bytes Sources/resources/showUVs.svg | 129 +++++ Sources/resources/skybox.frag.glsl | 2 +- Sources/utils/Mesh.cpp | 1 + 37 files changed, 2428 insertions(+), 523 deletions(-) create mode 100644 Sources/resources/centerCamCursor.png create mode 100644 Sources/resources/centerCamCursor.svg create mode 100644 Sources/resources/resetCamera.png create mode 100644 Sources/resources/resetCamera.svg create mode 100644 Sources/resources/showMaterials.png create mode 100644 Sources/resources/showMaterials.svg create mode 100644 Sources/resources/showSettings.svg create mode 100644 Sources/resources/showUVs.png create mode 100644 Sources/resources/showUVs.svg diff --git a/Bin/Configs/40_pistol.ini b/Bin/Configs/40_pistol.ini index 8fc4599..807f4ef 100644 --- a/Bin/Configs/40_pistol.ini +++ b/Bin/Configs/40_pistol.ini @@ -15,8 +15,8 @@ noPBRRays=2 noTessSubdivision=0 o_postfix=_o r_postfix=_r -recent_dir=C:/Users/mkk/Downloads/Cerberus_by_Andrew_Maximov/Cerberus_by_Andrew_Maximov/Textures/my2 -recent_mesh_dir=C:/Users/mkk/Downloads/Cerberus_by_Andrew_Maximov/Cerberus_by_Andrew_Maximov/untitled.obj +recent_dir=C:/Users/mkk/Downloads/Cerberus_by_Andrew_Maximov/Cerberus_by_Andrew_Maximov/Textures/Cerberus_A.jpg +recent_mesh_dir=E:/Doktorat/ZaawansowanaGrafika3D/AwesomeBumpRepo/AwesomeBump/Bin/Torus s_postfix=_s settings_description=... settings_name=pistol @@ -128,12 +128,12 @@ t_h_conversionBaseMapMixNormals=@Variant(\0\0\0\x87?\0\0\0) t_h_conversionBaseMapNoIters=2 t_h_conversionBaseMapPreSmoothRadius=@Variant(\0\0\0\x87\0\0\0\0) t_h_conversionHNDepth=@Variant(\0\0\0\x87\x41 \0\0) -t_h_conversionNHItersHuge=27 -t_h_conversionNHItersLarge=13 -t_h_conversionNHItersMedium=7 -t_h_conversionNHItersSmall=6 -t_h_conversionNHItersVeryLarge=19 -t_h_conversionNHItersVerySmall=6 +t_h_conversionNHItersHuge=46 +t_h_conversionNHItersLarge=23 +t_h_conversionNHItersMedium=15 +t_h_conversionNHItersSmall=14 +t_h_conversionNHItersVeryLarge=32 +t_h_conversionNHItersVerySmall=15 t_h_detailDepth=@Variant(\0\0\0\x87?\x80\0\0) t_h_grayScaleB=@Variant(\0\0\0\x87>\xa8\xa8\xa9) t_h_grayScaleG=@Variant(\0\0\0\x87>\xa8\xa8\xa9) @@ -306,7 +306,7 @@ t_n_inputImageType=3 t_n_mediumDetails=@Variant(\0\0\0\x87\0\0\0\0) t_n_noBlurPasses=0 t_n_noRemoveShadingGaussIter=1 -t_n_normalsStep=@Variant(\0\0\0\x87?\x80\0\0) +t_n_normalsStep=@Variant(\0\0\0\x87?\xb5\xc2\x8f) t_n_pickedColorB=@Variant(\0\0\0\x87\0\0\0\0) t_n_pickedColorG=@Variant(\0\0\0\x87\0\0\0\0) t_n_pickedColorR=@Variant(\0\0\0\x87\0\0\0\0) @@ -584,7 +584,7 @@ t_s_ssaoNoIters=20 tab_3d_settings_win_h=230 tab_3d_settings_win_w=772 tab_win_h=736 -tab_win_w=354 +tab_win_w=320 use_texture_interpolation=true uv_contrast_input_image=0 uv_contrast_power=0 @@ -615,3 +615,45 @@ t_n_removeShadingLFRadius=@Variant(\0\0\0\x87\0\0\0\0) t_o_removeShadingLFRadius=@Variant(\0\0\0\x87\0\0\0\0) t_r_removeShadingLFRadius=@Variant(\0\0\0\x87\0\0\0\0) t_s_removeShadingLFRadius=@Variant(\0\0\0\x87\0\0\0\0) +font_size=10 +t_d_bHeightEnableNormalization=true +t_h_bHeightEnableNormalization=true +t_m_bHeightEnableNormalization=true +t_n_bHeightEnableNormalization=true +t_o_bHeightEnableNormalization=true +t_r_bHeightEnableNormalization=true +t_s_bHeightEnableNormalization=true +mouse_loop=true +t_d_conversionBaseMapAmplitude_Level0=@Variant(\0\0\0\x87\xbf\x80\0\0) +t_d_conversionBaseMapFlatness_Level0=@Variant(\0\0\0\x87\0\0\0\0) +t_d_conversionBaseMapNoIters_Level0=2 +t_d_conversionBaseMapFilterRadius_Level0=0 +t_d_conversionBaseMapMixNormals_Level0=@Variant(\0\0\0\x87?\0\0\0) +bDofEffect=true +t_d_conversionBaseMapPreSmoothRadius_Level0=@Variant(\0\0\0\x87\0\0\0\0) +t_d_conversionBaseMapBlending_Level0=@Variant(\0\0\0\x87?\0\0\0) +t_dconversionBaseMapWeight_Level0=@Variant(\0\0\0\x87\x42H\0\0) +t_d_conversionBaseMapAmplitude_Level1=@Variant(\0\0\0\x87\xbf\x80\0\0) +t_d_conversionBaseMapFlatness_Level1=@Variant(\0\0\0\x87\0\0\0\0) +t_d_conversionBaseMapNoIters_Level1=2 +t_d_conversionBaseMapFilterRadius_Level1=0 +t_d_conversionBaseMapMixNormals_Level1=@Variant(\0\0\0\x87?\0\0\0) +t_d_conversionBaseMapPreSmoothRadius_Level1=@Variant(\0\0\0\x87\0\0\0\0) +t_d_conversionBaseMapBlending_Level1=@Variant(\0\0\0\x87?\0\0\0) +t_dconversionBaseMapWeight_Level1=@Variant(\0\0\0\x87\x42H\0\0) +t_d_conversionBaseMapAmplitude_Level2=@Variant(\0\0\0\x87\xbf\x80\0\0) +t_d_conversionBaseMapFlatness_Level2=@Variant(\0\0\0\x87\0\0\0\0) +t_d_conversionBaseMapNoIters_Level2=2 +t_d_conversionBaseMapFilterRadius_Level2=0 +t_d_conversionBaseMapMixNormals_Level2=@Variant(\0\0\0\x87?\0\0\0) +t_d_conversionBaseMapPreSmoothRadius_Level2=@Variant(\0\0\0\x87\0\0\0\0) +t_d_conversionBaseMapBlending_Level2=@Variant(\0\0\0\x87?\0\0\0) +t_dconversionBaseMapWeight_Level2=@Variant(\0\0\0\x87\x42H\0\0) +t_d_conversionBaseMapAmplitude_Level3=@Variant(\0\0\0\x87\xbf\x80\0\0) +t_d_conversionBaseMapFlatness_Level3=@Variant(\0\0\0\x87\0\0\0\0) +t_d_conversionBaseMapNoIters_Level3=2 +t_d_conversionBaseMapFilterRadius_Level3=0 +t_d_conversionBaseMapMixNormals_Level3=@Variant(\0\0\0\x87?\0\0\0) +t_d_conversionBaseMapPreSmoothRadius_Level3=@Variant(\0\0\0\x87\0\0\0\0) +t_d_conversionBaseMapBlending_Level3=@Variant(\0\0\0\x87?\0\0\0) +t_dconversionBaseMapWeight_Level3=@Variant(\0\0\0\x87\x42H\0\0) diff --git a/Sources/CommonObjects.h b/Sources/CommonObjects.h index 338cfd6..8f8ebbb 100644 --- a/Sources/CommonObjects.h +++ b/Sources/CommonObjects.h @@ -21,7 +21,7 @@ #define AB_LOG_ALT "log.txt" #endif -#define AWESOME_BUMP_VERSION "AwesomeBump v3.0.4 " +#define AWESOME_BUMP_VERSION "AwesomeBump Pi (2015)" #define TEXTURE_FORMAT GL_RGB16F @@ -286,13 +286,15 @@ class Performance3DSettings{ int noPBRRays; bool bBloomEffect; bool bDofEffect; + bool bShowTriangleEdges; Performance3DSettings(){ bUseCullFace = false; bUseSimplePBR = false; - noTessSubdivision = 16; - noPBRRays = 15; - bBloomEffect = true; - bDofEffect = true; + noTessSubdivision = 16; + noPBRRays = 15; + bBloomEffect = true; + bDofEffect = true; + bShowTriangleEdges = false; } }; @@ -380,6 +382,7 @@ class FBOImageProporties{ QGLFramebufferObject *fbo ; // output image GLuint scr_tex_id; // Id of texture loaded from image, from loaded file + GLuint normalMixerInputTexId; // Used only by normal texture int scr_tex_width; // width of the image loaded from file. int scr_tex_height; // height ... QGLWidget* glWidget_ptr; // pointer to GL context @@ -481,6 +484,15 @@ class FBOImageProporties{ int selectiveBlurNoIters; float roughnessColorGlobalOffset; + // normal map mixer + bool bNormalMixerEnabled; + bool bNormalMixerApplyNormals; + float normalMixerDepth; + float normalMixerScale; + float normalMixerAngle; + float normalMixerPosX; + float normalMixerPosY; + // global settings seamless parameters static SeamlessMode seamlessMode; @@ -496,12 +508,15 @@ class FBOImageProporties{ static map materialIndices; static int currentMaterialIndeks; + + FBOImageProporties(){ //ref_fbo = NULL; fbo = NULL; //aux_fbo = NULL; //aux2_fbo = NULL; + normalMixerInputTexId = 0; glWidget_ptr = NULL; bFirstDraw = true; bGrayScale = false; @@ -597,6 +612,18 @@ class FBOImageProporties{ seamlessMode = SEAMLESS_NONE; + + + // normal map mixer + bNormalMixerEnabled = false; + bNormalMixerApplyNormals = false; + normalMixerDepth = 0.0; + + normalMixerScale = 1.0; + normalMixerAngle = 0.0; + normalMixerPosX = 0.0; + normalMixerPosY = 0.0; + } void copySettings(FBOImageProporties &src){ @@ -693,6 +720,15 @@ class FBOImageProporties{ selectiveBlurMaskInputImageType = src.selectiveBlurMaskInputImageType; selectiveBlurNoIters = src.selectiveBlurNoIters; + // normal map mixer + bNormalMixerEnabled = src.bNormalMixerEnabled; + bNormalMixerApplyNormals = src.bNormalMixerApplyNormals; + normalMixerDepth = src.normalMixerDepth; + + normalMixerScale = src.normalMixerScale; + normalMixerAngle = src.normalMixerAngle; + normalMixerPosX = src.normalMixerPosX; + normalMixerPosY = src.normalMixerPosY; } @@ -751,7 +787,11 @@ class FBOImageProporties{ if(glWidget_ptr != NULL){ qDebug() << Q_FUNC_INFO; glWidget_ptr->makeCurrent(); + + if(glIsTexture(normalMixerInputTexId)) glWidget_ptr->deleteTexture(normalMixerInputTexId); if(glIsTexture(scr_tex_id)) GLCHK(glWidget_ptr->deleteTexture(scr_tex_id)); + normalMixerInputTexId = 0; + scr_tex_id = 0; glWidget_ptr = NULL; if(fbo != NULL ) delete fbo; } diff --git a/Sources/camera.cpp b/Sources/camera.cpp index b88ccc8..7c99513 100644 --- a/Sources/camera.cpp +++ b/Sources/camera.cpp @@ -43,8 +43,8 @@ QMatrix4x4& AwesomeCamera::updateCamera(void){ updown_direction ); } - rotM = unit_mat; - return rotM; + + return unit_mat; } QVector3D AwesomeCamera::get_position(){ if(isFree){ @@ -98,7 +98,38 @@ void AwesomeCamera::moveDown(float speed){ void AwesomeCamera::rotateView(float z_angle,float x_angle){ - rotM.setToIdentity(); +// rotM.setToIdentity(); + + + double cosPhi = cos(mouse_sens*(-z_angle)/180*M_PI); + double sinPhi = sin(mouse_sens*(-z_angle)/180*M_PI); + + + direction = QVector3D(cosPhi*direction.x()+sinPhi*direction.z(),direction.y(), + cosPhi*direction.z()-sinPhi*direction.x()); + + QMatrix4x4 rotMat; + rotMat.setToIdentity(); + rotMat.rotate(mouse_sens*(-x_angle),QVector3D::crossProduct(direction,QVector3D(0,1,0))); + QVector3D tmpVec = (rotMat*QVector4D(direction)).toVector3D(); + tmpVec.normalize(); + double angleTheta = QVector3D::dotProduct(tmpVec,QVector3D(0,1,0)); + if(qAbs(angleTheta) < 0.9){ + rotMat.setToIdentity(); + rotMat.rotate(mouse_sens*(-x_angle)*(1-qAbs(angleTheta)),QVector3D::crossProduct(direction,QVector3D(0,1,0))); + QVector3D tmpVec = (rotMat*QVector4D(direction)).toVector3D(); + tmpVec.normalize(); + direction = tmpVec; + } + + side_direction = QVector3D(cosPhi*side_direction.x()+sinPhi*side_direction.z(),0, + cosPhi*side_direction.z()-sinPhi*side_direction.x()); + + updown_direction = QVector3D::crossProduct(direction,side_direction); + + + +/* rot_angles[0] += mouse_sens*(z_angle);//przesuniecie X rot_angles[1] -= mouse_sens*(x_angle);//przesuniecie Y if(rot_angles[1] > 90) rot_angles[1] = 90; @@ -109,13 +140,21 @@ void AwesomeCamera::rotateView(float z_angle,float x_angle){ side_direction = QVector3D(sin((rot_angles[0]+90)/180*M_PI),0,-cos((rot_angles[0]+90)/180*M_PI)); // przesuwanie gora dol updown_direction = QVector3D::crossProduct(direction,side_direction); +*/ direction.normalize(); side_direction.normalize(); updown_direction.normalize(); -} +} +void AwesomeCamera::reset(){ + radius = 1; + position = QVector3D(0,0,0); + direction = QVector3D(0,0,1); + side_direction = QVector3D(1,0,0); + updown_direction = QVector3D(0,1,0); +} void AwesomeCamera::mouseWheelMove(int direction){ radius+=mouse_sens*0.0025f*direction; diff --git a/Sources/camera.h b/Sources/camera.h index 91ca6eb..81e667c 100644 --- a/Sources/camera.h +++ b/Sources/camera.h @@ -29,7 +29,7 @@ class AwesomeCamera void toggleFreeCamera(bool free); bool isFreeCamera(){return isFree;} void mouseWheelMove(int direction); - + void reset(); void moveForward(float speed); // ruch do przodu - zwykle klawisz W void moveBackward(float speed); // ruch do tylu - klawisz S @@ -57,7 +57,7 @@ class AwesomeCamera void setMouseSensitivity(int value); public: - QMatrix4x4 rotM; + QMatrix3x3 rotM; QVector3D position; // pozycja obserwatora QVector3D direction; // kierunek patrzenia QVector3D side_direction; //kierunek chodzenia na bok diff --git a/Sources/content.qrc b/Sources/content.qrc index 784bf05..632ba64 100644 --- a/Sources/content.qrc +++ b/Sources/content.qrc @@ -52,5 +52,9 @@ resources/filters.frag resources/filters_3d.frag resources/filters_3d.vert + resources/showMaterials.png + resources/showUVs.png + resources/resetCamera.png + resources/centerCamCursor.png diff --git a/Sources/dialogshortcuts.ui b/Sources/dialogshortcuts.ui index bc71d06..7c02aab 100644 --- a/Sources/dialogshortcuts.ui +++ b/Sources/dialogshortcuts.ui @@ -6,8 +6,8 @@ 0 0 - 298 - 300 + 302 + 400 @@ -142,76 +142,121 @@ - + Crtl+Return - + Restore 2D image position - + S - + Show material texture preview - + Ctrl+V - + (On Image tab) Paste Image from clipboard - + Ctrl+O - + (On Image tab) Open image from file - + Ctrl+C - + (On Image tab) Copy Image to clipboard + + + + Alt+W + + + + + + + Show Materials tab + + + + + + + Alt+E + + + + + + + Show UV settings tab + + + + + + + Shift + + + + + + + <html><head/><body><p>(On 3D Widget) Press Shift button then select point on the 3D mesh to choose new position of camera.</p></body></html> + + + true + + + diff --git a/Sources/formimageprop.cpp b/Sources/formimageprop.cpp index 976cd4e..1aeb09a 100644 --- a/Sources/formimageprop.cpp +++ b/Sources/formimageprop.cpp @@ -10,6 +10,8 @@ FormImageProp::FormImageProp(QMainWindow *parent, QGLWidget* qlW_ptr) : { ui->setupUi(this); + bOpenNormalMapMixer = false; + imageProp.glWidget_ptr = qlW_ptr; connect(ui->pushButtonOpenImage,SIGNAL(released()),this,SLOT(open())); @@ -162,6 +164,18 @@ FormImageProp::FormImageProp(QMainWindow *parent, QGLWidget* qlW_ptr) : connect(ui->comboBoxOcclusionInputImage,SIGNAL(activated(int)),this,SLOT(updateComboBoxes(int))); connect(ui->comboBoxRoughnessInputImage,SIGNAL(activated(int)),this,SLOT(updateComboBoxes(int))); + // normal map mixer + connect(ui->pushButtonNormalMixerLoadImage,SIGNAL(released()) ,this,SLOT(openNormalMixerImage())); + connect(ui->pushButtonNormalMixerPasteFromCB,SIGNAL(released()) ,this,SLOT(pasteNormalFromClipBoard())); + + connect(ui->checkBoxNormalMixerEnable,SIGNAL(clicked()) ,this,SLOT(updateGuiCheckBoxes())); + connect(ui->horizontalSliderNormalMixerDepth,SIGNAL(sliderReleased()),this,SLOT(updateSlidersOnRelease())); + connect(ui->horizontalSliderNormalMixerAngle,SIGNAL(sliderReleased()),this,SLOT(updateSlidersOnRelease())); + connect(ui->horizontalSliderNormalMixerScale,SIGNAL(sliderReleased()),this,SLOT(updateSlidersOnRelease())); + connect(ui->horizontalSliderNormalMixerScale,SIGNAL(valueChanged(int)),this,SLOT(updateSlidersNow(int))); + connect(ui->horizontalSliderNormalMixerPosX,SIGNAL(sliderReleased()),this,SLOT(updateSlidersOnRelease())); + connect(ui->horizontalSliderNormalMixerPosY,SIGNAL(sliderReleased()),this,SLOT(updateSlidersOnRelease())); + setAcceptDrops(true); @@ -192,9 +206,13 @@ FormImageProp::FormImageProp(QMainWindow *parent, QGLWidget* qlW_ptr) : ui->verticalLayoutBaseMapConvLevel3->addWidget(baseMapConvLevels[3]); for(int i = 0; i < 4 ; i++){ - baseMapConvLevels[i]->show(); } + + // normal mixer + ui->groupBoxNormalMixerSettings->hide(); + ui->groupBoxNormalMixer->hide(); + setMouseTracking(true); setFocus(); setFocusPolicy(Qt::ClickFocus); @@ -202,6 +220,7 @@ FormImageProp::FormImageProp(QMainWindow *parent, QGLWidget* qlW_ptr) : FormImageProp::~FormImageProp() { + delete heightCalculator; for(int i = 0; i < 4 ; i++) delete baseMapConvLevels[i]; delete ui; @@ -228,16 +247,26 @@ bool FormImageProp::loadFile(const QString &fileName) tr("Cannot load %1.").arg(QDir::toNativeSeparators(fileName))); return false; } + if(bOpenNormalMapMixer){ + qDebug() << " Open normal mixer image:" << fileName; + + imageProp.glWidget_ptr->makeCurrent(); + if(glIsTexture(imageProp.normalMixerInputTexId)) imageProp.glWidget_ptr->deleteTexture(imageProp.normalMixerInputTexId); + imageProp.normalMixerInputTexId = imageProp.glWidget_ptr->bindTexture(_image,GL_TEXTURE_2D); + ui->labelNormalMixerInfo->setText("Current image:"+ fileInfo.baseName()); + emit imageChanged(); - qDebug() << " Open image:" << fileName; + }else{ + qDebug() << " Open image:" << fileName; - imageName = fileInfo.baseName(); - (*recentDir).setPath(fileName); - image = _image; - imageProp.init(image); + imageName = fileInfo.baseName(); + (*recentDir).setPath(fileName); + image = _image; + imageProp.init(image); - //emit imageChanged(); - emit imageLoaded(image.width(),image.height()); + //emit imageChanged(); + emit imageLoaded(image.width(),image.height()); + } return true; } @@ -486,6 +515,14 @@ void FormImageProp::updateGuiSpinBoxesAndLabes(int){ imageProp.roughnessColorGlobalOffset= ui->horizontalSliderRoughnessColorGlobalOffset->value()/255.0; + + imageProp.normalMixerDepth = ui->horizontalSliderNormalMixerDepth->value(); + imageProp.normalMixerScale = ui->horizontalSliderNormalMixerScale->value()/10.0; + imageProp.normalMixerAngle = 3.1415926*ui->horizontalSliderNormalMixerAngle->value()/180.0; + imageProp.normalMixerPosX = ui->horizontalSliderNormalMixerPosX->value()/100.0; + imageProp.normalMixerPosY = ui->horizontalSliderNormalMixerPosY->value()/100.0; + + ui->labelNormalMixerScale->setText(QString::number(imageProp.normalMixerScale)); } void FormImageProp::updateSlidersOnRelease(){ @@ -494,6 +531,12 @@ void FormImageProp::updateSlidersOnRelease(){ emit imageChanged(); } +void FormImageProp::updateSlidersNow(int){ + + imageProp.normalMixerScale = ui->horizontalSliderNormalMixerScale->value()/10.0; + ui->labelNormalMixerScale->setText(QString::number(imageProp.normalMixerScale)); +} + void FormImageProp::updateGuiCheckBoxes(){ if(bLoading == true) return; @@ -519,6 +562,8 @@ void FormImageProp::updateGuiCheckBoxes(){ imageProp.bRoughnessInvertColorMask = ui->checkBoxRoughnessColorInvert->isChecked(); imageProp.bHeightEnableNormalization = ui->checkBoxHeightProcEnableNormalization->isChecked(); + imageProp.bNormalMixerEnabled = ui->checkBoxNormalMixerEnable->isChecked(); + if(imageProp.bRoughnessEnableColorPicking){ if(!imageProp.bRoughnessColorPickingToggled)ui->groupBoxGeneral->setDisabled(true); @@ -601,6 +646,32 @@ void FormImageProp::cancelColorPicking(){ } +void FormImageProp::openNormalMixerImage(){ + bOpenNormalMapMixer = true; + open(); + bOpenNormalMapMixer = false; +} + +void FormImageProp::pasteNormalFromClipBoard(){ + const QClipboard *clipboard = QApplication::clipboard(); + const QMimeData *mimeData = clipboard->mimeData(); + + if (mimeData->hasImage()) { + qDebug() << " Normal image :"+ + PostfixNames::getTextureName(imageProp.imageType)+ + " loaded from clipboard."; + QPixmap pixmap = qvariant_cast(mimeData->imageData()); + QImage _image = pixmap.toImage(); + + imageProp.glWidget_ptr->makeCurrent(); + if(glIsTexture(imageProp.normalMixerInputTexId)) imageProp.glWidget_ptr->deleteTexture(imageProp.normalMixerInputTexId); + imageProp.normalMixerInputTexId = imageProp.glWidget_ptr->bindTexture(_image,GL_TEXTURE_2D); + ui->labelNormalMixerInfo->setText("Current image: (clipboard source)"); + emit imageChanged(); + + } +} + void FormImageProp::togglePreviewSelectiveBlurMask(bool toggle){ QPalette palette = ui->pushButtonSelectiveBlurPreviewMask->palette(); palette.setColor(ui->pushButtonSelectiveBlurPreviewMask->backgroundRole(), QColor(255*int(toggle), 255*int(!toggle), 0, 127)); @@ -624,6 +695,10 @@ void FormImageProp::hideRoughnessInputGroup(){ ui->groupBoxRoughnessInputImage->hide(); } +void FormImageProp::showNormalMixerGroup(){ + ui->groupBoxNormalMixer->show(); +} + void FormImageProp::hideOcclusionInputGroup(){ ui->groupBoxOcclusionInputImage->hide(); } diff --git a/Sources/formimageprop.h b/Sources/formimageprop.h index 44c421e..bded9ed 100644 --- a/Sources/formimageprop.h +++ b/Sources/formimageprop.h @@ -44,6 +44,7 @@ class FormImageProp : public FormImageBase void hideNormalInputGroup(); void hideSpecularInputGroup(); void hideRoughnessInputGroup(); + void showNormalMixerGroup(); ~FormImageProp(); @@ -57,6 +58,7 @@ public slots: void updateGuiSpinBoxesAndLabes(int); void updateSlidersOnRelease(); void updateGuiCheckBoxes(); + void updateSlidersNow(int); void applyHeightToNormalConversion(); @@ -72,7 +74,9 @@ public slots: void colorPicked(QVector4D); void cancelColorPicking(); - + // normal mixer + void openNormalMixerImage(); + void pasteNormalFromClipBoard(); signals: void reloadSettingsFromConfigFile(TextureTypes type); void imageChanged(); @@ -94,6 +98,10 @@ public slots: DialogHeightCalculator *heightCalculator; // height calculator tool FormBaseMapConversionLevels* baseMapConvLevels[4]; // for levels of mipmaps +public: + + bool bOpenNormalMapMixer; + }; diff --git a/Sources/formimageprop.ui b/Sources/formimageprop.ui index 77446d9..46093e6 100644 --- a/Sources/formimageprop.ui +++ b/Sources/formimageprop.ui @@ -7,7 +7,7 @@ 0 0 279 - 2380 + 2511 @@ -373,6 +373,254 @@ + + + + + + + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + + + + + Normal mixer + + + + + + + Normal mixer settings + + + + 2 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + No image loaded. + + + + + + + + + + 30 + 0 + + + + 0 + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Load... + + + + + + + Paste from Clipboard + + + + + + + Depth + + + + + + + -180 + + + 0 + + + 0 + + + Qt::Horizontal + + + + + + + Angle + + + + + + + 100 + + + 0 + + + 10 + + + Qt::Horizontal + + + + + + + -100 + + + 100 + + + 0 + + + Qt::Horizontal + + + + + + + Scale + + + + + + + Pos X + + + + + + + Pos Y + + + + + + + -100 + + + 100 + + + 0 + + + Qt::Horizontal + + + + + + + 0 + + + + + + + 1 + + + + + + + 0 + + + + + + + 0 + + + + + + + -200 + + + 200 + + + 0 + + + Qt::Horizontal + + + + + + + + + + + @@ -4077,12 +4325,12 @@ setNum(int) - 257 - 1686 + 233 + 1462 - 293 - 1686 + 269 + 1462 @@ -4093,12 +4341,12 @@ setNum(int) - 280 - 1793 + 236 + 1535 - 295 - 1793 + 272 + 1535 @@ -4109,12 +4357,12 @@ setNum(int) - 280 - 1828 + 236 + 1558 - 295 - 1828 + 272 + 1558 @@ -4125,12 +4373,12 @@ setNum(int) - 280 - 1863 + 236 + 1582 - 295 - 1863 + 272 + 1582 @@ -4141,12 +4389,12 @@ setNum(int) - 280 - 1898 + 236 + 1605 - 295 - 1898 + 272 + 1605 @@ -4157,12 +4405,12 @@ setNum(int) - 280 - 1933 + 236 + 1629 - 295 - 1933 + 272 + 1629 @@ -4173,12 +4421,12 @@ setNum(int) - 259 - 1143 + 236 + 1067 - 295 - 1143 + 272 + 1067 @@ -4189,12 +4437,12 @@ setNum(int) - 280 - 1968 + 236 + 1653 - 295 - 1968 + 272 + 1653 @@ -4205,12 +4453,12 @@ setNum(int) - 259 - 1108 + 236 + 1042 - 295 - 1108 + 272 + 1042 @@ -4221,12 +4469,12 @@ setNum(int) - 259 - 1178 + 236 + 1092 - 295 - 1178 + 272 + 1092 @@ -4237,12 +4485,12 @@ setNum(int) - 259 - 1213 + 236 + 1117 - 295 - 1213 + 272 + 1117 @@ -4253,12 +4501,12 @@ setNum(int) - 259 - 1248 + 236 + 1142 - 295 - 1248 + 272 + 1142 @@ -4269,12 +4517,12 @@ setNum(int) - 259 - 1283 + 236 + 1167 - 295 - 1283 + 272 + 1167 @@ -4285,12 +4533,12 @@ setNum(int) - 247 - 2089 + 223 + 1761 - 293 - 2089 + 269 + 1761 @@ -4301,12 +4549,12 @@ setVisible(bool) - 295 - 1335 + 272 + 1211 - 295 - 1513 + 272 + 1329 @@ -4317,12 +4565,12 @@ setNum(int) - 249 - 1431 + 225 + 1282 - 285 - 1431 + 261 + 1282 @@ -4333,12 +4581,12 @@ setNum(int) - 249 - 1466 + 225 + 1300 - 285 - 1466 + 261 + 1300 @@ -4349,12 +4597,12 @@ setNum(int) - 249 - 1501 + 225 + 1318 - 285 - 1501 + 261 + 1318 @@ -4365,12 +4613,12 @@ setNum(int) - 247 - 2124 + 223 + 1786 - 293 - 2124 + 269 + 1786 @@ -4381,12 +4629,12 @@ setNum(int) - 226 - 2567 + 203 + 2089 - 292 - 2567 + 269 + 2089 @@ -4397,12 +4645,12 @@ setNum(int) - 226 - 2602 + 203 + 2114 - 292 - 2602 + 269 + 2114 @@ -4413,12 +4661,12 @@ setNum(int) - 255 - 2688 + 230 + 2178 - 291 - 2688 + 266 + 2178 @@ -4429,12 +4677,12 @@ setNum(int) - 255 - 2723 + 230 + 2203 - 291 - 2723 + 266 + 2203 @@ -4445,12 +4693,12 @@ setNum(int) - 255 - 2758 + 230 + 2228 - 291 - 2758 + 266 + 2228 @@ -4461,12 +4709,12 @@ setNum(int) - 255 - 2793 + 230 + 2253 - 291 - 2793 + 266 + 2253 @@ -4477,12 +4725,12 @@ setNum(int) - 259 - 2848 + 242 + 2295 - 291 - 2848 + 266 + 2295 @@ -4493,12 +4741,12 @@ setNum(int) - 259 - 2883 + 242 + 2320 - 291 - 2883 + 266 + 2320 @@ -4509,12 +4757,12 @@ setNum(int) - 259 - 2918 + 242 + 2345 - 291 - 2918 + 266 + 2345 @@ -4525,12 +4773,12 @@ setNum(int) - 259 - 2953 + 242 + 2370 - 291 - 2953 + 266 + 2370 @@ -4541,12 +4789,12 @@ setVisible(bool) - 107 - 2451 + 117 + 1996 - 85 - 2962 + 90 + 2265 @@ -4557,12 +4805,12 @@ setNum(int) - 280 - 1758 + 236 + 1511 - 295 - 1758 + 272 + 1511 @@ -4573,12 +4821,12 @@ setNum(int) - 257 - 1721 + 233 + 1487 - 293 - 1721 + 269 + 1487 @@ -4589,12 +4837,12 @@ setVisible(bool) - 120 - 1335 + 107 + 1211 - 95 - 1726 + 100 + 1370 @@ -4605,12 +4853,12 @@ setNum(int) - 254 - 690 + 229 + 730 - 290 - 690 + 265 + 730 @@ -4621,12 +4869,12 @@ setNum(int) - 254 - 725 + 229 + 755 - 290 - 725 + 265 + 755 @@ -4637,12 +4885,12 @@ setNum(int) - 254 - 760 + 229 + 780 - 290 - 760 + 265 + 780 @@ -4653,12 +4901,12 @@ setNum(int) - 254 - 922 + 229 + 912 - 290 - 922 + 265 + 912 @@ -4669,12 +4917,12 @@ setNum(int) - 254 - 957 + 229 + 937 - 290 - 957 + 265 + 937 @@ -4685,12 +4933,12 @@ setNum(int) - 226 - 2637 + 203 + 2139 - 292 - 2637 + 269 + 2139 @@ -4701,12 +4949,12 @@ setVisible(bool) - 191 - 639 + 180 + 691 - 98 - 765 + 116 + 784 @@ -4717,12 +4965,12 @@ setVisible(bool) - 292 - 639 + 268 + 691 - 107 - 997 + 116 + 841 @@ -4733,12 +4981,12 @@ setVisible(bool) - 109 - 2171 + 125 + 1825 - 98 - 2397 + 106 + 1839 @@ -4749,12 +4997,12 @@ setVisible(bool) - 98 - 3012 + 108 + 2419 - 105 - 3362 + 115 + 2499 @@ -4765,7 +5013,7 @@ setEnabled(bool) - 123 + 92 887 @@ -4781,12 +5029,12 @@ setNum(int) - 254 - 992 + 229 + 962 - 290 - 992 + 265 + 962 @@ -4797,12 +5045,12 @@ setNum(int) - 244 - 1613 + 219 + 1410 - 290 - 1613 + 265 + 1410 @@ -4813,12 +5061,92 @@ setNum(int) - 244 - 1648 + 219 + 1435 + + + 265 + 1435 + + + + + horizontalSliderNormalMixerDepth + valueChanged(int) + label_22 + setNum(int) + + + 150 + 292 + + + 271 + 304 + + + + + checkBoxNormalMixerEnable + toggled(bool) + groupBoxNormalMixerSettings + setVisible(bool) + + + 85 + 223 + + + 69 + 253 + + + + + horizontalSliderNormalMixerAngle + valueChanged(int) + label_28 + setNum(int) + + + 217 + 322 + + + 250 + 321 + + + + + horizontalSliderNormalMixerPosX + valueChanged(int) + label_31 + setNum(int) + + + 217 + 374 - 290 - 1648 + 255 + 368 + + + + + horizontalSliderNormalMixerPosY + valueChanged(int) + label_32 + setNum(int) + + + 200 + 395 + + + 249 + 394 diff --git a/Sources/formmaterialindicesmanager.cpp b/Sources/formmaterialindicesmanager.cpp index 60fe25a..de9c418 100644 --- a/Sources/formmaterialindicesmanager.cpp +++ b/Sources/formmaterialindicesmanager.cpp @@ -65,7 +65,7 @@ bool FormMaterialIndicesManager::updateMaterials(QImage& image){ if(colorIndices.size() > 32){ QMessageBox msgBox; msgBox.setText("Error: too much colors!"); - msgBox.setInformativeText(" Sorry, but this image does not look like a material texture." + msgBox.setInformativeText(" Sorry, but this image does not look like a material texture.\n" " Your image contains more than 32 different colors"); msgBox.setStandardButtons(QMessageBox::Cancel); msgBox.exec(); @@ -259,8 +259,8 @@ void FormMaterialIndicesManager::chooseMaterialByColor(QColor color){ // if color not found on the list if(!bColorFound){ QMessageBox::information(this, QGuiApplication::applicationDisplayName(), - "The picked color was not found in the materials table" - "make sure you chose the correct color e.g" + "The picked color was not found in the materials table\n" + "make sure you chose the correct color e.g\n" "not the sky box background."); } } diff --git a/Sources/formmaterialindicesmanager.ui b/Sources/formmaterialindicesmanager.ui index 89cc5cf..0097177 100644 --- a/Sources/formmaterialindicesmanager.ui +++ b/Sources/formmaterialindicesmanager.ui @@ -6,14 +6,35 @@ 0 0 - 222 - 335 + 264 + 405 + + + 0 + 0 + + Form + + QLayout::SetMaximumSize + + + 2 + + + 2 + + + 2 + + + 2 + @@ -57,13 +78,6 @@ - - - - Qt::Horizontal - - - @@ -83,15 +97,36 @@ - + 0 0 + + + 10000 + 16777215 + + Material Indices + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + @@ -100,23 +135,56 @@ 0 + + + 2000 + 16777215 + + + + QFrame::NoFrame + + + QFrame::Plain + + + Qt::ScrollBarAlwaysOff + true + + Qt::AlignCenter + 0 0 - 182 - 131 + 260 + 240 + + 3 + + + 2 + + + 2 + + + 2 + + + 2 + - + 0 0 @@ -127,9 +195,24 @@ 0 + + + 2000 + 16777215 + + + + Qt::ScrollBarAlwaysOff + QListView::ListMode + + 80 + + + false + Material1 diff --git a/Sources/glimageeditor.cpp b/Sources/glimageeditor.cpp index f1e25fc..65a8fd2 100644 --- a/Sources/glimageeditor.cpp +++ b/Sources/glimageeditor.cpp @@ -173,6 +173,8 @@ void GLImage::initializeGL() GLCHK( subroutines["mode_height_to_normal"] = glGetSubroutineIndex(program->programId(),GL_FRAGMENT_SHADER,"mode_height_to_normal") ); GLCHK( subroutines["mode_sharpen_blur"] = glGetSubroutineIndex(program->programId(),GL_FRAGMENT_SHADER,"mode_sharpen_blur") ); GLCHK( subroutines["mode_normals_step_filter"] = glGetSubroutineIndex(program->programId(),GL_FRAGMENT_SHADER,"mode_normals_step_filter") ); + GLCHK( subroutines["mode_normal_mixer_filter"] = glGetSubroutineIndex(program->programId(),GL_FRAGMENT_SHADER,"mode_normal_mixer_filter") ); + GLCHK( subroutines["mode_invert_components_filter"] = glGetSubroutineIndex(program->programId(),GL_FRAGMENT_SHADER,"mode_invert_components_filter") ); GLCHK( subroutines["mode_normal_to_height"] = glGetSubroutineIndex(program->programId(),GL_FRAGMENT_SHADER,"mode_normal_to_height") ); GLCHK( subroutines["mode_sobel_filter"] = glGetSubroutineIndex(program->programId(),GL_FRAGMENT_SHADER,"mode_sobel_filter") ); @@ -725,7 +727,13 @@ void GLImage::render(){ if(activeImage->imageType == NORMAL_TEXTURE){ applyNormalsStepFilter(activeFBO,auxFBO1); - copyFBO(auxFBO1,activeFBO); + + // apply normal mixer filter + if(activeImage->bNormalMixerEnabled && activeImage->normalMixerInputTexId != 0){ + applyNormalMixerFilter(auxFBO1,activeFBO); + }else{// otherwise skip + copyFBO(auxFBO1,activeFBO); + } } // -------------------------------------------------------- // @@ -1303,7 +1311,7 @@ void GLImage::applySeamlessLinearFilter(QGLFramebufferObject* inputFBO, // when translations are applied first one has to translate // alse the contrast mask image if(FBOImageProporties::bSeamlessTranslationsFirst){ - applyPerspectiveTransformFilter(auxFBO1,outputFBO);// the output is save to auxFBO2 + applyPerspectiveTransformFilter(auxFBO1,outputFBO);// the output is save to auxFBO1 } GLCHK( glActiveTexture(GL_TEXTURE1) ); @@ -1716,6 +1724,35 @@ void GLImage::applyNormalsStepFilter(QGLFramebufferObject* inputFBO, } +void GLImage::applyNormalMixerFilter(QGLFramebufferObject* inputFBO, + QGLFramebufferObject* outputFBO){ + + + GLCHK( glUniformSubroutinesuiv( GL_FRAGMENT_SHADER, 1, &subroutines["mode_normal_mixer_filter"]) ); + GLCHK( program->setUniformValue("quad_scale", QVector2D(1.0,1.0)) ); + GLCHK( program->setUniformValue("quad_pos" , QVector2D(0.0,0.0)) ); + + GLCHK( program->setUniformValue("gui_normal_mixer_depth", activeImage->normalMixerDepth) ); + GLCHK( program->setUniformValue("gui_normal_mixer_angle", activeImage->normalMixerAngle) ); + GLCHK( program->setUniformValue("gui_normal_mixer_scale", activeImage->normalMixerScale) ); + GLCHK( program->setUniformValue("gui_normal_mixer_pos_x", activeImage->normalMixerPosX) ); + GLCHK( program->setUniformValue("gui_normal_mixer_pos_y", activeImage->normalMixerPosY) ); + + GLCHK( glViewport(0,0,inputFBO->width(),inputFBO->height()) ); + GLCHK( outputFBO->bind() ); + GLCHK( glActiveTexture(GL_TEXTURE0) ); + GLCHK( glBindTexture(GL_TEXTURE_2D, inputFBO->texture()) ); + + GLCHK( glActiveTexture(GL_TEXTURE1) ); + GLCHK( glBindTexture(GL_TEXTURE_2D, activeImage->normalMixerInputTexId) ); + + + GLCHK( glDrawElements(GL_TRIANGLES, 3*2, GL_UNSIGNED_INT, 0) ); + GLCHK( outputFBO->bindDefault() ); + GLCHK( glActiveTexture(GL_TEXTURE0) ); + +} + void GLImage::applyPreSmoothFilter( QGLFramebufferObject* inputFBO, QGLFramebufferObject* auxFBO, diff --git a/Sources/glimageeditor.h b/Sources/glimageeditor.h index 3088a4c..a871f57 100644 --- a/Sources/glimageeditor.h +++ b/Sources/glimageeditor.h @@ -177,6 +177,11 @@ public slots: void applyNormalsStepFilter(QGLFramebufferObject* inputFBO, QGLFramebufferObject* outputFBO); + + + void applyNormalMixerFilter(QGLFramebufferObject* inputFBO, + QGLFramebufferObject* outputFBO); + void applySobelToNormalFilter(QGLFramebufferObject* inputFBO, QGLFramebufferObject* outputFBO, BaseMapConvLevelProperties &convProp); diff --git a/Sources/glwidget.cpp b/Sources/glwidget.cpp index 58b345b..d4b4c77 100644 --- a/Sources/glwidget.cpp +++ b/Sources/glwidget.cpp @@ -47,6 +47,7 @@ QDir* GLWidget::recentMeshDir = NULL; GLWidget::GLWidget(QWidget *parent, QGLWidget * shareWidget) : GLWidgetBase(QGLFormat::defaultFormat(), parent, shareWidget) { + setAcceptDrops(true); zoom = 60; lightPosition = QVector4D(0,0,5.0,1); depthScale = 1; @@ -70,6 +71,7 @@ GLWidget::GLWidget(QWidget *parent, QGLWidget * shareWidget) setCursor(Qt::PointingHandCursor); lightCursor = QCursor(QPixmap(":/resources/lightCursor.png")); + glImagePtr = (GLImage*)shareWidget; // Post processing variables: colorFBO = NULL; @@ -80,6 +82,8 @@ GLWidget::GLWidget(QWidget *parent, QGLWidget * shareWidget) glowOutputColor[i] = NULL; } + cameraInterpolation = 1.0; + } GLWidget::~GLWidget() @@ -93,6 +97,7 @@ void GLWidget::cleanup() deleteFBOs(); delete program; + delete line_program; delete skybox_program; delete env_program; delete filters_program; @@ -137,6 +142,16 @@ void GLWidget::setCameraMouseSensitivity(int value){ camera.setMouseSensitivity(value); } +void GLWidget::resetCameraPosition(){ + + camera.reset(); + newCamera.reset(); + cameraInterpolation = 1.0; + emit changeCamPositionApplied(false); + updateGL(); +} + + void GLWidget::toggleDiffuseView(bool enable){ bToggleDiffuseView = enable; updateGL(); @@ -179,6 +194,7 @@ void GLWidget::selectShadingType(int indeks){ void GLWidget::selectShadingModel(int i){ shadingModel = (ShadingModel) i; + updateGL(); } @@ -237,7 +253,16 @@ void GLWidget::initializeGL() qDebug() << "Loading quad (geometry shader)"; QOpenGLShader *gshader = new QOpenGLShader(QOpenGLShader::Geometry, this); - gshader->compileSourceFile(":/resources/plane.geom"); + QFile gFile(":/resources/plane.geom"); + gFile.open(QFile::ReadOnly); + qDebug() << gFile.isOpen() << " File"; + + QTextStream in(&gFile); + QString preambule = "#version 400 core\n" + "layout(triangle_strip, max_vertices = 3) out;\n" ; + QString shaderCode = in.readAll(); + gshader->compileSourceCode(preambule+shaderCode); + //gshader->compileSourceFile(in.readAll()); if (!gshader->log().isEmpty()) qDebug() << gshader->log(); else qDebug() << "done"; @@ -266,8 +291,37 @@ void GLWidget::initializeGL() program->setUniformValue("texDiffuseEnvMap", 8); program->setUniformValue("texEnvMap" , 9); + // lines shader + qDebug() << "Compiling lines program..."; + preambule = QString("#version 400 core\n")+ + "layout(line_strip, max_vertices = 3) out;\n" ; + gshader->compileSourceCode(preambule+shaderCode); + + line_program = new QOpenGLShaderProgram(this); + line_program->addShader(vshader); + line_program->addShader(fshader); + line_program->addShader(tcshader); + line_program->addShader(teshader); + line_program->addShader(gshader); + line_program->bindAttributeLocation("FragColor",0); + line_program->bindAttributeLocation("FragNormal",1); + line_program->bindAttributeLocation("FragGlowColor",2); + line_program->bindAttributeLocation("FragPosition",3); + GLCHK(line_program->link()); + + GLCHK(line_program->bind()); + line_program->setUniformValue("texDiffuse" , 0); + line_program->setUniformValue("texNormal" , 1); + line_program->setUniformValue("texSpecular" , 2); + line_program->setUniformValue("texHeight" , 3); + line_program->setUniformValue("texSSAO" , 4); + line_program->setUniformValue("texRoughness", 5); + line_program->setUniformValue("texMetallic", 6); + line_program->setUniformValue("texMaterial", 7); + + line_program->setUniformValue("texDiffuseEnvMap", 8); + line_program->setUniformValue("texEnvMap" , 9); - //GLCHK( subroutines["render_shader"] = glGetSubroutineIndex(program->programId(),GL_FRAGMENT_SHADER,"render_shader") ); delete vshader; delete fshader; @@ -381,6 +435,7 @@ void GLWidget::initializeGL() camera.position.setZ( -0 ); camera.toggleFreeCamera(false); + newCamera.toggleFreeCamera(false); lightDirection.position.setZ(0); lightDirection.toggleFreeCamera(false); @@ -401,12 +456,23 @@ void GLWidget::paintGL() { + glReadBuffer(GL_BACK); // --------------------------------------------------------- // Drawing env // --------------------------------------------------------- bakeEnviromentalMaps(); - + colorFBO->bindDefault(); GLCHK( glViewport(0, 0, width(), height()) ); + + if(cameraInterpolation < 1.0){ + double w = cameraInterpolation; + camera.position = camera.position*(1-w) + newCamera.position * w; + cameraInterpolation += 0.01; + + } + + + // setting the camera viewpoint viewMatrix = camera.updateCamera(); @@ -418,6 +484,7 @@ void GLWidget::paintGL() + // set to which FBO result will be drawn GLuint attachments[4] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 , GL_COLOR_ATTACHMENT3 }; glDrawBuffers(4, attachments); @@ -452,16 +519,24 @@ void GLWidget::paintGL() - // --------------------------------------------------------- // Drawing model // --------------------------------------------------------- + QOpenGLShaderProgram* program_ptrs[2] = {program,line_program}; + + GLCHK( glEnable(GL_CULL_FACE) ); GLCHK( glEnable(GL_DEPTH_TEST) ); GLCHK( glCullFace(GL_FRONT) ); - GLCHK( program->bind() ); + glDisable(GL_POLYGON_OFFSET_LINE); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - GLCHK( program->setUniformValue("ProjectionMatrix", projectionMatrix) ); + for(int pindex = 0 ; pindex < 2 ; pindex ++){ + + QOpenGLShaderProgram* program_ptr = program_ptrs[pindex]; + GLCHK( program_ptr->bind() ); + + GLCHK( program_ptr->setUniformValue("ProjectionMatrix", projectionMatrix) ); objectMatrix.setToIdentity(); if( fboIdPtrs[0] != NULL){ @@ -473,45 +548,67 @@ void GLWidget::paintGL() objectMatrix.scale(0.5/mesh->radius); objectMatrix.translate(-mesh->centre_of_mass); } - modelViewMatrix = camera.updateCamera()*objectMatrix; + modelViewMatrix = viewMatrix*objectMatrix; NormalMatrix = modelViewMatrix.normalMatrix(); float mesh_scale = 0.5/mesh->radius; - GLCHK( program->setUniformValue("ModelViewMatrix" , modelViewMatrix) ); - GLCHK( program->setUniformValue("NormalMatrix" , NormalMatrix) ); - GLCHK( program->setUniformValue("ModelMatrix" , objectMatrix) ); - GLCHK( program->setUniformValue("meshScale" , mesh_scale) ); - GLCHK( program->setUniformValue("lightPos" , lightPosition) ); - - GLCHK( program->setUniformValue("lightDirection" , lightDirection.direction) ); - GLCHK( program->setUniformValue("cameraPos" , camera.get_position()) ); - GLCHK( program->setUniformValue("gui_depthScale" , depthScale) ); - GLCHK( program->setUniformValue("gui_uvScale" , uvScale) ); - GLCHK( program->setUniformValue("gui_uvScaleOffset" , uvOffset) ); - GLCHK( program->setUniformValue("gui_bSpecular" , bToggleSpecularView) ); - GLCHK( program->setUniformValue("gui_bDiffuse" , bToggleDiffuseView) ); - GLCHK( program->setUniformValue("gui_bOcclusion" , bToggleOcclusionView) ); - GLCHK( program->setUniformValue("gui_bHeight" , bToggleHeightView) ); - GLCHK( program->setUniformValue("gui_bNormal" , bToggleNormalView) ); - GLCHK( program->setUniformValue("gui_bRoughness" , bToggleRoughnessView) ); - GLCHK( program->setUniformValue("gui_bMetallic" , bToggleMetallicView) ); - GLCHK( program->setUniformValue("gui_shading_type" , shadingType) ); - GLCHK( program->setUniformValue("gui_shading_model" , shadingModel) ); - GLCHK( program->setUniformValue("gui_SpecularIntensity" , specularIntensity) ); - GLCHK( program->setUniformValue("gui_DiffuseIntensity" , diffuseIntensity) ); - GLCHK( program->setUniformValue("gui_LightPower" , lightPower) ); - GLCHK( program->setUniformValue("gui_LightRadius" , lightRadius) ); + GLCHK( program_ptr->setUniformValue("ModelViewMatrix" , modelViewMatrix) ); + GLCHK( program_ptr->setUniformValue("NormalMatrix" , NormalMatrix) ); + GLCHK( program_ptr->setUniformValue("ModelMatrix" , objectMatrix) ); + GLCHK( program_ptr->setUniformValue("meshScale" , mesh_scale) ); + GLCHK( program_ptr->setUniformValue("lightPos" , lightPosition) ); + + GLCHK( program_ptr->setUniformValue("lightDirection" , lightDirection.direction) ); + GLCHK( program_ptr->setUniformValue("cameraPos" , camera.get_position()) ); + GLCHK( program_ptr->setUniformValue("gui_depthScale" , depthScale) ); + GLCHK( program_ptr->setUniformValue("gui_uvScale" , uvScale) ); + GLCHK( program_ptr->setUniformValue("gui_uvScaleOffset" , uvOffset) ); + GLCHK( program_ptr->setUniformValue("gui_bSpecular" , bToggleSpecularView) ); + GLCHK( program_ptr->setUniformValue("gui_bDiffuse" , bToggleDiffuseView) ); + GLCHK( program_ptr->setUniformValue("gui_bOcclusion" , bToggleOcclusionView) ); + GLCHK( program_ptr->setUniformValue("gui_bHeight" , bToggleHeightView) ); + GLCHK( program_ptr->setUniformValue("gui_bNormal" , bToggleNormalView) ); + GLCHK( program_ptr->setUniformValue("gui_bRoughness" , bToggleRoughnessView) ); + GLCHK( program_ptr->setUniformValue("gui_bMetallic" , bToggleMetallicView) ); + GLCHK( program_ptr->setUniformValue("gui_shading_type" , shadingType) ); + GLCHK( program_ptr->setUniformValue("gui_shading_model" , shadingModel) ); + GLCHK( program_ptr->setUniformValue("gui_SpecularIntensity" , specularIntensity) ); + GLCHK( program_ptr->setUniformValue("gui_DiffuseIntensity" , diffuseIntensity) ); + GLCHK( program_ptr->setUniformValue("gui_LightPower" , lightPower) ); + GLCHK( program_ptr->setUniformValue("gui_LightRadius" , lightRadius) ); // number of mipmaps - GLCHK( program->setUniformValue("num_mipmaps" , m_env_map->numMipmaps ) ); + GLCHK( program_ptr->setUniformValue("num_mipmaps" , m_env_map->numMipmaps ) ); // 3D settings - GLCHK( program->setUniformValue("gui_bUseCullFace" , performanceSettings.bUseCullFace) ); - GLCHK( program->setUniformValue("gui_bUseSimplePBR" , performanceSettings.bUseSimplePBR) ); - GLCHK( program->setUniformValue("gui_noTessSub" , performanceSettings.noTessSubdivision) ); - GLCHK( program->setUniformValue("gui_noPBRRays" , performanceSettings.noPBRRays) ); + GLCHK( program_ptr->setUniformValue("gui_bUseCullFace" , performanceSettings.bUseCullFace) ); + GLCHK( program_ptr->setUniformValue("gui_bUseSimplePBR" , performanceSettings.bUseSimplePBR) ); + GLCHK( program_ptr->setUniformValue("gui_noTessSub" , performanceSettings.noTessSubdivision) ); + GLCHK( program_ptr->setUniformValue("gui_noPBRRays" , performanceSettings.noPBRRays) ); + + if(performanceSettings.bShowTriangleEdges && pindex == 0){ + glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); + glEnable( GL_POLYGON_OFFSET_FILL ); + glPolygonOffset( 1.0f, 1.0f ); + GLCHK( program_ptr->setUniformValue("gui_bShowTriangleEdges", true) ); + GLCHK( program_ptr->setUniformValue("gui_bMaterialsPreviewEnabled" , true) ); + }else{ + if(performanceSettings.bShowTriangleEdges){ + glDisable( GL_POLYGON_OFFSET_FILL ); + glEnable( GL_POLYGON_OFFSET_LINE ); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glPolygonOffset( -2.0f, -2.0f ); + glLineWidth(1.0f); + + } + + GLCHK( program_ptr->setUniformValue("gui_bShowTriangleEdges", performanceSettings.bShowTriangleEdges) ); + + // Material preview: M key : when triangles are disabled + if(!performanceSettings.bShowTriangleEdges) + GLCHK( program_ptr->setUniformValue("gui_bMaterialsPreviewEnabled" , bool(keyPressed == KEY_SHOW_MATERIALS)) ); + } + - // Material preview: M key - GLCHK( program->setUniformValue("gui_bMaterialsPreviewEnabled" , bool(keyPressed == KEY_SHOW_MATERIALS)) ); if( fboIdPtrs[0] != NULL){ @@ -527,13 +624,17 @@ void GLWidget::paintGL() tindeks++; GLCHK( glActiveTexture(GL_TEXTURE0 + tindeks) ); - GLCHK(m_env_map->bind()); + GLCHK( m_env_map->bind()); GLCHK( mesh->drawMesh() ); // set default active texture glActiveTexture(GL_TEXTURE0); } + if(!performanceSettings.bShowTriangleEdges) break; + }// end of loop over triangles + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glDisable( GL_POLYGON_OFFSET_LINE ); // return to standard settings GLCHK( glDisable(GL_CULL_FACE) ); GLCHK( glDisable(GL_DEPTH_TEST) ); @@ -542,11 +643,13 @@ void GLWidget::paintGL() GLuint attachments2[1] = { GL_COLOR_ATTACHMENT0 }; glDrawBuffers(1, attachments2); + colorFBO->bindDefault(); GLCHK( glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ); GLCHK( filters_program->bind() ); + // do post processing if materials are not shown if( keyPressed != KEY_SHOW_MATERIALS ){ // ----------------------------------------------------------- @@ -558,7 +661,7 @@ void GLWidget::paintGL() if(performanceSettings.bBloomEffect){ applyGlowFilter(outputFBO->fbo); copyTexToFBO(outputFBO->fbo->texture(),colorFBO->fbo); - //applyNormalFilter(outputFBO->fbo->texture()); + //applyNormalFilter(outputFBO->fbo->texture()); }// end of if bloom effect // ----------------------------------------------------------- @@ -572,7 +675,7 @@ void GLWidget::paintGL() applyNormalFilter(colorFBO->fbo->texture()); }else{ // end of if SHOW MATERIALS TEXTURE DISABLED - applyNormalFilter(colorFBO->fbo->texture()); + GLCHK( applyNormalFilter(colorFBO->fbo->texture())); } GLCHK( filters_program->release() ); @@ -631,6 +734,33 @@ void GLWidget::mousePressEvent(QMouseEvent *event) setCursor(lightCursor); + }else if((event->buttons() & Qt::LeftButton) && (keyPressed == Qt::Key_Shift) ){ + + colorFBO->bind(); + glReadBuffer(GL_COLOR_ATTACHMENT1); // NormalFBO actually it contains World Space position + vector< float > pixels( 1 * 1 * 4 ); + glReadPixels(event->pos().x(), height()-event->pos().y(), 1, 1,GL_RGBA, GL_FLOAT, &pixels[0]); + QVector3D position = QVector3D(pixels[0],pixels[1],pixels[2]); + + // when clicked on mesh other wise it has to be skybox + if(position.length() < 50.0){ + qDebug() << "Picked position pixel (" << event->pos().x() << " , " << height()-event->pos().y() << ") with position:" << position; + colorFBO->bindDefault(); + QVector3D curr_pos = camera.position - camera.radius * camera.direction; + QVector3D new_dir = (position - curr_pos); + new_dir.normalize(); + // update new Camera position + cameraInterpolation = 0 ; // reset camera interpolation 'clock' + newCamera.position = position; + newCamera.direction = new_dir; + newCamera.radius =-QVector3D::dotProduct(curr_pos - position,new_dir); + glReadBuffer(GL_BACK); + keyPressed = (Qt::Key)0; + newCamera.side_direction = QVector3D(newCamera.direction.z(),0,-newCamera.direction.x()); + newCamera.rotateView(0,0); + } + emit changeCamPositionApplied(false); + } @@ -639,6 +769,7 @@ void GLWidget::mousePressEvent(QMouseEvent *event) if((event->buttons() & Qt::LeftButton) && keyPressed == KEY_SHOW_MATERIALS){ vector< unsigned char > pixels( 1 * 1 * 4 ); + glReadPixels(event->pos().x(), height()-event->pos().y(), 1, 1,GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]); QColor color = QColor(pixels[0],pixels[1],pixels[2],pixels[3]); @@ -713,6 +844,28 @@ void GLWidget::wheelEvent(QWheelEvent *event){ updateGL(); } +void GLWidget::dropEvent(QDropEvent *event) +{ + + QList droppedUrls = event->mimeData()->urls(); + int i = 0; + QString localPath = droppedUrls[i].toLocalFile(); + QFileInfo fileInfo(localPath); + + loadMeshFile(fileInfo.absoluteFilePath(),false); + + + event->acceptProposedAction(); + +} + +void GLWidget::dragEnterEvent(QDragEnterEvent *event) +{ + if(event->mimeData()->hasText()) { + event->acceptProposedAction(); + } +} + void GLWidget::setPointerToTexture(QGLFramebufferObject **pointer, TextureTypes tType){ @@ -879,11 +1032,14 @@ void GLWidget::applyNormalFilter(GLuint input_tex){ GLCHK( glViewport(0,0,width(),height()) ); GLCHK( glUniformSubroutinesuiv( GL_FRAGMENT_SHADER, 1, &subroutines["mode_normal_filter"]) ); + GLCHK( filters_program->setUniformValue("quad_scale", QVector2D(1.0,1.0)) ); GLCHK( filters_program->setUniformValue("quad_pos" , QVector2D(0.0,0.0)) ); GLCHK( glActiveTexture(GL_TEXTURE0) ); GLCHK( glBindTexture(GL_TEXTURE_2D, input_tex) ); - quad_mesh->drawMesh(true); + + GLCHK( quad_mesh->drawMesh(true) ); + } diff --git a/Sources/glwidget.h b/Sources/glwidget.h index aa4955a..b34e5f6 100644 --- a/Sources/glwidget.h +++ b/Sources/glwidget.h @@ -87,6 +87,7 @@ public slots: void setLightParameters(float,float); void setUVScaleOffset(double x,double y); void setCameraMouseSensitivity(int value); + void resetCameraPosition(); void cleanup(); // mesh loading functions @@ -114,7 +115,8 @@ public slots: void mouseReleaseEvent(QMouseEvent *event); void relativeMouseMoveEvent(int dx, int dy, bool *wrapMouse, Qt::MouseButtons buttons); void wheelEvent(QWheelEvent *event); - + void dropEvent(QDropEvent *event); + void dragEnterEvent(QDragEnterEvent *event); private: @@ -128,6 +130,7 @@ public slots: void bakeEnviromentalMaps(); // calculate prefiltered enviromental map QOpenGLShaderProgram *program; + QOpenGLShaderProgram *line_program; // same as "program" but instead of triangles lines are used QOpenGLShaderProgram *skybox_program; QOpenGLShaderProgram *env_program; @@ -166,10 +169,13 @@ public slots: float ratio; float zoom; AwesomeCamera camera; // light used for standard phong shading + AwesomeCamera newCamera;// to make smooth linear interpolation between two views + double cameraInterpolation; AwesomeCamera lightDirection;//second light - use camera class to rotate light QCursor lightCursor; + Mesh* mesh; // displayed 3d mesh Mesh* skybox_mesh; // sky box cube Mesh* env_mesh; // one trinagle used for calculation of prefiltered env. map diff --git a/Sources/glwidgetbase.cpp b/Sources/glwidgetbase.cpp index 78ef490..af23bcf 100644 --- a/Sources/glwidgetbase.cpp +++ b/Sources/glwidgetbase.cpp @@ -18,7 +18,7 @@ GLWidgetBase::GLWidgetBase(const QGLFormat& format, QWidget *parent, QGLWidget * connect(this, &GLWidgetBase::handleAccumulatedMouseMovementLater, this, &GLWidgetBase::handleAccumulatedMouseMovement, Qt::QueuedConnection); setMouseTracking(true); setFocusPolicy(Qt::ClickFocus); - + centerCamCursor = QCursor(QPixmap(":/resources/centerCamCursor.png")); wrapMouse = true; } @@ -159,6 +159,18 @@ void GLWidgetBase::toggleMouseWrap(bool toggle){ wrapMouse = toggle; } +void GLWidgetBase::toggleChangeCamPosition(bool toggle){ + + if(!toggle){ + setCursor(Qt::PointingHandCursor); + keyPressed = (Qt::Key)0; + }else{ + keyPressed = Qt::Key_Shift; + setCursor(centerCamCursor); + } + updateGL(); +} + // ---------------------------------------------------------------- // Key events // ---------------------------------------------------------------- @@ -174,6 +186,18 @@ void GLWidgetBase::keyPressEvent(QKeyEvent *event){ keyPressed = KEY_SHOW_MATERIALS; updateGL(); } + if( event->key() == Qt::Key_Shift ) + { + if(keyPressed == Qt::Key_Shift){ + setCursor(Qt::PointingHandCursor); + keyPressed = (Qt::Key)0; + emit changeCamPositionApplied(false); + }else{ + keyPressed = Qt::Key_Shift; + setCursor(centerCamCursor); + } + updateGL(); + } }// end of event type @@ -183,14 +207,13 @@ void GLWidgetBase::keyPressEvent(QKeyEvent *event){ void GLWidgetBase::keyReleaseEvent(QKeyEvent *event) { if (event->type() == QEvent::KeyRelease){ + if( event->key() == KEY_SHOW_MATERIALS) + { + keyPressed = (Qt::Key)0; + updateGL(); + event->accept(); - if( event->key() == KEY_SHOW_MATERIALS) - { - keyPressed = (Qt::Key)0; - updateGL(); - event->accept(); - - } + } }// end of key press } diff --git a/Sources/glwidgetbase.h b/Sources/glwidgetbase.h index c574701..cc6f10f 100644 --- a/Sources/glwidgetbase.h +++ b/Sources/glwidgetbase.h @@ -28,7 +28,7 @@ class GLWidgetBase : public QGLWidget signals: void updateGLLater(); void handleAccumulatedMouseMovementLater(); - + void changeCamPositionApplied(bool); protected: virtual void relativeMouseMoveEvent(int dx, int dy, bool* bMouseDragged, Qt::MouseButtons buttons) = 0; static bool wrapMouse; @@ -36,6 +36,7 @@ class GLWidgetBase : public QGLWidget public slots: void updateGLNow(); void toggleMouseWrap(bool toggle); + void toggleChangeCamPosition(bool toggle); private slots: void handleAccumulatedMouseMovement(); @@ -54,6 +55,7 @@ private slots: protected: Qt::Key keyPressed; + QCursor centerCamCursor; }; #endif // GLWIDGETBASE_H diff --git a/Sources/mainwindow.cpp b/Sources/mainwindow.cpp index 344b6e2..5967cd5 100644 --- a/Sources/mainwindow.cpp +++ b/Sources/mainwindow.cpp @@ -105,6 +105,7 @@ MainWindow::MainWindow(QWidget *parent) : normalImageProp->hideSelectiveBlurBox(); normalImageProp->hideHeightInputGroup(); normalImageProp->hideRoughnessInputGroup(); + normalImageProp->showNormalMixerGroup(); heightImageProp->hideSpecularInputGroup(); @@ -270,10 +271,17 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->checkBoxPerformanceSimplePBR ,SIGNAL(clicked()),this,SLOT(updatePerformanceSettings())); connect(ui->checkBoxBloomEffect ,SIGNAL(clicked()),this,SLOT(updatePerformanceSettings())); connect(ui->checkBoxDOFEffect ,SIGNAL(clicked()),this,SLOT(updatePerformanceSettings())); + connect(ui->checkBoxShowTriangleEdges ,SIGNAL(clicked()),this,SLOT(updatePerformanceSettings())); connect(ui->pushButtonReplotAll ,SIGNAL(released()),this,SLOT(replotAllImages())); + connect(ui->pushButtonResetCameraPosition ,SIGNAL(released()),glWidget,SLOT(resetCameraPosition())); + connect(ui->pushButtonChangeCamPosition ,SIGNAL(toggled(bool)),glWidget,SLOT(toggleChangeCamPosition(bool))); + connect(glWidget,SIGNAL(changeCamPositionApplied(bool)),ui->pushButtonChangeCamPosition ,SLOT(setChecked(bool))); + + + connect(ui->pushButtonToggleDiffuse ,SIGNAL(toggled(bool)),glWidget,SLOT(toggleDiffuseView(bool))); connect(ui->pushButtonToggleSpecular ,SIGNAL(toggled(bool)),glWidget,SLOT(toggleSpecularView(bool))); connect(ui->pushButtonToggleOcclusion ,SIGNAL(toggled(bool)),glWidget,SLOT(toggleOcclusionView(bool))); @@ -295,7 +303,7 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->pushButtonLoadMesh ,SIGNAL(released()), glWidget,SLOT(loadMeshFromFile())); connect(ui->comboBoxChooseOBJModel ,SIGNAL(activated(QString)),glWidget,SLOT(chooseMeshFile(QString))); connect(ui->comboBoxShadingType ,SIGNAL(activated(int)), glWidget,SLOT(selectShadingType(int))); - connect(ui->comboBoxShadingModel ,SIGNAL(activated(int)), glWidget,SLOT(selectShadingModel(int))); + connect(ui->comboBoxShadingModel ,SIGNAL(activated(int)), this,SLOT(selectShadingModel(int))); // PBR settings @@ -312,9 +320,11 @@ MainWindow::MainWindow(QWidget *parent) : connect(ui->actionShowOcclusiontImage,SIGNAL(triggered()),this,SLOT(selectOcclusionTab())); connect(ui->actionShowRoughnessImage ,SIGNAL(triggered()),this,SLOT(selectRoughnessTab())); connect(ui->actionShowMetallicImage ,SIGNAL(triggered()),this,SLOT(selectMetallicTab())); - //connect(ui->actionShowOcclusiontImage,SIGNAL(triggered()),this,SLOT(selectOcclusionTab())); + connect(ui->actionShowMaterialsImage ,SIGNAL(triggered()),this,SLOT(selectMaterialsTab())); + connect(ui->actionShowSettingsImage ,SIGNAL(triggered()),this,SLOT(selectGeneralSettingsTab())); + connect(ui->actionShowUVsTab ,SIGNAL(triggered()),this,SLOT(selectUVsTab())); connect(ui->actionFitToScreen ,SIGNAL(triggered()),this,SLOT(fitImage())); // perspective tool @@ -627,9 +637,18 @@ void MainWindow::selectMetallicTab(){ updateImage(6); } +void MainWindow::selectMaterialsTab(){ + ui->tabWidget->setCurrentIndex(7); + updateImage(7); +} + void MainWindow::selectGeneralSettingsTab(){ ui->tabWidget->setCurrentIndex(TAB_SETTINGS); } +void MainWindow::selectUVsTab(){ + ui->tabWidget->setCurrentIndex(TAB_SETTINGS+1); +} + void MainWindow::fitImage(){ glImage->resetView(); @@ -1268,6 +1287,12 @@ void MainWindow::updateSpinBoxes(int){ glWidget->setUVScaleOffset(ui->doubleSpinBoxUVXOffset->value(),ui->doubleSpinBoxUVYOffset->value()); } +void MainWindow::selectShadingModel(int i){ + glWidget->selectShadingModel(i); + if(i == 0) ui->tabWidget->setTabText(5,"Roughness"); + if(i == 1) ui->tabWidget->setTabText(5,"Glossiness"); +} + void MainWindow::updatePerformanceSettings(){ Performance3DSettings settings; @@ -1277,6 +1302,7 @@ void MainWindow::updatePerformanceSettings(){ settings.noTessSubdivision = ui->comboBoxPerformanceNoTessSub->currentText().toInt(); settings.bBloomEffect = ui->checkBoxBloomEffect->isChecked(); settings.bDofEffect = ui->checkBoxDOFEffect->isChecked(); + settings.bShowTriangleEdges = ui->checkBoxShowTriangleEdges->isChecked(); glWidget->updatePerformanceSettings(settings); } void MainWindow::updatePerformanceSettings(int indeks){ @@ -1779,11 +1805,13 @@ void MainWindow::loadSettings(){ if(bFirstTime){ this->resize(settings.value("d_win_w",800).toInt(),settings.value("d_win_h",600).toInt()); - ui->tabWidget->resize(settings.value("tab_win_w",300).toInt(), + ui->tabWidget->resize(settings.value("tab_win_w",200).toInt(), settings.value("tab_win_h",600).toInt()); ui->widget3DSettings->resize(settings.value("tab_3d_settings_win_w",400).toInt(), settings.value("tab_3d_settings_win_h",230).toInt()); + //ui->tabWidget->resize(150,400); + } PostfixNames::diffuseName = settings.value("d_postfix","_d").toString(); diff --git a/Sources/mainwindow.h b/Sources/mainwindow.h index 6ebb3b4..29fd5ee 100644 --- a/Sources/mainwindow.h +++ b/Sources/mainwindow.h @@ -67,7 +67,9 @@ public slots: void selectOcclusionTab(); void selectRoughnessTab(); void selectMetallicTab(); + void selectMaterialsTab(); void selectGeneralSettingsTab(); + void selectUVsTab(); void fitImage();// resize 2D image // repaint views after changes @@ -96,6 +98,7 @@ public slots: void setSpecularIntensity(int); void setDiffuseIntensity(int); void updateSpinBoxes(int); + void selectShadingModel(int i); // change current performance settings void updatePerformanceSettings(); void updatePerformanceSettings(int); diff --git a/Sources/mainwindow.ui b/Sources/mainwindow.ui index db20e4b..9eba0c8 100644 --- a/Sources/mainwindow.ui +++ b/Sources/mainwindow.ui @@ -62,7 +62,7 @@ QTabWidget::East - 9 + 5 Qt::ElideMiddle @@ -115,8 +115,8 @@ 0 0 - 96 - 26 + 398 + 646 @@ -189,8 +189,8 @@ 0 0 - 96 - 26 + 398 + 646 @@ -266,8 +266,8 @@ 0 0 - 96 - 26 + 398 + 646 @@ -337,8 +337,8 @@ 0 0 - 96 - 26 + 398 + 646 @@ -408,8 +408,8 @@ 0 0 - 96 - 26 + 398 + 646 @@ -476,8 +476,8 @@ 0 0 - 96 - 26 + 398 + 646 @@ -550,8 +550,8 @@ 0 0 - 96 - 26 + 398 + 646 @@ -603,8 +603,8 @@ 0 0 - 87 - 24 + 389 + 644 @@ -707,7 +707,7 @@ 0 0 - 344 + 381 656 @@ -2019,7 +2019,7 @@ 0 0 - 426 + 398 646 @@ -2381,12 +2381,6 @@ 2 - - - - - - @@ -2657,10 +2651,65 @@ - 32 + 20 + 20 + + + + true + + + + + + + + 20 + 16777215 + + + + Reset Camera position + + + Reset camera position + + + + + + + :/resources/resetCamera.png:/resources/resetCamera.png + + + + 20 + 20 + + + + true + + + + + + + + + + + :/resources/centerCamCursor.png:/resources/centerCamCursor.png + + + + 20 20 + + true + true @@ -3163,6 +3212,13 @@ + + + + Triangle edges + + + @@ -3936,7 +3992,9 @@ + + @@ -4150,6 +4208,36 @@ Alt+7 + + + + :/resources/showMaterials.png:/resources/showMaterials.png + + + Show Materials + + + <html><head/><body><p>Show materials tab (Alt+W)</p></body></html> + + + Alt+W + + + + + + :/resources/showUVs.png:/resources/showUVs.png + + + Show UVs + + + <html><head/><body><p>Show materials tab (Alt+E)</p></body></html> + + + Alt+E + + @@ -4178,8 +4266,8 @@ setVisible(bool) - 900 - 200 + 705 + 292 640 @@ -4194,12 +4282,12 @@ setDisabled(bool) - 633 - 421 + 680 + 542 - 1439 - 423 + 1035 + 544 diff --git a/Sources/resources/centerCamCursor.png b/Sources/resources/centerCamCursor.png new file mode 100644 index 0000000000000000000000000000000000000000..8359bde610152aa34350d3f455a53aee99b2458f GIT binary patch literal 963 zcmV;!13dhRP)~15ims zK~y-)m6Sbb99Iy>|MT9y_jdQaUETL7`eYA-1VN_{f)0Yz+;z#JB1ej(h?;<`CLd~? z6mc7Z(gYlm!Z>y(Cxle#To{3>G-)DK*bx>)DE1)`ilaj(-Am!!V}$~;2Oc{+Z|29$ z?CbylhKGldmg(tfzfdSNT-W{981q<4*;7hct@R(C=Y3Nw78hq`X2j^|C?zq6hleke z!NI{ks9LScTrSse9OpLxHa_R6=V@Yh9A~RkD!mzoA;2fMAQLbjWIVaWS7h38gXXNl~Om;cXM-do-yX_LZMJu zUS6j3o#%P$aVw6p*=)1_0g|2xA?~GGaG}3x`~3WT|6NLX2Y}_AZ#J7vgM2<;PkI(b z(X}M#Drqzti2F9q7;6*JVGsoG!FAnR0IZbqZaRyrWMg9^QOWbXuVcn-7-Jp-=!RkV zeLkPBwpuNTSCDeKJR64LS21u4LWmxK9_RcS=lpjm<%h2Tt1`wOan26_Sl{=bG0r&w zAOLyBSV1Xu^0Gi7#6OHN4?rCm^fUqhBHBi=SX_+9X1`LY zybb`hTJ1{U-rgRpwHO;4ix^`kMD)}c^Dbs*XNBW9Tk#M7a}rRm*AYe0CD7#LBzAXq zlUa0K*S!zGGR7WSYZ-=yhNw^|%mX+lqK@mj>(<&nU}9oo!1w(Ra=F}etyW_IV68>H zUUz-pzZq9|kj-Y_>IY>q8E%aEC|Ofd${$LlQWP(T>qK;>lzK2QFz}jE${imckCM!Y z=*aWDFD{kRYPFmo2tEUF6g##(&s*18-)D@SDW$f9Ah@oSy2ThfNis{rR#sM0n>Lng zHrwQ!ZxYdAYRO(WMD#c3{9(Gxg@uJnQ{UH@mX>r71n)~JZ%Zk+wAN33-`^KPY)UD= lGse7Qt!0V->gsAg_CKJX-ggHnN`U|X002ovPDHLkV1hC(v)TXv literal 0 HcmV?d00001 diff --git a/Sources/resources/centerCamCursor.svg b/Sources/resources/centerCamCursor.svg new file mode 100644 index 0000000..3e6a43d --- /dev/null +++ b/Sources/resources/centerCamCursor.svg @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/resources/filters.frag b/Sources/resources/filters.frag index 7e9a1f8..498ad54 100644 --- a/Sources/resources/filters.frag +++ b/Sources/resources/filters.frag @@ -378,8 +378,8 @@ subroutine(filterModeType) vec4 mode_seamless_linear_filter(){ float x = tc.x; float y = tc.y; float rad = make_seamless_radius/2; - float pwr = gui_seamless_contrast_power*10; - float cst = (gui_seamless_contrast_strenght)*50; + float pwr = gui_seamless_contrast_power*2+0.001; + float cst = (gui_seamless_contrast_strenght)*20; // simple seamless - GIMP like behaviour if(gui_seamless_mode == 0){ vec2 offset = -sign(x-0.5)*vec2(0.5,0); @@ -388,7 +388,7 @@ subroutine(filterModeType) vec4 mode_seamless_linear_filter(){ vec4 hA = texture( layerB, tc); vec4 hB = texture( layerB, vec2(tc.x,tc.y) + offset); float omega = 1 - smoothstep(0.0,rad,tc.x) + smoothstep(1.0-rad,1.0,tc.x); - float bomega = clamp(omega + omega*pow(length(hA.xyz-hB.xyz)/sqrt(2.0),pwr)*cst,0,1); + float bomega = clamp(omega + omega*pow(length(hA.xyz-hB.xyz)/sqrt(2.0)*cst,pwr),0,1); return mix(colorA,colorB,bomega); }else{ vec2 offset = -sign(y-0.5)*vec2(0.0,0.5); @@ -397,7 +397,7 @@ subroutine(filterModeType) vec4 mode_seamless_linear_filter(){ vec4 hA = texture( layerB, tc); vec4 hB = texture( layerB, vec2(tc.x,tc.y) + offset); float omega = 1 - smoothstep(0.0,rad,tc.y) + smoothstep(1.0-rad,1.0,tc.y); - float bomega = clamp(omega + omega*pow(length(hA.xyz-hB.xyz)/sqrt(2.0),pwr)*cst,0,1); + float bomega = clamp(omega + omega*pow(length(hA.xyz-hB.xyz)/sqrt(2.0)*cst,pwr),0,1); return mix(colorA,colorB,bomega); } @@ -410,8 +410,8 @@ subroutine(filterModeType) vec4 mode_seamless_filter(){ float x = tc.x; float y = tc.y; - float pwr = gui_seamless_contrast_power*10; - float cst = (gui_seamless_contrast_strenght)*50; + float pwr = gui_seamless_contrast_power*2+0.001; + float cst = (gui_seamless_contrast_strenght)*0; if(gui_seamless_mode == 2){ // XY - mirror image @@ -469,7 +469,7 @@ subroutine(filterModeType) vec4 mode_seamless_filter(){ highp float alpha = 1-smoothstep(gui_seamless_random_inner_radius,gui_seamless_random_outer_radius,dist); vec4 hB = texture( layerB, rot_mat*(tc - atom_pos)+0.5); - float diff = cst*pow(length(hA.xyz-hB.xyz)/sqrt(3.0),pwr+0.0001); + float diff = pow(cst*length(hA.xyz-hB.xyz)/sqrt(3.0),pwr+0.0001); total_diff += diff; alpha = clamp(alpha + alpha * diff,0,1); weight += alpha; @@ -619,12 +619,52 @@ subroutine(filterModeType) vec4 mode_normals_step_filter(){ color.xy *= gui_normals_step;//(1+2*gui_normals_step); - color.xyz = normalize(color.xyz); return color*0.5 +0.5; } +// ---------------------------------------------------------------- +// +// ---------------------------------------------------------------- +uniform float gui_normal_mixer_depth; +uniform float gui_normal_mixer_angle; +uniform float gui_normal_mixer_scale; +uniform float gui_normal_mixer_pos_x; +uniform float gui_normal_mixer_pos_y; + +subroutine(filterModeType) vec4 mode_normal_mixer_filter(){ + + vec2 newTexCoords = vec2(v2QuadCoords.xy-0.5) - vec2(gui_normal_mixer_pos_x,gui_normal_mixer_pos_y); + // rotate + newTexCoords = vec2(newTexCoords.x*cos(gui_normal_mixer_angle)+ + newTexCoords.y*sin(gui_normal_mixer_angle), + -newTexCoords.x*sin(gui_normal_mixer_angle)+ + newTexCoords.y*cos(gui_normal_mixer_angle)); + // scale coords + newTexCoords = newTexCoords*gui_normal_mixer_scale; + + newTexCoords = newTexCoords + 0.5; + + float ndepth = gui_normal_mixer_depth/50; + vec3 normalA = 2*(texture( layerA, v2QuadCoords.xy).xyz - 0.5); + vec3 normalB = 2*(texture( layerB, newTexCoords.xy).xyz - 0.5); + // rotate normals + normalB = vec3(normalB.x*cos(-gui_normal_mixer_angle)+ + normalB.y*sin(-gui_normal_mixer_angle), + -normalB.x*sin(-gui_normal_mixer_angle)+ + normalB.y*cos(-gui_normal_mixer_angle), + normalB.z); + + vec3 finalNormal = vec3(normalA.xy,normalA.z)+ + vec3(normalB.xy*ndepth,0); + + vec4 finalColor = vec4((finalNormal)*0.5+0.5,1); + + + return finalColor; +} + // ---------------------------------------------------------------- // // ---------------------------------------------------------------- diff --git a/Sources/resources/filters_3d.frag b/Sources/resources/filters_3d.frag index 39576d0..98444e5 100644 --- a/Sources/resources/filters_3d.frag +++ b/Sources/resources/filters_3d.frag @@ -144,128 +144,34 @@ changelog: //uniform variables from external script -float focalDepth = 10.0; //focal distance value in meters, but you may use autofocus option below -float focalLength = 25.0; //focal length in mm -float fstop = 140.0; //f-stop value -bool showFocus = false; //show debug focus point and focal range (red = focal point, green = focal range) +const float focalDepth = 10.0; //focal distance value in meters, but you may use autofocus option below +const float focalLength = 25.0; //focal length in mm +const float fstop = 140.0; //f-stop value #define PI 3.14159265 //------------------------------------------ //user variables -int samples = 4; //samples on the first ring -int rings = 10; //ring count +const int samples = 4; //samples on the first ring +const int rings = 8; //ring count -bool manualdof = false; //manual dof calculation -float ndofstart = 1.0; //near dof blur start -float ndofdist = 2.0; //near dof blur falloff distance -float fdofstart = 1.0; //far dof blur start -float fdofdist = 3.0; //far dof blur falloff distance -float CoC = 0.03;//circle of confusion size in mm (35mm film = 0.03mm) +const float CoC = 0.03;//circle of confusion size in mm (35mm film = 0.03mm) -bool vignetting = false; //use optical lens vignetting? -float vignout = 1.3; //vignetting outer border -float vignin = 0.0; //vignetting inner border -float vignfade =22.0; //f-stops till vignete fades +const vec2 focus = vec2(0.5,0.5); // autofocus point on screen (0.0,0.0 - left lower corner, 1.0,1.0 - upper right) +const float maxblur = 1.0; //clamp value of max blur (0.0 = no blur,1.0 default) -bool autofocus = true; //use autofocus in shader? disable if you use external focalDepth value -vec2 focus = vec2(0.5,0.5); // autofocus point on screen (0.0,0.0 - left lower corner, 1.0,1.0 - upper right) -float maxblur = 1.0; //clamp value of max blur (0.0 = no blur,1.0 default) +const float threshold = 0.25; //highlight threshold; +const float gain = 1.0; //highlight gain; -float threshold = 0.25; //highlight threshold; -float gain = 1.0; //highlight gain; +const float bias = 0.25; //bokeh edge bias 0.5 +const float fringe = 0.7; //bokeh chromatic aberration/fringing -float bias = 0.25; //bokeh edge bias 0.5 -float fringe = 0.7; //bokeh chromatic aberration/fringing +const bool noise = false; //use noise instead of pattern for sample dithering +const float namount = 0.0001; //dither amount -bool noise = false; //use noise instead of pattern for sample dithering -float namount = 0.0001; //dither amount -bool depthblur = true; //blur the depth buffer? -float dbsize = 1.25; //depthblursize - -/* -next part is experimental -not looking good with small sample and ring count -looks okay starting from samples = 4, rings = 4 -*/ - -bool pentagon = false; //use pentagon as bokeh shape? -float feather = 0.4; //pentagon shape feather - -//------------------------------------------ - - -float penta(vec2 coords) //pentagonal shape -{ - float scale = float(rings) - 1.3; - vec4 HS0 = vec4( 1.0, 0.0, 0.0, 1.0); - vec4 HS1 = vec4( 0.309016994, 0.951056516, 0.0, 1.0); - vec4 HS2 = vec4(-0.809016994, 0.587785252, 0.0, 1.0); - vec4 HS3 = vec4(-0.809016994,-0.587785252, 0.0, 1.0); - vec4 HS4 = vec4( 0.309016994,-0.951056516, 0.0, 1.0); - vec4 HS5 = vec4( 0.0 ,0.0 , 1.0, 1.0); - - vec4 one = vec4( 1.0 ); - - vec4 P = vec4((coords),vec2(scale, scale)); - - vec4 dist = vec4(0.0); - float inorout = -4.0; - - dist.x = dot( P, HS0 ); - dist.y = dot( P, HS1 ); - dist.z = dot( P, HS2 ); - dist.w = dot( P, HS3 ); - - dist = smoothstep( -feather, feather, dist ); - - inorout += dot( dist, one ); - - dist.x = dot( P, HS4 ); - dist.y = HS5.w - abs( P.z ); - - dist = smoothstep( -feather, feather, dist ); - inorout += dist.x; - - return clamp( inorout, 0.0, 1.0 ); -} - -vec3 bdepth(vec2 coords) //blurring depth -{ - vec3 d = vec3(0.0); - float kernel[9]; - vec2 offset[9]; - - vec2 wh = vec2(texel.x, texel.y) * dbsize; - - offset[0] = vec2(-wh.x,-wh.y); - offset[1] = vec2( 0.0, -wh.y); - offset[2] = vec2( wh.x -wh.y); - - offset[3] = vec2(-wh.x, 0.0); - offset[4] = vec2( 0.0, 0.0); - offset[5] = vec2( wh.x, 0.0); - - offset[6] = vec2(-wh.x, wh.y); - offset[7] = vec2( 0.0, wh.y); - offset[8] = vec2( wh.x, wh.y); - - kernel[0] = 1.0/16.0; kernel[1] = 2.0/16.0; kernel[2] = 1.0/16.0; - kernel[3] = 2.0/16.0; kernel[4] = 4.0/16.0; kernel[5] = 2.0/16.0; - kernel[6] = 1.0/16.0; kernel[7] = 2.0/16.0; kernel[8] = 1.0/16.0; - - - for( int i=0; i<9; i++ ) - { - vec3 tmp = texture2D(layerB, coords + offset[i]).xyz; - d += tmp * kernel[i]; - } - - return d; -} vec3 color(vec2 coords,float blur) //processing the sample @@ -295,29 +201,12 @@ vec2 rand(vec2 coord) //generating noise/pattern texture for dithering return vec2(noiseX,noiseY); } -vec3 debugFocus(vec3 col, float blur, float depth) -{ - float edge = 0.002*depth; //distance based edge smoothing - float m = clamp(smoothstep(0.0,edge,blur),0.0,1.0); - float e = clamp(smoothstep(1.0-edge,1.0,blur),0.0,1.0); - - col = mix(col,vec3(1.0,0.5,0.0),(1.0-m)*0.6); - col = mix(col,vec3(0.0,0.5,1.0),((1.0-e)-(1.0-m))*0.2); - - return col; -} float linearize(vec3 position) { return length(position.xyz); } -float vignette() -{ - float dist = distance(v2QuadCoords.xy, vec2(0.5,0.5)); - dist = smoothstep(vignout+(fstop/vignfade), vignin+(fstop/vignfade), dist); - return clamp(dist,0.0,1.0); -} // ---------------------------------------------------------------- // DOF/BOKEH EFFECT @@ -326,46 +215,32 @@ float vignette() subroutine(filterModeType) vec4 mode_dof_filter(){ //scene depth calculation - float depth = linearize(texture2D(layerB,v2QuadCoords.xy).xyz); - if (depthblur) - { - depth = linearize(bdepth(v2QuadCoords.xy)); - } + float depth = linearize(texture2D(layerB,v2QuadCoords.xy).xyz); //focal plane calculation float fDepth = focalDepth; - if (autofocus) - { - fDepth = linearize(texture2D(layerB,focus).xyz); - } + + fDepth = linearize(texture2D(layerB,focus).xyz); + //dof blur factor calculation float blur = 0.0; - if (manualdof) - { - float a = depth-fDepth; //focal plane - float b = (a-fdofstart)/fdofdist; //far DoF - float c = (-a-ndofstart)/ndofdist; //near Dof - blur = (a>0.0)?b:c; - } - else - { - float f = focalLength; //focal length in mm - float d = fDepth*1000.0; //focal plane in mm - float o = depth*1000.0; //depth in mm + float f = focalLength; //focal length in mm + float d = fDepth*1000.0; //focal plane in mm + float o = depth*1000.0; //depth in mm - float a = (o*f)/(o-f); - float b = (d*f)/(d-f); - float c = (d-f)/(d*fstop*CoC); + float a = (o*f)/(o-f); + float b = (d*f)/(d-f); + float c = (d-f)/(d*fstop*CoC); + + blur = abs(a-b)*c; - blur = abs(a-b)*c; - } blur = clamp(blur,0.0,1.0); @@ -382,53 +257,47 @@ subroutine(filterModeType) vec4 mode_dof_filter(){ vec3 col = vec3(0.0); + if(blur < 0.05) //some optimization thing { col = texture2D(layerA, v2QuadCoords.xy).rgb; - } - - else - { + }else{ col = texture2D(layerA, v2QuadCoords.xy).rgb; float s = 1.0; int ringsamples; for (int i = 1; i <= rings; i += 1) { - ringsamples = i * samples; + ringsamples = i * samples; + float step = PI*2.0 / float(ringsamples); + float rr = i/float(rings); + float mb = mix(1.0,rr,bias); for (int j = 0 ; j < ringsamples ; j += 1) { - float step = PI*2.0 / float(ringsamples); + float pw = (cos(float(j)*step)*float(i)); float ph = (sin(float(j)*step)*float(i)); - float p = 1.0; - if (pentagon) - { - p = penta(vec2(pw,ph)); - } - col += color(v2QuadCoords.xy + vec2(pw*w,ph*h),blur)*mix(1.0,(float(i))/(float(rings)),bias)*p; - s += 1.0*mix(1.0,(float(i))/(float(rings)),bias)*p; + + col += color(v2QuadCoords.xy + vec2(pw*w,ph*h),blur)*mb; + s += mb; } + } + + col /= s; //divide by sample count - } - if (showFocus) - { - col = debugFocus(col, blur, depth); } - if (vignetting) - { - col *= vignette(); - } return vec4(col,1); + } out vec4 FragColor; void main() { - FragColor = filterMode(); + FragColor = filterMode(); + //FragColor = texture( layerA, v2QuadCoords.xy); } diff --git a/Sources/resources/plane.frag b/Sources/resources/plane.frag index 2b77ee6..1a991d9 100644 --- a/Sources/resources/plane.frag +++ b/Sources/resources/plane.frag @@ -29,6 +29,7 @@ uniform float gui_LightRadius; uniform int gui_noPBRRays; uniform bool gui_bUseSimplePBR; uniform bool gui_bMaterialsPreviewEnabled; +uniform bool gui_bShowTriangleEdges; uniform float gui_depthScale; uniform float gui_SpecularIntensity; @@ -41,7 +42,7 @@ uniform vec3 lightDirection; vec3 Kd = vec3(gui_DiffuseIntensity); vec3 Ks = vec3(gui_SpecularIntensity*0.5); vec3 Ka = vec3(0.0); -float alpha = 1 / (gui_LightRadius*0.1 + 0.01); +float alpha = 1.0 / (gui_LightRadius*0.1 + 0.01); vec3 LightSource_diffuse = vec3(1.0); vec3 LightSource_ambient = vec3(1.0); @@ -68,6 +69,7 @@ vec3 fvESVertexNormal; vec4 fvBaseColor; vec4 fvSpecularColor; vec4 fvSSAOColor; +float fvGlossiness; vec4 fvRoughness; vec4 fvMetallic; @@ -80,6 +82,7 @@ vec4 bump_mapping(int lightIndeks,vec2 texcoord){ vec3 fvReflection = normalize( ( ( 2.0 * fvESVertexNormal ) * fNDotL ) - fvTSLightPosition ); vec3 fvTSViewDirection = normalize( TSViewDirection[lightIndeks] ); + float fRDotV = max( 0.0, dot( fvReflection, fvTSViewDirection ) ); @@ -89,7 +92,9 @@ vec4 bump_mapping(int lightIndeks,vec2 texcoord){ vec3 lightDirection = normalize( TSLightPosition[lightIndeks] ); - vec4 fvTotalSpecular = gui_LightPower * vec4(Ks * LightSource_specular,1) * ( pow( fRDotV, alpha ) ) * fvSpecularColor * 3; + vec4 fvTotalSpecular = gui_LightPower * vec4(Ks * LightSource_specular,1) * ( pow( fRDotV, alpha*fvGlossiness ) ) * fvSpecularColor * 3; + + if(!gui_bSpecular) fvTotalSpecular = vec4(0); @@ -385,13 +390,30 @@ vec4 PBR_Specular_SIMPLE(float roughness, return vec4(radiance ,1); } +// From : http://prideout.net/blog/?p=48 +in vec3 gTriDistance; +in vec3 gPatchDistance; + + void main( void ) { + // Triangle edges: + if(gui_bShowTriangleEdges){ + if(gui_bMaterialsPreviewEnabled) FragColor = texture(texDiffuse, texcoord.st); + else FragColor = vec4(0); + FragColor.a = 1; + FragNormal = vec4(0); + FragGlowColor = vec4(0); + FragPosition = vec4(10); + return; + } + if(gui_bMaterialsPreviewEnabled){ FragColor = texture(texMaterial, texcoord.st); FragNormal = vec4(0); FragGlowColor = vec4(0); + FragPosition = vec4(0); return; } @@ -412,6 +434,7 @@ void main( void ) fvSSAOColor = texture( texSSAO, texcoords.xy ); fvRoughness = texture( texRoughness, texcoords.xy ); fvMetallic = texture( texMetallic, texcoords.xy ); + fvGlossiness = clamp(fvRoughness.r,0.0,1.0)*100+1.0; if(!gui_bDiffuse) fvBaseColor = vec4(0.8); // some gray color if(!gui_bOcclusion)fvSSAOColor = vec4(1.0); @@ -432,6 +455,7 @@ void main( void ) vec3 diffuse = fvBaseColor.rgb * irradiance ; fvBaseColor.rgb = diffuse; vec4 bumpMapShadingColor = (bump_mapping(0,texcoords)+bump_mapping(1,texcoords))/2; + bumpMapShadingColor = bump_mapping(1,texcoords); FragColor = bumpMapShadingColor; finalColor = FragColor ; @@ -481,8 +505,8 @@ void main( void ) finalColor = FragColor ; } - FragNormal = vec4(surfaceNormal,1); - //FragGlowColor = FragColor; + // Final colors + FragNormal = vec4(WSPosition,1); float bloomLevel = 0.5; float level = dot(finalColor.rgb,finalColor.rgb)/3; @@ -490,5 +514,7 @@ void main( void ) if(level > bloomLevel )FragGlowColor = finalColor; FragPosition = vec4(ESVertexPosition,1); - //FragColor = fvBaseColor; + + + } diff --git a/Sources/resources/plane.geom b/Sources/resources/plane.geom index b0a3d41..b2e94ac 100644 --- a/Sources/resources/plane.geom +++ b/Sources/resources/plane.geom @@ -1,8 +1,7 @@ -#version 400 core +//#version 400 core +//layout(triangle_strip, max_vertices = 3) out; layout(triangles) in; -layout(triangle_strip, max_vertices = 3) out; - uniform sampler2D texHeight; @@ -24,6 +23,7 @@ in vec3 teNormal[3]; in vec3 teTangent[3]; in vec3 teBitangent[3]; in vec3 teSmoothedNormal[3]; +in vec3 tePatchDistance[3]; out vec3 texcoord; out vec3 ESVertexPosition; @@ -42,6 +42,8 @@ out vec3 WSNormal; out vec3 WSTangent; out vec3 WSBitangent; out vec3 WSPosition; +out vec3 gPatchDistance; +out vec3 gTriDistance; void bump_mapping(vec3 eyeLightDir[2],vec3 eyeVertexDir[2],vec3 halfVector){ @@ -106,6 +108,10 @@ void main() WSPosition = (ModelMatrix * vec4( newPos[i],1)).xyz; TBN = transpose(mat3(WSTangent,WSBitangent,WSNormal)); + // tessellation edges + gPatchDistance = tePatchDistance[i]; + gTriDistance = vec3((i==0)?1:0, (i==1)?1:0, (i==2)?1:0); + EmitVertex(); } diff --git a/Sources/resources/plane.tes.vert b/Sources/resources/plane.tes.vert index a014648..6366875 100644 --- a/Sources/resources/plane.tes.vert +++ b/Sources/resources/plane.tes.vert @@ -18,6 +18,7 @@ out vec3 teNormal; out vec3 teTangent; out vec3 teBitangent; out vec3 teSmoothedNormal; +out vec3 tePatchDistance; vec3 average(vec3 a,vec3 b,vec3 c){ return gl_TessCoord.x * a + gl_TessCoord.y * b + gl_TessCoord.z * c; @@ -34,4 +35,7 @@ void main() teSmoothedNormal = normalize(average(tcSmoothedNormal[0],tcSmoothedNormal[1],tcSmoothedNormal[2])); gl_Position = ProjectionMatrix * ModelViewMatrix * vec4(tePosition, 1); + + tePatchDistance = gl_TessCoord; + } diff --git a/Sources/resources/resetCamera.png b/Sources/resources/resetCamera.png new file mode 100644 index 0000000000000000000000000000000000000000..0126bd29214e913a9c20afbd2b2e726ba3b5f96d GIT binary patch literal 1948 zcmaJ?2{7C17Ef~#OIt*>l+eHzu~(E3 zQz~vsNvjm8B{x^?PgQlXMWh$4?fu=`c{6Y3&6{t|_nY~h?|k1k=gc|3Ob4vx5y_L1 zAQ0$?wH4Y4K-z(civhbs#+O(C#Qbe7(V+cj+Hq}ju3(aK;jTvk_tf@Z6kKJjA_t!kW3l1Mkb z)u8?EMKvw{P*0=pZanl5S)3wbcLopD%}lXotNkbN|9eubzsJ=7A?Bjp*XY^yeyT0( z2cb~d`Ajd$`-Hu{eHER~0nxxP(_}9j%{vWp<{inq9vz9B+OZqU?o;7d9F8;izz|}` zi`s#73mSL0)s_`V(JEWb$e5%qJGg3MLPCTa!%Jdgb90Hu;~CZ7zdf(@p%zyT?zw-C zGs|zQ51M>8Uqv#nEFlg9k8>c>r$mVRd*_fGXbCOT4qmNd9Mw0gyPF%%l1wwV?@Bf< zEgEa`mA2B1mJcHxky-OC*7nZFm0gmk@6gpa5-E7|VRZSfo`HcXDLoxrZc2RPGFx{| zFKJ|Y+Ka^Dm^$-DhHrL?qh64CF9UAjpiI9y5ILH*)hM2Cms6P^_7 z_zqN7R1ABvxX!`Ps?tkBD4!_`mZ66Z+-idzStX0apq>YV>$O5cqZ#x2z2lLCY_ z#*GtvQ7fxU4DsTNl#Q#Ms9DkW_$o=xW$O^W$NBJeqaTw!G;h~AEWG`ysICk1Q7>i` z)L+V`Hc}fsjbs`q6>9kUZ0I9))Zp9h05DD8FplMyAx{qOabInn?&*SP=)xc#tCI+`5R?a$VX$w&|DffHnjO84)%(FrVPd=#=$@Fz~z#~e6O3vh2 z?eHcizr9l97x%*`k|)GP_DqO-9dBl5%bS{-d_f*da~VKN>RGG_1sH5J_tfQ*COUol zhg`R|82r;mS8K6~++WUjMSjFix#I9nn3eIz-5EbsPk!dr3T;WMoaUQ*G%)+2{LD0}IFpyb=kqj#i2l{p(CRm{^Q$xMtia*2&r378 zfq{XT$jBB{{JL6f)~^F&V=rIcz4vOK&gi2BWigpdm#%+pZT)5iCmV^!-|A@)*l5lR z;s~w7CUI*OsMu91{H}~AGq@iZF^%FzzuGODChzo>qQYOKK(%fRI!c~K<8b%66BDdO zhmEy4i`@@{4;rZKhRZet@KyJMw<0%2+krZ}IHbx^TrfuZ`c4-BlGd#8T*5BE5g-Su zM9%6KVkEG5L^hPlc0R6-x?P9-JDPYWGA>Sm>XTZB7-)T`tfB&`b;H-^LaA5o8tLgd z%G&VG!!Rs`K$J2={4DNbjOJ^gWk@8FmU+D39VWnMab#@FO?K$pKA+Oe z&CXxAkV!x-KUHdJYa1JH3oBo0BEf=SFj&BFVZKcb3hyig8fmB*ITP(^6s`j30-zrU zGH@{L!EjQ_-}qfQ!0`W4j)N2bTT?{roLU2hpEH6y%DOFD8Pi|K(yq;UYZYxvqk|Xz eQjtUC>GA#EWlMgx@%jj$qabSx7R@lnr~VuHP>vJ; literal 0 HcmV?d00001 diff --git a/Sources/resources/resetCamera.svg b/Sources/resources/resetCamera.svg new file mode 100644 index 0000000..fc70db2 --- /dev/null +++ b/Sources/resources/resetCamera.svg @@ -0,0 +1,171 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/resources/showMaterials.png b/Sources/resources/showMaterials.png new file mode 100644 index 0000000000000000000000000000000000000000..98e90384880defb90b02f7eeffe93159384722ac GIT binary patch literal 7999 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 literal 0 HcmV?d00001 diff --git a/Sources/resources/showMaterials.svg b/Sources/resources/showMaterials.svg new file mode 100644 index 0000000..e73e4d2 --- /dev/null +++ b/Sources/resources/showMaterials.svg @@ -0,0 +1,129 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + M + diff --git a/Sources/resources/showSettings.png b/Sources/resources/showSettings.png index fe411e142ac6192f4b86b9468d2c49d025742cdf..1d53d67c1a1f0b466132a5ea3d63d99b1b72a560 100644 GIT binary patch literal 7480 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 literal 4695 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 A4gdfE diff --git a/Sources/resources/showSettings.svg b/Sources/resources/showSettings.svg new file mode 100644 index 0000000..665fd27 --- /dev/null +++ b/Sources/resources/showSettings.svg @@ -0,0 +1,222 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + S + + diff --git a/Sources/resources/showUVs.png b/Sources/resources/showUVs.png new file mode 100644 index 0000000000000000000000000000000000000000..433484d1a506f4bd7bcac414c0236c3de87038b2 GIT binary patch literal 7669 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 literal 0 HcmV?d00001 diff --git a/Sources/resources/showUVs.svg b/Sources/resources/showUVs.svg new file mode 100644 index 0000000..98f5ba8 --- /dev/null +++ b/Sources/resources/showUVs.svg @@ -0,0 +1,129 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + UV + diff --git a/Sources/resources/skybox.frag.glsl b/Sources/resources/skybox.frag.glsl index 3400b05..ff22f4e 100644 --- a/Sources/resources/skybox.frag.glsl +++ b/Sources/resources/skybox.frag.glsl @@ -12,7 +12,7 @@ layout(location = 3) out vec4 FragPosition; void main( void ) { FragColor = texture(texEnv, texcoord); - FragNormal = vec4(0,0,1,1); + FragNormal = vec4(50.0,50.0,50.0,1); float bloomLevel = 0.8; //FragGlowColor = pow(FragColor+0.2,vec4(3.0))-pow(1.1,3)+1; diff --git a/Sources/utils/Mesh.cpp b/Sources/utils/Mesh.cpp index db12172..162d267 100644 --- a/Sources/utils/Mesh.cpp +++ b/Sources/utils/Mesh.cpp @@ -265,6 +265,7 @@ void Mesh::drawMesh(bool bUseArrays ){ if(bUseArrays){ GLCHK(glDrawArrays(GL_TRIANGLES, 0, gl_vertices.size())); + }else{ glPatchParameteri(GL_PATCH_VERTICES, 3); // tell OpenGL that every patch has 16 verts GLCHK(glDrawArrays(GL_PATCHES, 0, gl_vertices.size())); // draw a bunch of patches