Found a problem with sdf shader. A part of the shader has been disabled with comments.

This commit is contained in:
Andrea Baldacci baldacci 2011-05-26 14:40:27 +00:00
parent 0726ceaf3c
commit 6d905f85ff
2 changed files with 353 additions and 415 deletions

View File

@ -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<GLint*>(&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<GLW::NMNone, GLW::CMNone, GLW::TMNone>();
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");
}

View File

@ -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);
}