1347 lines
32 KiB
JavaScript
1347 lines
32 KiB
JavaScript
|
|
Potree.Shaders["pointcloud.vs"] = `
|
|
precision highp float;
|
|
precision highp int;
|
|
|
|
#define max_clip_polygons 8
|
|
#define PI 3.141592653589793
|
|
|
|
attribute vec3 position;
|
|
attribute vec3 color;
|
|
attribute float intensity;
|
|
attribute float classification;
|
|
attribute float returnNumber;
|
|
attribute float numberOfReturns;
|
|
attribute float pointSourceID;
|
|
attribute vec4 indices;
|
|
attribute float spacing;
|
|
|
|
uniform mat4 modelMatrix;
|
|
uniform mat4 modelViewMatrix;
|
|
uniform mat4 projectionMatrix;
|
|
uniform mat4 viewMatrix;
|
|
|
|
uniform float uScreenWidth;
|
|
uniform float uScreenHeight;
|
|
uniform float fov;
|
|
uniform float near;
|
|
uniform float far;
|
|
|
|
uniform bool uDebug;
|
|
|
|
uniform bool uUseOrthographicCamera;
|
|
uniform float uOrthoWidth;
|
|
uniform float uOrthoHeight;
|
|
|
|
|
|
#define CLIPTASK_NONE 0
|
|
#define CLIPTASK_HIGHLIGHT 1
|
|
#define CLIPTASK_SHOW_INSIDE 2
|
|
#define CLIPTASK_SHOW_OUTSIDE 3
|
|
|
|
#define CLIPMETHOD_INSIDE_ANY 0
|
|
#define CLIPMETHOD_INSIDE_ALL 1
|
|
|
|
uniform int clipTask;
|
|
uniform int clipMethod;
|
|
#if defined(num_clipboxes) && num_clipboxes > 0
|
|
uniform mat4 clipBoxes[num_clipboxes];
|
|
#endif
|
|
|
|
#if defined(num_clippolygons) && num_clippolygons > 0
|
|
uniform int uClipPolygonVCount[num_clippolygons];
|
|
uniform vec3 uClipPolygonVertices[num_clippolygons * 8];
|
|
uniform mat4 uClipPolygonWVP[num_clippolygons];
|
|
#endif
|
|
|
|
uniform float size;
|
|
uniform float minSize;
|
|
uniform float maxSize;
|
|
|
|
uniform float uPCIndex;
|
|
uniform float uOctreeSpacing;
|
|
uniform float uNodeSpacing;
|
|
uniform float uOctreeSize;
|
|
uniform vec3 uBBSize;
|
|
uniform float uLevel;
|
|
uniform float uVNStart;
|
|
uniform bool uIsLeafNode;
|
|
|
|
uniform vec3 uColor;
|
|
uniform float uOpacity;
|
|
|
|
uniform vec2 elevationRange;
|
|
uniform vec2 intensityRange;
|
|
uniform float intensityGamma;
|
|
uniform float intensityContrast;
|
|
uniform float intensityBrightness;
|
|
uniform float rgbGamma;
|
|
uniform float rgbContrast;
|
|
uniform float rgbBrightness;
|
|
uniform float uTransition;
|
|
uniform float wRGB;
|
|
uniform float wIntensity;
|
|
uniform float wElevation;
|
|
uniform float wClassification;
|
|
uniform float wReturnNumber;
|
|
uniform float wSourceID;
|
|
|
|
uniform vec3 uShadowColor;
|
|
|
|
uniform sampler2D visibleNodes;
|
|
uniform sampler2D gradient;
|
|
uniform sampler2D classificationLUT;
|
|
|
|
#if defined(num_shadowmaps) && num_shadowmaps > 0
|
|
uniform sampler2D uShadowMap[num_shadowmaps];
|
|
uniform mat4 uShadowWorldView[num_shadowmaps];
|
|
uniform mat4 uShadowProj[num_shadowmaps];
|
|
#endif
|
|
|
|
#if defined(num_snapshots) && num_snapshots > 0
|
|
uniform sampler2D uSnapshot[num_snapshots];
|
|
uniform mat4 uSnapView[num_snapshots];
|
|
uniform mat4 uSnapProj[num_snapshots];
|
|
uniform mat4 uSnapScreenToCurrentView[num_snapshots];
|
|
|
|
varying float vSnapTextureID;
|
|
#endif
|
|
|
|
varying vec3 vColor;
|
|
varying float vLogDepth;
|
|
varying vec3 vViewPosition;
|
|
varying float vRadius;
|
|
varying float vPointSize;
|
|
|
|
|
|
float round(float number){
|
|
return floor(number + 0.5);
|
|
}
|
|
|
|
//
|
|
// ### ######## ### ######## ######## #### ## ## ######## ###### #### ######## ######## ######
|
|
// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
|
// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
|
// ## ## ## ## ## ## ######## ## ## ## ## ###### ###### ## ## ###### ######
|
|
// ######### ## ## ######### ## ## ## ## ## ## ## ## ## ## ##
|
|
// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
|
// ## ## ######## ## ## ## ## #### ### ######## ###### #### ######## ######## ######
|
|
//
|
|
|
|
|
|
// ---------------------
|
|
// OCTREE
|
|
// ---------------------
|
|
|
|
#if (defined(adaptive_point_size) || defined(color_type_lod)) && defined(tree_type_octree)
|
|
/**
|
|
* number of 1-bits up to inclusive index position
|
|
* number is treated as if it were an integer in the range 0-255
|
|
*
|
|
*/
|
|
int numberOfOnes(int number, int index){
|
|
int numOnes = 0;
|
|
int tmp = 128;
|
|
for(int i = 7; i >= 0; i--){
|
|
|
|
if(number >= tmp){
|
|
number = number - tmp;
|
|
|
|
if(i <= index){
|
|
numOnes++;
|
|
}
|
|
}
|
|
|
|
tmp = tmp / 2;
|
|
}
|
|
|
|
return numOnes;
|
|
}
|
|
|
|
|
|
/**
|
|
* checks whether the bit at index is 1
|
|
* number is treated as if it were an integer in the range 0-255
|
|
*
|
|
*/
|
|
bool isBitSet(int number, int index){
|
|
|
|
// weird multi else if due to lack of proper array, int and bitwise support in WebGL 1.0
|
|
int powi = 1;
|
|
if(index == 0){
|
|
powi = 1;
|
|
}else if(index == 1){
|
|
powi = 2;
|
|
}else if(index == 2){
|
|
powi = 4;
|
|
}else if(index == 3){
|
|
powi = 8;
|
|
}else if(index == 4){
|
|
powi = 16;
|
|
}else if(index == 5){
|
|
powi = 32;
|
|
}else if(index == 6){
|
|
powi = 64;
|
|
}else if(index == 7){
|
|
powi = 128;
|
|
}else{
|
|
return false;
|
|
}
|
|
|
|
int ndp = number / powi;
|
|
|
|
return mod(float(ndp), 2.0) != 0.0;
|
|
}
|
|
|
|
|
|
/**
|
|
* find the LOD at the point position
|
|
*/
|
|
float getLOD(){
|
|
|
|
vec3 offset = vec3(0.0, 0.0, 0.0);
|
|
int iOffset = int(uVNStart);
|
|
float depth = uLevel;
|
|
for(float i = 0.0; i <= 30.0; i++){
|
|
float nodeSizeAtLevel = uOctreeSize / pow(2.0, i + uLevel + 0.0);
|
|
|
|
vec3 index3d = (position-offset) / nodeSizeAtLevel;
|
|
index3d = floor(index3d + 0.5);
|
|
int index = int(round(4.0 * index3d.x + 2.0 * index3d.y + index3d.z));
|
|
|
|
vec4 value = texture2D(visibleNodes, vec2(float(iOffset) / 2048.0, 0.0));
|
|
int mask = int(round(value.r * 255.0));
|
|
|
|
if(isBitSet(mask, index)){
|
|
// there are more visible child nodes at this position
|
|
int advanceG = int(round(value.g * 255.0)) * 256;
|
|
int advanceB = int(round(value.b * 255.0));
|
|
int advanceChild = numberOfOnes(mask, index - 1);
|
|
int advance = advanceG + advanceB + advanceChild;
|
|
|
|
iOffset = iOffset + advance;
|
|
|
|
depth++;
|
|
}else{
|
|
// no more visible child nodes at this position
|
|
return value.a * 255.0;
|
|
//return depth;
|
|
}
|
|
|
|
offset = offset + (vec3(1.0, 1.0, 1.0) * nodeSizeAtLevel * 0.5) * index3d;
|
|
}
|
|
|
|
return depth;
|
|
}
|
|
|
|
float getSpacing(){
|
|
vec3 offset = vec3(0.0, 0.0, 0.0);
|
|
int iOffset = int(uVNStart);
|
|
float depth = uLevel;
|
|
float spacing = uNodeSpacing;
|
|
for(float i = 0.0; i <= 30.0; i++){
|
|
float nodeSizeAtLevel = uOctreeSize / pow(2.0, i + uLevel + 0.0);
|
|
|
|
vec3 index3d = (position-offset) / nodeSizeAtLevel;
|
|
index3d = floor(index3d + 0.5);
|
|
int index = int(round(4.0 * index3d.x + 2.0 * index3d.y + index3d.z));
|
|
|
|
vec4 value = texture2D(visibleNodes, vec2(float(iOffset) / 2048.0, 0.0));
|
|
int mask = int(round(value.r * 255.0));
|
|
float spacingFactor = value.a;
|
|
|
|
if(i > 0.0){
|
|
spacing = spacing / (255.0 * spacingFactor);
|
|
}
|
|
|
|
|
|
if(isBitSet(mask, index)){
|
|
// there are more visible child nodes at this position
|
|
int advanceG = int(round(value.g * 255.0)) * 256;
|
|
int advanceB = int(round(value.b * 255.0));
|
|
int advanceChild = numberOfOnes(mask, index - 1);
|
|
int advance = advanceG + advanceB + advanceChild;
|
|
|
|
iOffset = iOffset + advance;
|
|
|
|
//spacing = spacing / (255.0 * spacingFactor);
|
|
//spacing = spacing / 3.0;
|
|
|
|
depth++;
|
|
}else{
|
|
// no more visible child nodes at this position
|
|
return spacing;
|
|
}
|
|
|
|
offset = offset + (vec3(1.0, 1.0, 1.0) * nodeSizeAtLevel * 0.5) * index3d;
|
|
}
|
|
|
|
return spacing;
|
|
}
|
|
|
|
float getPointSizeAttenuation(){
|
|
return pow(2.0, getLOD());
|
|
}
|
|
|
|
|
|
#endif
|
|
|
|
|
|
// ---------------------
|
|
// KD-TREE
|
|
// ---------------------
|
|
|
|
#if (defined(adaptive_point_size) || defined(color_type_lod)) && defined(tree_type_kdtree)
|
|
|
|
float getLOD(){
|
|
vec3 offset = vec3(0.0, 0.0, 0.0);
|
|
float iOffset = 0.0;
|
|
float depth = 0.0;
|
|
|
|
|
|
vec3 size = uBBSize;
|
|
vec3 pos = position;
|
|
|
|
for(float i = 0.0; i <= 1000.0; i++){
|
|
|
|
vec4 value = texture2D(visibleNodes, vec2(iOffset / 2048.0, 0.0));
|
|
|
|
int children = int(value.r * 255.0);
|
|
float next = value.g * 255.0;
|
|
int split = int(value.b * 255.0);
|
|
|
|
if(next == 0.0){
|
|
return depth;
|
|
}
|
|
|
|
vec3 splitv = vec3(0.0, 0.0, 0.0);
|
|
if(split == 1){
|
|
splitv.x = 1.0;
|
|
}else if(split == 2){
|
|
splitv.y = 1.0;
|
|
}else if(split == 4){
|
|
splitv.z = 1.0;
|
|
}
|
|
|
|
iOffset = iOffset + next;
|
|
|
|
float factor = length(pos * splitv / size);
|
|
if(factor < 0.5){
|
|
// left
|
|
if(children == 0 || children == 2){
|
|
return depth;
|
|
}
|
|
}else{
|
|
// right
|
|
pos = pos - size * splitv * 0.5;
|
|
if(children == 0 || children == 1){
|
|
return depth;
|
|
}
|
|
if(children == 3){
|
|
iOffset = iOffset + 1.0;
|
|
}
|
|
}
|
|
size = size * ((1.0 - (splitv + 1.0) / 2.0) + 0.5);
|
|
|
|
depth++;
|
|
}
|
|
|
|
|
|
return depth;
|
|
}
|
|
|
|
float getPointSizeAttenuation(){
|
|
return 0.5 * pow(1.3, getLOD());
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//
|
|
// ### ######## ######## ######## #### ######## ## ## ######## ######## ######
|
|
// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
|
// ## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
|
// ## ## ## ## ######## ## ######## ## ## ## ###### ######
|
|
// ######### ## ## ## ## ## ## ## ## ## ## ## ##
|
|
// ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
|
|
// ## ## ## ## ## ## #### ######## ####### ## ######## ######
|
|
//
|
|
|
|
|
|
|
|
// formula adapted from: http://www.dfstudios.co.uk/articles/programming/image-programming-algorithms/image-processing-algorithms-part-5-contrast-adjustment/
|
|
float getContrastFactor(float contrast){
|
|
return (1.0158730158730156 * (contrast + 1.0)) / (1.0158730158730156 - contrast);
|
|
}
|
|
|
|
vec3 getRGB(){
|
|
vec3 rgb = color;
|
|
|
|
rgb = pow(rgb, vec3(rgbGamma));
|
|
rgb = rgb + rgbBrightness;
|
|
//rgb = (rgb - 0.5) * getContrastFactor(rgbContrast) + 0.5;
|
|
rgb = clamp(rgb, 0.0, 1.0);
|
|
|
|
//rgb = indices.rgb;
|
|
//rgb.b = pcIndex / 255.0;
|
|
|
|
|
|
return rgb;
|
|
}
|
|
|
|
float getIntensity(){
|
|
float w = (intensity - intensityRange.x) / (intensityRange.y - intensityRange.x);
|
|
w = pow(w, intensityGamma);
|
|
w = w + intensityBrightness;
|
|
w = (w - 0.5) * getContrastFactor(intensityContrast) + 0.5;
|
|
w = clamp(w, 0.0, 1.0);
|
|
|
|
//w = w + color.x * 0.0001;
|
|
|
|
//float w = color.x * 0.001 + intensity / 1.0;
|
|
|
|
return w;
|
|
}
|
|
|
|
vec3 getElevation(){
|
|
vec4 world = modelMatrix * vec4( position, 1.0 );
|
|
float w = (world.z - elevationRange.x) / (elevationRange.y - elevationRange.x);
|
|
vec3 cElevation = texture2D(gradient, vec2(w,1.0-w)).rgb;
|
|
|
|
return cElevation;
|
|
}
|
|
|
|
vec4 getClassification(){
|
|
vec2 uv = vec2(classification / 255.0, 0.5);
|
|
vec4 classColor = texture2D(classificationLUT, uv);
|
|
|
|
return classColor;
|
|
}
|
|
|
|
vec3 getReturnNumber(){
|
|
if(numberOfReturns == 1.0){
|
|
return vec3(1.0, 1.0, 0.0);
|
|
}else{
|
|
if(returnNumber == 1.0){
|
|
return vec3(1.0, 0.0, 0.0);
|
|
}else if(returnNumber == numberOfReturns){
|
|
return vec3(0.0, 0.0, 1.0);
|
|
}else{
|
|
return vec3(0.0, 1.0, 0.0);
|
|
}
|
|
}
|
|
}
|
|
|
|
vec3 getSourceID(){
|
|
float w = mod(pointSourceID, 10.0) / 10.0;
|
|
return texture2D(gradient, vec2(w,1.0 - w)).rgb;
|
|
}
|
|
|
|
vec3 getCompositeColor(){
|
|
vec3 c;
|
|
float w;
|
|
|
|
c += wRGB * getRGB();
|
|
w += wRGB;
|
|
|
|
c += wIntensity * getIntensity() * vec3(1.0, 1.0, 1.0);
|
|
w += wIntensity;
|
|
|
|
c += wElevation * getElevation();
|
|
w += wElevation;
|
|
|
|
c += wReturnNumber * getReturnNumber();
|
|
w += wReturnNumber;
|
|
|
|
c += wSourceID * getSourceID();
|
|
w += wSourceID;
|
|
|
|
vec4 cl = wClassification * getClassification();
|
|
c += cl.a * cl.rgb;
|
|
w += wClassification * cl.a;
|
|
|
|
c = c / w;
|
|
|
|
if(w == 0.0){
|
|
//c = color;
|
|
gl_Position = vec4(100.0, 100.0, 100.0, 0.0);
|
|
}
|
|
|
|
return c;
|
|
}
|
|
|
|
|
|
//
|
|
// ###### ## #### ######## ######## #### ## ## ######
|
|
// ## ## ## ## ## ## ## ## ## ### ## ## ##
|
|
// ## ## ## ## ## ## ## ## #### ## ##
|
|
// ## ## ## ######## ######## ## ## ## ## ## ####
|
|
// ## ## ## ## ## ## ## #### ## ##
|
|
// ## ## ## ## ## ## ## ## ### ## ##
|
|
// ###### ######## #### ## ## #### ## ## ######
|
|
//
|
|
|
|
|
|
|
|
vec3 getColor(){
|
|
vec3 color;
|
|
|
|
#ifdef color_type_rgb
|
|
color = getRGB();
|
|
#elif defined color_type_height
|
|
color = getElevation();
|
|
#elif defined color_type_rgb_height
|
|
vec3 cHeight = getElevation();
|
|
color = (1.0 - uTransition) * getRGB() + uTransition * cHeight;
|
|
#elif defined color_type_depth
|
|
float linearDepth = gl_Position.w;
|
|
float expDepth = (gl_Position.z / gl_Position.w) * 0.5 + 0.5;
|
|
color = vec3(linearDepth, expDepth, 0.0);
|
|
#elif defined color_type_intensity
|
|
float w = getIntensity();
|
|
color = vec3(w, w, w);
|
|
#elif defined color_type_intensity_gradient
|
|
float w = getIntensity();
|
|
color = texture2D(gradient, vec2(w,1.0-w)).rgb;
|
|
#elif defined color_type_color
|
|
color = uColor;
|
|
#elif defined color_type_lod
|
|
float depth = getLOD();
|
|
float w = depth / 10.0;
|
|
color = texture2D(gradient, vec2(w,1.0-w)).rgb;
|
|
#elif defined color_type_point_index
|
|
color = indices.rgb;
|
|
#elif defined color_type_classification
|
|
vec4 cl = getClassification();
|
|
color = cl.rgb;
|
|
#elif defined color_type_return_number
|
|
color = getReturnNumber();
|
|
#elif defined color_type_source
|
|
color = getSourceID();
|
|
#elif defined color_type_normal
|
|
color = (modelMatrix * vec4(normal, 0.0)).xyz;
|
|
#elif defined color_type_phong
|
|
color = color;
|
|
#elif defined color_type_composite
|
|
color = getCompositeColor();
|
|
#endif
|
|
|
|
return color;
|
|
}
|
|
|
|
float getPointSize(){
|
|
float pointSize = 1.0;
|
|
|
|
float slope = tan(fov / 2.0);
|
|
float projFactor = -0.5 * uScreenHeight / (slope * vViewPosition.z);
|
|
|
|
float r = uOctreeSpacing * 1.7;
|
|
vRadius = r;
|
|
#if defined fixed_point_size
|
|
pointSize = size;
|
|
#elif defined attenuated_point_size
|
|
if(uUseOrthographicCamera){
|
|
pointSize = size;
|
|
}else{
|
|
pointSize = size * spacing * projFactor;
|
|
//pointSize = pointSize * projFactor;
|
|
}
|
|
#elif defined adaptive_point_size
|
|
if(uUseOrthographicCamera) {
|
|
float worldSpaceSize = 1.0 * size * r / getPointSizeAttenuation();
|
|
pointSize = (worldSpaceSize / uOrthoWidth) * uScreenWidth;
|
|
} else {
|
|
|
|
if(uIsLeafNode && false){
|
|
pointSize = size * spacing * projFactor;
|
|
}else{
|
|
float worldSpaceSize = 1.0 * size * r / getPointSizeAttenuation();
|
|
pointSize = worldSpaceSize * projFactor;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
pointSize = max(minSize, pointSize);
|
|
pointSize = min(maxSize, pointSize);
|
|
|
|
vRadius = pointSize / projFactor;
|
|
|
|
return pointSize;
|
|
}
|
|
|
|
#if defined(num_clippolygons) && num_clippolygons > 0
|
|
bool pointInClipPolygon(vec3 point, int polyIdx) {
|
|
|
|
mat4 wvp = uClipPolygonWVP[polyIdx];
|
|
//vec4 screenClipPos = uClipPolygonVP[polyIdx] * modelMatrix * vec4(point, 1.0);
|
|
//screenClipPos.xy = screenClipPos.xy / screenClipPos.w * 0.5 + 0.5;
|
|
|
|
vec4 pointNDC = wvp * vec4(point, 1.0);
|
|
pointNDC.xy = pointNDC.xy / pointNDC.w;
|
|
|
|
int j = uClipPolygonVCount[polyIdx] - 1;
|
|
bool c = false;
|
|
for(int i = 0; i < 8; i++) {
|
|
if(i == uClipPolygonVCount[polyIdx]) {
|
|
break;
|
|
}
|
|
|
|
//vec4 verti = wvp * vec4(uClipPolygonVertices[polyIdx * 8 + i], 1);
|
|
//vec4 vertj = wvp * vec4(uClipPolygonVertices[polyIdx * 8 + j], 1);
|
|
|
|
//verti.xy = verti.xy / verti.w;
|
|
//vertj.xy = vertj.xy / vertj.w;
|
|
|
|
//verti.xy = verti.xy / verti.w * 0.5 + 0.5;
|
|
//vertj.xy = vertj.xy / vertj.w * 0.5 + 0.5;
|
|
|
|
vec3 verti = uClipPolygonVertices[polyIdx * 8 + i];
|
|
vec3 vertj = uClipPolygonVertices[polyIdx * 8 + j];
|
|
|
|
if( ((verti.y > pointNDC.y) != (vertj.y > pointNDC.y)) &&
|
|
(pointNDC.x < (vertj.x-verti.x) * (pointNDC.y-verti.y) / (vertj.y-verti.y) + verti.x) ) {
|
|
c = !c;
|
|
}
|
|
j = i;
|
|
}
|
|
|
|
return c;
|
|
}
|
|
#endif
|
|
|
|
void doClipping(){
|
|
|
|
#if !defined color_type_composite
|
|
vec4 cl = getClassification();
|
|
if(cl.a == 0.0){
|
|
gl_Position = vec4(100.0, 100.0, 100.0, 0.0);
|
|
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
int clipVolumesCount = 0;
|
|
int insideCount = 0;
|
|
|
|
#if defined(num_clipboxes) && num_clipboxes > 0
|
|
for(int i = 0; i < num_clipboxes; i++){
|
|
vec4 clipPosition = clipBoxes[i] * modelMatrix * vec4( position, 1.0 );
|
|
bool inside = -0.5 <= clipPosition.x && clipPosition.x <= 0.5;
|
|
inside = inside && -0.5 <= clipPosition.y && clipPosition.y <= 0.5;
|
|
inside = inside && -0.5 <= clipPosition.z && clipPosition.z <= 0.5;
|
|
|
|
insideCount = insideCount + (inside ? 1 : 0);
|
|
clipVolumesCount++;
|
|
}
|
|
#endif
|
|
|
|
#if defined(num_clippolygons) && num_clippolygons > 0
|
|
for(int i = 0; i < num_clippolygons; i++) {
|
|
bool inside = pointInClipPolygon(position, i);
|
|
|
|
insideCount = insideCount + (inside ? 1 : 0);
|
|
clipVolumesCount++;
|
|
}
|
|
#endif
|
|
|
|
bool insideAny = insideCount > 0;
|
|
bool insideAll = (clipVolumesCount > 0) && (clipVolumesCount == insideCount);
|
|
|
|
if(clipMethod == CLIPMETHOD_INSIDE_ANY){
|
|
if(insideAny && clipTask == CLIPTASK_HIGHLIGHT){
|
|
vColor.r += 0.5;
|
|
}else if(!insideAny && clipTask == CLIPTASK_SHOW_INSIDE){
|
|
gl_Position = vec4(100.0, 100.0, 100.0, 1.0);
|
|
}else if(insideAny && clipTask == CLIPTASK_SHOW_OUTSIDE){
|
|
gl_Position = vec4(100.0, 100.0, 100.0, 1.0);
|
|
}
|
|
}else if(clipMethod == CLIPMETHOD_INSIDE_ALL){
|
|
if(insideAll && clipTask == CLIPTASK_HIGHLIGHT){
|
|
vColor.r += 0.5;
|
|
}else if(!insideAll && clipTask == CLIPTASK_SHOW_INSIDE){
|
|
gl_Position = vec4(100.0, 100.0, 100.0, 1.0);
|
|
}else if(insideAll && clipTask == CLIPTASK_SHOW_OUTSIDE){
|
|
gl_Position = vec4(100.0, 100.0, 100.0, 1.0);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// ## ## ### #### ## ##
|
|
// ### ### ## ## ## ### ##
|
|
// #### #### ## ## ## #### ##
|
|
// ## ### ## ## ## ## ## ## ##
|
|
// ## ## ######### ## ## ####
|
|
// ## ## ## ## ## ## ###
|
|
// ## ## ## ## #### ## ##
|
|
//
|
|
|
|
void main() {
|
|
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
|
|
vViewPosition = mvPosition.xyz;
|
|
gl_Position = projectionMatrix * mvPosition;
|
|
vLogDepth = log2(-mvPosition.z);
|
|
|
|
// POINT SIZE
|
|
float pointSize = getPointSize();
|
|
gl_PointSize = pointSize;
|
|
vPointSize = pointSize;
|
|
|
|
// COLOR
|
|
vColor = getColor();
|
|
|
|
|
|
#if defined hq_depth_pass
|
|
float originalDepth = gl_Position.w;
|
|
float adjustedDepth = originalDepth + 2.0 * vRadius;
|
|
float adjust = adjustedDepth / originalDepth;
|
|
|
|
mvPosition.xyz = mvPosition.xyz * adjust;
|
|
gl_Position = projectionMatrix * mvPosition;
|
|
#endif
|
|
|
|
|
|
// CLIPPING
|
|
doClipping();
|
|
|
|
|
|
|
|
|
|
|
|
//#if defined(num_snapshots) && num_snapshots > 0
|
|
|
|
// for(int i = 0; i < num_snapshots; i++){
|
|
// vSnapProjected[i] = uSnapProj[i] * uSnapView[i] * modelMatrix * vec4(position, 1.0);
|
|
// vSnapProjectedDistance[i] = -(uSnapView[i] * modelMatrix * vec4(position, 1.0)).z;
|
|
// }
|
|
//
|
|
//#endif
|
|
|
|
#if defined(num_shadowmaps) && num_shadowmaps > 0
|
|
|
|
const float sm_near = 0.1;
|
|
const float sm_far = 10000.0;
|
|
|
|
for(int i = 0; i < num_shadowmaps; i++){
|
|
vec3 viewPos = (uShadowWorldView[i] * vec4(position, 1.0)).xyz;
|
|
float distanceToLight = abs(viewPos.z);
|
|
|
|
vec4 projPos = uShadowProj[i] * uShadowWorldView[i] * vec4(position, 1);
|
|
vec3 nc = projPos.xyz / projPos.w;
|
|
|
|
float u = nc.x * 0.5 + 0.5;
|
|
float v = nc.y * 0.5 + 0.5;
|
|
|
|
vec2 sampleStep = vec2(1.0 / (2.0*1024.0), 1.0 / (2.0*1024.0)) * 1.5;
|
|
vec2 sampleLocations[9];
|
|
sampleLocations[0] = vec2(0.0, 0.0);
|
|
sampleLocations[1] = sampleStep;
|
|
sampleLocations[2] = -sampleStep;
|
|
sampleLocations[3] = vec2(sampleStep.x, -sampleStep.y);
|
|
sampleLocations[4] = vec2(-sampleStep.x, sampleStep.y);
|
|
|
|
sampleLocations[5] = vec2(0.0, sampleStep.y);
|
|
sampleLocations[6] = vec2(0.0, -sampleStep.y);
|
|
sampleLocations[7] = vec2(sampleStep.x, 0.0);
|
|
sampleLocations[8] = vec2(-sampleStep.x, 0.0);
|
|
|
|
float visibleSamples = 0.0;
|
|
float numSamples = 0.0;
|
|
|
|
float bias = vRadius * 2.0;
|
|
|
|
for(int j = 0; j < 9; j++){
|
|
vec4 depthMapValue = texture2D(uShadowMap[i], vec2(u, v) + sampleLocations[j]);
|
|
|
|
float linearDepthFromSM = depthMapValue.x + bias;
|
|
float linearDepthFromViewer = distanceToLight;
|
|
|
|
if(linearDepthFromSM > linearDepthFromViewer){
|
|
visibleSamples += 1.0;
|
|
}
|
|
|
|
numSamples += 1.0;
|
|
}
|
|
|
|
float visibility = visibleSamples / numSamples;
|
|
|
|
if(u < 0.0 || u > 1.0 || v < 0.0 || v > 1.0 || nc.x < -1.0 || nc.x > 1.0 || nc.y < -1.0 || nc.y > 1.0 || nc.z < -1.0 || nc.z > 1.0){
|
|
//vColor = vec3(0.0, 0.0, 0.2);
|
|
}else{
|
|
//vColor = vec3(1.0, 1.0, 1.0) * visibility + vec3(1.0, 1.0, 1.0) * vec3(0.5, 0.0, 0.0) * (1.0 - visibility);
|
|
vColor = vColor * visibility + vColor * uShadowColor * (1.0 - visibility);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
if(uDebug){
|
|
vColor.b = (vColor.r + vColor.g + vColor.b) / 3.0;
|
|
vColor.r = 1.0;
|
|
vColor.g = 1.0;
|
|
}
|
|
|
|
}
|
|
`
|
|
|
|
Potree.Shaders["pointcloud.fs"] = `
|
|
#if defined paraboloid_point_shape
|
|
#extension GL_EXT_frag_depth : enable
|
|
#endif
|
|
|
|
precision highp float;
|
|
precision highp int;
|
|
|
|
uniform mat4 viewMatrix;
|
|
uniform mat4 uViewInv;
|
|
uniform mat4 uProjInv;
|
|
uniform vec3 cameraPosition;
|
|
|
|
|
|
uniform mat4 projectionMatrix;
|
|
uniform float uOpacity;
|
|
|
|
uniform float blendHardness;
|
|
uniform float blendDepthSupplement;
|
|
uniform float fov;
|
|
uniform float uSpacing;
|
|
uniform float near;
|
|
uniform float far;
|
|
uniform float uPCIndex;
|
|
uniform float uScreenWidth;
|
|
uniform float uScreenHeight;
|
|
|
|
varying vec3 vColor;
|
|
varying float vLogDepth;
|
|
varying vec3 vViewPosition;
|
|
varying float vRadius;
|
|
varying float vPointSize;
|
|
varying vec3 vPosition;
|
|
|
|
#if defined(num_snapshots) && num_snapshots > 0
|
|
uniform sampler2D uSnapshot[num_snapshots];
|
|
uniform sampler2D uSnapshotDepth[num_snapshots];
|
|
uniform mat4 uSnapView[num_snapshots];
|
|
uniform mat4 uSnapProj[num_snapshots];
|
|
uniform mat4 uSnapProjInv[num_snapshots];
|
|
uniform mat4 uSnapViewInv[num_snapshots];
|
|
|
|
varying float vSnapTextureID;
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float specularStrength = 1.0;
|
|
|
|
void main() {
|
|
|
|
vec3 color = vColor;
|
|
float depth = gl_FragCoord.z;
|
|
|
|
|
|
//#if defined(num_snapshots) && num_snapshots > 0
|
|
// vec3 sRGB = vec3(0.0, 0.0, 0.0);
|
|
// float sA = 0.0;
|
|
|
|
// for(int i = 0; i < num_snapshots; i++){
|
|
|
|
// float snapLinearDistance = 0.0;
|
|
// float currentLinearDistance = vSnapProjectedDistance[i];
|
|
// vec2 uv;
|
|
|
|
// {
|
|
// vec2 pc = vec2(gl_PointCoord.x - 0.5, (1.0 - gl_PointCoord.y) - 0.5);
|
|
// vec2 offset = (pc * vPointSize) / vec2(uScreenWidth, uScreenHeight);
|
|
//
|
|
// uv = 0.5 * (vSnapProjected[i].xy /vSnapProjected[i].w) + 0.5 + offset;
|
|
//
|
|
// vec4 td = texture2D(uSnapshotDepth[i], uv);
|
|
// float d = td.r;
|
|
|
|
// // TODO save linear distance in uSnapshotDepth!!!
|
|
// vec4 snapViewPos = uSnapProjInv[i] * vec4(uv * 2.0 - 1.0, d * 2.0 - 1.0, 1.0);
|
|
// snapViewPos = snapViewPos / snapViewPos.w;
|
|
// snapLinearDistance = -snapViewPos.z;
|
|
|
|
// }
|
|
|
|
// if(abs(currentLinearDistance - snapLinearDistance) < vRadius * 1.0){
|
|
// vec4 col = texture2D(uSnapshot[i], uv);
|
|
// //vec4 col = vec4(0.5, 1.0, 0.0, 1.0);
|
|
// sRGB += col.rgb;
|
|
|
|
// if(col.a != 0.0){
|
|
// sA = sA + 1.0;
|
|
// }
|
|
// }else{
|
|
// //sRGB += vColor;
|
|
// //sA += 1.0;
|
|
//
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
// color = sRGB / sA;
|
|
// if(sA == 0.0){
|
|
// //color = vColor;
|
|
// discard;
|
|
// }
|
|
//
|
|
//#endif
|
|
|
|
|
|
#if defined(circle_point_shape) || defined(paraboloid_point_shape)
|
|
float u = 2.0 * gl_PointCoord.x - 1.0;
|
|
float v = 2.0 * gl_PointCoord.y - 1.0;
|
|
#endif
|
|
|
|
#if defined(circle_point_shape)
|
|
float cc = u*u + v*v;
|
|
if(cc > 1.0){
|
|
discard;
|
|
}
|
|
#endif
|
|
|
|
#if defined color_type_point_index
|
|
gl_FragColor = vec4(color, uPCIndex / 255.0);
|
|
#else
|
|
gl_FragColor = vec4(color, uOpacity);
|
|
#endif
|
|
|
|
#if defined paraboloid_point_shape
|
|
float wi = 0.0 - ( u*u + v*v);
|
|
vec4 pos = vec4(vViewPosition, 1.0);
|
|
pos.z += wi * vRadius;
|
|
float linearDepth = -pos.z;
|
|
pos = projectionMatrix * pos;
|
|
pos = pos / pos.w;
|
|
float expDepth = pos.z;
|
|
depth = (pos.z + 1.0) / 2.0;
|
|
gl_FragDepthEXT = depth;
|
|
|
|
#if defined(color_type_depth)
|
|
color.r = linearDepth;
|
|
color.g = expDepth;
|
|
#endif
|
|
|
|
#if defined(use_edl)
|
|
gl_FragColor.a = log2(linearDepth);
|
|
#endif
|
|
|
|
#else
|
|
#if defined(use_edl)
|
|
gl_FragColor.a = vLogDepth;
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(weighted_splats)
|
|
float distance = 2.0 * length(gl_PointCoord.xy - 0.5);
|
|
float weight = max(0.0, 1.0 - distance);
|
|
weight = pow(weight, 1.5);
|
|
|
|
gl_FragColor.a = weight;
|
|
gl_FragColor.xyz = gl_FragColor.xyz * weight;
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
`
|
|
|
|
Potree.Shaders["pointcloud_sm.vs"] = `
|
|
precision mediump float;
|
|
precision mediump int;
|
|
|
|
attribute vec3 position;
|
|
attribute vec3 color;
|
|
|
|
uniform mat4 modelMatrix;
|
|
uniform mat4 modelViewMatrix;
|
|
uniform mat4 projectionMatrix;
|
|
uniform mat4 viewMatrix;
|
|
|
|
uniform float uScreenWidth;
|
|
uniform float uScreenHeight;
|
|
uniform float near;
|
|
uniform float far;
|
|
|
|
uniform float uSpacing;
|
|
uniform float uOctreeSize;
|
|
uniform float uLevel;
|
|
uniform float uVNStart;
|
|
|
|
uniform sampler2D visibleNodes;
|
|
|
|
varying float vLinearDepth;
|
|
varying vec3 vColor;
|
|
|
|
#define PI 3.141592653589793
|
|
|
|
|
|
|
|
// ---------------------
|
|
// OCTREE
|
|
// ---------------------
|
|
|
|
#if defined(adaptive_point_size)
|
|
/**
|
|
* number of 1-bits up to inclusive index position
|
|
* number is treated as if it were an integer in the range 0-255
|
|
*
|
|
*/
|
|
float numberOfOnes(float number, float index){
|
|
float tmp = mod(number, pow(2.0, index + 1.0));
|
|
float numOnes = 0.0;
|
|
for(float i = 0.0; i < 8.0; i++){
|
|
if(mod(tmp, 2.0) != 0.0){
|
|
numOnes++;
|
|
}
|
|
tmp = floor(tmp / 2.0);
|
|
}
|
|
return numOnes;
|
|
}
|
|
|
|
|
|
/**
|
|
* checks whether the bit at index is 1
|
|
* number is treated as if it were an integer in the range 0-255
|
|
*
|
|
*/
|
|
bool isBitSet(float number, float index){
|
|
return mod(floor(number / pow(2.0, index)), 2.0) != 0.0;
|
|
}
|
|
|
|
|
|
/**
|
|
* find the LOD at the point position
|
|
*/
|
|
float getLOD(){
|
|
|
|
vec3 offset = vec3(0.0, 0.0, 0.0);
|
|
float iOffset = uVNStart;
|
|
float depth = uLevel;
|
|
for(float i = 0.0; i <= 30.0; i++){
|
|
float nodeSizeAtLevel = uOctreeSize / pow(2.0, i + uLevel + 0.0);
|
|
|
|
vec3 index3d = (position-offset) / nodeSizeAtLevel;
|
|
index3d = floor(index3d + 0.5);
|
|
float index = 4.0 * index3d.x + 2.0 * index3d.y + index3d.z;
|
|
|
|
vec4 value = texture2D(visibleNodes, vec2(iOffset / 2048.0, 0.0));
|
|
float mask = value.r * 255.0;
|
|
if(isBitSet(mask, index)){
|
|
// there are more visible child nodes at this position
|
|
iOffset = iOffset + value.g * 255.0 * 256.0 + value.b * 255.0 + numberOfOnes(mask, index - 1.0);
|
|
depth++;
|
|
}else{
|
|
// no more visible child nodes at this position
|
|
return depth;
|
|
}
|
|
|
|
offset = offset + (vec3(1.0, 1.0, 1.0) * nodeSizeAtLevel * 0.5) * index3d;
|
|
}
|
|
|
|
return depth;
|
|
}
|
|
|
|
#endif
|
|
|
|
float getPointSize(){
|
|
float pointSize = 1.0;
|
|
|
|
float slope = tan(fov / 2.0);
|
|
float projFactor = -0.5 * uScreenHeight / (slope * vViewPosition.z);
|
|
|
|
float r = uOctreeSpacing * 1.5;
|
|
vRadius = r;
|
|
#if defined fixed_point_size
|
|
pointSize = size;
|
|
#elif defined attenuated_point_size
|
|
if(uUseOrthographicCamera){
|
|
pointSize = size;
|
|
}else{
|
|
pointSize = pointSize * projFactor;
|
|
}
|
|
#elif defined adaptive_point_size
|
|
if(uUseOrthographicCamera) {
|
|
float worldSpaceSize = 1.5 * size * r / getPointSizeAttenuation();
|
|
pointSize = (worldSpaceSize / uOrthoWidth) * uScreenWidth;
|
|
} else {
|
|
float worldSpaceSize = 1.5 * size * r / getPointSizeAttenuation();
|
|
pointSize = worldSpaceSize * projFactor;
|
|
}
|
|
#endif
|
|
|
|
pointSize = max(minSize, pointSize);
|
|
pointSize = min(maxSize, pointSize);
|
|
|
|
vRadius = pointSize / projFactor;
|
|
|
|
return pointSize;
|
|
}
|
|
|
|
|
|
void main() {
|
|
|
|
vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
|
|
vLinearDepth = gl_Position.w;
|
|
|
|
float pointSize = getPointSize();
|
|
gl_PointSize = pointSize;
|
|
|
|
}
|
|
`
|
|
|
|
Potree.Shaders["pointcloud_sm.fs"] = `
|
|
precision mediump float;
|
|
precision mediump int;
|
|
|
|
varying vec3 vColor;
|
|
varying float vLinearDepth;
|
|
|
|
void main() {
|
|
|
|
//gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
|
//gl_FragColor = vec4(vColor, 1.0);
|
|
//gl_FragColor = vec4(vLinearDepth, pow(vLinearDepth, 2.0), 0.0, 1.0);
|
|
gl_FragColor = vec4(vLinearDepth, vLinearDepth / 30.0, vLinearDepth / 30.0, 1.0);
|
|
|
|
}
|
|
|
|
|
|
`
|
|
|
|
Potree.Shaders["normalize.vs"] = `
|
|
precision mediump float;
|
|
precision mediump int;
|
|
|
|
attribute vec3 position;
|
|
attribute vec2 uv;
|
|
|
|
uniform mat4 projectionMatrix;
|
|
uniform mat4 modelViewMatrix;
|
|
|
|
varying vec2 vUv;
|
|
|
|
void main() {
|
|
vUv = uv;
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
|
|
}`
|
|
|
|
Potree.Shaders["normalize.fs"] = `
|
|
#extension GL_EXT_frag_depth : enable
|
|
|
|
precision mediump float;
|
|
precision mediump int;
|
|
|
|
uniform sampler2D uWeightMap;
|
|
uniform sampler2D uDepthMap;
|
|
|
|
varying vec2 vUv;
|
|
|
|
void main() {
|
|
float depth = texture2D(uDepthMap, vUv).r;
|
|
|
|
if(depth >= 1.0){
|
|
discard;
|
|
}
|
|
|
|
gl_FragColor = vec4(depth, 1.0, 0.0, 1.0);
|
|
|
|
vec4 color = texture2D(uWeightMap, vUv);
|
|
color = color / color.w;
|
|
|
|
gl_FragColor = vec4(color.xyz, 1.0);
|
|
|
|
gl_FragDepthEXT = depth;
|
|
|
|
|
|
}`
|
|
|
|
Potree.Shaders["normalize_and_edl.fs"] = `
|
|
#extension GL_EXT_frag_depth : enable
|
|
|
|
precision mediump float;
|
|
precision mediump int;
|
|
|
|
uniform sampler2D uWeightMap;
|
|
uniform sampler2D uEDLMap;
|
|
uniform sampler2D uDepthMap;
|
|
|
|
uniform float screenWidth;
|
|
uniform float screenHeight;
|
|
uniform vec2 neighbours[NEIGHBOUR_COUNT];
|
|
uniform float edlStrength;
|
|
uniform float radius;
|
|
|
|
varying vec2 vUv;
|
|
|
|
float response(float depth){
|
|
vec2 uvRadius = radius / vec2(screenWidth, screenHeight);
|
|
|
|
float sum = 0.0;
|
|
|
|
for(int i = 0; i < NEIGHBOUR_COUNT; i++){
|
|
vec2 uvNeighbor = vUv + uvRadius * neighbours[i];
|
|
|
|
float neighbourDepth = texture2D(uEDLMap, uvNeighbor).a;
|
|
|
|
if(neighbourDepth != 0.0){
|
|
if(depth == 0.0){
|
|
sum += 100.0;
|
|
}else{
|
|
sum += max(0.0, depth - neighbourDepth);
|
|
}
|
|
}
|
|
}
|
|
|
|
return sum / float(NEIGHBOUR_COUNT);
|
|
}
|
|
|
|
void main() {
|
|
|
|
float edlDepth = texture2D(uEDLMap, vUv).a;
|
|
float res = response(edlDepth);
|
|
float shade = exp(-res * 300.0 * edlStrength);
|
|
|
|
float depth = texture2D(uDepthMap, vUv).r;
|
|
if(depth >= 1.0 && res == 0.0){
|
|
discard;
|
|
}
|
|
|
|
vec4 color = texture2D(uWeightMap, vUv);
|
|
color = color / color.w;
|
|
color = color * shade;
|
|
|
|
gl_FragColor = vec4(color.xyz, 1.0);
|
|
|
|
gl_FragDepthEXT = depth;
|
|
}`
|
|
|
|
Potree.Shaders["edl.vs"] = `
|
|
|
|
varying vec2 vUv;
|
|
|
|
void main() {
|
|
vUv = uv;
|
|
|
|
vec4 mvPosition = modelViewMatrix * vec4(position,1.0);
|
|
|
|
gl_Position = projectionMatrix * mvPosition;
|
|
}`
|
|
|
|
Potree.Shaders["edl.fs"] = `//
|
|
// adapted from the EDL shader code from Christian Boucheny in cloud compare:
|
|
// https://github.com/cloudcompare/trunk/tree/master/plugins/qEDL/shaders/EDL
|
|
//
|
|
|
|
uniform float screenWidth;
|
|
uniform float screenHeight;
|
|
uniform vec2 neighbours[NEIGHBOUR_COUNT];
|
|
uniform float edlStrength;
|
|
uniform float radius;
|
|
uniform float opacity;
|
|
|
|
//uniform sampler2D colorMap;
|
|
uniform sampler2D uRegularColor;
|
|
uniform sampler2D uRegularDepth;
|
|
uniform sampler2D uEDLColor;
|
|
uniform sampler2D uEDLDepth;
|
|
|
|
varying vec2 vUv;
|
|
|
|
float response(float depth){
|
|
vec2 uvRadius = radius / vec2(screenWidth, screenHeight);
|
|
|
|
float sum = 0.0;
|
|
|
|
for(int i = 0; i < NEIGHBOUR_COUNT; i++){
|
|
vec2 uvNeighbor = vUv + uvRadius * neighbours[i];
|
|
|
|
float neighbourDepth = texture2D(uEDLColor, uvNeighbor).a;
|
|
neighbourDepth = (neighbourDepth == 1.0) ? 0.0 : neighbourDepth;
|
|
|
|
if(neighbourDepth != 0.0){
|
|
if(depth == 0.0){
|
|
sum += 100.0;
|
|
}else{
|
|
sum += max(0.0, depth - neighbourDepth);
|
|
}
|
|
}
|
|
}
|
|
|
|
return sum / float(NEIGHBOUR_COUNT);
|
|
}
|
|
|
|
void main(){
|
|
vec4 cReg = texture2D(uRegularColor, vUv);
|
|
vec4 cEDL = texture2D(uEDLColor, vUv);
|
|
|
|
float depth = cEDL.a;
|
|
depth = (depth == 1.0) ? 0.0 : depth;
|
|
float res = response(depth);
|
|
float shade = exp(-res * 300.0 * edlStrength);
|
|
|
|
float dReg = texture2D(uRegularDepth, vUv).r;
|
|
float dEDL = texture2D(uEDLDepth, vUv).r;
|
|
|
|
if(dEDL < dReg){
|
|
gl_FragColor = vec4(cEDL.rgb * shade, opacity);
|
|
}else{
|
|
gl_FragColor = vec4(cReg.rgb * shade, cReg.a);
|
|
}
|
|
|
|
}
|
|
`
|
|
|
|
Potree.Shaders["blur.vs"] = `
|
|
varying vec2 vUv;
|
|
|
|
void main() {
|
|
vUv = uv;
|
|
|
|
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
|
|
}`
|
|
|
|
Potree.Shaders["blur.fs"] = `
|
|
uniform mat4 projectionMatrix;
|
|
|
|
uniform float screenWidth;
|
|
uniform float screenHeight;
|
|
uniform float near;
|
|
uniform float far;
|
|
|
|
uniform sampler2D map;
|
|
|
|
varying vec2 vUv;
|
|
|
|
void main() {
|
|
|
|
float dx = 1.0 / screenWidth;
|
|
float dy = 1.0 / screenHeight;
|
|
|
|
vec3 color = vec3(0.0, 0.0, 0.0);
|
|
color += texture2D(map, vUv + vec2(-dx, -dy)).rgb;
|
|
color += texture2D(map, vUv + vec2( 0, -dy)).rgb;
|
|
color += texture2D(map, vUv + vec2(+dx, -dy)).rgb;
|
|
color += texture2D(map, vUv + vec2(-dx, 0)).rgb;
|
|
color += texture2D(map, vUv + vec2( 0, 0)).rgb;
|
|
color += texture2D(map, vUv + vec2(+dx, 0)).rgb;
|
|
color += texture2D(map, vUv + vec2(-dx, dy)).rgb;
|
|
color += texture2D(map, vUv + vec2( 0, dy)).rgb;
|
|
color += texture2D(map, vUv + vec2(+dx, dy)).rgb;
|
|
|
|
color = color / 9.0;
|
|
|
|
gl_FragColor = vec4(color, 1.0);
|
|
|
|
|
|
}`
|