diff --git a/src/fgt/filter_sdfgpu/filter_sdfgpu.cpp b/src/fgt/filter_sdfgpu/filter_sdfgpu.cpp index e61c653e4..4a5db8af1 100644 --- a/src/fgt/filter_sdfgpu/filter_sdfgpu.cpp +++ b/src/fgt/filter_sdfgpu/filter_sdfgpu.cpp @@ -16,7 +16,6 @@ using namespace vcg; #define PI 3.14159265358979323846264; #define USEVBO_BY_DEFAULT false -#define MACOS SdfGpuPlugin::SdfGpuPlugin() : mPeelingTextureSize(256) @@ -194,7 +193,6 @@ bool SdfGpuPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterS TraceRay(peel, (*vi), md.mm()); cb(100*((float)tracedRays/(float)unifDirVec.size()), "Tracing rays..."); ++tracedRays; - Log(0, "traced rays: %i ", tracedRays ); } //read back the result texture and store result in the mesh @@ -223,7 +221,7 @@ bool SdfGpuPlugin::initGL(MeshModel& mm) glDisable(GL_ALPHA_TEST); glEnable(GL_NORMALIZE); glDisable(GL_COLOR_MATERIAL); - glClearColor(0,0,0,0); + glClearColor(1,0,0,0); glClearDepth(1.0); GLenum err = glewInit(); @@ -263,6 +261,13 @@ bool SdfGpuPlugin::initGL(MeshModel& mm) } //INIT FBOs AND TEXs + for(int i = 0; i < 3; i++) + { + mFboArray[i] = new FramebufferObject(); + } + + mFboResult = new FramebufferObject(); + unsigned int maxTexSize; glGetIntegerv(GL_MAX_TEXTURE_SIZE, reinterpret_cast(&maxTexSize) ); Log(0, "QUERY HARDWARE FOR: MAX TEX SIZE: %i ", maxTexSize ); @@ -279,66 +284,38 @@ bool SdfGpuPlugin::initGL(MeshModel& mm) Log(0, "Mesh has %i vertices\n", numVertices ); Log(0, "Result texture is %i X %i = %i", mResTextureDim, mResTextureDim, mResTextureDim*mResTextureDim); - mVertexCoordsTexture = new FloatTexture2D( TextureFormat( GL_TEXTURE_2D, mResTextureDim, mResTextureDim, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT ), TextureParams( GL_LINEAR/*GL_NEAREST*/, /*GL_NEAREST*/GL_LINEAR ) ); - mVertexNormalsTexture = new FloatTexture2D( TextureFormat( GL_TEXTURE_2D, mResTextureDim, mResTextureDim, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT ), TextureParams( /*GL_NEAREST*/GL_LINEAR, /*GL_NEAREST*/GL_LINEAR ) ); + mVertexCoordsTexture = new FloatTexture2D( TextureFormat( GL_TEXTURE_2D, mResTextureDim, mResTextureDim, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT ), TextureParams( GL_NEAREST, GL_NEAREST ) ); + mVertexNormalsTexture = new FloatTexture2D( TextureFormat( GL_TEXTURE_2D, mResTextureDim, mResTextureDim, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT ), TextureParams( GL_NEAREST, GL_NEAREST ) ); + + mResultTexture = new FloatTexture2D( TextureFormat( GL_TEXTURE_2D, mResTextureDim, mResTextureDim, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT ), TextureParams( GL_NEAREST, GL_NEAREST ) ); + + // FloatTexture2D* df = new FloatTexture2D( TextureFormat( GL_TEXTURE_2D, mResTextureDim, mResTextureDim, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_FLOAT ), + // TextureParams( GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE ) ); - mResultTexture = new FloatTexture2D( TextureFormat( GL_TEXTURE_2D, mResTextureDim, mResTextureDim, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT ), TextureParams( GL_LINEAR/*GL_NEAREST*/, GL_LINEAR/*GL_NEAREST*/ ) ); -#ifdef MACOS - mResultTextureDepth = new FloatTexture2D(TextureFormat( GL_TEXTURE_2D, mResTextureDim, mResTextureDim, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_FLOAT ), - TextureParams( /*GL_NEAREST*/GL_LINEAR, /*GL_NEAREST*/GL_LINEAR) ); -#endif - mFboResult = new FramebufferObject(); mFboResult->attachTexture( mResultTexture->format().target(), mResultTexture->id(), GL_COLOR_ATTACHMENT0_EXT ); -#ifdef MACOS - mFboResult->attachTexture(mResultTextureDepth->format().target(),mResultTextureDepth->id(),GL_DEPTH_ATTACHMENT_EXT ); -#endif - assert(mFboResult->isValid()); - checkGLError::qDebug("Error during mFboResult "); + + + //clear first time + mFboResult->bind(); + glClear(GL_COLOR_BUFFER_BIT); + mFboResult->unbind(); //We use 3 FBOs to avoid z-fighting in sdf and obscurance calculation, see TraceRays function for details for(int i = 0; i < 3; i++) { + mDepthTextureArray[i] = new FloatTexture2D( TextureFormat( GL_TEXTURE_2D, mPeelingTextureSize, mPeelingTextureSize, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_FLOAT ), + TextureParams( GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE ) ); - mFboArray[i] = new FramebufferObject(); + mFboArray[i]->attachTexture( mDepthTextureArray[i]->format().target(), mDepthTextureArray[i]->id(), GL_DEPTH_ATTACHMENT ); mFboArray[i]->bind(); - - mDepthTextureArray[i] = new FloatTexture2D(TextureFormat( GL_TEXTURE_2D, mPeelingTextureSize, mPeelingTextureSize, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_FLOAT ), - TextureParams( /*GL_NEAREST*/GL_LINEAR, /*GL_NEAREST*/GL_LINEAR) ); - -#ifdef MACOS - mColorTextureArray[i] = new FloatTexture2D( TextureFormat( GL_TEXTURE_2D, mPeelingTextureSize, mPeelingTextureSize, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT ), TextureParams( GL_LINEAR/*GL_NEAREST*/, /*GL_NEAREST*/GL_LINEAR ) ); - - mColorTextureArray[i]->bind(); - - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT, - GL_TEXTURE_2D, mColorTextureArray[i]->id(),0); - -#endif - mDepthTextureArray[i]->bind(); - - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT, - GL_TEXTURE_2D, mDepthTextureArray[i]->id(),0); - - - -#ifndef MACOS glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); -#endif - - assert(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT && "mFboArray error"); mFboArray[i]->unbind(); - - #ifndef MACOS - glDrawBuffer(GL_BACK); - glReadBuffer(GL_BACK); -#endif - } //Depth peeling shader used for both sdf and obscurance @@ -386,10 +363,10 @@ bool SdfGpuPlugin::initGL(MeshModel& mm) mObscuranceProgram->addUniform("maxDist"); //mesh BB diagonal mObscuranceProgram->disable(); - assert(mFboResult->isValid() && "Error during init"); - assert(mFboArray[0]->isValid() && "Error during init"); - assert(mFboArray[1]->isValid() && "Error during init"); - assert(mFboArray[2]->isValid() && "Error during init"); + assert(mFboResult->isValid()); + assert(mFboArray[0]->isValid()); + assert(mFboArray[1]->isValid()); + assert(mFboArray[2]->isValid()); //If required from the user, we use VBO to speed up mesh rendering @@ -472,33 +449,16 @@ void SdfGpuPlugin::releaseGL(MeshModel &m) void SdfGpuPlugin::fillFrameBuffer(bool front, MeshModel* mm) { -#ifndef MACOS glClear(GL_DEPTH_BUFFER_BIT); -#else - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -#endif - checkGLError::qDebug("Error during fillFrameBuffer 1"); glEnable(GL_CULL_FACE); - checkGLError::qDebug("Error during fillFrameBuffer 2"); glCullFace((front)?GL_BACK:GL_FRONT); - checkGLError::qDebug("Error during fillFrameBuffer 3"); -#ifndef MACOS //the most recent GPUs can do double speed Z-only rendering //(also alpha test must be turned off, depth replace and texkill must not be used in fragment shader) glColorMask(0, 0, 0, 0); - -#endif - checkGLError::qDebug("Error during fillFrameBuffer 4"); mm->glw.DrawFill(); - checkGLError::qDebug("Error during fillFrameBuffer 5"); -#ifndef MACOS glColorMask(1, 1, 1, 1); -#endif - checkGLError::qDebug("Error during fillFrameBuffer 6"); + glDisable(GL_CULL_FACE); - checkGLError::qDebug("Error during fillFrameBuffer 7"); - - } void SdfGpuPlugin::setupMesh(MeshDocument& md, ONPRIMITIVE onPrimitive ) @@ -556,21 +516,17 @@ void SdfGpuPlugin::setCamera(Point3f camDir, Box3f &meshBBox) void SdfGpuPlugin::useDepthPeelingShader(FramebufferObject* fbo) { glUseProgram(mDeepthPeelingProgram->id()); - checkGLError::qDebug("Error during useDepthPeelingShader 1 "); mDeepthPeelingProgram->setUniform1f("tolerance", mTolerance); - checkGLError::qDebug("Error during useDepthPeelingShader 2 "); mDeepthPeelingProgram->setUniform2f("oneOverBufSize", 1.0f/mPeelingTextureSize, 1.0f/mPeelingTextureSize); - checkGLError::qDebug("Error during useDepthPeelingShader 3 "); glActiveTexture(GL_TEXTURE0); - checkGLError::qDebug("Error during useDepthPeelingShader 4 "); glBindTexture(GL_TEXTURE_2D, fbo->getAttachedId(GL_DEPTH_ATTACHMENT)); - checkGLError::qDebug("Error during useDepthPeelingShader 5 "); mDeepthPeelingProgram->setUniform1i("textureLastDepth",0); - checkGLError::qDebug("Error during useDepthPeelingShader 6 "); } void SdfGpuPlugin::calculateSdfHW(FramebufferObject* fboFront, FramebufferObject* fboBack, FramebufferObject* fboPrevBack, const vcg::Point3f& cameraDir) { + mFboResult->bind(); + glViewport(0, 0, mResTextureDim, mResTextureDim); GLfloat mv_pr_Matrix_f[16]; // modelview-projection matrix glGetFloatv(GL_MODELVIEW_MATRIX, mv_pr_Matrix_f); @@ -585,6 +541,14 @@ void SdfGpuPlugin::calculateSdfHW(FramebufferObject* fboFront, FramebufferObject glMatrixMode(GL_MODELVIEW); glLoadIdentity(); + glDisable(GL_DEPTH_TEST); + glDepthMask(GL_FALSE); + + glEnable (GL_BLEND); + glBlendFunc (GL_ONE, GL_ONE); + glBlendEquation(GL_FUNC_ADD); + + glUseProgram(mSDFProgram->id()); glActiveTexture(GL_TEXTURE0); @@ -623,6 +587,7 @@ void SdfGpuPlugin::calculateSdfHW(FramebufferObject* fboFront, FramebufferObject vcg::Invert(mvprINV); mSDFProgram->setUniformMatrix4fv( "mvprMatrixINV", mvprINV.V(), 1, GL_TRUE ); + // Set texture Size mSDFProgram->setUniform1f("texSize", mPeelingTextureSize); @@ -650,21 +615,6 @@ void SdfGpuPlugin::calculateSdfHW(FramebufferObject* fboFront, FramebufferObject else mSDFProgram->setUniform1i("removeOutliers",0); - mFboResult->bind(); - glViewport(0, 0, mResTextureDim, mResTextureDim); -#ifndef MACOS - glDrawBuffer(GL_COLOR_ATTACHMENT0); -#endif - checkGLError::qDebug("error after glDrawBuffer"); - glDisable(GL_DEPTH_TEST); -#ifndef MACOS - glDepthMask(GL_FALSE); -#endif - - glEnable (GL_BLEND); - glBlendFunc (GL_ONE, GL_ONE); - glBlendEquation(GL_FUNC_ADD); - // Screen-aligned Quad glBegin(GL_QUADS); glVertex3f(-1.0f, -1.0f, 0.0f); //L-L @@ -673,14 +623,9 @@ void SdfGpuPlugin::calculateSdfHW(FramebufferObject* fboFront, FramebufferObject glVertex3f(-1.0f, 1.0f, 0.0f); //U-L glEnd(); - - assert(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT && "mFboResult error while drawing"); - mFboResult->unbind(); -#ifndef MACOS - glDepthMask(GL_TRUE); -#endif glEnable(GL_DEPTH_TEST); + glDepthMask(GL_TRUE); glDisable(GL_BLEND); } @@ -709,6 +654,9 @@ void SdfGpuPlugin::applySdfHW(MeshModel &m, float numberOfRays) void SdfGpuPlugin::calculateObscurance(FramebufferObject* fboFront, FramebufferObject* fboBack, FramebufferObject* nextBack, const vcg::Point3f& cameraDir, float bbDiag) { + mFboResult->bind(); + glViewport(0, 0, mResTextureDim, mResTextureDim); + GLfloat mv_pr_Matrix_f[16]; // modelview-projection matrix glGetFloatv(GL_MODELVIEW_MATRIX, mv_pr_Matrix_f); @@ -723,7 +671,17 @@ void SdfGpuPlugin::calculateObscurance(FramebufferObject* fboFront, FramebufferO glMatrixMode(GL_MODELVIEW); glLoadIdentity(); + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + + glEnable (GL_BLEND); + glBlendFunc (GL_ONE, GL_ONE); + glBlendEquation(GL_FUNC_ADD); + + glUseProgram(mObscuranceProgram->id()); + assert(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)==GL_FRAMEBUFFER_COMPLETE_EXT && "before draw"); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, fboFront->getAttachedId(GL_DEPTH_ATTACHMENT)); @@ -771,22 +729,6 @@ void SdfGpuPlugin::calculateObscurance(FramebufferObject* fboFront, FramebufferO else mObscuranceProgram->setUniform1i("firstRendering",0); - mFboResult->bind(); - glViewport(0, 0, mResTextureDim, mResTextureDim); - - -#ifndef MACOS - glDrawBuffer(GL_COLOR_ATTACHMENT0); -#endif - glDisable(GL_DEPTH_TEST); - -#ifndef MACOS - glDepthMask(GL_FALSE); -#endif - glEnable (GL_BLEND); - glBlendFunc (GL_ONE, GL_ONE); - glBlendEquation(GL_FUNC_ADD); - // Screen-aligned Quad glBegin(GL_QUADS); glVertex3f(-1.0f, -1.0f, 0.0f); //L-L @@ -795,13 +737,12 @@ void SdfGpuPlugin::calculateObscurance(FramebufferObject* fboFront, FramebufferO glVertex3f(-1.0f, 1.0f, 0.0f); //U-L glEnd(); - assert(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT && "mFboResult error while drawing"); + assert(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)==GL_FRAMEBUFFER_COMPLETE_EXT && "after draw"); mFboResult->unbind(); - #ifndef MACOS - glDepthMask(GL_TRUE); - #endif + glEnable(GL_DEPTH_TEST); + glDepthMask(GL_TRUE); glDisable(GL_BLEND); } @@ -879,13 +820,11 @@ void SdfGpuPlugin::TraceRay(int peelingIteration,const Point3f& dir, MeshModel* int prevBack = (j+1)%3; int prevFront = (j==0)? 2 : (j-1); calculateSdfHW( mFboArray[prevFront], mFboArray[j], mFboArray[prevBack],dir );// front back prevback - checkGLError::qDebug("Error during calculateSdfHW 1 "); } else { //we have first and second depth layers, so we can use "second-depth shadow mapping" to avoid z-fighting assert(j!=0); calculateSdfHW( mFboArray[j-1], mFboArray[j], NULL, dir );// front back prevback - checkGLError::qDebug("Error during calculateSdfHW 2 "); } } } @@ -894,10 +833,10 @@ void SdfGpuPlugin::TraceRay(int peelingIteration,const Point3f& dir, MeshModel* j = (j+1) % 3; } - assert(mFboResult->isValid()&& "Error during depth peeling" ); - assert(mFboArray[0]->isValid() && "Error during depth peeling"); - assert(mFboArray[1]->isValid() && "Error during depth peeling"); - assert(mFboArray[2]->isValid() && "Error during depth peeling"); + assert(mFboResult->isValid()); + assert(mFboArray[0]->isValid()); + assert(mFboArray[1]->isValid()); + assert(mFboArray[2]->isValid()); checkGLError::qDebug("Error during depth peeling"); } diff --git a/src/fgt/filter_sdfgpu/shaders/calculateSdf.frag b/src/fgt/filter_sdfgpu/shaders/calculateSdf.frag index a3ba1975e..52127f071 100644 --- a/src/fgt/filter_sdfgpu/shaders/calculateSdf.frag +++ b/src/fgt/filter_sdfgpu/shaders/calculateSdf.frag @@ -1,293 +1,292 @@ -/**************************************************************************** -* MeshLab o o * -* An extendible mesh processor o o * -* _ O _ * -* Copyright(C) 2005, 2009 \/)\/ * -* Visual Computing Lab /\/| * -* ISTI - Italian National Research Council | * -* \ * -* All rights reserved. * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU General Public License as published by * -* the Free Software Foundation; either version 2 of the License, or * -* (at your option) any later version. * -* * -* This program is distributed in the hope that it will be useful, * -* but WITHOUT ANY WARRANTY; without even the implied warranty of * -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * -* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * -* for more details. * -* * -****************************************************************************/ - -/* -Author: Andrea Baldacci baldacci85@hotmail.it -*/ - -#define EXTRA_RAYS 40 - -uniform sampler2D vTexture; -uniform sampler2D nTexture; -uniform sampler2D depthTextureFront; -uniform sampler2D depthTextureBack; -uniform sampler2D depthTexturePrevBack; -uniform vec3 viewDirection; -uniform mat4 mvprMatrix; -uniform float viewpSize; -uniform float texSize; -uniform float minCos; -uniform int firstRendering; -uniform mat4 mvprMatrixINV; -uniform int removeFalse; -uniform int removeOutliers; -uniform vec3 coneRays[EXTRA_RAYS]; -float _vals[EXTRA_RAYS]; - - - -vec4 project(vec4 coords) -{ - coords = mvprMatrix * coords; // clip space [-1 .. 1] - return vec4(coords.xyz * 0.5+0.5, coords.w); -} - -//Sort values -void InsertionSort(int n) -{ - int i, j; - - float app; - - for (i = 1; i < n; i++) - { - app = _vals[i]; - - for (j = i - 1; (j >= 0) && (_vals[j] > app); j--) - _vals[j+1] = _vals[j]; - - _vals[j + 1] = app; - } -} - -/* -Recostruct normal at the point of intersection and check for false intersection. -For each ray we check the normal at the point of intersection, -and ignore intersections where the normal at the intersection -points is in the same direction as the point-of-origin -(the same direction is defined as an angle difference lessthan 90) -*/ -bool isFalseIntersection(vec3 P, vec3 objSpaceNormal) -{ - - //Recostructing the normal at intersection point - - vec2 coordX1 = vec2( P.x - 1.0/texSize, P.y ); - vec2 coordX2 = vec2( P.x + 1.0/texSize, P.y ); - vec2 coordY1 = vec2( P.x , P.y - 1.0/texSize); - vec2 coordY2 = vec2( P.x , P.y + 1.0/texSize); - - if(coordX1.x < 0.0 ) coordX1.x = 0.0; - if(coordX2.x > 1.0 ) coordX2.x = 1.0; - if(coordY1.y < 0.0 ) coordY1.y = 0.0; - if(coordY2.y > 1.0 ) coordY2.y = 1.0; - - float sampleX1 = texture2D(depthTextureBack, coordX1).r; - float sampleX2 = texture2D(depthTextureBack, coordX2).r; - float sampleY1 = texture2D(depthTextureBack, coordY1).r; - float sampleY2 = texture2D(depthTextureBack, coordY2).r; - - vec3 x1 = vec3( coordX1.x, coordX1.y, sampleX1 ); - vec3 x2 = vec3( coordX2.x, coordX2.y, sampleX2 ); - vec3 y1 = vec3( coordY1.x, coordY1.y, sampleY1 ); - vec3 y2 = vec3( coordY2.x, coordY2.y, sampleY2 ); - - // - vec3 intersectionPointNormal = normalize(cross((x2-x1),(y2-y1)));// * 2.0 -0.5; - - vec4 tmpNormal = vec4( intersectionPointNormal, 0.0 ); - - //from texture space to object space - tmpNormal = mvprMatrixINV * tmpNormal ; - - intersectionPointNormal = tmpNormal.xyz; - - // intersectionPointNormal = normalize(intersectionPointNormal); - - //if angles dont differ at least 90 degrees reject intersection - if(dot(-intersectionPointNormal, objSpaceNormal) > 0.0) return true; - -} - -//Based on the paper "Dynamic Parallax Occlusion Mapping with Approximate Soft Shadows" Natalya Tatarchuk ATI Research, Inc. -float TraceRay(vec2 P, vec3 dir, float sourceHeight) -{ - - int LinearSearchSteps = 256; - - float StepSize = 1.0/256.0; - float Depth = sourceHeight; //Initial depth is that of front vertex - int StepIndex = 0; - - float CurrD = 0.0; - float PrevD = sourceHeight; - - vec2 p1 = vec2(0.0); - vec2 p2 = vec2(0.0); - - // Compute max displacement: - vec2 V = dir.xy*1.41422; - - // - float cotan = sqrt(length(dir)*length(dir) - dir.z*dir.z) / (dir.z); - - float coordStepSize = StepSize * cotan; - - vec2 coordOffset = vec2(0.0,0.0); - - - while(StepIndex < LinearSearchSteps) - { - Depth += StepSize; - coordOffset += V.xy * coordStepSize; - - vec2 tc = P + coordOffset; - - CurrD = texture2D( depthTextureBack, tc).r; - - if(CurrD < Depth) - { - p1 = vec2(Depth, CurrD); - p2 = vec2(Depth - StepSize, PrevD); - StepIndex = LinearSearchSteps; - } - else - { - - //no intersections found, the height map values along the edges is below one. - //In this case the parallax vector near the edges crosses the texture boundary without hitting any features - if(tc.x < 0.0 || tc.x > 1.0 || tc.y < 0.0 || tc.y > 1.0) return 0.0; - - StepIndex++; - PrevD = CurrD; - } - } - - - //Linear approximation using current and last step - float d2 = p2.x - p2.y; - float d1 = p1.x - p1.y; - - float fDenominator = d2 - d1; - - if(fDenominator == 0.0) - { - - return 0.0; - } - //y=m0*x+b0 and y=m1*x+b1 intersection - float destHeight = (p1.x * d2 - p2.x * d1) / fDenominator; - - float sdf = sqrt((destHeight - sourceHeight)* (destHeight - sourceHeight) + length(coordOffset)*length(coordOffset)); - - return sdf; - -} - -float calculateSdf(vec3 P, vec3 objSpacePos, vec3 objSpaceNormal) -{ - - float sdf = 0.0; - - float zFront = texture2D(depthTextureFront, P.xy).r; - float zBack = texture2D(depthTextureBack, P.xy).r; - float zPrevBack = texture2D(depthTexturePrevBack, P.xy).r; - - - - - //first hit of the ray on the mesh. We compare vertex's depth to the next depth layer (back faces), - // this technique is called second-depth shadow mapping - if(firstRendering==1) - { - if ( P.z <= zBack ) - { - sdf = max(0.0,(zBack-zFront) ) ; - - } - }//We have are interested in vertices belonging to the "front" depth layer - //, so we check vertex's depth against the previous layer and the next one - else if ( zPrevBack <= P.z && P.z <= zBack ) - sdf = max(0.0,(zBack-zFront) ) ; - - if(removeFalse==1) - if( isFalseIntersection(P,objSpaceNormal) ) return 0.0; - - if( sdf != 0.0 && removeOutliers == 1) - { - - - int i = 0; - - for( ; i < EXTRA_RAYS ; i++ ) - { - _vals[i] = TraceRay( P.xy, coneRays[i] , zFront ); - } - - - - InsertionSort(EXTRA_RAYS); - - - for( i = 0; i < EXTRA_RAYS; i++ ) - { - if(_vals[i] != 0.0 ) break; - - } - - float valids = float(EXTRA_RAYS - i); - int median = int(valids / 2.0); - int percentile = int(valids / 10.0); - - - if( sdf < _vals[i+median-4*percentile ] || sdf > _vals[i+median+4*percentile] ) return 0.0; - - // sdf = _vals[i+median]; - - } - - - return sdf; -} - -void main(void) -{ - - float sdf = 0.0; - - vec2 coords = vec2(gl_FragCoord.xy/viewpSize); - - vec4 V = texture2D(vTexture, coords); - vec4 N = texture2D(nTexture, coords); - - N = normalize(N); - - vec4 P = project(V); //* (viewpSize/texSize); - - - float cosAngle = max(0.0,dot(N.xyz, viewDirection)); - - - if( cosAngle >= minCos ) - { - - sdf = calculateSdf( P.xyz , V.xyz, N.xyz ) * cosAngle; - } - - - if(sdf == 0.0) cosAngle = 0.0; - - - - gl_FragColor = vec4(sdf, cosAngle , 0.0, 1.0); -} +/**************************************************************************** +* MeshLab o o * +* An extendible mesh processor o o * +* _ O _ * +* Copyright(C) 2005, 2009 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ + +/* +Author: Andrea Baldacci baldacci85@hotmail.it +*/ + +#define EXTRA_RAYS 40 + +uniform sampler2D vTexture; +uniform sampler2D nTexture; +uniform sampler2D depthTextureFront; +uniform sampler2D depthTextureBack; +uniform sampler2D depthTexturePrevBack; +uniform vec3 viewDirection; +uniform mat4 mvprMatrix; +uniform float viewpSize; +uniform float texSize; +uniform float minCos; +uniform int firstRendering; +uniform mat4 mvprMatrixINV; +uniform int removeFalse; +uniform int removeOutliers; +uniform vec3 coneRays[EXTRA_RAYS]; +float _vals[EXTRA_RAYS]; + + + +vec4 project(vec4 coords) +{ + coords = mvprMatrix * coords; // clip space [-1 .. 1] + return vec4(coords.xyz * 0.5+0.5, coords.w); +} + +//Sort values +void InsertionSort(int n) +{ + int i, j; + + float app; + + for (i = 1; i < n; i++) + { + app = _vals[i]; + + for (j = i - 1; (j >= 0) && (_vals[j] > app); j--) + _vals[j+1] = _vals[j]; + + _vals[j + 1] = app; + } +} + +/* +Recostruct normal at the point of intersection and check for false intersection. +For each ray we check the normal at the point of intersection, +and ignore intersections where the normal at the intersection +points is in the same direction as the point-of-origin +(the same direction is defined as an angle difference lessthan 90) +*/ +bool isFalseIntersection(vec3 P, vec3 objSpaceNormal) +{ + + //Recostructing the normal at intersection point + + vec2 coordX1 = vec2( P.x - 1.0/texSize, P.y ); + vec2 coordX2 = vec2( P.x + 1.0/texSize, P.y ); + vec2 coordY1 = vec2( P.x , P.y - 1.0/texSize); + vec2 coordY2 = vec2( P.x , P.y + 1.0/texSize); + + if(coordX1.x < 0.0 ) coordX1.x = 0.0; + if(coordX2.x > 1.0 ) coordX2.x = 1.0; + if(coordY1.y < 0.0 ) coordY1.y = 0.0; + if(coordY2.y > 1.0 ) coordY2.y = 1.0; + + float sampleX1 = texture2D(depthTextureBack, coordX1).r; + float sampleX2 = texture2D(depthTextureBack, coordX2).r; + float sampleY1 = texture2D(depthTextureBack, coordY1).r; + float sampleY2 = texture2D(depthTextureBack, coordY2).r; + + vec3 x1 = vec3( coordX1.x, coordX1.y, sampleX1 ); + vec3 x2 = vec3( coordX2.x, coordX2.y, sampleX2 ); + vec3 y1 = vec3( coordY1.x, coordY1.y, sampleY1 ); + vec3 y2 = vec3( coordY2.x, coordY2.y, sampleY2 ); + + // + vec3 intersectionPointNormal = normalize(cross((x2-x1),(y2-y1)));// * 2.0 -0.5; + + vec4 tmpNormal = vec4( intersectionPointNormal, 0.0 ); + + //from texture space to object space + tmpNormal = mvprMatrixINV * tmpNormal ; + + intersectionPointNormal = tmpNormal.xyz; + + // intersectionPointNormal = normalize(intersectionPointNormal); + + //if angles dont differ at least 90 degrees reject intersection + if(dot(intersectionPointNormal, objSpaceNormal) > 0.0) return true; + +} + +//Based on the paper "Dynamic Parallax Occlusion Mapping with Approximate Soft Shadows" Natalya Tatarchuk ATI Research, Inc. +float TraceRay(vec2 P, vec3 dir, float sourceHeight) +{ + + int LinearSearchSteps = 256; + + float StepSize = 1.0/256.0; + float Depth = sourceHeight; //Initial depth is that of front vertex + int StepIndex = 0; + + float CurrD = 0.0; + float PrevD = sourceHeight; + + vec2 p1 = vec2(0.0); + vec2 p2 = vec2(0.0); + + // Compute max displacement: + vec2 V = dir.xy*1.41422; + + // + float cotan = sqrt(length(dir)*length(dir) - dir.z*dir.z) / (dir.z); + + float coordStepSize = StepSize * cotan; + + vec2 coordOffset = vec2(0.0,0.0); + + + while(StepIndex < LinearSearchSteps) + { + Depth += StepSize; + coordOffset += V.xy * coordStepSize; + + vec2 tc = P + coordOffset; + + CurrD = texture2D( depthTextureBack, tc).r; + + if(CurrD < Depth) + { + p1 = vec2(Depth, CurrD); + p2 = vec2(Depth - StepSize, PrevD); + StepIndex = LinearSearchSteps; + } + else + { + + //no intersections found, the height map values along the edges is below one. + //In this case the parallax vector near the edges crosses the texture boundary without hitting any features + if(tc.x < 0.0 || tc.x > 1.0 || tc.y < 0.0 || tc.y > 1.0) return 0.0; + + StepIndex++; + PrevD = CurrD; + } + } + + + //Linear approximation using current and last step + float d2 = p2.x - p2.y; + float d1 = p1.x - p1.y; + + float fDenominator = d2 - d1; + + if(fDenominator == 0.0) + { + + return 0.0; + } + //y=m0*x+b0 and y=m1*x+b1 intersection + float destHeight = (p1.x * d2 - p2.x * d1) / fDenominator; + + float sdf = sqrt((destHeight - sourceHeight)* (destHeight - sourceHeight) + length(coordOffset)*length(coordOffset)); + + return sdf; + +} + +float calculateSdf(vec3 P, vec3 objSpacePos, vec3 objSpaceNormal) +{ + + float sdf = 0.0; + + float zFront = texture2D(depthTextureFront, P.xy).r; + float zBack = texture2D(depthTextureBack, P.xy).r; + float zPrevBack = texture2D(depthTexturePrevBack, P.xy).r; + + + //first hit of the ray on the mesh. We compare vertex's depth to the next depth layer (back faces), + // this technique is called second-depth shadow mapping + if(firstRendering==1) + { + if ( P.z <= zBack ) + { + sdf = max(0.0,(zBack-zFront) ) ; + + } + }//We have are interested in vertices belonging to the "front" depth layer + //, so we check vertex's depth against the previous layer and the next one + else if ( zPrevBack <= P.z && P.z <= zBack ) + sdf = max(0.0,(zBack-zFront) ) ; + +// if(removeFalse==1) +// if( isFalseIntersection(P,objSpaceNormal) ) return 0.0; + +/* if( sdf != 0.0 && removeOutliers == 1) + { + + + int i = 0; + + for( ; i < EXTRA_RAYS ; i++ ) + { + _vals[i] = TraceRay( P.xy, coneRays[i] , zFront ); + } + + + + InsertionSort(EXTRA_RAYS); + + + for( i = 0; i < EXTRA_RAYS; i++ ) + { + if(_vals[i] != 0.0 ) break; + + } + + float valids = float(EXTRA_RAYS - i); + int median = int(valids / 2.0); + int percentile = int(valids / 10.0); + + + if( sdf < _vals[i+median-4*percentile ] || sdf > _vals[i+median+4*percentile] ) return 0.0; + + // sdf = _vals[i+median]; + + + }*/ + + + return sdf; +} + +void main(void) +{ + + float sdf = 0.0; + + vec2 coords = vec2(gl_FragCoord.xy/viewpSize); + + vec4 V = texture2D(vTexture, coords); + vec4 N = texture2D(nTexture, coords); + + N = normalize(N); + + vec4 P = project(V); //* (viewpSize/texSize); + + + float cosAngle = max(0.0,dot(N.xyz, viewDirection)); + + + if( cosAngle >= minCos ) + { + + sdf = calculateSdf( P.xyz , V.xyz, N.xyz ) * cosAngle; + } + + + if(sdf == 0.0) cosAngle = 0.0; + + + + gl_FragColor = vec4(sdf, cosAngle , 0.0, 1.0); +}