first working commit for the apss (from Algebraic point set surfaces
Gaël Guennebaud and Markus Gross, SIG07)
This commit is contained in:
parent
969f556691
commit
42c69abccf
|
@ -0,0 +1,112 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* 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. *
|
||||||
|
* *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#extension GL_ARB_texture_rectangle : enable
|
||||||
|
|
||||||
|
#ifndef EXPE_DEPTH_INTERPOLATION
|
||||||
|
#define EXPE_DEPTH_INTERPOLATION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EXPE_OUTPUT_DEPTH
|
||||||
|
#define EXPE_OUTPUT_DEPTH 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// avoid an annoying bug with the nvidia driver 87XX serie.
|
||||||
|
#define epsilon 0.000001
|
||||||
|
|
||||||
|
uniform vec4 viewport;
|
||||||
|
|
||||||
|
#ifndef EXPE_DEFERRED_SHADING
|
||||||
|
|
||||||
|
uniform sampler2DRect ColorWeight;
|
||||||
|
#if (EXPE_OUTPUT_DEPTH==1)
|
||||||
|
uniform sampler2DRect Depth;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Finalization(void)
|
||||||
|
{
|
||||||
|
vec4 color = texture2DRect(ColorWeight, gl_FragCoord.st - viewport.xy + epsilon);
|
||||||
|
#if (EXPE_OUTPUT_DEPTH==1)
|
||||||
|
gl_FragDepth = texture2DRect(Depth, gl_FragCoord.st + epsilon).x;
|
||||||
|
#endif
|
||||||
|
if (color.w<0.001)
|
||||||
|
discard;
|
||||||
|
gl_FragColor = color/color.w;
|
||||||
|
gl_FragColor.a = 1.;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
uniform vec2 unproj;
|
||||||
|
|
||||||
|
uniform sampler2DRect ColorWeight;
|
||||||
|
uniform sampler2DRect NormalWeight;
|
||||||
|
|
||||||
|
#if ( (EXPE_DEPTH_INTERPOLATION==0) || (EXPE_OUTPUT_DEPTH==1))
|
||||||
|
uniform sampler2DRect Depth;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Finalization(void)
|
||||||
|
{
|
||||||
|
vec4 color = texture2DRect(ColorWeight, gl_FragCoord.st - viewport.xy + epsilon);
|
||||||
|
|
||||||
|
if (color.w<0.001)
|
||||||
|
discard;
|
||||||
|
|
||||||
|
|
||||||
|
if(color.w>0.001)
|
||||||
|
color.xyz /= color.w;
|
||||||
|
|
||||||
|
vec3 viewVec = normalize(gl_TexCoord[0].xyz);
|
||||||
|
vec4 normaldepth = texture2DRect(NormalWeight, gl_FragCoord.st + epsilon);
|
||||||
|
|
||||||
|
normaldepth.xyz = normaldepth.xyz/normaldepth.w;
|
||||||
|
|
||||||
|
#if (EXPE_OUTPUT_DEPTH==1)
|
||||||
|
gl_FragDepth = texture2DRect(Depth, gl_FragCoord.st + epsilon).x;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if EXPE_DEPTH_INTERPOLATION==2
|
||||||
|
float depth = -normaldepth.z;
|
||||||
|
#elif EXPE_DEPTH_INTERPOLATION==1
|
||||||
|
float depth = unproj.y/(2.0*normaldepth.z+unproj.x-1.0);
|
||||||
|
#else
|
||||||
|
float depth = texture2DRect(Depth, gl_FragCoord.st + epsilon).x;
|
||||||
|
depth = unproj.y/(2.0*depth+unproj.x-1.0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec3 normal = normaldepth.xyz;
|
||||||
|
#if EXPE_DEPTH_INTERPOLATION!=0
|
||||||
|
normal.z = sqrt(1. - dot(vec3(normal.xy,0),vec3(normal.xy,0)));
|
||||||
|
#endif
|
||||||
|
normal = normalize(normal);
|
||||||
|
vec3 eyePos = gl_TexCoord[0].xyz * depth;
|
||||||
|
|
||||||
|
gl_FragColor = meshlabLighting(color, eyePos, normal);
|
||||||
|
gl_FragColor.a = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,345 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* 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. *
|
||||||
|
* *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
// #version 110
|
||||||
|
// #extension all : enable
|
||||||
|
|
||||||
|
#pragma optimize(on)
|
||||||
|
|
||||||
|
#ifndef EXPE_EWA_HINT
|
||||||
|
#define EXPE_EWA_HINT 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EXPE_DEPTH_INTERPOLATION
|
||||||
|
#define EXPE_DEPTH_INTERPOLATION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// shared variables
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// custom vertex attributes
|
||||||
|
//attribute float radius;
|
||||||
|
|
||||||
|
#ifdef CLIPPED_SPLAT
|
||||||
|
attribute vec3 secondNormal;
|
||||||
|
varying vec4 clipLine;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// standard uniforms
|
||||||
|
uniform float expeRadiusScale;
|
||||||
|
uniform float expePreComputeRadius;
|
||||||
|
uniform float expeDepthOffset;
|
||||||
|
|
||||||
|
// varying
|
||||||
|
varying vec4 covmat;
|
||||||
|
varying vec3 fragNormal;
|
||||||
|
|
||||||
|
varying vec3 fragNoverCdotN;
|
||||||
|
varying vec3 fragCenter;
|
||||||
|
varying float scaleSquaredDistance;
|
||||||
|
|
||||||
|
#ifdef EXPE_ATI_WORKAROUND
|
||||||
|
varying vec4 fragCenterAndRadius;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef EXPE_DEPTH_CORRECTION
|
||||||
|
varying float depthOffset;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform vec2 halfVp;
|
||||||
|
uniform float oneOverEwaRadius;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef EXPE_BACKFACE_SHADING
|
||||||
|
#undef EXPE_EARLY_BACK_FACE_CULLING
|
||||||
|
//#define EXPE_EWA_HINT 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// Visibility Splatting
|
||||||
|
// Vertex Shader
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __VisibilityVP__
|
||||||
|
varying vec2 scaledFragCenter2d;
|
||||||
|
void VisibilityVP(void)
|
||||||
|
{
|
||||||
|
vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||||
|
// Point in eye space
|
||||||
|
vec4 ePos = gl_ModelViewMatrix * gl_Vertex;
|
||||||
|
|
||||||
|
float dotpn = dot(normal.xyz,ePos.xyz);
|
||||||
|
|
||||||
|
vec4 oPos;
|
||||||
|
|
||||||
|
#ifdef EXPE_EARLY_BACK_FACE_CULLING
|
||||||
|
// back_face culling
|
||||||
|
oPos = vec4(0,0,1,0);
|
||||||
|
if(dotpn<0.)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float radius = gl_MultiTexCoord2.x * expeRadiusScale;
|
||||||
|
|
||||||
|
vec4 pointSize;
|
||||||
|
pointSize.x = radius * expePreComputeRadius / ePos.z;
|
||||||
|
gl_PointSize = max(1.0, pointSize.x);
|
||||||
|
|
||||||
|
scaleSquaredDistance = 1.0 / (radius * radius);
|
||||||
|
//fragNormal = normal;
|
||||||
|
fragCenter = ePos.xyz;
|
||||||
|
fragNoverCdotN = normal/dot(ePos.xyz,normal);
|
||||||
|
|
||||||
|
#ifndef EXPE_DEPTH_CORRECTION
|
||||||
|
ePos.xyz += normalize(ePos.xyz) * expeDepthOffset * radius;
|
||||||
|
#else
|
||||||
|
//ePos.xyz += normalize(ePos.xyz) * expeDepthOffset * radius;
|
||||||
|
depthOffset = expeDepthOffset * radius;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
oPos = gl_ProjectionMatrix * ePos;
|
||||||
|
|
||||||
|
#if (EXPE_EWA_HINT>0)
|
||||||
|
scaledFragCenter2d = 0.5*((oPos.xy/oPos.w)+1.0)*halfVp*oneOverEwaRadius;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef EXPE_ATI_WORKAROUND
|
||||||
|
fragCenterAndRadius.xyz = (oPos.xyz/oPos.w) + 1.0;
|
||||||
|
fragCenterAndRadius.xy = fragCenterAndRadius.xy*halfVp;
|
||||||
|
fragCenterAndRadius.z = fragCenterAndRadius.z*0.5;
|
||||||
|
fragCenterAndRadius.w = pointSize.x;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EXPE_EARLY_BACK_FACE_CULLING
|
||||||
|
oPos.w = oPos.w * ( (dotpn<0.0) ? 1.0 : 0.0);
|
||||||
|
#else
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gl_Position = oPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// Visibility Splatting
|
||||||
|
// Fragment Shader
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __VisibilityFP__
|
||||||
|
varying vec2 scaledFragCenter2d;
|
||||||
|
uniform vec3 rayCastParameter1;
|
||||||
|
uniform vec3 rayCastParameter2;
|
||||||
|
uniform vec2 depthParameterCast;
|
||||||
|
|
||||||
|
void VisibilityFP(void)
|
||||||
|
{
|
||||||
|
#ifdef EXPE_ATI_WORKAROUND
|
||||||
|
vec3 fragCoord;
|
||||||
|
fragCoord.xy = fragCenterAndRadius.xy + (gl_TexCoord[0].st-0.5) * fragCenterAndRadius.w;
|
||||||
|
fragCoord.z = fragCenterAndRadius.z;
|
||||||
|
#else
|
||||||
|
vec3 fragCoord = gl_FragCoord.xyz;
|
||||||
|
#endif
|
||||||
|
// compute q in object space
|
||||||
|
vec3 qOne = rayCastParameter1 * fragCoord + rayCastParameter2; // MAD
|
||||||
|
float oneOverDepth = dot(qOne,-fragNoverCdotN); // DP3
|
||||||
|
float depth = (1.0/oneOverDepth); // RCP
|
||||||
|
vec3 diff = fragCenter + qOne * depth; // MAD
|
||||||
|
float r2 = dot(diff,diff); // DP3
|
||||||
|
|
||||||
|
#if (EXPE_EWA_HINT>0)
|
||||||
|
vec2 d2 = oneOverEwaRadius*gl_FragCoord.xy - scaledFragCenter2d; // MAD
|
||||||
|
float r2d = dot(d2,d2); // DP3
|
||||||
|
gl_FragColor = vec4(min(r2d,r2*scaleSquaredDistance));
|
||||||
|
#else
|
||||||
|
gl_FragColor = vec4(r2*scaleSquaredDistance);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef EXPE_DEPTH_CORRECTION
|
||||||
|
oneOverDepth = 1.0/(-depth+depthOffset);
|
||||||
|
gl_FragDepth = depthParameterCast.x * oneOverDepth + depthParameterCast.y; // MAD
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __AttributeVP__
|
||||||
|
|
||||||
|
varying vec2 scaledFragCenter2d;
|
||||||
|
|
||||||
|
void AttributeVP(void)
|
||||||
|
{
|
||||||
|
// transform normal
|
||||||
|
vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
|
||||||
|
// Point in eye space
|
||||||
|
vec4 ePos = gl_ModelViewMatrix * gl_Vertex;
|
||||||
|
|
||||||
|
float dotpn = dot(normal.xyz,ePos.xyz);
|
||||||
|
|
||||||
|
vec4 oPos;
|
||||||
|
|
||||||
|
#ifdef EXPE_EARLY_BACK_FACE_CULLING
|
||||||
|
// back_face culling
|
||||||
|
oPos = vec4(0,0,1,0);
|
||||||
|
if(dotpn<0.)
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef EXPE_BACKFACE_SHADING
|
||||||
|
if(dotpn>0.)
|
||||||
|
{
|
||||||
|
dotpn = -dotpn;
|
||||||
|
normal = -normal;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float radius = gl_MultiTexCoord2.x * expeRadiusScale * 1.05;
|
||||||
|
|
||||||
|
vec4 pointSize;
|
||||||
|
pointSize.x = radius * expePreComputeRadius / ePos.z;
|
||||||
|
|
||||||
|
#if (EXPE_EWA_HINT>0)
|
||||||
|
gl_PointSize = max(2.0, pointSize.x);
|
||||||
|
#else
|
||||||
|
gl_PointSize = max(1.0, pointSize.x);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
scaleSquaredDistance = 1. / (radius * radius);
|
||||||
|
///********* uncommented fragNormal....
|
||||||
|
//fragNormal = normal;
|
||||||
|
fragCenter = ePos.xyz;
|
||||||
|
fragNoverCdotN = normal/dot(ePos.xyz,normal);
|
||||||
|
|
||||||
|
// Output color
|
||||||
|
#ifdef EXPE_DEFERRED_SHADING
|
||||||
|
fragNormal.xyz = normal.xyz;
|
||||||
|
gl_FrontColor = gl_Color;
|
||||||
|
#else
|
||||||
|
// Output color
|
||||||
|
#ifdef EXPE_LIGHTING
|
||||||
|
gl_FrontColor = expeLighting(gl_Color, ePos.xyz, normal.xyz, 1.);
|
||||||
|
#else
|
||||||
|
gl_FrontColor = meshlabLighting(gl_Color, ePos.xyz, normal.xyz);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
oPos = gl_ModelViewProjectionMatrix * gl_Vertex;
|
||||||
|
|
||||||
|
#ifdef EXPE_ATI_WORKAROUND
|
||||||
|
fragCenterAndRadius.xyz = (oPos.xyz/oPos.w) + 1.0;
|
||||||
|
fragCenterAndRadius.xy = fragCenterAndRadius.xy*halfVp;
|
||||||
|
fragCenterAndRadius.z = fragCenterAndRadius.z*0.5;
|
||||||
|
fragCenterAndRadius.w = pointSize.x;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (EXPE_EWA_HINT>0)
|
||||||
|
scaledFragCenter2d = ((oPos.xy/oPos.w)+1.0)*halfVp*oneOverEwaRadius;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef EXPE_EARLY_BACK_FACE_CULLING
|
||||||
|
oPos.w = oPos.w * (dotpn<0. ? 1.0 : 0.0);
|
||||||
|
#else
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
gl_Position = oPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
// EWA Splatting
|
||||||
|
// Fragment Shader
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifdef __AttributeFP__
|
||||||
|
// this sampler is only used by this fragment shader
|
||||||
|
|
||||||
|
varying vec2 scaledFragCenter2d;
|
||||||
|
uniform vec3 rayCastParameter1;
|
||||||
|
uniform vec3 rayCastParameter2;
|
||||||
|
uniform vec2 depthParameterCast;
|
||||||
|
|
||||||
|
// uniform sampler1D Kernel1dMap;
|
||||||
|
|
||||||
|
void AttributeFP(void)
|
||||||
|
{
|
||||||
|
#ifdef EXPE_ATI_WORKAROUND
|
||||||
|
vec3 fragCoord;
|
||||||
|
fragCoord.xy = fragCenterAndRadius.xy + (gl_TexCoord[0].st-0.5) * fragCenterAndRadius.w;
|
||||||
|
fragCoord.z = fragCenterAndRadius.z;
|
||||||
|
#else
|
||||||
|
vec3 fragCoord = gl_FragCoord.xyz;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
vec3 qOne = rayCastParameter1 * fragCoord + rayCastParameter2; // MAD
|
||||||
|
float oneOverDepth = dot(qOne,fragNoverCdotN); // DP3
|
||||||
|
float depth = (1.0/oneOverDepth); // RCP
|
||||||
|
vec3 diff = fragCenter - qOne * depth; // MAD
|
||||||
|
float r2 = dot(diff,diff); // DP3
|
||||||
|
|
||||||
|
#if (EXPE_EWA_HINT>0)
|
||||||
|
vec2 d2 = oneOverEwaRadius*gl_FragCoord.xy - scaledFragCenter2d; // MAD
|
||||||
|
float r2d = dot(d2,d2); // DP3
|
||||||
|
// float weight = texture1D(Kernel1dMap, min(r2d,r2*scaleSquaredDistance)).a; // MUL + MIN + TEX
|
||||||
|
float weight = min(r2d,r2*scaleSquaredDistance);
|
||||||
|
weight = clamp(1.-weight,0,1);
|
||||||
|
weight = weight*weight;
|
||||||
|
#else
|
||||||
|
//float weight = texture1D(Kernel1dMap, r2*scaleSquaredDistance).a; // MUL + TEX
|
||||||
|
float weight = clamp(1.-r2*scaleSquaredDistance,0.0,1.0);
|
||||||
|
weight = weight*weight;
|
||||||
|
#endif
|
||||||
|
weight *= 0.1; // limits overflow
|
||||||
|
|
||||||
|
#ifdef EXPE_DEPTH_CORRECTION
|
||||||
|
gl_FragDepth = depthParameterCast.x * oneOverDepth + depthParameterCast.y; // MAD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef EXPE_DEFERRED_SHADING
|
||||||
|
gl_FragData[0].rgb = gl_Color.rgb; // MOV
|
||||||
|
gl_FragData[1].xyz = fragNormal.xyz; // MOV
|
||||||
|
gl_FragData[1].w = weight; // MOV
|
||||||
|
gl_FragData[0].w = weight;
|
||||||
|
|
||||||
|
#if EXPE_DEPTH_INTERPOLATION==2 // linear space
|
||||||
|
gl_FragData[1].z = -depth; // MOV
|
||||||
|
#elif EXPE_DEPTH_INTERPOLATION==1 // window space
|
||||||
|
#ifdef EXPE_DEPTH_CORRECTION
|
||||||
|
gl_FragData[1].z = gl_FragDepth;
|
||||||
|
#else
|
||||||
|
gl_FragData[1].z = fragCoord.z;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else
|
||||||
|
gl_FragColor.rgb = gl_Color.rgb; // MOV
|
||||||
|
gl_FragColor.w = weight;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,843 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* MeshLab o o *
|
||||||
|
* A versatile mesh processing toolbox o o *
|
||||||
|
* _ O _ *
|
||||||
|
* Copyright(C) 2005 \/)\/ *
|
||||||
|
* 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. *
|
||||||
|
* *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef SPLATRENDERER_H
|
||||||
|
#define SPLATRENDERER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <wrap/gl/trimesh.h>
|
||||||
|
#include <wrap/gl/shaders.h>
|
||||||
|
#include <wrap/gl/trimesh.h>
|
||||||
|
#include <QGLFramebufferObject>
|
||||||
|
#define GL_TEST_ERR\
|
||||||
|
{\
|
||||||
|
GLenum eCode;\
|
||||||
|
if((eCode=glGetError())!=GL_NO_ERROR)\
|
||||||
|
std::cerr << "OpenGL error : " << gluErrorString(eCode) << " in " << __FILE__ << " : " << __LINE__ << std::endl;\
|
||||||
|
}
|
||||||
|
|
||||||
|
class QGLFramebufferObject;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Rendering with Algebraic Point Set Surfaces, by Gael Guennebaud.
|
||||||
|
paper: Algebraic Point Set Surfaces SIGGRAPH '07
|
||||||
|
*/
|
||||||
|
template <class MeshType>
|
||||||
|
class SplatRenderer
|
||||||
|
{
|
||||||
|
bool mIsSupported;
|
||||||
|
bool init_called;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DEFERRED_SHADING_BIT = 0x000001,
|
||||||
|
DEPTH_CORRECTION_BIT = 0x000002,
|
||||||
|
OUTPUT_DEPTH_BIT = 0x000004,
|
||||||
|
BACKFACE_SHADING_BIT = 0x000008,
|
||||||
|
FLOAT_BUFFER_BIT = 0x000010
|
||||||
|
};
|
||||||
|
int mFlags;
|
||||||
|
int mCachedFlags;
|
||||||
|
int mRenderBufferMask;
|
||||||
|
int mSupportedMask;
|
||||||
|
|
||||||
|
//int mCurrentPass;
|
||||||
|
int mBindedPass;
|
||||||
|
GLuint mDummyTexId; // on ATI graphics card we need to bind a texture to get point sprite working !
|
||||||
|
bool mWorkaroundATI;
|
||||||
|
bool mBuggedAtiBlending;
|
||||||
|
GLuint mNormalTextureID;
|
||||||
|
GLuint mDepthTextureID;
|
||||||
|
ProgramVF mShaders[3];
|
||||||
|
QString mShaderSrcs[6];
|
||||||
|
QGLFramebufferObject* mRenderBuffer;
|
||||||
|
float mCachedMV[16];
|
||||||
|
float mCachedProj[16];
|
||||||
|
GLint mCachedVP[4];
|
||||||
|
|
||||||
|
struct UniformParameters
|
||||||
|
{
|
||||||
|
float radiusScale;
|
||||||
|
float preComputeRadius;
|
||||||
|
float depthOffset;
|
||||||
|
float oneOverEwaRadius;
|
||||||
|
vcg::Point2f halfVp;
|
||||||
|
vcg::Point3f rayCastParameter1;
|
||||||
|
vcg::Point3f rayCastParameter2;
|
||||||
|
vcg::Point2f depthParameterCast;
|
||||||
|
|
||||||
|
void loadTo(Program& prg);
|
||||||
|
void update(float* mv, float* proj, GLint* vp);
|
||||||
|
};
|
||||||
|
|
||||||
|
UniformParameters mParams;
|
||||||
|
|
||||||
|
QString loadSource(const QString& func,const QString& file);
|
||||||
|
void configureShaders();
|
||||||
|
void updateRenderBuffer();
|
||||||
|
void enablePass(int n);
|
||||||
|
void drawSplats(std::vector<MeshType*> & , vcg::GLW::ColorMode cm, vcg::GLW::TextureMode tm);
|
||||||
|
void drawSplats(
|
||||||
|
std::vector< std::vector<vcg::Point3f> * > & positions,
|
||||||
|
std::vector< std::vector<vcg::Point3f> * > & normals,
|
||||||
|
std::vector< std::vector<vcg::Point3<unsigned char> > * > & colors,
|
||||||
|
std::vector<float> & radius,
|
||||||
|
vcg::GLW::ColorMode cm, vcg::GLW::TextureMode tm);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
void Destroy();
|
||||||
|
bool isSupported() {return mIsSupported;}
|
||||||
|
void Init(QGLWidget *gla);
|
||||||
|
void Render( std::vector<MeshType*> &meshes, vcg::GLW::ColorMode cm, vcg::GLW::TextureMode tm);
|
||||||
|
|
||||||
|
void Render(
|
||||||
|
std::vector< std::vector<vcg::Point3f> * > & positions,
|
||||||
|
std::vector< std::vector<vcg::Point3f> * > & normals,
|
||||||
|
std::vector< std::vector<vcg::Point3<unsigned char> > * > & colors,
|
||||||
|
std::vector<float> & radius,
|
||||||
|
vcg::GLW::ColorMode cm, vcg::GLW::TextureMode tm);
|
||||||
|
|
||||||
|
};// end class
|
||||||
|
|
||||||
|
template <class MeshType>
|
||||||
|
void SplatRenderer<MeshType>:: Destroy(){
|
||||||
|
delete mRenderBuffer;
|
||||||
|
mRenderBuffer = 0;
|
||||||
|
glDeleteTextures(1,&mDepthTextureID);
|
||||||
|
glDeleteTextures(1,&mNormalTextureID);
|
||||||
|
for(int i = 0; i < 3; ++i)
|
||||||
|
this->mShaders[i].prog.Del();
|
||||||
|
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class MeshType>
|
||||||
|
void SplatRenderer<MeshType>::Clear()
|
||||||
|
{
|
||||||
|
mNormalTextureID = 0;
|
||||||
|
mDepthTextureID = 0;
|
||||||
|
mIsSupported = false;
|
||||||
|
mRenderBuffer = 0;
|
||||||
|
mWorkaroundATI = false;
|
||||||
|
mBuggedAtiBlending = false;
|
||||||
|
mDummyTexId = 0;
|
||||||
|
|
||||||
|
mFlags = DEFERRED_SHADING_BIT | DEPTH_CORRECTION_BIT | FLOAT_BUFFER_BIT | OUTPUT_DEPTH_BIT;
|
||||||
|
mCachedFlags = ~mFlags;
|
||||||
|
// union of bits which controls the render buffer
|
||||||
|
mRenderBufferMask = DEFERRED_SHADING_BIT | FLOAT_BUFFER_BIT;
|
||||||
|
|
||||||
|
init_called = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class MeshType>
|
||||||
|
QString SplatRenderer<MeshType>::loadSource(const QString& func,const QString& filename)
|
||||||
|
{
|
||||||
|
QString res;
|
||||||
|
QFile f(":/SplatRenderer/shaders/" + filename);
|
||||||
|
if (!f.open(QFile::ReadOnly))
|
||||||
|
{
|
||||||
|
std::cerr << "failed to load shader file " << filename.toAscii().data() << "\n";
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
else qDebug("Succesfully loaded shader func '%s' in file '%s'",qPrintable(func),qPrintable(filename));
|
||||||
|
QTextStream stream(&f);
|
||||||
|
res = stream.readAll();
|
||||||
|
f.close();
|
||||||
|
res = QString("#define __%1__ 1\n").arg(func)
|
||||||
|
+ QString("#define %1 main\n").arg(func)
|
||||||
|
+ res;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
template <class MeshType>
|
||||||
|
void SplatRenderer<MeshType>::configureShaders()
|
||||||
|
{
|
||||||
|
const char* passNames[3] = {"Visibility","Attribute","Finalization"};
|
||||||
|
QString defines = "";
|
||||||
|
if (mFlags & DEFERRED_SHADING_BIT)
|
||||||
|
defines += "#define EXPE_DEFERRED_SHADING\n";
|
||||||
|
if (mFlags & DEPTH_CORRECTION_BIT)
|
||||||
|
defines += "#define EXPE_DEPTH_CORRECTION\n";
|
||||||
|
if (mFlags & OUTPUT_DEPTH_BIT)
|
||||||
|
defines += "#define EXPE_OUTPUT_DEPTH 1\n";
|
||||||
|
if (mFlags & BACKFACE_SHADING_BIT)
|
||||||
|
defines += "#define EXPE_BACKFACE_SHADING\n";
|
||||||
|
if (mWorkaroundATI)
|
||||||
|
defines += "#define EXPE_ATI_WORKAROUND\n";
|
||||||
|
|
||||||
|
QString shading =
|
||||||
|
"vec4 meshlabLighting(vec4 color, vec3 eyePos, vec3 normal)"
|
||||||
|
"{"
|
||||||
|
" normal = normalize(normal);"
|
||||||
|
" vec3 lightVec = normalize(gl_LightSource[0].position.xyz);"
|
||||||
|
" vec3 halfVec = normalize( lightVec - normalize(eyePos) );"
|
||||||
|
" float aux_dot = dot(normal,lightVec);"
|
||||||
|
" float diffuseCoeff = clamp(aux_dot, 0.0, 1.0);"
|
||||||
|
" float specularCoeff = aux_dot>0.0 ? clamp(pow(clamp(dot(halfVec, normal),0.0,1.0),gl_FrontMaterial.shininess), 0.0, 1.0) : 0.0;"
|
||||||
|
" return vec4(color.rgb * ( gl_FrontLightProduct[0].ambient.rgb + diffuseCoeff * gl_FrontLightProduct[0].diffuse.rgb) + specularCoeff * gl_FrontLightProduct[0].specular.rgb, 1.0);"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
for (int k=0;k<3;++k)
|
||||||
|
{
|
||||||
|
QString vsrc = shading + defines + mShaderSrcs[k*2+0];
|
||||||
|
QString fsrc = shading + defines + mShaderSrcs[k*2+1];
|
||||||
|
mShaders[k].SetSources(mShaderSrcs[k*2+0]!="" ? vsrc.toAscii().data() : 0,
|
||||||
|
mShaderSrcs[k*2+1]!="" ? fsrc.toAscii().data() : 0);
|
||||||
|
mShaders[k].prog.Link();
|
||||||
|
if (mShaderSrcs[k*2+0]!="")
|
||||||
|
{
|
||||||
|
std::string compileinfo = mShaders[k].vshd.InfoLog();
|
||||||
|
if (compileinfo.size()>0)
|
||||||
|
std::cout << "Vertex shader info (" << passNames[k] << ":\n" << compileinfo << "\n";
|
||||||
|
}
|
||||||
|
if (mShaderSrcs[k*2+1]!="")
|
||||||
|
{
|
||||||
|
std::string compileinfo = mShaders[k].fshd.InfoLog();
|
||||||
|
if (compileinfo.size()>0)
|
||||||
|
std::cout << "Fragment shader info (" << passNames[k] << ":\n" << compileinfo << "\n";
|
||||||
|
}
|
||||||
|
std::string linkinfo = mShaders[k].prog.InfoLog();
|
||||||
|
if (linkinfo.size()>0)
|
||||||
|
std::cout << "Link info (" << passNames[k] << ":\n" << linkinfo << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class MeshType>
|
||||||
|
void SplatRenderer<MeshType>::Init(QGLWidget *gla)
|
||||||
|
{
|
||||||
|
|
||||||
|
mIsSupported = true;
|
||||||
|
gla->makeCurrent();
|
||||||
|
// FIXME this should be done in meshlab !!! ??
|
||||||
|
glewInit();
|
||||||
|
|
||||||
|
const char* rs = (const char*)glGetString(GL_RENDERER);
|
||||||
|
QString rendererString("");
|
||||||
|
if(rs)
|
||||||
|
rendererString = QString(rs);
|
||||||
|
mWorkaroundATI = rendererString.startsWith("ATI") || rendererString.startsWith("AMD");
|
||||||
|
// FIXME: maybe some recent HW correctly supports floating point blending...
|
||||||
|
mBuggedAtiBlending = rendererString.startsWith("ATI") || rendererString.startsWith("AMD");
|
||||||
|
|
||||||
|
if (mWorkaroundATI && mDummyTexId==0)
|
||||||
|
{
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glGenTextures(1,&mDummyTexId);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, mDummyTexId);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 4, 4, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// let's check the GPU capabilities
|
||||||
|
mSupportedMask = DEPTH_CORRECTION_BIT | BACKFACE_SHADING_BIT;
|
||||||
|
if (!QGLFramebufferObject::hasOpenGLFramebufferObjects ())
|
||||||
|
{
|
||||||
|
mIsSupported = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (GLEW_ARB_texture_float)
|
||||||
|
mSupportedMask |= FLOAT_BUFFER_BIT;
|
||||||
|
else
|
||||||
|
std::cout << "Splatting: warning floating point textures are not supported.\n";
|
||||||
|
|
||||||
|
if (GLEW_ARB_draw_buffers && (!mBuggedAtiBlending))
|
||||||
|
mSupportedMask |= DEFERRED_SHADING_BIT;
|
||||||
|
else
|
||||||
|
std::cout << "Splatting: warning deferred shading is not supported.\n";
|
||||||
|
|
||||||
|
if (GLEW_ARB_shadow)
|
||||||
|
mSupportedMask |= OUTPUT_DEPTH_BIT;
|
||||||
|
else
|
||||||
|
std::cerr << "Splatting: warning copy of the depth buffer is not supported.\n";
|
||||||
|
|
||||||
|
mFlags = mFlags & mSupportedMask;
|
||||||
|
|
||||||
|
// load shader source
|
||||||
|
mShaderSrcs[0] = loadSource("VisibilityVP","Raycasting.glsl");
|
||||||
|
mShaderSrcs[1] = loadSource("VisibilityFP","Raycasting.glsl");
|
||||||
|
mShaderSrcs[2] = loadSource("AttributeVP","Raycasting.glsl");
|
||||||
|
mShaderSrcs[3] = loadSource("AttributeFP","Raycasting.glsl");
|
||||||
|
mShaderSrcs[4] = "";
|
||||||
|
mShaderSrcs[5] = loadSource("Finalization","Finalization.glsl");
|
||||||
|
|
||||||
|
//mCurrentPass = 2;
|
||||||
|
mBindedPass = -1;
|
||||||
|
GL_TEST_ERR
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class MeshType>
|
||||||
|
void SplatRenderer<MeshType>::updateRenderBuffer()
|
||||||
|
{
|
||||||
|
if ( (!mRenderBuffer)
|
||||||
|
|| (mRenderBuffer->width()!=mCachedVP[2])
|
||||||
|
|| (mRenderBuffer->height()!=mCachedVP[3])
|
||||||
|
|| ( (mCachedFlags & mRenderBufferMask) != (mFlags & mRenderBufferMask) ))
|
||||||
|
{
|
||||||
|
delete mRenderBuffer;
|
||||||
|
GLenum fmt = (mFlags&FLOAT_BUFFER_BIT) ? GL_RGBA16F_ARB : GL_RGBA;
|
||||||
|
mRenderBuffer = new QGLFramebufferObject(mCachedVP[2], mCachedVP[3],
|
||||||
|
(mFlags&OUTPUT_DEPTH_BIT) ? QGLFramebufferObject::NoAttachment : QGLFramebufferObject::Depth,
|
||||||
|
GL_TEXTURE_RECTANGLE_ARB, fmt);
|
||||||
|
|
||||||
|
if (!mRenderBuffer->isValid())
|
||||||
|
{
|
||||||
|
std::cout << "SplatRenderer: invalid FBO\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
GL_TEST_ERR
|
||||||
|
if (mFlags&DEFERRED_SHADING_BIT)
|
||||||
|
{
|
||||||
|
// in deferred shading mode we need an additional buffer to accumulate the normals
|
||||||
|
if (mNormalTextureID==0)
|
||||||
|
glGenTextures(1,&mNormalTextureID);
|
||||||
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mNormalTextureID);
|
||||||
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, fmt, mCachedVP[2], mCachedVP[3], 0, GL_RGBA, GL_FLOAT, 0);
|
||||||
|
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
mRenderBuffer->bind();
|
||||||
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, mNormalTextureID, 0);
|
||||||
|
mRenderBuffer->release();
|
||||||
|
GL_TEST_ERR
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFlags&OUTPUT_DEPTH_BIT)
|
||||||
|
{
|
||||||
|
// to output the depth values to the final depth buffer we need to
|
||||||
|
// attach a depth buffer as a texture
|
||||||
|
if (mDepthTextureID==0)
|
||||||
|
glGenTextures(1,&mDepthTextureID);
|
||||||
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mDepthTextureID);
|
||||||
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24_ARB, mCachedVP[2], mCachedVP[3], 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
|
||||||
|
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
mRenderBuffer->bind();
|
||||||
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, mDepthTextureID, 0);
|
||||||
|
mRenderBuffer->release();
|
||||||
|
GL_TEST_ERR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class MeshType>
|
||||||
|
void SplatRenderer<MeshType>::Render(std::vector<MeshType*> & meshes, vcg::GLW::ColorMode cm, vcg::GLW::TextureMode tm )
|
||||||
|
{
|
||||||
|
if(meshes.empty()) return;
|
||||||
|
|
||||||
|
GL_TEST_ERR
|
||||||
|
|
||||||
|
/*************** First Pass ***********/
|
||||||
|
// this is the first pass of the frame, so let's update the shaders, buffers, etc...
|
||||||
|
glGetIntegerv(GL_VIEWPORT, mCachedVP);
|
||||||
|
glGetFloatv(GL_MODELVIEW_MATRIX, mCachedMV);
|
||||||
|
glGetFloatv(GL_PROJECTION_MATRIX, mCachedProj);
|
||||||
|
|
||||||
|
updateRenderBuffer();
|
||||||
|
if (mCachedFlags != mFlags)
|
||||||
|
configureShaders();
|
||||||
|
|
||||||
|
mCachedFlags = mFlags;
|
||||||
|
|
||||||
|
mParams.update(mCachedMV, mCachedProj, mCachedVP);
|
||||||
|
//float s = meshes[0]->glw.GetHintParamf(vcg::GLW::HNPPointSize);
|
||||||
|
//if (s>1)
|
||||||
|
// s = pow(s,0.3f);
|
||||||
|
float s = 1.f;
|
||||||
|
mParams.radiusScale *= s;
|
||||||
|
|
||||||
|
// FIXME since meshlab does not set any material properties, let's define some here
|
||||||
|
glDisable(GL_COLOR_MATERIAL);
|
||||||
|
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 64);
|
||||||
|
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, vcg::Point4f(0.3, 0.3, 0.3, 1.).V());
|
||||||
|
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, vcg::Point4f(0.6, 0.6, 0.6, 1.).V());
|
||||||
|
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vcg::Point4f(0.5, 0.5, 0.5, 1.).V());
|
||||||
|
|
||||||
|
mRenderBuffer->bind();
|
||||||
|
if (mFlags&DEFERRED_SHADING_BIT)
|
||||||
|
{
|
||||||
|
GLenum buf[2] = {GL_COLOR_ATTACHMENT0_EXT,GL_COLOR_ATTACHMENT1_EXT};
|
||||||
|
glDrawBuffersARB(2, buf);
|
||||||
|
}
|
||||||
|
glViewport(mCachedVP[0],mCachedVP[1],mCachedVP[2],mCachedVP[3]);
|
||||||
|
glClearColor(0,0,0,0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
//* End Setup of first Pass Now a simple rendering of all the involved meshes.*/
|
||||||
|
mParams.loadTo(mShaders[0].prog);
|
||||||
|
enablePass(0);
|
||||||
|
drawSplats(meshes,cm,tm);
|
||||||
|
|
||||||
|
// begin second pass
|
||||||
|
mParams.loadTo(mShaders[1].prog);
|
||||||
|
enablePass(1);
|
||||||
|
|
||||||
|
drawSplats(meshes,cm,tm);
|
||||||
|
|
||||||
|
//* Start third Pass Setup */
|
||||||
|
|
||||||
|
// this is the last pass: normalization by the sum of weights + deferred shading
|
||||||
|
mRenderBuffer->release();
|
||||||
|
if (mFlags&DEFERRED_SHADING_BIT)
|
||||||
|
glDrawBuffer(GL_BACK);
|
||||||
|
|
||||||
|
enablePass(2);
|
||||||
|
|
||||||
|
// switch to normalized 2D rendering mode
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
mShaders[2].prog.Uniform("viewport",float(mCachedVP[0]),float(mCachedVP[1]),float(mCachedVP[2]),float(mCachedVP[3]));
|
||||||
|
mShaders[2].prog.Uniform("ColorWeight",GLint(0)); // this is a texture unit
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mRenderBuffer->texture());
|
||||||
|
|
||||||
|
if (mFlags&DEFERRED_SHADING_BIT)
|
||||||
|
{
|
||||||
|
mShaders[2].prog.Uniform("unproj", mCachedProj[10], mCachedProj[14]);
|
||||||
|
mShaders[2].prog.Uniform("NormalWeight",GLint(1)); // this is a texture unit
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mNormalTextureID);
|
||||||
|
GL_TEST_ERR
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFlags&OUTPUT_DEPTH_BIT)
|
||||||
|
{
|
||||||
|
mShaders[2].prog.Uniform("Depth",GLint(2)); // this is a texture unit
|
||||||
|
glActiveTexture(GL_TEXTURE2);GL_TEST_ERR
|
||||||
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mDepthTextureID);GL_TEST_ERR
|
||||||
|
GL_TEST_ERR
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw a quad covering the whole screen
|
||||||
|
vcg::Point3f viewVec(1./mCachedProj[0], 1./mCachedProj[5], -1);
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glColor3f(1, 0, 0);
|
||||||
|
glTexCoord3f(viewVec.X(),viewVec.Y(),viewVec.Z());
|
||||||
|
glMultiTexCoord2f(GL_TEXTURE1,1.,1.);
|
||||||
|
glVertex3f(1,1,0);
|
||||||
|
|
||||||
|
glColor3f(1, 1, 0);
|
||||||
|
glTexCoord3f(-viewVec.X(),viewVec.Y(),viewVec.Z());
|
||||||
|
glMultiTexCoord2f(GL_TEXTURE1,0.,1.);
|
||||||
|
glVertex3f(-1,1,0);
|
||||||
|
|
||||||
|
glColor3f(0, 1, 1);
|
||||||
|
glTexCoord3f(-viewVec.X(),-viewVec.Y(),viewVec.Z());
|
||||||
|
glMultiTexCoord2f(GL_TEXTURE1,0.,0.);
|
||||||
|
glVertex3f(-1,-1,0);
|
||||||
|
|
||||||
|
glColor3f(1, 0, 1);
|
||||||
|
glTexCoord3f(viewVec.X(),-viewVec.Y(),viewVec.Z());
|
||||||
|
glMultiTexCoord2f(GL_TEXTURE1,1.,0.);
|
||||||
|
glVertex3f(1,-1,0);
|
||||||
|
glEnd();
|
||||||
|
if (!(mFlags&OUTPUT_DEPTH_BIT))
|
||||||
|
{
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
glUseProgram(0);
|
||||||
|
|
||||||
|
// restore matrices
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPopMatrix();
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
GL_TEST_ERR
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class MeshType>
|
||||||
|
void SplatRenderer<MeshType>::Render(
|
||||||
|
std::vector< std::vector<vcg::Point3f> * > & positions,
|
||||||
|
std::vector< std::vector<vcg::Point3f> * > & normals,
|
||||||
|
std::vector< std::vector<vcg::Point3<unsigned char> > * > & colors,
|
||||||
|
std::vector<float> & radius, vcg::GLW::ColorMode cm, vcg::GLW::TextureMode tm )
|
||||||
|
{
|
||||||
|
if(positions.empty()) return;
|
||||||
|
|
||||||
|
GL_TEST_ERR
|
||||||
|
|
||||||
|
/*************** First Pass ***********/
|
||||||
|
// this is the first pass of the frame, so let's update the shaders, buffers, etc...
|
||||||
|
glGetIntegerv(GL_VIEWPORT, mCachedVP);
|
||||||
|
glGetFloatv(GL_MODELVIEW_MATRIX, mCachedMV);
|
||||||
|
glGetFloatv(GL_PROJECTION_MATRIX, mCachedProj);
|
||||||
|
|
||||||
|
updateRenderBuffer();
|
||||||
|
if (mCachedFlags != mFlags)
|
||||||
|
configureShaders();
|
||||||
|
|
||||||
|
mCachedFlags = mFlags;
|
||||||
|
|
||||||
|
mParams.update(mCachedMV, mCachedProj, mCachedVP);
|
||||||
|
//float s = meshes[0]->glw.GetHintParamf(vcg::GLW::HNPPointSize);
|
||||||
|
//if (s>1)
|
||||||
|
// s = pow(s,0.3f);
|
||||||
|
float s = 1.f;
|
||||||
|
mParams.radiusScale *= s;
|
||||||
|
|
||||||
|
// FIXME since meshlab does not set any material properties, let's define some here
|
||||||
|
glDisable(GL_COLOR_MATERIAL);
|
||||||
|
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 64);
|
||||||
|
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, vcg::Point4f(0.3, 0.3, 0.3, 1.).V());
|
||||||
|
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, vcg::Point4f(0.6, 0.6, 0.6, 1.).V());
|
||||||
|
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vcg::Point4f(0.5, 0.5, 0.5, 1.).V());
|
||||||
|
|
||||||
|
mRenderBuffer->bind();
|
||||||
|
if (mFlags&DEFERRED_SHADING_BIT)
|
||||||
|
{
|
||||||
|
GLenum buf[2] = {GL_COLOR_ATTACHMENT0_EXT,GL_COLOR_ATTACHMENT1_EXT};
|
||||||
|
glDrawBuffersARB(2, buf);
|
||||||
|
}
|
||||||
|
glViewport(mCachedVP[0],mCachedVP[1],mCachedVP[2],mCachedVP[3]);
|
||||||
|
glClearColor(0,0,0,0);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
//* End Setup of first Pass Now a simple rendering of all the involved meshes.*/
|
||||||
|
mParams.loadTo(mShaders[0].prog);
|
||||||
|
enablePass(0);
|
||||||
|
drawSplats(positions,normals,colors,radius,cm,tm);
|
||||||
|
|
||||||
|
// begin second pass
|
||||||
|
mParams.loadTo(mShaders[1].prog);
|
||||||
|
enablePass(1);
|
||||||
|
|
||||||
|
drawSplats(positions,normals,colors,radius,cm,tm);
|
||||||
|
|
||||||
|
//* Start third Pass Setup */
|
||||||
|
|
||||||
|
// this is the last pass: normalization by the sum of weights + deferred shading
|
||||||
|
mRenderBuffer->release();
|
||||||
|
if (mFlags&DEFERRED_SHADING_BIT)
|
||||||
|
glDrawBuffer(GL_BACK);
|
||||||
|
|
||||||
|
enablePass(2);
|
||||||
|
|
||||||
|
// switch to normalized 2D rendering mode
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
mShaders[2].prog.Uniform("viewport",float(mCachedVP[0]),float(mCachedVP[1]),float(mCachedVP[2]),float(mCachedVP[3]));
|
||||||
|
mShaders[2].prog.Uniform("ColorWeight",GLint(0)); // this is a texture unit
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mRenderBuffer->texture());
|
||||||
|
|
||||||
|
if (mFlags&DEFERRED_SHADING_BIT)
|
||||||
|
{
|
||||||
|
mShaders[2].prog.Uniform("unproj", mCachedProj[10], mCachedProj[14]);
|
||||||
|
mShaders[2].prog.Uniform("NormalWeight",GLint(1)); // this is a texture unit
|
||||||
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mNormalTextureID);
|
||||||
|
GL_TEST_ERR
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFlags&OUTPUT_DEPTH_BIT)
|
||||||
|
{
|
||||||
|
mShaders[2].prog.Uniform("Depth",GLint(2)); // this is a texture unit
|
||||||
|
glActiveTexture(GL_TEXTURE2);GL_TEST_ERR
|
||||||
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mDepthTextureID);GL_TEST_ERR
|
||||||
|
GL_TEST_ERR
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw a quad covering the whole screen
|
||||||
|
vcg::Point3f viewVec(1./mCachedProj[0], 1./mCachedProj[5], -1);
|
||||||
|
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glColor3f(1, 0, 0);
|
||||||
|
glTexCoord3f(viewVec.X(),viewVec.Y(),viewVec.Z());
|
||||||
|
glMultiTexCoord2f(GL_TEXTURE1,1.,1.);
|
||||||
|
glVertex3f(1,1,0);
|
||||||
|
|
||||||
|
glColor3f(1, 1, 0);
|
||||||
|
glTexCoord3f(-viewVec.X(),viewVec.Y(),viewVec.Z());
|
||||||
|
glMultiTexCoord2f(GL_TEXTURE1,0.,1.);
|
||||||
|
glVertex3f(-1,1,0);
|
||||||
|
|
||||||
|
glColor3f(0, 1, 1);
|
||||||
|
glTexCoord3f(-viewVec.X(),-viewVec.Y(),viewVec.Z());
|
||||||
|
glMultiTexCoord2f(GL_TEXTURE1,0.,0.);
|
||||||
|
glVertex3f(-1,-1,0);
|
||||||
|
|
||||||
|
glColor3f(1, 0, 1);
|
||||||
|
glTexCoord3f(viewVec.X(),-viewVec.Y(),viewVec.Z());
|
||||||
|
glMultiTexCoord2f(GL_TEXTURE1,1.,0.);
|
||||||
|
glVertex3f(1,-1,0);
|
||||||
|
glEnd();
|
||||||
|
if (!(mFlags&OUTPUT_DEPTH_BIT))
|
||||||
|
{
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
glUseProgram(0);
|
||||||
|
|
||||||
|
// restore matrices
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPopMatrix();
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
GL_TEST_ERR
|
||||||
|
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
void SplatRenderer::Draw(QAction *a, MeshModel &m, RenderMode &rm, QGLWidget * gla)
|
||||||
|
{
|
||||||
|
if (m.vert.RadiusEnabled)
|
||||||
|
{
|
||||||
|
if (mCurrentPass==2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
enablePass(mCurrentPass);
|
||||||
|
/*if (mCurrentPass==1)*/ drawSplats(m, rm);
|
||||||
|
}
|
||||||
|
else if (mCurrentPass==2)
|
||||||
|
{
|
||||||
|
MeshRenderInterface::Draw(a, m, rm, gla);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
template <class MeshType>
|
||||||
|
void SplatRenderer<MeshType>::enablePass(int n)
|
||||||
|
{
|
||||||
|
if (mBindedPass!=n)
|
||||||
|
{
|
||||||
|
if (mBindedPass>=0)
|
||||||
|
mShaders[mBindedPass].prog.Unbind();
|
||||||
|
mShaders[n].prog.Bind();
|
||||||
|
mBindedPass = n;
|
||||||
|
|
||||||
|
// set GL states
|
||||||
|
if (n==0)
|
||||||
|
{
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
// glDisable(GL_POINT_SMOOTH);
|
||||||
|
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||||
|
|
||||||
|
glAlphaFunc(GL_LESS,1);
|
||||||
|
glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glEnable(GL_ALPHA_TEST);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
|
// glActiveTexture(GL_TEXTURE0);
|
||||||
|
// glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
|
||||||
|
// glEnable(GL_POINT_SPRITE_ARB);
|
||||||
|
}
|
||||||
|
if (n==1)
|
||||||
|
{
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
glEnable(GL_POINT_SMOOTH);
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
|
||||||
|
|
||||||
|
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
|
||||||
|
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE,GL_ONE);
|
||||||
|
// //glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE,GL_ZERO);
|
||||||
|
// glBlendFunc(GL_ONE,GL_ZERO);
|
||||||
|
glDepthMask(GL_FALSE);
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDisable(GL_ALPHA_TEST);
|
||||||
|
|
||||||
|
// glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
}
|
||||||
|
if ( (n==0) || (n==1) )
|
||||||
|
{
|
||||||
|
// enable point sprite rendering mode
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
if (mWorkaroundATI)
|
||||||
|
{
|
||||||
|
glBindTexture(GL_TEXTURE_2D, mDummyTexId);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);
|
||||||
|
glPointParameterf(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
|
||||||
|
// hm... ^^^^
|
||||||
|
}
|
||||||
|
glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
|
||||||
|
glEnable(GL_POINT_SPRITE_ARB);
|
||||||
|
}
|
||||||
|
if (n==2)
|
||||||
|
{
|
||||||
|
glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
|
||||||
|
glDepthMask(GL_TRUE);
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class MeshType>
|
||||||
|
void SplatRenderer<MeshType>::drawSplats(
|
||||||
|
std::vector< std::vector<vcg::Point3f> * > & positions,
|
||||||
|
std::vector< std::vector<vcg::Point3f> * > & normals,
|
||||||
|
std::vector< std::vector<vcg::Point3<unsigned char> > * > & colors,
|
||||||
|
std::vector<float> & radius,
|
||||||
|
vcg::GLW::ColorMode cm, vcg::GLW::TextureMode tm)
|
||||||
|
{
|
||||||
|
for(unsigned int ii = 0; ii < positions.size();++ii)
|
||||||
|
{
|
||||||
|
|
||||||
|
glBegin(GL_POINTS);
|
||||||
|
glMultiTexCoord1f(GL_TEXTURE2, radius[ii] );
|
||||||
|
|
||||||
|
for(unsigned int vi= 0;vi< positions[ii]->size() ;++vi){
|
||||||
|
vcg::Point3<unsigned char> co = (*colors[ii])[vi];
|
||||||
|
glColor3ub ( co[0],co[1],co[2]);
|
||||||
|
glNormal((*normals[ii])[vi]);
|
||||||
|
glVertex( (*positions[ii])[vi]);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class MeshType>
|
||||||
|
void SplatRenderer<MeshType>::drawSplats(std::vector<MeshType*> & meshes, vcg::GLW::ColorMode cm, vcg::GLW::TextureMode tm)
|
||||||
|
{
|
||||||
|
|
||||||
|
// check if we have to use the immediate mode
|
||||||
|
if(meshes.empty()) return;
|
||||||
|
int nV = 0;
|
||||||
|
unsigned int ii = 0;
|
||||||
|
for(; ii < meshes.size();++ii){
|
||||||
|
nV+=meshes[ii]->vn;
|
||||||
|
if((nV>150000) || (meshes[ii]->vn!=(int) meshes[ii]->vert.size()))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bool immediatemode = ii<meshes.size() ;
|
||||||
|
|
||||||
|
|
||||||
|
if(immediatemode){
|
||||||
|
for(unsigned int ii = 0; ii < meshes.size();++ii)
|
||||||
|
{
|
||||||
|
MeshType & m = *meshes[ii];
|
||||||
|
// immediate mode
|
||||||
|
|
||||||
|
if( (cm == vcg::GLW::CMPerFace) && (!vcg::tri::HasPerFaceColor( m)) )
|
||||||
|
cm=vcg::GLW::CMNone;
|
||||||
|
glPushMatrix();
|
||||||
|
glMultMatrix( m.Tr);
|
||||||
|
CMeshO::VertexIterator vi;
|
||||||
|
glBegin(GL_POINTS);
|
||||||
|
if(cm==vcg::GLW::CMPerMesh)
|
||||||
|
glColor( m.C());
|
||||||
|
|
||||||
|
|
||||||
|
for(vi= m.vert.begin();vi!= m.vert.end();++vi)
|
||||||
|
if(!(*vi).IsD())
|
||||||
|
{
|
||||||
|
glMultiTexCoord1f(GL_TEXTURE2, (*vi).cR());
|
||||||
|
glNormal((*vi).cN());
|
||||||
|
if (cm==vcg::GLW::CMPerVert) glColor((*vi).C());
|
||||||
|
glVertex((*vi).P());
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(unsigned int ii = 0; ii < meshes.size();++ii){
|
||||||
|
MeshType & m = *meshes[ii];
|
||||||
|
// bind the radius
|
||||||
|
glClientActiveTexture(GL_TEXTURE2);
|
||||||
|
glTexCoordPointer(
|
||||||
|
1,
|
||||||
|
GL_FLOAT,
|
||||||
|
size_t(m.vert[1].cR())-size_t(m.vert[0].cR()),
|
||||||
|
&m.vert[0].cR()
|
||||||
|
);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glClientActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
// draw the vertices
|
||||||
|
vcg::GlTrimesh<MeshType> glw;
|
||||||
|
glw.m = &m;
|
||||||
|
glw.Draw(vcg::GLW::DMPoints,cm,tm);
|
||||||
|
|
||||||
|
glClientActiveTexture(GL_TEXTURE2);
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glClientActiveTexture(GL_TEXTURE0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class MeshType>
|
||||||
|
void SplatRenderer<MeshType>::UniformParameters::update(float* mv, float* proj, GLint* vp)
|
||||||
|
{
|
||||||
|
// extract the uniform scale
|
||||||
|
float scale = vcg::Point3f(mv[0],mv[1],mv[2]).Norm();
|
||||||
|
|
||||||
|
radiusScale = scale;
|
||||||
|
preComputeRadius = - std::max(proj[0]*vp[2], proj[5]*vp[3]);
|
||||||
|
depthOffset = 2.0;
|
||||||
|
oneOverEwaRadius = 0.70710678118654;
|
||||||
|
halfVp = vcg::Point2f(0.5*vp[2], 0.5*vp[3]);
|
||||||
|
rayCastParameter1 =vcg::Point3f(2./(proj[0]*vp[2]), 2./(proj[5]*vp[3]), 0.0);
|
||||||
|
rayCastParameter2 =vcg::Point3f(-1./proj[0], -1./proj[5], -1.0);
|
||||||
|
depthParameterCast = vcg::Point2f(0.5*proj[14], 0.5-0.5*proj[10]);
|
||||||
|
}
|
||||||
|
template <class MeshType>
|
||||||
|
void SplatRenderer <MeshType>::UniformParameters::loadTo(Program& prg)
|
||||||
|
{
|
||||||
|
prg.Bind();
|
||||||
|
prg.Uniform("expeRadiusScale",radiusScale);
|
||||||
|
prg.Uniform("expePreComputeRadius",preComputeRadius);
|
||||||
|
prg.Uniform("expeDepthOffset",depthOffset);
|
||||||
|
prg.Uniform("oneOverEwaRadius",oneOverEwaRadius);
|
||||||
|
prg.Uniform("halfVp",halfVp);
|
||||||
|
prg.Uniform("rayCastParameter1",rayCastParameter1);
|
||||||
|
prg.Uniform("rayCastParameter2",rayCastParameter2);
|
||||||
|
prg.Uniform("depthParameterCast",depthParameterCast);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!DOCTYPE RCC><RCC version="1.0">
|
||||||
|
<qresource prefix="/SplatRenderer">
|
||||||
|
<file>shaders/Raycasting.glsl</file>
|
||||||
|
<file>shaders/Finalization.glsl</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
Loading…
Reference in New Issue