aboutsummaryrefslogtreecommitdiff
path: root/KaplaDemo/samples/sampleViewer3/Render
diff options
context:
space:
mode:
Diffstat (limited to 'KaplaDemo/samples/sampleViewer3/Render')
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.cpp342
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.h220
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/MyShaders.cpp2878
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/MyShaders.h21
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/glmesh.cpp271
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/glmesh.h42
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/newParameters.cpp46
-rw-r--r--KaplaDemo/samples/sampleViewer3/Render/newParameters.h42
8 files changed, 3862 insertions, 0 deletions
diff --git a/KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.cpp b/KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.cpp
new file mode 100644
index 00000000..f79a657a
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.cpp
@@ -0,0 +1,342 @@
+
+/**********************************************************************\
+* AUTHOR : HILLAIRE S�bastien
+*
+* SITE : sebastien.hillaire.free.fr
+*
+* You are free to totally or partially use this file/code.
+* If you do, please credit me in your software or demo and leave this
+* note.
+* Share your work and your ideas as much as possible!
+\*********************************************************************/
+
+#include "FrameBufferObjectMRT.h"
+
+
+//#include "ImageBMP.h"
+
+bool CheckFramebufferStatus(const GLuint fbo)
+{
+ GLenum status;
+ bool ret = false;
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
+
+ status = (GLenum) glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ switch(status) {
+ case GL_FRAMEBUFFER_COMPLETE_EXT:
+ //printf("Frame Buffer Created\n");
+ ret = true;
+ break;
+ case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
+ printf("Unsupported framebuffer format\n");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
+ printf("Framebuffer incomplete, missing attachment\n");
+ break;
+ //case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
+ // printf("Framebuffer incomplete, duplicate attachment\n");
+ // break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
+ printf("Framebuffer incomplete, attached images must have same dimensions\n");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
+ printf("Framebuffer incomplete, attached images must have same format\n");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
+ printf("Framebuffer incomplete, missing draw buffer\n");
+ break;
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
+ printf("Framebuffer incomplete, missing read buffer\n");
+ break;
+ default:
+ printf("Framebuffer incomplete, UNKNOW ERROR\n");
+ assert(0);
+ }
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////////////
+
+FrameBufferObjectMRT::FrameBufferObjectMRT(unsigned int width, unsigned int height,
+ unsigned int nbColorBuffer,
+ const unsigned int* colorBufferInternalFormat,
+ const unsigned int* colorBufferSWRAP,
+ const unsigned int* colorBufferTWRAP,
+ const unsigned int* colorBufferMinFiltering,
+ const unsigned int* colorBufferMagFiltering,
+ FBO_DepthBufferType depthBufferType,
+ const unsigned int depthBufferMinFiltering,
+ const unsigned int depthBufferMagFiltering,
+ const unsigned int depthBufferSWRAP,
+ const unsigned int depthBufferTWRAP)
+{
+ this->width = width;
+ this->height= height;
+ this->nbColorAttachement = nbColorBuffer;
+ if(this->nbColorAttachement>this->getMaxColorAttachments())
+ this->nbColorAttachement = this->getMaxColorAttachments();
+
+
+ /////////////////INITIALIZATION/////////////////
+
+ //color render buffer
+ if(this->nbColorAttachement>0)
+ {
+ this->colorTextures = new GLuint[this->nbColorAttachement];
+ this->colorMinificationFiltering = new GLuint[this->nbColorAttachement];
+ for(int i=0; i<this->nbColorAttachement; i++)
+ {
+ glGenTextures(1, &this->colorTextures[i]);
+ glBindTexture(GL_TEXTURE_2D, this->colorTextures[i]);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, colorBufferMinFiltering[i]);
+ this->colorMinificationFiltering[i] = colorBufferMinFiltering[i];
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, colorBufferMagFiltering[i]);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, colorBufferSWRAP[i]);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, colorBufferTWRAP[i]);
+ glTexImage2D(GL_TEXTURE_2D, 0, colorBufferInternalFormat[i], width, height, 0, GL_RGB, GL_FLOAT, NULL);
+
+ if(this->colorMinificationFiltering[i]==GL_NEAREST_MIPMAP_NEAREST
+ || this->colorMinificationFiltering[i]==GL_LINEAR_MIPMAP_NEAREST
+ ||this->colorMinificationFiltering[i]==GL_NEAREST_MIPMAP_LINEAR
+ || this->colorMinificationFiltering[i]==GL_LINEAR_MIPMAP_LINEAR)
+ {
+ glGenerateMipmapEXT(GL_TEXTURE_2D);
+ }
+ }
+ }
+
+ //depth render buffer
+ this->depthType = depthBufferType;
+ if(this->depthType!=FBO_DepthBufferType_NONE)
+ {
+ switch(this->depthType)
+ {
+ case FBO_DepthBufferType_TEXTURE:
+ glGenTextures(1, &this->depthID);
+ glBindTexture(GL_TEXTURE_2D, this->depthID);
+ this->depthMinificationFiltering = depthBufferMinFiltering;
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, depthBufferMinFiltering);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, depthBufferMagFiltering);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, depthBufferSWRAP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, depthBufferTWRAP);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24_ARB, width, height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
+
+ if(this->depthMinificationFiltering==GL_NEAREST_MIPMAP_NEAREST
+ || this->depthMinificationFiltering==GL_LINEAR_MIPMAP_NEAREST
+ ||this->depthMinificationFiltering==GL_NEAREST_MIPMAP_LINEAR
+ || this->depthMinificationFiltering==GL_LINEAR_MIPMAP_LINEAR)
+ {
+ glGenerateMipmapEXT(GL_TEXTURE_2D);
+ }
+ break;
+
+ case FBO_DepthBufferType_RENDERTARGET:
+ default:
+ glGenRenderbuffersEXT(1, &this->depthID);
+ glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, this->depthID);
+ glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_ARB, width, height);
+ break;
+ }
+ }
+
+ /////////////////ATTACHEMENT/////////////////
+ glGenFramebuffersEXT(1, &this->fbo);
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,this->fbo);
+
+ //color render buffer attachement
+ if(nbColorBuffer>0)
+ {
+ for(int i=0; i<this->nbColorAttachement; i++)
+ {
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_TEXTURE_2D, this->colorTextures[i], 0 );
+ }
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ }
+ else
+ {
+ glReadBuffer(GL_NONE);
+ glDrawBuffer(GL_NONE);
+ }
+
+ //depth render buffer attachement
+ if(this->depthType!=FBO_DepthBufferType_NONE)
+ {
+ switch(this->depthType)
+ {
+ case FBO_DepthBufferType_TEXTURE:
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, this->depthID, 0);
+ break;
+
+ case FBO_DepthBufferType_RENDERTARGET:
+ default:
+ glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, this->depthID);
+ break;
+ }
+ }
+
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+ CheckFramebufferStatus(this->fbo);
+}
+
+FrameBufferObjectMRT::~FrameBufferObjectMRT()
+{
+ if(this->nbColorAttachement>0)
+ {
+ delete [] this->colorTextures;
+ delete [] this->colorMinificationFiltering;
+ }
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////
+
+
+
+const GLint FrameBufferObjectMRT::getMaxColorAttachments()
+{
+ GLint maxAttach = 0;
+ glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS_EXT, &maxAttach );
+ return maxAttach;
+}
+const GLint FrameBufferObjectMRT::getMaxBufferSize()
+{
+ GLint maxSize = 0;
+ glGetIntegerv( GL_MAX_RENDERBUFFER_SIZE_EXT, &maxSize );
+ return maxSize;
+}
+
+
+
+void FrameBufferObjectMRT::enableRenderToColorAndDepth(const unsigned int colorBufferNum) const
+{
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->fbo);
+
+ if(this->nbColorAttachement>0)
+ {
+ unsigned int colorBuffer = GL_COLOR_ATTACHMENT0_EXT + colorBufferNum;
+ if((int)colorBufferNum>this->nbColorAttachement)
+ colorBuffer = GL_COLOR_ATTACHMENT0_EXT;
+ glDrawBuffer(colorBuffer);
+ }
+ else
+ {
+ glDrawBuffer(GL_NONE); //for example, in the case of rendering in a depth buffer
+ }
+}
+
+void FrameBufferObjectMRT::enableRenderToColorAndDepth_MRT(const GLuint numBuffers, const GLenum* drawbuffers) const
+{
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, this->fbo);
+
+ //HERE, THERE SHOULD HAVE A TEST OF THE DRAW BUFFERS ID AND NUMBER
+ /*for(GLuint i=0; i<numBuffers; i++)
+ {
+ }*/
+ glDrawBuffers(numBuffers, drawbuffers);
+
+}
+
+void FrameBufferObjectMRT::disableRenderToColorDepth()
+{
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+}
+
+
+
+void FrameBufferObjectMRT::saveAndSetViewPort() const
+{
+ glPushAttrib(GL_VIEWPORT_BIT);
+ glViewport(0, 0, this->width, this->height);
+}
+
+void FrameBufferObjectMRT::restoreViewPort() const
+{
+ glPopAttrib();
+}
+
+
+
+void FrameBufferObjectMRT::bindColorTexture(const unsigned int colorBufferNum) const
+{
+ if(this->nbColorAttachement>0 && (int)colorBufferNum<this->nbColorAttachement)
+ {
+ glBindTexture(GL_TEXTURE_2D, this->colorTextures[colorBufferNum]);
+ }
+ else
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+void FrameBufferObjectMRT::bindDepthTexture() const
+{
+ if(this->depthType==FBO_DepthBufferType_TEXTURE)
+ {
+ glBindTexture(GL_TEXTURE_2D, this->depthID);
+ }
+ else
+ glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+void FrameBufferObjectMRT::generateColorBufferMipMap(const unsigned int colorBufferNum) const
+{
+ if(this->nbColorAttachement>0 && (int)colorBufferNum<this->nbColorAttachement)
+ {
+ if(this->colorMinificationFiltering[colorBufferNum]==GL_NEAREST
+ || this->colorMinificationFiltering[colorBufferNum]==GL_LINEAR)
+ return; //don't allow to generate mipmap chain for texture that don't support it at the creation
+
+ glBindTexture(GL_TEXTURE_2D, this->colorTextures[colorBufferNum]);
+ glGenerateMipmapEXT(GL_TEXTURE_2D);
+ }
+}
+
+void FrameBufferObjectMRT::generateDepthBufferMipMap() const
+{
+ if(this->depthType==FBO_DepthBufferType_TEXTURE)
+ {
+ if(this->depthMinificationFiltering==GL_NEAREST
+ || this->depthMinificationFiltering==GL_LINEAR)
+ return; //don't allow to generate mipmap chain for texture that don't support it at the creation
+
+ glBindTexture(GL_TEXTURE_2D, this->depthID);
+ glGenerateMipmapEXT(GL_TEXTURE_2D);
+ }
+}
+
+
+
+unsigned int FrameBufferObjectMRT::getNumberOfColorAttachement() const
+{
+ return this->nbColorAttachement;
+}
+
+FBO_DepthBufferType FrameBufferObjectMRT::getDepthBufferType() const
+{
+ return this->depthType;
+}
+
+unsigned int FrameBufferObjectMRT::getWidth() const
+{
+ return this->width;
+}
+
+unsigned int FrameBufferObjectMRT::getHeight() const
+{
+ return this->height;
+}
+
+/*
+void FrameBufferObjectMRT::saveToDisk(const unsigned int colorBufferNum, const char* filepath) const
+{
+ if(this->nbColorAttachement>0 && (int)colorBufferNum<this->nbColorAttachement)
+ {
+ ImageBMP::TextureToDisk(filepath,GL_TEXTURE_2D,this->colorTextures[colorBufferNum]);
+ }
+}*/ \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.h b/KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.h
new file mode 100644
index 00000000..d899cda0
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/FrameBufferObjectMRT.h
@@ -0,0 +1,220 @@
+
+/**********************************************************************\
+* AUTHOR : HILLAIRE S�bastien
+*
+* SITE : sebastien.hillaire.free.fr
+*
+* You are free to totally or partially use this file/code.
+* If you do, please credit me in your software or demo and leave this
+* note.
+* Share your work and your ideas as much as possible!
+\*********************************************************************/
+
+
+#ifndef _FRAME_BUFFER_OBJECT_OPENGL_
+#define _FRAME_BUFFER_OBJECT_OPENGL_
+
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include "stdlib.h"
+#include "assert.h"
+#include "stdio.h"
+#include "GL/glew.h"
+
+typedef enum{
+ FBO_DepthBufferType_NONE=0,
+ FBO_DepthBufferType_TEXTURE=1,
+ FBO_DepthBufferType_RENDERTARGET=2
+} FBO_DepthBufferType;
+
+/**
+ * The FrameBufferObject class allowing to use render to texture
+ */
+class FrameBufferObjectMRT
+{
+private:
+ /**
+ * The OpenGL FBO ID
+ */
+ GLuint fbo;
+
+ /**
+ * the table containing all texture id of each render target
+ */
+ GLuint* colorTextures;
+ /**
+ * the number of color attachement
+ */
+ GLint nbColorAttachement;
+ /**
+ * The minification filtering for the color buffer textures
+ */
+ GLuint *colorMinificationFiltering;
+
+ /**
+ * the depth texture/buffer id
+ */
+ GLuint depthID;
+ /**
+ * the depth type
+ */
+ FBO_DepthBufferType depthType;
+ /**
+ * The minification filtering for the depth buffer texture
+ */
+ GLuint depthMinificationFiltering;
+
+ /**
+ * the width in pixel
+ */
+ unsigned int width;
+ /**
+ * the height in pixel
+ */
+ unsigned int height;
+
+ /**
+ * default constructeur not allowed
+ */
+ FrameBufferObjectMRT();
+ /**
+ * copy constructeur not allowed
+ */
+ FrameBufferObjectMRT(FrameBufferObjectMRT&);
+ /**
+ * copy assignement operator not allowed
+ */
+ FrameBufferObjectMRT& operator=(const FrameBufferObjectMRT&);
+
+public:
+
+ /**
+ * The only available constructor
+ */
+ FrameBufferObjectMRT(unsigned int width, unsigned int height,
+ unsigned int nbColorBuffer,
+ const unsigned int* colorBufferInternalFormat,
+ const unsigned int* colorBufferSWRAP,
+ const unsigned int* colorBufferTWRAP,
+ const unsigned int* colorBufferMinFiltering,
+ const unsigned int* colorBufferMagFiltering,
+ FBO_DepthBufferType depthBufferType=FBO_DepthBufferType_NONE,
+ const unsigned int depthBufferMinFiltering=GL_LINEAR,
+ const unsigned int depthBufferMagFiltering=GL_LINEAR,
+ const unsigned int depthBufferSWRAP=GL_CLAMP,
+ const unsigned int depthBufferTWRAP=GL_CLAMP);
+
+ /**
+ * The destructor
+ */
+ ~FrameBufferObjectMRT();
+
+ /**
+ * @return the number of color attachment of this FBO
+ */
+ unsigned int getNumberOfColorAttachement() const;
+ /**
+ * @return the type of depth buffer of this FBO
+ */
+ FBO_DepthBufferType getDepthBufferType() const;
+
+ /**
+ * @return the width in pixel of this FBO
+ */
+ unsigned int getWidth() const;
+ /**
+ * @return the height in pixel of this FBO
+ */
+ unsigned int getHeight() const;
+
+ /**
+ * @return the maximum number of color texture attachement
+ */
+ static const GLint getMaxColorAttachments();
+ /**
+ * @return the maximum width and height allowed
+ */
+ static const GLint getMaxBufferSize();
+
+ /**
+ * Enable this FBO to render in ONE texture using the depth buffer if it exist.
+ * To disable rendering in the depth buffer and/or depth testing, use glDepthMask and glDisable(GL_DEPTH_TEST).
+ *
+ * @param colorBufferNum : the number of the render texture (0 for GL_COLOR_ATTACHMENT0_EXT, etc)
+ */
+ void enableRenderToColorAndDepth(const unsigned int colorBufferNum) const;
+ /**
+ * Enable this FBO to render in MULTIPLE texture using the depth buffer if it exist.
+ * To disable rendering in the depth buffer and/or depth testing, use glDepthMask and glDisable(GL_DEPTH_TEST).
+ * Using this method, you must not use gl_fragColor in the fragment program but gl_fragData[i].
+ *
+ * @param numBuffers : the number of renger target we want
+ * @param drawbuffers : an array containing the color texture ID binded to the fragment program output gl_fragData[i]
+ */
+ void enableRenderToColorAndDepth_MRT(const GLuint numBuffers, const GLenum* drawbuffers) const;
+ /**
+ * Disable render to texture. This method os static because it works the same way for all fbo instance.
+ * Thus, if you want to render to two render texture sequentially, you don't need to disable fbo rendering
+ * and it will improves performances.
+ */
+ static void disableRenderToColorDepth();
+
+ /**
+ * Save the current viewport and set up the viewport for this fbo. If the FBO is has same resolution as the current
+ * viewport, you don't need to call this method.
+ */
+ void saveAndSetViewPort() const;
+ /**
+ * Restore previous viewport.
+ * @see saveAndSetViewPort
+ */
+ void restoreViewPort() const;
+
+
+ GLuint getColorBuffer(int colorBufferNum) {
+ if(this->nbColorAttachement>0 && (int)colorBufferNum<this->nbColorAttachement)
+ {
+ return this->colorTextures[colorBufferNum];
+ }
+ return NULL;
+ }
+ /**
+ * Bind a color buffer in the current texture unit as a GL_TEXTURE_2D.
+ *
+ * @param colorBufferNum : the number of the color buffer texture to bind. If the number is invalid, texture 0 is binded
+ */
+ void bindColorTexture(const unsigned int colorBufferNum) const;
+ /**
+ * Bind the depth buffer in the current texture unit as a GL_TEXTURE_2D.
+ */
+ void bindDepthTexture() const;
+
+ /**
+ * Generate the mipmap chain for a given color buffer.
+ * The mipmap generation will not work for texture-buffer you have specified with GL_NEAREST or GL_LINEAR at the creation.
+ *
+ * @param colorBufferNum : the number of the color buffer texture to bind. If the number is invalid, we return.
+ */
+ void generateColorBufferMipMap(const unsigned int colorBufferNum) const;
+ /**
+ * Generate the mipmap chain for the depth buffer. Some driver don't support it.
+ */
+ void generateDepthBufferMipMap() const;
+
+ /**
+ * Save a given color bufferin a bitmap file.
+ *
+ * @param colorBufferNum : the number of the color buffer texture to bind. If the number is invalid, we return.
+ * @param filepath : the path of the bitmap file.
+ */
+ //void saveToDisk(const unsigned int colorBufferNum, const char* filepath) const;
+
+};
+
+
+
+#endif
+
diff --git a/KaplaDemo/samples/sampleViewer3/Render/MyShaders.cpp b/KaplaDemo/samples/sampleViewer3/Render/MyShaders.cpp
new file mode 100644
index 00000000..7a2cec9c
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/MyShaders.cpp
@@ -0,0 +1,2878 @@
+// GLSL shaders
+#include "Compound.h"
+#define STRINGIFY(A) #A
+
+// particle vertex shader
+const char *particleVS = STRINGIFY(
+uniform float pointRadius; // point size in world space
+uniform float pointScale; // scale to calculate size in pixels
+uniform float densityThreshold = 500.0;
+uniform float pointShrink = 0.2;
+void main()
+{
+ // scale down point size based on density
+ float density = gl_MultiTexCoord1.x;
+ float scaledPointRadius = pointRadius * (pointShrink + smoothstep(densityThreshold, densityThreshold*2.0, density)*(1.0-pointShrink));
+// float scaledPointRadius = pointRadius;
+
+ // calculate window-space point size
+ vec4 eyeSpacePos = gl_ModelViewMatrix * gl_Vertex;
+ float dist = length(eyeSpacePos.xyz);
+ gl_PointSize = scaledPointRadius * (pointScale / dist);
+
+ gl_TexCoord[0] = gl_MultiTexCoord0; // sprite texcoord
+ gl_TexCoord[1] = vec4(eyeSpacePos.xyz, scaledPointRadius); // eye space pos
+ gl_TexCoord[2] = vec4(gl_MultiTexCoord2.xyz, density); // velocity and density
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+
+ if (density < densityThreshold) gl_Position.w = -1.0; // cull particles with small density
+
+ gl_FrontColor = gl_Color;
+}
+);
+const char *particleVSNoKill = STRINGIFY(
+uniform float pointRadius; // point size in world space
+uniform float pointScale; // scale to calculate size in pixels
+uniform float densityThreshold = 500.0;
+uniform float pointShrink = 0.2;
+void main()
+{
+ // scale down point size based on density
+ float density = gl_MultiTexCoord1.x;
+// float scaledPointRadius = pointRadius * (pointShrink + smoothstep(densityThreshold, densityThreshold*2.0, density)*(1.0-pointShrink))*max(0.0f, min(gl_MultiTexCoord3.x, 0.1))*10.0f;;
+ float scaledPointRadius = pointRadius;
+
+ // calculate window-space point size
+ vec4 eyeSpacePos = gl_ModelViewMatrix * gl_Vertex;
+ float dist = length(eyeSpacePos.xyz);
+ gl_PointSize = scaledPointRadius * (pointScale / dist);
+ //gl_PointSize = 10.0f;
+ gl_TexCoord[0] = gl_MultiTexCoord0; // sprite texcoord
+ gl_TexCoord[1] = vec4(eyeSpacePos.xyz, scaledPointRadius); // eye space pos
+ gl_TexCoord[2] = vec4(gl_MultiTexCoord2.xyz, density); // velocity and density
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+
+ gl_FrontColor = gl_Color;
+}
+);
+// render particle as constant shaded disc
+const char *particleDebugPS = STRINGIFY(
+uniform float pointRadius;
+void main()
+{
+ // calculate eye-space sphere normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float r2 = dot(N.xy, N.xy);
+ if (r2 > 1.0) discard; // kill pixels outside circle
+
+// gl_FragColor = gl_Color;
+ gl_FragColor = gl_TexCoord[2].w * 0.001; // show density
+// gl_FragColor = gl_TexCoord[2]; // show vel
+}
+);
+
+// render particle as lit sphere
+const char *particleSpherePS = STRINGIFY(
+uniform float pointRadius;
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+void main()
+{
+ // calculate eye-space sphere normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float r2 = dot(N.xy, N.xy);
+ if (r2 > 1.0) discard; // kill pixels outside circle
+ N.z = sqrt(1.0-r2);
+
+ // calculate depth
+ vec4 eyeSpacePos = vec4(gl_TexCoord[1].xyz + N*pointRadius, 1.0); // position of this pixel on sphere in eye space
+ vec4 clipSpacePos = gl_ProjectionMatrix * eyeSpacePos;
+ gl_FragDepth = (clipSpacePos.z / clipSpacePos.w)*0.5+0.5;
+
+ float diffuse = max(0.0, dot(N, lightDir));
+
+ gl_FragColor = diffuse*gl_Color;
+}
+);
+
+// visualize density
+const char *particleDensityPS = STRINGIFY(
+uniform float pointRadius;
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform float densityScale;
+uniform float densityOffset;
+void main()
+{
+ // calculate eye-space sphere normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float r2 = dot(N.xy, N.xy);
+ if (r2 > 1.0) discard; // kill pixels outside circle
+ N.z = sqrt(1.0-r2);
+
+ // calculate depth
+ vec4 eyeSpacePos = vec4(gl_TexCoord[1].xyz + N*pointRadius, 1.0); // position of this pixel on sphere in eye space
+ vec4 clipSpacePos = gl_ProjectionMatrix * eyeSpacePos;
+ gl_FragDepth = (clipSpacePos.z / clipSpacePos.w)*0.5+0.5;
+
+ float diffuse = max(0.0, dot(N, lightDir));
+
+ // calculate color based on density
+ float x = 1.0 - saturate((gl_TexCoord[2].w - densityOffset) * densityScale);
+ vec3 color = lerp(gl_Color.xyz, vec3(1.0, 1.0, 1.0), x);
+
+ gl_FragColor = vec4(diffuse*color, 1.0);
+}
+);
+
+// renders eye-space depth
+const char *particleSurfacePS = STRINGIFY(
+uniform float pointRadius;
+uniform float faceScale = 1.0;
+void main()
+{
+ // calculate eye-space normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float r2 = dot(N.xy, N.xy);
+ if (r2 > 1.0) discard; // kill pixels outside circle
+ N.z = sqrt(1.0-r2)*faceScale;
+
+ // calculate depth
+ vec4 eyeSpacePos = vec4(gl_TexCoord[1].xyz + N*gl_TexCoord[1].w, 1.0); // position of this pixel on sphere in eye space
+ vec4 clipSpacePos = gl_ProjectionMatrix * eyeSpacePos;
+ gl_FragDepth = (clipSpacePos.z / clipSpacePos.w)*0.5+0.5;
+
+ gl_FragColor = eyeSpacePos.z; // output eye-space depth
+// gl_FragColor = -eyeSpacePos.z/10.0;
+}
+);
+
+// render particle thickness
+const char *particleThicknessPS = STRINGIFY(
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform float pointRadius;
+uniform float faceScale = 1.0;
+void main()
+{
+ // calculate eye-space normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float r2 = dot(N.xy, N.xy);
+ if (r2 > 1.0) discard; // kill pixels outside circle
+ N.z = sqrt(1.0-r2) * faceScale;
+
+ // calculate depth
+ vec4 eyeSpacePos = vec4(gl_TexCoord[1].xyz + N*gl_TexCoord[1].w, 1.0); // position of this pixel on sphere in eye space
+ vec4 clipSpacePos = gl_ProjectionMatrix * eyeSpacePos;
+ gl_FragDepth = (clipSpacePos.z / clipSpacePos.w)*0.5+0.5;
+
+ float alpha = exp(-r2*2.0);
+
+// gl_FragColor = eyeSpacePos.z; // output distance
+ gl_FragColor = N.z*pointRadius*2.0*alpha; // output thickness
+}
+);
+
+// motion blur shaders
+const char *mblurVS = STRINGIFY(
+uniform float timestep = 0.02;
+uniform vec3 eyeVel;
+uniform float iStartFade = 1.0;
+void main()
+{
+ vec3 pos = gl_Vertex.xyz;
+ vec3 vel = gl_MultiTexCoord2.xyz;
+ //vel = vec3(10.0f,0.0f,0.0f);
+ vec3 pos2 = (pos - (vel+eyeVel)*timestep); // previous position
+
+ gl_Position = gl_ModelViewMatrix * vec4(pos, 1.0); // eye space
+ gl_TexCoord[0] = gl_ModelViewMatrix * vec4(pos2, 1.0);
+ gl_TexCoord[1].x = gl_MultiTexCoord1.x;
+ gl_TexCoord[1].y = max(0.0f, min(gl_MultiTexCoord3.x*iStartFade, 1.0f));
+ gl_TexCoord[2].xyz = pos;
+ gl_TexCoord[3] = gl_MultiTexCoord4;
+
+ gl_FrontColor = gl_Color;
+}
+
+);
+
+const char *mblurGS = STRINGIFY(
+//#version 120\n
+//#extension GL_EXT_geometry_shader4 : enable\n
+uniform float pointRadius; // point size in world space
+uniform float densityThreshold = 50.0;
+uniform float idensityThreshold = 1.0 / 50.0;
+uniform float pointShrink = 0.25;
+void main()
+{
+ gl_FrontColor = gl_FrontColorIn[0];
+ float density = gl_TexCoordIn[0][1].x;
+ float life = gl_TexCoordIn[0][1].y;
+
+ // scale down point size based on density
+ float pointSize = pointRadius;
+
+ pointSize *= gl_TexCoordIn[0][3].x;
+
+ // eye space
+ vec3 pos = gl_PositionIn[0].xyz;
+ vec3 pos2 = gl_TexCoordIn[0][0].xyz;
+ vec3 motion = pos - pos2;
+ vec3 dir = normalize(motion);
+ float len = length(motion);
+
+ vec3 x = dir * pointSize;
+ vec3 view = normalize(-pos);
+ vec3 y = normalize(cross(dir, view)) * pointSize;
+ float facing = dot(view, dir);
+
+ // check for very small motion to avoid jitter
+ float threshold = 0.01;
+// if (len < threshold) {
+ if ((len < threshold) || (facing > 0.95) || (facing < -0.95)) {
+ pos2 = pos;
+ x = vec3(pointSize, 0.0, 0.0);
+ y = vec3(0.0, -pointSize, 0.0);
+ }
+
+
+
+ //if (density < densityThreshold) {
+
+ gl_TexCoord[0] = vec4(0, 0, 0, life);
+ gl_TexCoord[2] = vec4(pos + x + y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = gl_TexCoordIn[0][2];
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(0, 1, 0, life);
+ gl_TexCoord[2] = vec4(pos + x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = gl_TexCoordIn[0][2];
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(1, 0, 0, life);
+ gl_TexCoord[2] = vec4(pos2 - x + y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = gl_TexCoordIn[0][2];
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(1, 1, 0, life);
+ gl_TexCoord[2] = vec4(pos2 - x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = gl_TexCoordIn[0][2];
+ EmitVertex();
+
+
+ //}
+}
+);
+const char *mblurGSNoKill = STRINGIFY(
+//#version 120\n
+//#extension GL_EXT_geometry_shader4 : enable\n
+uniform float pointRadius; // point size in world space
+uniform float densityThreshold = 50.0;
+uniform float idensityThreshold = 1.0 / 30.0;
+uniform float pointShrink = 0.25;
+uniform sampler2D meteorTex;
+void main()
+{
+ gl_FrontColor = gl_FrontColorIn[0];
+ float density = gl_TexCoordIn[0][1].x;
+ float life = gl_TexCoordIn[0][1].y;
+
+
+ gl_TexCoord[1].xy = 0.25f*vec2(gl_PrimitiveIDIn / 4, gl_PrimitiveIDIn % 4);
+ // scale down point size based on density
+ float factor = 1.0f;//density * idensityThreshold;
+ //smoothstep(0.0f, densityThreshold, density);
+ //density * idensityThreshold;
+ //clamp(density / 50.0f, 0, 1);
+ float pointSize = pointRadius*factor;//*(pointShrink + smoothstep(0.0, densityThreshold, density)*(1.0-pointShrink));
+
+ pointSize *= gl_TexCoordIn[0][3].x;
+ float tmp = gl_TexCoordIn[0][3].y;
+
+ float bb = 1.0f;
+ if (tmp > 0.5f) {
+ //gl_FrontColor = vec4(3*life,0,0,1);
+ // TODO: Meteor trail color here...
+ //vec2 fetchPos = vec2( min(max((3-lifeTime)/3,0),1), 0);
+ float val = 1-min(max((life-0.3)/0.2,0.01),0.99);
+ vec2 fetchPos = vec2(val, 0);
+ gl_FrontColor = texture2D(meteorTex, fetchPos);
+ if (gl_FrontColor.r > 0.5) bb += (gl_FrontColor.r-0.5)*(gl_FrontColor.r-0.5)*10;
+
+ }
+// float pointSize = pointRadius;
+
+ // eye space
+ vec3 pos = gl_PositionIn[0].xyz;
+ vec3 pos2 = gl_TexCoordIn[0][0].xyz;
+ vec3 motion = pos - pos2;
+ vec3 dir = normalize(motion);
+ float len = length(motion);
+
+ vec3 x = dir * pointSize;
+ vec3 view = normalize(-pos);
+ vec3 y = normalize(cross(dir, view)) * pointSize;
+ float facing = dot(view, dir);
+
+ // check for very small motion to avoid jitter
+ float threshold = 0.01;
+// if (len < threshold) {
+ if ((len < threshold) || (facing > 0.95) || (facing < -0.95)) {
+ pos2 = pos;
+ x = vec3(pointSize, 0.0, 0.0);
+ y = vec3(0.0, -pointSize, 0.0);
+ }
+
+ float angle = density;
+ float cv = cos(angle);
+ float sv = sin(angle);
+
+ vec3 xt = cv*x + sv*y;
+ vec3 yt = -sv*x + cv*y;
+ x = xt;
+ y = yt;
+
+ {
+
+ gl_TexCoord[0] = vec4(0, 0, bb, life);
+ gl_TexCoord[2] = vec4(pos + x + y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = gl_TexCoordIn[0][2];
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(0, 1, bb, life);
+ gl_TexCoord[2] = vec4(pos + x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(1, 0, bb, life);
+ gl_TexCoord[2] = vec4(pos2 - x + y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(1, 1, bb, life);
+ gl_TexCoord[2] = vec4(pos2 - x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+
+ EmitVertex();
+/*
+ gl_TexCoord[0] = vec4(0, 0, 0, life);
+ gl_TexCoord[2] = vec4(pos + x + y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(0, 1, 0, life);
+ gl_TexCoord[2] = vec4(pos + x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(1, 0, 0, life);
+ gl_TexCoord[2] = vec4(pos2 - x + y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ EmitVertex();
+
+ gl_TexCoord[0] = vec4(1, 1, 0, life);
+ gl_TexCoord[2] = vec4(pos2 - x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ EmitVertex();
+ */
+ }
+}
+);
+
+const char *particleSprayPS = STRINGIFY(
+uniform sampler2DArrayShadow stex;
+uniform float shadowAmbient = 0.5;
+uniform vec3 lightDir;
+float shadowCoef()
+{
+ const int index = 0;
+ /*
+ int index = 3;
+
+ // find the appropriate depth map to look up in based on the depth of this fragment
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ */
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[2].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+void main()
+{
+ //gl_FragColor = vec4(1.0f,1.0f,1.0f,1.0f);
+ //return;
+ // calculate eye-space normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float mag = dot(N.xy, N.xy);
+ if (mag > 1.0) discard; // kill pixels outside circle
+
+ float falloff = exp(-mag*4.0);
+ float shadowC = shadowCoef();
+
+ gl_FragColor = gl_Color*(shadowAmbient + (1.0f -shadowAmbient)*shadowC)*(abs(dot(lightDir, N))*0.3f+0.7f );//*falloff;
+
+ float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[2].z), 0.0, 1.0);
+ //float fog = exp(-gl_Fog.density*(gl_TexCoord[0].z*gl_TexCoord[0].z));
+ gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);
+
+ gl_FragColor.w *= falloff * gl_TexCoord[0].w;
+
+}
+);
+const char *particleSprayGenFOMPS= STRINGIFY(
+const float PI = 3.1415926535897932384626433832795;
+const vec4 factor_a = vec4(2.0*PI)*vec4(0.0,1.0,2.0,3.0);
+const vec4 factor_b = vec4(2.0*PI)*vec4(1.0,2.0,3.0,0.0);
+const vec4 factor_m2 = vec4(-2.0);
+uniform float ispotMaxDist;
+void main()
+{
+ // calculate eye-space normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float mag = dot(N.xy, N.xy);
+ if (mag > 1.0) discard; // kill pixels outside circle
+
+ // float falloff = exp(-mag*4.0);
+ //float falloff = pow(1.0-mag,1.5);//exp(-mag);
+ float falloff = 1.0;
+ float opacity = gl_Color.a * falloff * min(gl_TexCoord[0].w,1.0f);
+
+ float distance = sqrt(dot(gl_TexCoord[2].xyz, gl_TexCoord[2].xyz))*ispotMaxDist;
+
+
+ //compute value for projection into Fourier basis
+ vec4 cos_a0123 = cos(factor_a*vec4(distance));
+ vec4 sin_b123 = sin(factor_b*vec4(distance));
+ vec4 lnOpacitR = factor_m2*vec4(log(1.0-opacity));
+
+ gl_FragData[0] = lnOpacitR*cos_a0123;
+ gl_FragData[1] = lnOpacitR*sin_b123;
+}
+);
+
+const char *particleSprayUseFOMPS = STRINGIFY(
+uniform sampler2DArrayShadow stex;
+uniform float shadowAmbient = 0.5;
+float shadowCoef()
+{
+ const int index = 0;
+ /*
+ int index = 3;
+
+ // find the appropriate depth map to look up in based on the depth of this fragment
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ */
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[2].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+uniform float ispotMaxDist;
+uniform vec3 spotOriginEye;
+uniform sampler2D spot_a0123;
+uniform sampler2D spot_b123;
+
+const float PI = 3.1415926535897932384626433832795;
+const vec3 _2pik = vec3(2.0) * vec3(PI,2.0*PI,3.0*PI);
+const vec3 factor_a = vec3(2.0*PI)*vec3(1.0,2.0,3.0);
+const vec3 factor_b = vec3(2.0*PI)*vec3(1.0,2.0,3.0);
+const vec3 value_1 = vec3(1.0);
+
+uniform mat4 eyeToSpotMatrix;
+void main()
+{
+ // calculate eye-space normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float mag = dot(N.xy, N.xy);
+ if (mag > 1.0) discard; // kill pixels outside circle
+
+ float falloff = pow(1.0-mag,1.0);//exp(-mag);
+ //falloff = 1.0f;
+ float shadowC = 1.0f;//shadowCoef();
+
+ // Also FOM
+
+// vec4 projectionCoordinate = eyeToSpotMatrix*vec4(gl_TexCoord[2].xyz, 1.0f);
+ vec4 projectionCoordinate = eyeToSpotMatrix*vec4(gl_TexCoord[2].xyz, 1.0f);
+ //gl_FragColor.xyz = gl_TexCoord[3].xyz*0.25f;
+ //gl_FragColor.xyz = projectionCoordinate.xyz / projectionCoordinate.w;
+ //gl_FragColor.w = 1.0f;
+
+ //read Fourier series coefficients for color extinction on RGB
+ vec4 sR_a0123 = texture2DProj(spot_a0123,projectionCoordinate);
+ vec3 sR_b123 = texture2DProj(spot_b123,projectionCoordinate).rgb;
+
+ //gl_FragColor.xyz = sR_a0123.xyz;
+ //gl_FragColor.w = 1.0f;
+ //return;
+ //compute absolute and normalized distance (in spot depth range)
+ float distance2spotCenter = length(spotOriginEye-gl_TexCoord[2].xyz);//distance from spot origin to surfel in world space
+ float d = distance2spotCenter*ispotMaxDist;
+
+
+ //compute some value to recover the extinction coefficient using the Fourier series
+ vec3 sin_a123 = sin(factor_a*vec3(d));
+ vec3 cos_b123 = value_1-cos(factor_b*vec3(d));
+
+ //compute the extinction coefficients using Fourier
+ float att = (sR_a0123.r*d/2.0) + dot(sin_a123*(sR_a0123.gba/_2pik) ,value_1) + dot(cos_b123*(sR_b123.rgb/_2pik) ,value_1);
+
+ att = max(0.0f, att);
+ att = min(1.0f, att);
+ shadowC = (1.0f-att);
+
+ //....
+
+ gl_FragColor.xyz = gl_Color.xyz*(shadowAmbient + (1.0f -shadowAmbient)*shadowC);//*falloff;
+ gl_FragColor.w = gl_Color.w;
+
+ //float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[2].z), 0.0, 1.0);
+ //float fog = exp(-gl_Fog.density*(gl_TexCoord[0].z*gl_TexCoord[0].z));
+ //gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);
+
+ gl_FragColor.w *= max(min(falloff,1.0f),0.0f) * max(min(gl_TexCoord[0].w,1.0f),0.0f);
+
+// gl_FragColor.w = 0.2f;
+ //gl_FragColor.w = falloff * gl_TexCoord[0].w;
+ //gl_FragColor.xyz = sR_a0123.xyz;
+}
+);
+
+// motion blur shaders
+const char *particleDumbFoamVS = STRINGIFY(
+uniform float timestep = 0.02;
+// GPU Water
+uniform sampler2D waterHFTex;
+uniform float minEta;
+uniform float fracEta;
+uniform vec2 hfScale; // 1/(sx*dx), 1/(sz*dx)
+uniform vec2 hfOffset; // 0.5/sx, 0.5/sz
+uniform vec2 hfCellOffset; // 1.0/sx, 1.0/sz
+uniform vec2 origin;
+uniform float dx;
+uniform float waterHOffset;
+uniform vec4 foamFactor = vec4(1.0/4, 1.0/4,0,0);
+void main()
+{
+ vec2 hfTexCoord = (gl_Vertex.xz - origin)*hfScale + hfOffset;
+ vec4 etaH = texture2D(waterHFTex, hfTexCoord);
+ vec4 etaHxp1 = texture2D(waterHFTex, hfTexCoord + hfCellOffset*vec2(1,0));
+ vec4 etaHxm1 = texture2D(waterHFTex, hfTexCoord + hfCellOffset*vec2(-1,0));
+ vec4 etaHzp1 = texture2D(waterHFTex, hfTexCoord + hfCellOffset*vec2(0,1));
+ vec4 etaHzm1 = texture2D(waterHFTex, hfTexCoord + hfCellOffset*vec2(0,-1));
+ float h = etaH.x+etaH.y;
+ float hxp1 = etaHxp1.x+etaHxp1.y;
+ float hxm1 = etaHxm1.x+etaHxm1.y;
+ float hzp1 = etaHzp1.x+etaHzp1.y;
+ float hzm1 = etaHzm1.x+etaHzm1.y;
+
+ vec3 pos = gl_Vertex.xyz;
+ vec3 vel = gl_MultiTexCoord2.xyz;
+
+ vec3 normal = vec3(-normalize(cross(vec3(2*dx, hxp1-hxm1, 0), vec3(0, hzp1-hzm1, 2*dx))));//vec3(0,1,0);
+ vec3 bitangent = normalize(cross(vec3(1,0,0), normal));
+ vec3 tangent = normalize(cross(bitangent, normal));
+
+ gl_Position = gl_ModelViewMatrix * vec4(pos, 1.0); // eye space
+ gl_TexCoord[0] = gl_MultiTexCoord2 * foamFactor;
+ gl_TexCoord[1] = gl_ModelViewMatrix * vec4(tangent, 0.0);
+ gl_TexCoord[2] = gl_ModelViewMatrixInverseTranspose * vec4(normal, 0.0);
+ gl_TexCoord[3] = gl_ModelViewMatrix * vec4(bitangent, 0.0);
+
+ gl_TexCoord[0].w = max(0.0f, min(gl_MultiTexCoord3.x, 0.1))*10;// Fade with life time
+ gl_FrontColor = gl_Color;
+}
+);
+const char *particleFoamVS = STRINGIFY(
+uniform float timestep = 0.02;
+// GPU Water
+uniform float minEta;
+uniform float fracEta;
+
+uniform float dx;
+uniform vec4 foamFactor = vec4(1.0/4, 1.0/4,0,0);
+uniform float foamOffset;
+uniform float foamOffset2;
+uniform float foamOffset3;
+void main()
+{
+
+
+ vec3 pos = gl_Vertex.xyz;
+
+ vec3 normal = normalize(gl_MultiTexCoord2.xyz);
+ vec3 bitangent = normalize(cross(vec3(1,0,0), normal));
+ vec3 tangent = normalize(cross(bitangent, normal));
+
+ gl_Position = gl_ModelViewMatrix * vec4(pos + normal*foamOffset + vec3(0.0f, foamOffset3, 0.0f), 1.0); // eye space
+ vec3 eyeVec = normalize(gl_Position.xyz);
+ gl_Position.xyz -= eyeVec*foamOffset2;
+ gl_TexCoord[0] = gl_MultiTexCoord2 * foamFactor;
+ gl_TexCoord[1] = gl_ModelViewMatrix * vec4(tangent, 0.0);
+ gl_TexCoord[2] = gl_ModelViewMatrixInverseTranspose * vec4(normal, 0.0);
+ gl_TexCoord[3] = gl_ModelViewMatrix * vec4(bitangent, 0.0);
+
+ gl_TexCoord[0].w = max(0.0f, min(gl_MultiTexCoord3.x, 0.1))*10;// Fade with life time
+ gl_FrontColor = gl_Color;
+}
+);
+
+const char *particleDumbFoamGS = STRINGIFY(
+//#version 120\n
+//#extension GL_EXT_geometry_shader4 : enable\n
+uniform float pointRadius; // point size in world space
+uniform float densityThreshold = 500.0;
+uniform float pointShrink = 0.25;
+uniform float foamTexSize = 0.249;
+void main()
+{
+ gl_FrontColor = gl_FrontColorIn[0];
+ // eye space
+ vec3 pos = gl_PositionIn[0].xyz;
+ vec3 x = pointRadius*gl_TexCoordIn[0][1].xyz;
+ vec3 normal = gl_TexCoordIn[0][2].xyz;
+ vec3 y = -pointRadius*gl_TexCoordIn[0][3].xyz;
+
+
+
+ gl_TexCoord[0] = gl_TexCoordIn[0][0]+vec4(0, 0, 0, 0);
+ gl_TexCoord[1] = vec4(normal, gl_TexCoordIn[0][0].w);
+ gl_TexCoord[2] = vec4(pos + x + y, 1);
+ gl_TexCoord[3] = vec4(1, 1, 0, 0);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ EmitVertex();
+
+ gl_TexCoord[0] = gl_TexCoordIn[0][0]+vec4(0, foamTexSize, 0, 0);
+ gl_TexCoord[2] = vec4(pos + x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = vec4(1, -1, 0, 0);
+ EmitVertex();
+
+ gl_TexCoord[0] = gl_TexCoordIn[0][0]+vec4(foamTexSize, 0, 0, 0);
+ gl_TexCoord[2] = vec4(pos - x + y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = vec4(-1, 1, 0, 0);
+ EmitVertex();
+
+ gl_TexCoord[0] = gl_TexCoordIn[0][0]+vec4(foamTexSize, foamTexSize, 0, 0);
+ gl_TexCoord[2] = vec4(pos - x - y, 1);
+ gl_Position = gl_ProjectionMatrix * gl_TexCoord[2];
+ gl_TexCoord[3] = vec4(-1, -1, 0, 0);
+ EmitVertex();
+
+}
+);
+
+const char *particleDumbFoamPS = STRINGIFY(
+uniform float pointRadius;
+uniform vec3 lightDir;
+uniform sampler2D foamTex;
+uniform sampler2DArrayShadow stex;
+float shadowCoef()
+{
+ const int index = 0;
+ /*
+ int index = 3;
+
+ // find the appropriate depth map to look up in based on the depth of this fragment
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ */
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[2].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+uniform float foamAmbient = 0.8f;
+uniform float foamDiffuse = 0.2f;
+void main()
+{
+ // calculate eye-space normal from texture coordinates
+
+ float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[2].z), 0.0, 1.0);
+ float mag = clamp(1.1-dot(gl_TexCoord[3].xy,gl_TexCoord[3].xy),0,1);
+
+
+ gl_FragColor.xyz = mix(gl_Fog.color, gl_Color*(foamAmbient + (foamDiffuse*max(dot(gl_TexCoord[1].xyz, lightDir),0.0f) )*shadowCoef()), fog);//*falloff;
+ gl_FragColor.w = /*texture2D(foamTex, gl_TexCoord[0]).r**/gl_Color.w*mag*gl_TexCoord[1].w;
+//
+
+}
+);
+
+const char *particleFoamPS = STRINGIFY(
+uniform float pointRadius;
+uniform vec3 lightDir;
+uniform sampler2D foamTex;
+uniform sampler2DArrayShadow stex;
+float shadowCoef()
+{
+ const int index = 0;
+ /*
+ int index = 3;
+
+ // find the appropriate depth map to look up in based on the depth of this fragment
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ */
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[2].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+uniform float foamAmbient = 0.5f;
+uniform float foamDiffuse = 0.5f;
+void main()
+{
+ // calculate eye-space normal from texture coordinates
+
+ //float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[2].z), 0.0, 1.0);
+ float mag = clamp(1.1-dot(gl_TexCoord[3].xy,gl_TexCoord[3].xy),0,1);
+
+
+ gl_FragColor.xyz = gl_Color*(
+ foamAmbient + (foamDiffuse*abs(dot(gl_TexCoord[1].xyz, lightDir)))*shadowCoef()
+ );//*falloff;
+ gl_FragColor.w = /*texture2D(foamTex, gl_TexCoord[0]).r**/gl_Color.w*mag*gl_TexCoord[1].w;
+//
+
+}
+);
+
+// screen-space shaders
+const char *passThruVS = STRINGIFY(
+void main()
+{
+ gl_Position = gl_Vertex;
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+ gl_TexCoord[1] = gl_Vertex;
+ gl_FrontColor = gl_Color;
+}
+);
+
+// blur depth map
+// separable version
+const char *depthBlurPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+sampler2DRect colorTex;
+uniform vec2 scale = 1.0;
+const float r = 10.0;
+uniform float blurScale = 2.0 / r;
+uniform float blurDepthFalloff = 2.0;
+uniform float depthThreshold = 0.5;
+void main()
+{
+ float center = texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+ if (center < -9999.0) {
+ // skip background pixels
+ discard;
+ return;
+ }
+
+ float sum = 0;
+ float wsum = 0;
+ for(float x=-r; x<=r; x+=1.0) {
+ float sample = texture2DRect(colorTex, gl_TexCoord[0].xy + x*scale).x;
+
+ // bilateral filter
+ // spatial domain
+ float r = x * blurScale;
+ float w = exp(-r*r);
+ //float w = 1.0;
+
+ // range domain (based on depth difference)
+ float r2 = (sample - center) * blurDepthFalloff;
+ //float g = 1.0;
+ float g = exp(-r2*r2);
+ //float g = abs(sample - center) < depthThreshold;
+
+ sum += sample * w * g;
+ wsum += w * g;
+ }
+
+ if (wsum > 0.0) {
+ sum /= wsum;
+ }
+ gl_FragColor.x = sum;
+}
+);
+
+// 2D non-separable version
+const char *depthBlur2DPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+sampler2DRect colorTex;
+uniform vec2 scale = 1.0;
+const float r = 10.0;
+uniform float blurScale = 2.0 / r;
+uniform float blurDepthFalloff = 1.0;
+uniform float depthThreshold = 0.1;
+void main()
+{
+ float center = texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+ if (center < -9999.0) {
+ discard;
+ return;
+ }
+
+ float sum = 0;
+ float wsum = 0;
+ for(float y=-r; y<=r; y+=1.0) {
+ for(float x=-r; x<=r; x+=1.0) {
+ float sample = texture2DRect(colorTex, gl_TexCoord[0].xy + vec2(x, y)).x;
+
+ // bilateral filter
+ // spatial domain
+ //float r = length(vec2(x, y)) * blurScale;
+ // float w = exp(-r*r);
+ float rsq = (x*x + y*y) * blurScale * blurScale;
+ float w = exp(-rsq);
+ //float w = 1.0;
+
+ // range domain (based on depth difference)
+ float r2 = (sample - center) * blurDepthFalloff;
+ //float g = 1.0;
+ float g = exp(-r2*r2);
+// float g = abs(sample - center) < depthThreshold;
+
+ sum += sample * w * g;
+ wsum += w * g;
+ }
+ }
+
+ if (wsum > 0.0) {
+ sum /= wsum;
+ }
+ gl_FragColor.x = sum;
+}
+);
+
+// symmetrical filter (see "Screen Space Meshes" paper)
+const char *depthBlurSymPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+sampler2DRect colorTex;
+uniform vec2 scale = 1.0;
+const float r = 10.0;
+uniform float blurScale = 2.0;
+uniform float blurDepthFalloff = 2.0;
+uniform float depthThreshold = 0.25;
+void main()
+{
+ float center = texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+ if (center == 0.0) {
+ discard; return;
+ }
+
+ float sum = center;
+ float wsum = 1.0;
+
+ for(float x=1.0; x<=r; x+=1.0) {
+ float sample = texture2DRect(colorTex, gl_TexCoord[0].xy + x*scale).x;
+ float sample2 = texture2DRect(colorTex, gl_TexCoord[0].xy - x*scale).x;
+
+ bool valid = abs(sample - center) < depthThreshold;
+ bool valid2 = abs(sample2 - center) < depthThreshold;
+
+ if (valid && valid2) {
+ float r = (x / r) * blurScale;
+ float w = exp(-r*r);
+
+ sum += sample * w;
+ wsum += w;
+
+ sum += sample2 * w;
+ wsum += w;
+ }
+ }
+
+ if (wsum > 0.0) {
+ sum /= wsum;
+ }
+ gl_FragColor.x = sum;
+}
+);
+
+// display final shaded surface
+const char *displaySurfacePS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect colorTex;
+uniform sampler2DRect depthTex;
+uniform sampler2DRect thicknessTex;
+uniform sampler2DRect sceneTex;
+uniform samplerCube cubemapTex;
+
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform vec2 invViewport = vec2(1.0 / 800, 1.0 / 600);
+uniform float2 invFocalLen;
+uniform float depthThreshold = 0.1;
+uniform float shininess = 40.0;
+uniform vec4 fluidColor = vec4(0.5, 0.7, 1.0, 0.0);
+
+uniform vec4 colorFalloff = vec4(2.0, 1.0, 0.5, 1.0);
+uniform vec4 specularColor = vec4(1.0, 1.0, 1.0, 1.0);
+//uniform vec4 specularColor = vec4(0.25, 0.25, 0.25, 1.0);
+
+uniform float falloffScale = 0.3;
+//uniform float falloffScale = 0.1;
+uniform vec3 thicknessRefraction = vec3(2.0, 2.3, 2.6);
+uniform float subSample = 1;
+
+uniform float fresnelBias = 0.1;
+uniform float fresnelScale = 0.4;
+uniform float fresnelPower = 2.0; // 5.0 is physically correct
+
+// convert [0,1] uv coords and eye-space Z to eye-space position
+vec3 uvToEye(vec2 uv, float eyeZ)
+{
+ uv = uv * vec2(-2.0, -2.0) - vec2(-1.0, -1.0);
+ return vec3(uv * invFocalLen * eyeZ, eyeZ);
+}
+
+vec3 getEyePos(sampler2DRect tex, vec2 texCoord)
+{
+ float eyeZ = texture2DRect(tex, texCoord).x;
+ return uvToEye(texCoord*invViewport, eyeZ);
+}
+
+void main()
+{
+ float c = texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+ if (c < -9999.0) {
+ discard;
+ return;
+ }
+
+ // calculate normal
+ // taking silohette edges into account
+ vec2 uv = gl_TexCoord[0].xy * invViewport;
+ vec3 eyePos = uvToEye(uv, c);
+
+ vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - eyePos;
+ if (abs(ddx.z) > depthThreshold) {
+ ddx = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+ }
+
+ vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - eyePos;
+ if (abs(ddy.z) > depthThreshold) {
+ ddy = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+ }
+
+ vec3 n = cross(ddx, ddy);
+ n = normalize(n);
+
+ // lighting
+// float diffuse = max(0.0, dot(n, lightDir));
+ float diffuse = dot(n, lightDir)*0.5+0.5; // wrap lighting
+
+ vec3 v = normalize(-eyePos);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(n, h)), shininess);
+
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(n, v)), fresnelPower);
+
+ // cubemap
+ vec3 r = reflect(-v, n);
+ r = r * gl_NormalMatrix;
+ vec4 reflectColor = textureCube(cubemapTex, r);
+
+ // color attenuation based on thickness
+ float thickness = texture2DRect(thicknessTex, gl_TexCoord[0].xy * subSample).x;
+ vec4 attenuatedColor = fluidColor * exp(-thickness*falloffScale*colorFalloff);
+// vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff);
+
+ // refraction
+ float refraction = thickness*thicknessRefraction.x;
+ vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+/*
+ // dispersive refraction
+ vec3 refraction = thickness*thicknessRefraction;
+ vec4 sceneCol;
+ sceneCol.r = texture2DRect(sceneTex, gl_TexCoord[0].xy + (n.xy * refraction.x)).r;
+ sceneCol.g = texture2DRect(sceneTex, gl_TexCoord[0].xy + (n.xy * refraction.y)).g;
+ sceneCol.b = texture2DRect(sceneTex, gl_TexCoord[0].xy + (n.xy * refraction.z)).b;
+ sceneCol.a = 1.0;
+*/
+
+ vec4 finalCol = vec4(attenuatedColor.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+ float alpha = saturate(attenuatedColor.w);
+
+// gl_FragColor = -c.z;
+// gl_FragColor = vec4(n*0.5+0.5, 1.0);
+// gl_FragColor = vec4(diffuse.xxx, 1.0);
+// gl_FragColor = vec4(specular.xxx, 1.0);
+// gl_FragColor = vec4(fresnel.xxx, 1.0);
+// gl_FragColor = diffuse*fluidColor + specular;
+// gl_FragColor = vec4(eyePos*0.5+0.5, 1.0);
+// gl_FragColor = thickness;
+// gl_FragColor = vec4(attenuatedColor.xyz, 1.0);
+// gl_FragColor = attenuatedColor.w;
+// gl_FragColor = alpha;
+
+ gl_FragColor = lerp(finalCol, sceneCol, alpha);
+
+// gl_FragColor = sceneCol*attenuatedColor + reflectColor*fresnel + specularColor*specular;
+
+// gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy).x;
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * subSample).x;
+ //gl_FragColor.w = 1.0;
+}
+);
+
+// new version (handles transparency differently)
+const char *displaySurfaceNewPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect colorTex;
+uniform sampler2DRect depthTex;
+uniform sampler2DRect thicknessTex;
+uniform sampler2DRect sceneTex;
+uniform samplerCube cubemapTex;
+
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform vec2 invViewport = vec2(1.0 / 800, 1.0 / 600);
+uniform float2 invFocalLen;
+uniform float depthThreshold = 0.1;
+uniform float shininess = 40.0;
+uniform vec4 fluidColor = vec4(0.5, 0.7, 1.0, 0.0);
+
+uniform vec4 colorFalloff = vec4(2.0, 1.0, 0.5, 1.0);
+uniform vec4 specularColor = vec4(0.5, 0.5, 0.5, 1.0);
+
+uniform float falloffScale = 0.01;
+uniform vec3 thicknessRefraction = vec3(2.0, 2.1, 2.2);
+uniform float subSample = 1;
+
+uniform float fresnelBias = 0.1;
+uniform float fresnelScale = 0.4;
+uniform float fresnelPower = 2.0; // 5.0 is physically correct
+
+// convert [0,1] uv coords and eye-space Z to eye-space position
+vec3 uvToEye(vec2 uv, float eyeZ)
+{
+ uv = uv * vec2(-2.0, -2.0) - vec2(-1.0, -1.0);
+ return vec3(uv * invFocalLen * eyeZ, eyeZ);
+}
+
+vec3 getEyePos(sampler2DRect tex, vec2 texCoord)
+{
+ float eyeZ = texture2DRect(tex, texCoord).x;
+ return uvToEye(texCoord*invViewport, eyeZ);
+}
+
+void main()
+{
+ float c = texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+ if (c < -9999.0) {
+ discard;
+ return;
+ }
+
+ // calculate normal
+ // taking silohette edges into account
+ vec2 uv = gl_TexCoord[0].xy * invViewport;
+ vec3 eyePos = uvToEye(uv, c);
+
+ vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - eyePos;
+ if (abs(ddx.z) > depthThreshold) {
+ ddx = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+ }
+
+ vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - eyePos;
+ if (abs(ddy.z) > depthThreshold) {
+ ddy = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+ }
+
+ vec3 n = cross(ddx, ddy);
+ n = normalize(n);
+
+ // lighting
+// float diffuse = max(0.0, dot(n, lightDir));
+ float diffuse = dot(n, lightDir)*0.5+0.5; // wrap lighting
+
+ vec3 v = normalize(-eyePos);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(n, h)), shininess);
+
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(n, v)), fresnelPower);
+
+ // cubemap
+ vec3 r = reflect(-v, n);
+ r = r * gl_NormalMatrix;
+ vec4 reflectColor = textureCube(cubemapTex, r);
+
+ // color attenuation based on thickness
+ float thickness = texture2DRect(thicknessTex, gl_TexCoord[0].xy * subSample).x;
+ vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff);
+
+ // refraction
+// float refraction = thickness*thicknessRefraction.x;
+// vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+
+ // dispersive refraction
+ vec3 refraction = thickness*thicknessRefraction;
+ vec4 sceneCol;
+ sceneCol.r = texture2DRect(sceneTex, gl_TexCoord[0].xy + (n.xy * refraction.x)).r;
+ sceneCol.g = texture2DRect(sceneTex, gl_TexCoord[0].xy + (n.xy * refraction.y)).g;
+ sceneCol.b = texture2DRect(sceneTex, gl_TexCoord[0].xy + (n.xy * refraction.z)).b;
+ sceneCol.a = 1.0;
+
+ gl_FragColor = sceneCol*attenuatedColor + reflectColor*fresnel + specularColor*specular;
+
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * subSample).x;
+}
+);
+
+// non-transparent version for oil etc.
+const char *displaySurfaceSolidPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect colorTex;
+uniform sampler2DRect depthTex;
+uniform samplerCube cubemapTex;
+
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform vec2 invViewport = vec2(1.0 / 800, 1.0 / 600);
+uniform float2 invFocalLen;
+uniform float depthThreshold = 0.1;
+uniform float shininess = 40.0;
+uniform vec4 diffuseColor = vec4(0.0, 0.0, 0.0, 0.0);
+uniform vec4 specularColor = vec4(0.75, 0.75, 0.75, 1.0);
+
+uniform float subSample = 1;
+
+uniform float fresnelBias = 0.1;
+uniform float fresnelScale = 0.4;
+uniform float fresnelPower = 2.0; // 5.0 is physically correct
+
+// convert [0,1] uv coords and eye-space Z to eye-space position
+vec3 uvToEye(vec2 uv, float eyeZ)
+{
+ uv = uv * vec2(-2.0, -2.0) - vec2(-1.0, -1.0);
+ return vec3(uv * invFocalLen * eyeZ, eyeZ);
+}
+
+vec3 getEyePos(sampler2DRect tex, vec2 texCoord)
+{
+ float eyeZ = texture2DRect(tex, texCoord).x;
+ return uvToEye(texCoord*invViewport, eyeZ);
+}
+
+void main()
+{
+ float c = texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+ if (c < -9999.0) {
+ discard;
+ return;
+ }
+
+ // calculate normal
+ // taking silohette edges into account
+ vec2 uv = gl_TexCoord[0].xy * invViewport;
+ vec3 eyePos = uvToEye(uv, c);
+
+ vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - eyePos;
+ if (abs(ddx.z) > depthThreshold) {
+ ddx = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+ }
+
+ vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - eyePos;
+ if (abs(ddy.z) > depthThreshold) {
+ ddy = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+ }
+
+ vec3 n = cross(ddx, ddy);
+ n = normalize(n);
+
+ // lighting
+ float diffuse = max(0.0, dot(n, lightDir));
+// float diffuse = dot(n, lightDir)*0.5+0.5; // wrap lighting
+
+ vec3 v = normalize(-eyePos);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(n, h)), shininess);
+
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(n, v)), fresnelPower);
+
+ // cubemap
+ vec3 r = reflect(-v, n);
+ r = r * gl_NormalMatrix;
+ vec4 reflectColor = textureCube(cubemapTex, r);
+
+ gl_FragColor = diffuseColor*diffuse + reflectColor*fresnel + specularColor*specular;
+
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * subSample).x;
+}
+);
+
+// chrome surface using cubemap
+const char *displaySurfaceChromePS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect colorTex;
+uniform sampler2DRect depthTex;
+uniform samplerCube cubemapTex;
+
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform vec2 invViewport = vec2(1.0 / 800, 1.0 / 600);
+uniform float2 invFocalLen;
+uniform float depthThreshold = 0.1;
+uniform float shininess = 40.0;
+uniform vec4 fluidColor = vec4(0.5, 0.7, 1.0, 0.0);
+uniform float subSample = 1;
+
+// convert [0,1] uv coords and eye-space Z to eye-space position
+vec3 uvToEye(vec2 uv, float eyeZ)
+{
+ uv = uv * vec2(-2.0, -2.0) - vec2(-1.0, -1.0);
+ return vec3(uv * invFocalLen * eyeZ, eyeZ);
+}
+
+vec3 getEyePos(sampler2DRect tex, vec2 texCoord)
+{
+ float eyeZ = texture2DRect(tex, texCoord).x;
+ return uvToEye(texCoord*invViewport, eyeZ);
+}
+
+void main()
+{
+ float c = texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+ if (c < -9999.0) {
+ discard;
+ return;
+ }
+
+ // calculate normal
+ // taking silohette edges into account
+ vec2 uv = gl_TexCoord[0].xy * invViewport;
+ vec3 eyePos = uvToEye(uv, c);
+
+ vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - eyePos;
+ vec3 ddx2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+// if (abs(ddx.z) > abs(ddx2.z)) {
+ if (abs(ddx.z) > depthThreshold) {
+ ddx = ddx2;
+ }
+
+ vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - eyePos;
+ vec3 ddy2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+// if (abs(ddy2.z) < abs(ddy.z)) {
+ if (abs(ddy.z) > depthThreshold) {
+ ddy = ddy2;
+ }
+
+ vec3 n = cross(ddx, ddy);
+ n = normalize(n);
+
+ // lighting
+ float diffuse = max(0.0, dot(n, lightDir));
+// float diffuse = dot(n, lightDir)*0.5+0.5; // wrap lighting
+
+// vec3 v = vec3(0, 0, 1);
+ vec3 v = normalize(-eyePos);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(n, h)), shininess);
+
+// float fresnel = pow(1.0 - max(0.0, dot(n, v)), 5.0);
+ float fresnel = 0.2 + 0.8*pow(1.0 - max(0.0, dot(n, v)), 2.0);
+ //float fresnel = 1.0 - max(0.0, dot(n, v));
+
+ // cubemap
+ vec3 r = reflect(-v, n);
+// r = (mat3) gl_ModelViewMatrixInverse * r;
+ r = r * gl_NormalMatrix;
+ vec4 reflectColor = textureCube(cubemapTex, r);
+
+// gl_FragColor = reflectColor * fresnel;
+ gl_FragColor = reflectColor * (0.5 + 0.5*diffuse);
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * subSample).x;
+}
+);
+
+
+const char *textureRectPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect tex;
+
+void main()
+{
+ gl_FragColor = texture2DRect(tex, gl_TexCoord[0].xy);
+}
+);
+
+// dilate depth image by taking maximum value of neighbourhood
+const char *dilatePS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect tex;
+
+void main()
+{
+ float c = texture2DRect(tex, gl_TexCoord[0].xy).x;
+ if (c < -9999.0) {
+ c = max(c, texture2DRect(tex, gl_TexCoord[0].xy + vec2(1, 0)).x);
+ c = max(c, texture2DRect(tex, gl_TexCoord[0].xy + vec2(1, 1)).x);
+ c = max(c, texture2DRect(tex, gl_TexCoord[0].xy + vec2(0, 1)).x);
+
+ //c = max(c, texture2DRect(tex, gl_TexCoord[0].xy + vec2(-1, 0)).x);
+ //c = max(c, texture2DRect(tex, gl_TexCoord[0].xy + vec2(1, 0)).x);
+ //c = max(c, texture2DRect(tex, gl_TexCoord[0].xy + vec2(0, -1)).x);
+ //c = max(c, texture2DRect(tex, gl_TexCoord[0].xy + vec2(0, 1)).x);
+ }
+
+ gl_FragColor = c;
+}
+);
+
+// NUTT
+// Water heightfield thickness vertex shader
+const char *hfThicknessVS = STRINGIFY(
+uniform float zMax;
+void main()
+{
+ vec4 eyeSpacePos = gl_ModelViewMatrix * vec4(gl_Vertex.xyz,1);
+
+
+ vec4 eyeNormal = gl_ModelViewMatrixInverseTranspose * vec4(gl_Normal.xyz,0);
+ //gl_TexCoord[0] = vec4(eyeSpacePos.xyz,0); // sprite texcoord
+
+ //float tc = 0.1*(zFar + eyeSpacePos.z);
+ float dis = sqrt(dot(eyeSpacePos,eyeSpacePos));
+ float tc = (zMax-dis);
+ //gl_FrontColor = vec4(tc,tc,-tc,1);
+ //gl_BackColor = vec4(-tc,-tc,-tc,1);
+ //float tc = 0.1;
+
+ if (dot(eyeNormal.xyz,eyeSpacePos.xyz) > 0) {
+ gl_TexCoord[0] = vec4(tc,tc,tc,1);
+ } else
+ {
+ gl_TexCoord[0]= vec4(-tc,-tc,-tc,1);
+
+ }
+ gl_Position = gl_ProjectionMatrix * eyeSpacePos;
+ //gl_BackColor = vec4(1,1,1,1);//vec4(-1000,-1000,-1000,1);//vec4(-2*tc,-2*tc,-2*tc,1);
+}
+);
+
+
+// Water heightfield thickness PS
+const char *hfThicknessPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+void main()
+{
+
+ gl_FragColor = gl_TexCoord[0];
+ //gl_FragColor = gl_Color;
+ //gl_FragColor = (
+}
+);
+
+// Water heightfield thickness PS
+const char *hfThicknessAddPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect thicknessTex;
+void main()
+{
+ // Add contribution of heightfield fluid thickness to particle thickness
+ vec4 col = texture2DRect(thicknessTex, gl_TexCoord[0].xy);
+ col.x = max(col.x, 0.0);
+ //col.x*=-1;
+ /*
+ if (col.x > 10) {
+ gl_FragColor = vec4(0,0,0,1);
+ } else { */
+ gl_FragColor = vec4(col.x,col.x,col.x,1);
+ //}
+}
+);
+// Water heightfield depth vertex shader
+const char *hfDepthVS = STRINGIFY(
+void main()
+{
+ vec4 eyeSpacePos = gl_ModelViewMatrix * gl_Vertex;
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ gl_TexCoord[0] = vec4(eyeSpacePos.xyz,0); // sprite texcoord
+
+}
+);
+// Water heightfield depth PS
+const char *hfDepthPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+ void main()
+{
+ gl_FragColor = vec4(gl_TexCoord[0].z,gl_TexCoord[0].z,gl_TexCoord[0].z,1);
+}
+);
+
+// Turn depth map to distance from eye and subtract
+const char *depthToInitThicknessPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect depthTex;
+uniform float zNear;
+uniform float zFar;
+uniform float mulX;
+uniform float mulY;
+uniform float zMax;
+
+void main()
+{
+ float glDepth = texture2DRect(depthTex, gl_TexCoord[0].xy).x;
+ float eyeDepth = zNear*zFar / (zFar - glDepth*(zFar-zNear));
+ gl_FragDepth = glDepth;
+ //gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy).x;
+ //gl_FragColor = vec4(gl_FragDepth,gl_FragDepth,gl_FragDepth,1);
+ //float val = 0.001*(-(zFar - eyeDepth));
+ //float val = -(zFar-eyeDepth)*0.1;
+ vec3 eyePos = vec3(gl_TexCoord[1].x*eyeDepth*mulX, gl_TexCoord[1].y*eyeDepth*mulY, eyeDepth);
+
+ float val = -(zMax-sqrt(dot(eyePos,eyePos)));
+ gl_FragColor = vec4( val,val,val, 1);
+
+
+}
+);
+
+// Debug PS
+const char *debugPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect thicknessTex;
+
+void main()
+{
+ vec4 col = texture2DRect(thicknessTex, gl_TexCoord[0].xy);
+
+ col.x*=-0.01;
+// if (col.x > 1) {
+// gl_FragColor = vec4(1,0,0,1);
+// } else {
+ gl_FragColor = vec4(col.x,col.x,col.x,1);
+// }
+ //gl_FragColor = vec4(1,0,1,1);
+}
+);
+
+
+// Debug Triangle VS
+const char *debugTriVS = STRINGIFY(
+void main()
+{
+ vec4 eyeSpacePos = gl_ModelViewMatrix * gl_Vertex;
+ vec4 eyeSpaceNormal = gl_ModelViewMatrixInverseTranspose * vec4(gl_Normal.xyz,1);
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ vec3 eyeVec = normalize(eyeSpacePos.xyz);
+ float dp = dot(eyeSpaceNormal.xyz,eyeVec.xyz);
+
+ if (dp > 0) {
+ gl_FrontColor = vec4(dp,0,0,1);
+ } else {
+ gl_FrontColor = vec4(0,-dp,0,1);
+ }
+}
+);
+const char *copyPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform sampler2DRect depthTex;
+uniform sampler2DRect sceneTex;
+void main()
+{
+ gl_FragColor = texture2DRect(sceneTex, gl_TexCoord[0].xy);
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy).x;
+}
+);
+
+
+// Debug Triangle PS
+const char *debugTriPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+void main()
+{
+ gl_FragColor = gl_Color;
+}
+);
+
+// display final shaded surface Nuttapong's mod
+const char *displaySurfaceNutPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform vec2 colorTexScale;
+uniform sampler2DArrayShadow stex;
+uniform sampler2DRect colorTex;
+uniform sampler2DRect depthTex;
+uniform sampler2DRect thicknessTex;
+uniform sampler2DRect sceneTex;
+uniform samplerCube cubemapTex;
+
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform vec2 invViewport = vec2(1.0 / 800, 1.0 / 600);
+uniform float2 invFocalLen;
+uniform float depthThreshold = 0.01;
+uniform float shininess = 40.0;
+//uniform vec4 fluidColor = vec4(0.5, 0.7, 1.0, 0.0);
+uniform vec4 fluidColor = vec4(17/255.0, 52/255.0, 71/255.0, 0.0);
+
+uniform vec4 colorFalloff = vec4(2.0, 1.0, 0.5, 1.0);
+uniform vec4 specularColor = vec4(0.7, 0.7, 0.7, 1.0);
+//uniform vec4 specularColor = vec4(0.25, 0.25, 0.25, 1.0);
+
+uniform float falloffScale = 0.03;
+//uniform float falloffScale = 0.1;
+uniform vec3 thicknessRefraction = vec3(2.0, 2.3, 2.6);
+uniform float subSample = 1;
+
+uniform float fresnelBias = 0.0;
+uniform float fresnelScale = 1.0;
+uniform float fresnelPower = 2.0; // 5.0 is physically correct
+uniform float shadowAmbient = 0.9;
+uniform float splashZShadowBias = 0.001f;
+uniform float refracMultiplier = 1.0;
+
+uniform float epsilon = 0.0001f;
+uniform float thicknessAlphaMul = 3.0f;
+uniform float decayRate = 1.0f;
+// convert [0,1] uv coords and eye-space Z to eye-space position
+vec3 uvToEye(vec2 uv, float eyeZ)
+{
+ uv = uv * vec2(-2.0, -2.0) - vec2(-1.0, -1.0);
+ return vec3(uv * invFocalLen * eyeZ, eyeZ);
+}
+
+vec3 getEyePos(sampler2DRect tex, vec2 texCoord)
+{
+ float eyeZ = texture2DRect(tex, texCoord*colorTexScale).x;
+ return uvToEye(texCoord*invViewport, eyeZ);
+}
+float shadowCoef(float3 eyePos)
+{
+ const int index = 0;
+ /*
+ int index = 3;
+
+ // find the appropriate depth map to look up in based on the depth of this fragment
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ */
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(eyePos.x, eyePos.y, eyePos.z,1);
+
+ shadow_coord.w = shadow_coord.z + splashZShadowBias;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+
+void main()
+{
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+
+ //return;
+ float c = texture2DRect(colorTex, gl_TexCoord[0].xy*colorTexScale).x;
+ if (c < -9999.0) {
+ discard;
+ return;
+ }
+
+ // calculate normal
+ // taking silohette edges into account
+ vec2 uv = gl_TexCoord[0].xy * invViewport;
+ vec3 eyePos = uvToEye(uv, c);
+
+
+ vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - eyePos;
+ vec3 ddx2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+
+
+ vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - eyePos;
+ vec3 ddy2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+
+ float thickness = texture2DRect(thicknessTex, gl_TexCoord[0].xy * subSample).x;
+ float refBlend = 0.0f;
+ float maxDz = max(max(abs(ddx.z),abs(ddx2.z)), max(abs(ddy.z),abs(ddy2.z)));
+ if (maxDz > depthThreshold) {
+ refBlend = 1.0f - exp((depthThreshold - maxDz)*decayRate);
+ }
+
+// if (abs(ddx.z) > abs(ddx2.z)) {
+ //if (abs(ddx.z) > depthThreshold) {
+ if (abs(ddx2.z) < abs(ddx.z)) {
+ ddx = ddx2;
+ }
+ //}
+ // if (abs(ddy2.z) < abs(ddy.z)) {
+ //if (abs(ddy.z) > depthThreshold) {
+ if (abs(ddy2.z) < abs(ddy.z)) {
+ ddy = ddy2;
+ }
+ //}
+
+
+ ddx.x += epsilon;
+ ddy.y += epsilon;
+
+
+ //vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+ //vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+ //ddx.z = clamp(ddx.z, -depthThreshold, depthThreshold);
+ //ddy.z = clamp(ddy.z, -depthThreshold, depthThreshold);
+
+ // color attenuation based on thickness
+
+
+ //ddx = normalize(ddx);
+ //ddy = normalize(ddy);
+ //if (depthThreshold < 0.001f) {
+ // vec3 nn = cross(ddx, ddy);
+ //gl_FragColor = vec4(sqrt(dot(ddx,ddx)), sqrt(dot(ddy, ddy)), sqrt(dot(nn,nn)), 1.0f);
+ // gl_FragColor = vec4(10.0f*sqrt(dot(nn,nn)), 0.0f, 0.0f, 1.0f);
+ // return;
+ //}
+
+ //ddx.z = clamp(ddx.z, -depthThreshold, depthThreshold);
+ //ddy.z = clamp(ddy.z, -depthThreshold, depthThreshold);
+
+ vec3 n = normalize(cross(ddx, ddy));
+
+
+ // lighting
+ // float diffuse = max(0.0, dot(n, lightDir));
+ float diffuse = dot(n, lightDir)*0.5+0.5; // wrap lighting
+
+ vec3 v = normalize(-eyePos);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(n, h)), shininess*10);
+
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(n, v)), fresnelPower);
+
+ // cubemap
+ vec3 r = reflect(-v, n);
+ r = r * gl_NormalMatrix;
+ vec4 reflectColor = textureCube(cubemapTex, r);
+
+
+ // vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff);
+
+ // refraction
+ // -----------------
+ // Pond
+ //vec4 attenuatedColor = fluidColor * exp(-thickness*falloffScale*colorFalloff);
+ //float refracMultiplier = 1;
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+
+ // Whirlpool
+ //float refracMultiplier = 0.1;
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+ //vec3 blendFactor = vec3(1,1,1)+2*thickness*falloffScale*vec3(1,1,1);
+
+ //blendFactor = min(blendFactor, vec3(1,1,1));
+ //blendFactor = max(blendFactor, vec3(0,0,0));
+ //sceneCol.xyz = lerp(vec3(0.13, 0.19, 0.22), sceneCol.xyz, blendFactor);
+
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+
+ // FERMI
+ float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+
+ reflectColor = (1.0f-refBlend)*reflectColor + refBlend*sceneCol;
+
+// colorFalloff = vec4(0.5, 0.5, 0.5, 1.0);
+ vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff*10.0);
+ //vec3 blendFactor = vec3(1,1,1)+2*thickness*falloffScale*vec3(1,1,1);
+ //blendFactor = min(0.5, blendFactor);
+
+ //blendFactor = min(blendFactor, vec3(1,1,1));
+ //blendFactor = max(blendFactor, vec3(0,0,0));
+ //fluidColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
+ //fluidColor = vec4(28/255.0, 69/255.0, 89/255.0, 0.0);
+ //fluidColor = vec4(17/255.0, 52/255.0, 71/255.0, 0.0);
+ sceneCol.xyz = lerp(fluidColor, sceneCol.xyz, attenuatedColor);
+ //sceneCol = fluidColor;
+ //sceneCol.xyz = vec3(0.0f,0.0f,0.0f);
+
+
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel /*+ specularColor.xyz*specular*/, 1.0);
+ float shadow = shadowCoef(eyePos);
+ float sc = (1.0f - shadowAmbient)*shadow + shadowAmbient;
+ vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular*shadow*0.9, 1.0);
+
+ gl_FragColor = vec4(finalCol.xyz*(sc), max(0.0f, min(1.0, thicknessAlphaMul*thickness/*2.0f*(gl_TexCoord[1].w+waterHOffset)*/)));
+
+// gl_FragColor = finalCol;
+// gl_FragColor.w = max(0.0f, min(1.0, 3.0f*thickness));
+
+ /*
+ vec4 sceneSeethroughCol = texture2DRect(sceneTex, gl_TexCoord[0].xy);
+
+
+ //----------------
+ float thickPar = 0.0000001;
+ float blendBackground = max(0.0, min(1.0f, -thickness / thickPar));
+
+
+ gl_FragColor = (blendBackground)*finalCol + (1.0-blendBackground)*sceneSeethroughCol;
+ if (thickness < 0) gl_FragColor = vec4(1.0f,0.0f,0.0f,1.0f); else */
+ //gl_FragColor = finalCol;
+ // gl_FragColor = sceneCol*attenuatedColor + reflectColor*fresnel + specularColor*specular;
+
+ // gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy).x;
+ float fog = clamp(gl_Fog.scale*(gl_Fog.end+eyePos.z), 0.0, 1.0);
+ //float fog = exp(-gl_Fog.density*(eyePos.z*eyePos.z));
+
+ gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);
+
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * colorTexScale).x;
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+ //return;
+
+ //gl_FragColor.w = max(0.0, min((thickness)*5.0, 1.0));
+ //gl_FragColor.w = 1.0;
+
+ //gl_FragColor = vec4(n.z, n.z, n.z, 1);
+}
+);
+
+
+
+// render particle as lit sphere
+const char *particleBubblePS = STRINGIFY(
+ uniform float pointRadius;
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform samplerCube cubemapTex;
+uniform sampler2DRect sceneTex;
+
+uniform vec2 viewportd2 = vec2(300,300);
+uniform float shininess = 40.0;
+uniform vec4 fluidColor = vec4(0.5, 0.7, 1.0, 0.0);
+
+uniform vec4 colorFalloff = vec4(2.0, 1.0, 0.5, 1.0);
+uniform vec4 specularColor = vec4(0.5, 0.5, 0.5, 1.0);
+//uniform vec4 specularColor = vec4(0.25, 0.25, 0.25, 1.0);
+
+uniform float falloffScale = 0.3;
+//uniform float falloffScale = 0.1;
+uniform vec3 thicknessRefraction = vec3(2.0, 2.3, 2.6);
+uniform float subSample = 1;
+
+uniform float fresnelBias = 0;
+uniform float fresnelScale = 0.4;
+uniform float fresnelPower = 2.0; // 5.0 is physically correct
+void main()
+{
+ // calculate eye-space sphere normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float r2 = dot(N.xy, N.xy);
+ if (r2 > 1.0) discard; // kill pixels outside circle
+ N.z = sqrt(1.0-r2);
+
+ // calculate depth
+ vec4 eyeSpacePos = vec4(gl_TexCoord[1].xyz + N*pointRadius, 1.0); // position of this pixel on sphere in eye space
+ vec4 clipSpacePos = gl_ProjectionMatrix * eyeSpacePos;
+ gl_FragDepth = (clipSpacePos.z / clipSpacePos.w)*0.5+0.5;
+
+ float diffuse = max(0.0, dot(N, lightDir));
+
+ //gl_FragColor = diffuse*gl_Color;
+ gl_FragColor = gl_Color;
+ gl_FragColor.w = (1.0-r2)*(1.0-r2)*0.4;
+
+
+ vec3 v = normalize(-eyeSpacePos.xyz);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(N, h)), shininess);
+
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(N, v)), fresnelPower);
+
+ // cubemap
+ vec3 r = reflect(-v, N);
+ vec4 reflectColor = textureCube(cubemapTex, r);
+
+ // color attenuation based on thickness
+ float thickness = 0;
+
+ // refraction
+ // -----------------
+ // Pond
+ //vec4 attenuatedColor = fluidColor * exp(-thickness*falloffScale*colorFalloff);
+ //float refracMultiplier = 1;
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+
+ // Whirlpool
+ vec2 tx = viewportd2 + viewportd2*vec2(clipSpacePos.x/clipSpacePos.w, clipSpacePos.y/clipSpacePos.w);
+ vec4 sceneCol = texture2DRect(sceneTex, tx);
+ //vec4 sceneCol = texture2DRect(sceneTex, gl_TexCoord[0].xy);
+ //sceneCol = vec4(1,1,1,1);''
+
+ //sceneCol.xyz = lerp(vec3(0.13, 0.19, 0.22), sceneCol.xyz, blendFactor);
+
+
+ vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+ //vec4 finalCol = vec4((1-fresnel)*specularColor.xyz*specular, 1.0);
+
+ float vn = (1-dot(N,v));
+ finalCol = vn*vn*gl_Color+specularColor*specular;
+
+ finalCol.w = finalCol.x;
+ finalCol.xyz = gl_Color;
+
+ //----------------
+ gl_FragColor = finalCol*0.8;
+
+ //gl_FragColor.w = 0.4;
+ //gl_FragColor = vec4(clipSpacePos.x/clipSpacePos.w, clipSpacePos.y/clipSpacePos.w, 0, 1);
+
+ //gl_FragColor *= gl_FragColor.w;
+}
+);
+
+const char *depthBlurViewIDPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+sampler2DRect colorTex;
+uniform float world2texScale;
+uniform float tex2worldScale;
+uniform float maxBlurRadius = 50;
+uniform float blurRadiusImagePlane = 10; // in world space
+uniform vec2 blurDir; // direction of blur
+uniform float XYFalloff = 0.02;
+uniform float depthFalloff = 1.00;
+
+void main()
+{
+ float center = -texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+
+
+ if (center < -9999.0) {
+ // skip background pixels
+ discard;
+ return;
+ }
+
+ float myWorld2Tex = world2texScale / center;
+ float rawRad = blurRadiusImagePlane / center;
+ float sampleRadius = round(rawRad);
+ sampleRadius = min(sampleRadius, maxBlurRadius);
+ sampleRadius = max(0.0, sampleRadius);
+
+ float myTex2World = tex2worldScale * center;
+
+ //sampleRadius = max(0.0f, sampleRadius);
+ //sampleRadius = 0;
+ float sum = 0;
+ float wsum = 0;
+
+
+ for(float i=-sampleRadius; i<=sampleRadius; i+=1) { // step of 1 pixel
+ float sample = -texture2DRect(colorTex, gl_TexCoord[0].xy + i*blurDir).x;
+
+
+ float x = i * myTex2World;
+
+ // bilateral filter
+ // spatial domain
+ float r = x * XYFalloff;
+ float cut = (rawRad - abs(i)) / (rawRad);
+ float w = exp(-r*r) * max(0.0f, pow(cut, 0.4)) ;
+
+ // range domain (based on depth difference)
+ float r2 = (sample - center) * depthFalloff;
+ //float g = 1.0;
+ float g = exp(-r2*r2);
+
+ sum += sample * w * g;
+ wsum += w * g;
+ }
+
+ if (wsum > 0.0) {
+ sum /= wsum;
+ }
+ gl_FragColor.x = -sum;
+
+}
+);
+const char *depthBlurViewIDNonSepPS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+sampler2DRect colorTex;
+uniform float world2texScale;
+uniform float tex2worldScale;
+uniform float maxBlurRadius = 2;
+uniform float blurRadiusImagePlane = 10; // in world space
+uniform float XYFalloff = 0.02;
+uniform float depthFalloff = 1.00;
+
+void main()
+{
+ float center = -texture2DRect(colorTex, gl_TexCoord[0].xy).x;
+
+
+ if (center < -9999.0) {
+ // skip background pixels
+ discard;
+ return;
+ }
+
+ float myWorld2Tex = world2texScale / center;
+ float rawRad = blurRadiusImagePlane / center;
+ float sampleRadius = round(rawRad);
+ sampleRadius = min(sampleRadius, maxBlurRadius);
+ sampleRadius = max(0.0, sampleRadius);
+
+ float myTex2World = tex2worldScale * center;
+
+ //sampleRadius = max(0.0f, sampleRadius);
+ //sampleRadius = 0;
+ float sum = 0;
+ float wsum = 0;
+
+
+ for(float i=-sampleRadius; i<=sampleRadius; i+=1) { // step of 1 pixel
+ float y = i * myTex2World;
+ for(float j=-sampleRadius; j<=sampleRadius; j+=1) { // step of 1 pixel
+ float sample = -texture2DRect(colorTex, gl_TexCoord[0].xy + vec2(j, i)).x;
+
+ float x = j * myTex2World;
+ float dis = sqrt(x*x+y*y);
+
+ // bilateral filter
+ // spatial domain
+ float r = dis * XYFalloff;
+ float cut = (rawRad - abs(i)) / (rawRad);
+ float w = exp(-r*r) * max(0.0f, pow(cut, 0.4)) ;
+
+ // range domain (based on depth difference)
+ float r2 = (sample - center) * depthFalloff;
+ //float g = 1.0;
+ float g = exp(-r2*r2);
+
+ sum += sample * w * g;
+ wsum += w * g;
+ }
+ }
+
+ if (wsum > 0.0) {
+ sum /= wsum;
+ }
+ gl_FragColor.x = -sum;
+
+}
+);
+
+
+// display final shaded surface Nuttapong's mod
+const char *displaySurfaceNutEscapePS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform vec2 colorTexScale;
+uniform sampler2DArrayShadow stex;
+uniform sampler2DRect colorTex;
+uniform sampler2DRect depthTex;
+uniform sampler2DRect thicknessTex;
+uniform sampler2DRect sceneTex;
+uniform samplerCube cubemapTex;
+
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform vec2 invViewport = vec2(1.0 / 800, 1.0 / 600);
+uniform float2 invFocalLen;
+uniform float depthThreshold = 0.01;
+uniform float shininess = 40.0;
+//uniform vec4 fluidColor = vec4(0.5, 0.7, 1.0, 0.0);
+uniform vec4 fluidColor = vec4(17/255.0, 52/255.0, 71/255.0, 0.0);
+
+uniform vec4 colorFalloff = vec4(2.0, 1.0, 0.5, 1.0);
+uniform vec4 specularColor = vec4(0.7, 0.7, 0.7, 1.0);
+//uniform vec4 specularColor = vec4(0.25, 0.25, 0.25, 1.0);
+
+uniform float falloffScale = 1.0f;
+//uniform float falloffScale = 0.1;
+uniform vec3 thicknessRefraction = vec3(2.0, 2.3, 2.6);
+uniform float subSample = 1;
+
+uniform float fresnelBias = 0.0;
+uniform float fresnelScale = 1.0;
+uniform float fresnelPower = 2.0; // 5.0 is physically correct
+uniform float shadowAmbient = 0.9;
+uniform float splashZShadowBias = 0.0f;
+uniform float refracMultiplier = 1.0;
+
+uniform float epsilon = 0.0001f;
+uniform float thicknessAlphaMul = 3.0f;
+uniform float decayRate = 1.0f;
+uniform float thicknessScale = 1.0f;
+uniform float thicknessClamp = 1000.0f;
+// convert [0,1] uv coords and eye-space Z to eye-space position
+vec3 uvToEye(vec2 uv, float eyeZ)
+{
+ uv = uv * vec2(-2.0, -2.0) - vec2(-1.0, -1.0);
+ return vec3(uv * invFocalLen * eyeZ, eyeZ);
+}
+
+vec3 getEyePos(sampler2DRect tex, vec2 texCoord)
+{
+ float eyeZ = texture2DRect(tex, texCoord*colorTexScale).x;
+ return uvToEye(texCoord*invViewport, eyeZ);
+}
+float shadowCoef(float3 eyePos)
+{
+ const int index = 0;
+ /*
+ int index = 3;
+
+ // find the appropriate depth map to look up in based on the depth of this fragment
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ */
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(eyePos.x, eyePos.y, eyePos.z,1);
+
+ shadow_coord.w = shadow_coord.z + splashZShadowBias;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+
+void main()
+{
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+
+ //return;
+ float c = texture2DRect(colorTex, gl_TexCoord[0].xy*colorTexScale).x;
+ if (c < -9999.0) {
+ discard;
+ return;
+ }
+
+ // calculate normal
+ // taking silohette edges into account
+ vec2 uv = gl_TexCoord[0].xy * invViewport;
+ vec3 eyePos = uvToEye(uv, c);
+
+
+ vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - eyePos;
+ vec3 ddx2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+
+
+ vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - eyePos;
+ vec3 ddy2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+
+ float thickness = min(thicknessClamp, texture2DRect(thicknessTex, gl_TexCoord[0].xy * subSample).x* thicknessScale);
+ float refBlend = 0.0f;
+ float maxDz = max(max(abs(ddx.z),abs(ddx2.z)), max(abs(ddy.z),abs(ddy2.z)));
+ if (maxDz > depthThreshold) {
+ refBlend = 1.0f - exp((depthThreshold - maxDz)*decayRate);
+ }
+
+// if (abs(ddx.z) > abs(ddx2.z)) {
+ //if (abs(ddx.z) > depthThreshold) {
+ if (abs(ddx2.z) < abs(ddx.z)) {
+ ddx = ddx2;
+ }
+ //}
+ // if (abs(ddy2.z) < abs(ddy.z)) {
+ //if (abs(ddy.z) > depthThreshold) {
+ if (abs(ddy2.z) < abs(ddy.z)) {
+ ddy = ddy2;
+ }
+ //}
+
+
+ ddx.x += epsilon;
+ ddy.y += epsilon;
+
+
+ //vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+ //vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+ //ddx.z = clamp(ddx.z, -depthThreshold, depthThreshold);
+ //ddy.z = clamp(ddy.z, -depthThreshold, depthThreshold);
+
+ // color attenuation based on thickness
+
+
+ //ddx = normalize(ddx);
+ //ddy = normalize(ddy);
+ //if (depthThreshold < 0.001f) {
+ // vec3 nn = cross(ddx, ddy);
+ //gl_FragColor = vec4(sqrt(dot(ddx,ddx)), sqrt(dot(ddy, ddy)), sqrt(dot(nn,nn)), 1.0f);
+ // gl_FragColor = vec4(10.0f*sqrt(dot(nn,nn)), 0.0f, 0.0f, 1.0f);
+ // return;
+ //}
+
+ //ddx.z = clamp(ddx.z, -depthThreshold, depthThreshold);
+ //ddy.z = clamp(ddy.z, -depthThreshold, depthThreshold);
+
+ vec3 n = normalize(cross(ddx, ddy));
+
+
+ // lighting
+ // float diffuse = max(0.0, dot(n, lightDir));
+ float diffuse = dot(n, lightDir); // wrap lighting
+
+ vec3 v = normalize(-eyePos);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(n, h)), shininess);
+
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(n, v)), fresnelPower);
+
+ // cubemap
+ vec3 r = reflect(-v, n);
+ r = r * gl_NormalMatrix;
+ vec4 reflectColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);//textureCube(cubemapTex, r);
+
+
+ // vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff);
+
+ // refraction
+ // -----------------
+ // Pond
+ //vec4 attenuatedColor = fluidColor * exp(-thickness*falloffScale*colorFalloff);
+ //float refracMultiplier = 1;
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+
+ // Whirlpool
+ //float refracMultiplier = 0.1;
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+ //vec3 blendFactor = vec3(1,1,1)+2*thickness*falloffScale*vec3(1,1,1);
+
+ //blendFactor = min(blendFactor, vec3(1,1,1));
+ //blendFactor = max(blendFactor, vec3(0,0,0));
+ //sceneCol.xyz = lerp(vec3(0.13, 0.19, 0.22), sceneCol.xyz, blendFactor);
+
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+
+ // FERMI
+
+
+
+ float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ vec2 refractedCoord = gl_TexCoord[0].xy + (n.xy * refraction);
+
+ // don't refract objects in front of surface
+// float bgDepth = texture2DRect(sceneDepthTex, refractedCoord).x;
+
+ // if (bgDepth < surfaceDepth) refractedCoord = gl_TexCoord[0].xy;
+ //refractedCoord = lerp(refractedCoord, gl_TexCoord[0].xy, smoothstep(0.01, 0.0, bgDepth - surfaceDepth));
+
+ vec4 sceneCol = texture2DRect(sceneTex, refractedCoord);
+
+
+
+
+ vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff);
+ sceneCol.xyz = lerp(fluidColor, sceneCol.xyz, attenuatedColor);
+
+ vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + (reflectColor.xyz )*fresnel + specularColor.xyz*specular, 1.0);
+
+ gl_FragColor = vec4(diffuse, diffuse, diffuse, 1.0f);//finalCol;
+ gl_FragColor = finalCol;
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * colorTexScale).x;
+
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+
+ /*
+ float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+
+ reflectColor = (1.0f-refBlend)*reflectColor + refBlend*sceneCol;
+
+// colorFalloff = vec4(0.5, 0.5, 0.5, 1.0);
+ vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff*10.0);
+ //vec3 blendFactor = vec3(1,1,1)+2*thickness*falloffScale*vec3(1,1,1);
+ //blendFactor = min(0.5, blendFactor);
+
+ //blendFactor = min(blendFactor, vec3(1,1,1));
+ //blendFactor = max(blendFactor, vec3(0,0,0));
+ //fluidColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
+ //fluidColor = vec4(28/255.0, 69/255.0, 89/255.0, 0.0);
+ //fluidColor = vec4(17/255.0, 52/255.0, 71/255.0, 0.0);
+ sceneCol.xyz = lerp(fluidColor, sceneCol.xyz, attenuatedColor);
+ //sceneCol = fluidColor;
+ //sceneCol.xyz = vec3(0.0f,0.0f,0.0f);
+
+
+ vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel , 1.0);
+
+ float shadow = shadowCoef(eyePos);
+ gl_FragColor = vec4(finalCol.xyz*((1.0f - shadowAmbient)*shadow + shadowAmbient), max(0.0f, min(1.0, thicknessAlphaMul*thickness)));
+
+// gl_FragColor = finalCol;
+// gl_FragColor.w = max(0.0f, min(1.0, 3.0f*thickness));
+
+ //gl_FragColor = finalCol;
+ // gl_FragColor = sceneCol*attenuatedColor + reflectColor*fresnel + specularColor*specular;
+
+ // gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy).x;
+ float fog = clamp(gl_Fog.scale*(gl_Fog.end+eyePos.z), 0.0, 1.0);
+ //float fog = exp(-gl_Fog.density*(eyePos.z*eyePos.z));
+
+ gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);
+
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * colorTexScale).x;
+ */
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+ //return;
+
+ //gl_FragColor.w = max(0.0, min((thickness)*5.0, 1.0));
+ //gl_FragColor.w = 1.0;
+
+
+}
+);
+
+// display final shaded surface Nuttapong's mod
+const char *displaySurfaceNutEscapeDiffusePS = STRINGIFY(
+//#extension GL_ARB_texture_rectangle : enable\n
+uniform vec2 colorTexScale;
+uniform sampler2DArrayShadow stex;
+uniform sampler2DRect colorTex;
+uniform sampler2DRect depthTex;
+uniform sampler2DRect thicknessTex;
+uniform sampler2DRect sceneTex;
+uniform samplerCube cubemapTex;
+
+uniform vec3 lightDir = vec3(0.577, 0.577, 0.577);
+uniform vec2 invViewport = vec2(1.0 / 800, 1.0 / 600);
+uniform float2 invFocalLen;
+uniform float depthThreshold = 0.01;
+uniform float shininess = 40.0;
+//uniform vec4 fluidColor = vec4(0.5, 0.7, 1.0, 0.0);
+uniform vec4 fluidColor = vec4(17/255.0, 52/255.0, 71/255.0, 0.0);
+
+uniform vec4 colorFalloff = vec4(2.0, 1.0, 0.5, 1.0);
+uniform vec4 specularColor = vec4(0.7, 0.7, 0.7, 1.0);
+//uniform vec4 specularColor = vec4(0.25, 0.25, 0.25, 1.0);
+
+uniform float falloffScale = 1.0f;
+//uniform float falloffScale = 0.1;
+uniform vec3 thicknessRefraction = vec3(2.0, 2.3, 2.6);
+uniform float subSample = 1;
+
+uniform float fresnelBias = 0.0;
+uniform float fresnelScale = 1.0;
+uniform float fresnelPower = 2.0; // 5.0 is physically correct
+
+uniform float splashZShadowBias = -0.001f;
+uniform float refracMultiplier = 1.0;
+
+uniform float epsilon = 0.0001f;
+uniform float thicknessAlphaMul = 3.0f;
+uniform float decayRate = 1.0f;
+uniform float thicknessScale = 1.0f;
+uniform float thicknessClamp = 1000.0f;
+
+uniform vec3 spotLightPos;
+uniform vec3 spotLightPos2;
+uniform vec3 spotLightPos3;
+uniform float shadowAmbient = 0.5f;
+
+//#define BLUISH 1
+const int BLUISH = 0;
+// convert [0,1] uv coords and eye-space Z to eye-space position
+vec3 uvToEye(vec2 uv, float eyeZ)
+{
+ uv = uv * vec2(-2.0, -2.0) - vec2(-1.0, -1.0);
+ return vec3(uv * invFocalLen * eyeZ, eyeZ);
+}
+
+vec3 getEyePos(sampler2DRect tex, vec2 texCoord)
+{
+ float eyeZ = texture2DRect(tex, texCoord*colorTexScale).x;
+ return uvToEye(texCoord*invViewport, eyeZ);
+}
+
+float shadowCoef(float3 eyePos)
+{
+ const int index = 0;
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(eyePos.x, eyePos.y, eyePos.z,1);
+
+ shadow_coord.w = shadow_coord.z + splashZShadowBias;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+
+void main()
+{
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+
+ //return;
+ float c = texture2DRect(colorTex, gl_TexCoord[0].xy*colorTexScale).x;
+ if (c < -9999.0) {
+ discard;
+ return;
+ }
+
+ // calculate normal
+ // taking silohette edges into account
+ vec2 uv = gl_TexCoord[0].xy * invViewport;
+ vec3 eyePos = uvToEye(uv, c);
+
+
+ vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - eyePos;
+ vec3 ddx2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+
+
+ vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - eyePos;
+ vec3 ddy2 = eyePos - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+
+ float thickness = min(thicknessClamp, texture2DRect(thicknessTex, gl_TexCoord[0].xy * subSample).x* thicknessScale);
+ float refBlend = 0.0f;
+ float maxDz = max(max(abs(ddx.z),abs(ddx2.z)), max(abs(ddy.z),abs(ddy2.z)));
+ if (maxDz > depthThreshold) {
+ refBlend = 1.0f - exp((depthThreshold - maxDz)*decayRate);
+ }
+
+// if (abs(ddx.z) > abs(ddx2.z)) {
+ //if (abs(ddx.z) > depthThreshold) {
+ if (abs(ddx2.z) < abs(ddx.z)) {
+ ddx = ddx2;
+ }
+ //}
+ // if (abs(ddy2.z) < abs(ddy.z)) {
+ //if (abs(ddy.z) > depthThreshold) {
+ if (abs(ddy2.z) < abs(ddy.z)) {
+ ddy = ddy2;
+ }
+ //}
+
+
+ ddx.x += epsilon;
+ ddy.y += epsilon;
+
+
+ //vec3 ddx = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(1, 0)) - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(-1, 0));
+ //vec3 ddy = getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, 1)) - getEyePos(colorTex, gl_TexCoord[0].xy + vec2(0, -1));
+ //ddx.z = clamp(ddx.z, -depthThreshold, depthThreshold);
+ //ddy.z = clamp(ddy.z, -depthThreshold, depthThreshold);
+
+ // color attenuation based on thickness
+
+
+ //ddx = normalize(ddx);
+ //ddy = normalize(ddy);
+ //if (depthThreshold < 0.001f) {
+ // vec3 nn = cross(ddx, ddy);
+ //gl_FragColor = vec4(sqrt(dot(ddx,ddx)), sqrt(dot(ddy, ddy)), sqrt(dot(nn,nn)), 1.0f);
+ // gl_FragColor = vec4(10.0f*sqrt(dot(nn,nn)), 0.0f, 0.0f, 1.0f);
+ // return;
+ //}
+
+ //ddx.z = clamp(ddx.z, -depthThreshold, depthThreshold);
+ //ddy.z = clamp(ddy.z, -depthThreshold, depthThreshold);
+
+ vec3 n = normalize(cross(ddx, ddy));
+
+ if (dot(n, eyePos.xyz) > 0) {
+ n.xyz *= -1;
+ }
+
+ // lighting
+ // float diffuse = max(0.0, dot(n, lightDir));
+ //float diffuse = dot(n, lightDir); // wrap lighting
+ vec3 lvec = normalize(spotLightPos - eyePos);
+ vec3 lvec2 = normalize(spotLightPos2 - eyePos);
+ vec3 lvec3 = normalize(spotLightPos3 - eyePos);
+
+ float shadowC = shadowCoef(eyePos);
+ float shadowFactor = ((1.0f - shadowAmbient)*shadowC + shadowAmbient);
+ float diffuse = (0.33333f*0.7f*(max(dot(n, lvec),0.0f)+max(dot(n, lvec2),0.0f)+max(dot(n, lvec3),0.0f)))*shadowFactor+0.3f; // wrap lighting
+
+ vec3 v = normalize(-eyePos);
+ vec3 h = normalize(lightDir + v);
+ float specular = pow(max(0.0, dot(n, h)), shininess);
+
+ float fresnel = fresnelBias + fresnelScale*pow(1.0 - max(0.0, dot(n, v)), fresnelPower);
+
+ // cubemap
+ vec3 r = reflect(-v, n);
+ r = r * gl_NormalMatrix;
+ vec4 reflectColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);//textureCube(cubemapTex, r);
+
+
+ // vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff);
+
+ // refraction
+ // -----------------
+ // Pond
+ //vec4 attenuatedColor = fluidColor * exp(-thickness*falloffScale*colorFalloff);
+ //float refracMultiplier = 1;
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+
+ // Whirlpool
+ //float refracMultiplier = 0.1;
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+ //vec3 blendFactor = vec3(1,1,1)+2*thickness*falloffScale*vec3(1,1,1);
+
+ //blendFactor = min(blendFactor, vec3(1,1,1));
+ //blendFactor = max(blendFactor, vec3(0,0,0));
+ //sceneCol.xyz = lerp(vec3(0.13, 0.19, 0.22), sceneCol.xyz, blendFactor);
+
+ //vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel + specularColor.xyz*specular, 1.0);
+
+ // FERMI
+
+
+
+ //float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ //vec2 refractedCoord = gl_TexCoord[0].xy + (n.xy * refraction);
+
+ // don't refract objects in front of surface
+// float bgDepth = texture2DRect(sceneDepthTex, refractedCoord).x;
+
+ // if (bgDepth < surfaceDepth) refractedCoord = gl_TexCoord[0].xy;
+ //refractedCoord = lerp(refractedCoord, gl_TexCoord[0].xy, smoothstep(0.01, 0.0, bgDepth - surfaceDepth));
+
+
+
+
+
+
+
+
+ vec3 sceneCol = texture2DRect(sceneTex, gl_TexCoord[0].xy).xyz;
+ vec3 bb = vec3(diffuse,diffuse,diffuse);
+ if (BLUISH) {
+ vec4 col1 = 1.5*vec4(116,147,179,255) / 200.0;
+ bb = col1.xyz*diffuse;
+ }
+//#endif
+ float alpha = clamp(thickness, 0.0f, 1.0f);
+
+
+ gl_FragColor.xyz = (1.0f-alpha)*sceneCol + alpha*bb;
+ gl_FragColor.w = 1.0f;
+ //gl_FragColor = finalCol;
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * colorTexScale).x;
+
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+
+ /*
+ float refraction = thickness*thicknessRefraction.x*refracMultiplier;
+ vec4 sceneCol = texture2DRect(sceneTex, (gl_TexCoord[0].xy * subSample) + (n.xy * refraction));
+
+ reflectColor = (1.0f-refBlend)*reflectColor + refBlend*sceneCol;
+
+// colorFalloff = vec4(0.5, 0.5, 0.5, 1.0);
+ vec4 attenuatedColor = exp(-thickness*falloffScale*colorFalloff*10.0);
+ //vec3 blendFactor = vec3(1,1,1)+2*thickness*falloffScale*vec3(1,1,1);
+ //blendFactor = min(0.5, blendFactor);
+
+ //blendFactor = min(blendFactor, vec3(1,1,1));
+ //blendFactor = max(blendFactor, vec3(0,0,0));
+ //fluidColor = vec4(1.0f, 1.0f, 1.0f, 1.0f);
+ //fluidColor = vec4(28/255.0, 69/255.0, 89/255.0, 0.0);
+ //fluidColor = vec4(17/255.0, 52/255.0, 71/255.0, 0.0);
+ sceneCol.xyz = lerp(fluidColor, sceneCol.xyz, attenuatedColor);
+ //sceneCol = fluidColor;
+ //sceneCol.xyz = vec3(0.0f,0.0f,0.0f);
+
+
+ vec4 finalCol = vec4((1-fresnel)*sceneCol.xyz + reflectColor.xyz*fresnel , 1.0);
+
+ float shadow = shadowCoef(eyePos);
+ gl_FragColor = vec4(finalCol.xyz*((1.0f - shadowAmbient)*shadow + shadowAmbient), max(0.0f, min(1.0, thicknessAlphaMul*thickness)));
+
+// gl_FragColor = finalCol;
+// gl_FragColor.w = max(0.0f, min(1.0, 3.0f*thickness));
+
+ //gl_FragColor = finalCol;
+ // gl_FragColor = sceneCol*attenuatedColor + reflectColor*fresnel + specularColor*specular;
+
+ // gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy).x;
+ float fog = clamp(gl_Fog.scale*(gl_Fog.end+eyePos.z), 0.0, 1.0);
+ //float fog = exp(-gl_Fog.density*(eyePos.z*eyePos.z));
+
+ gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);
+
+ gl_FragDepth = texture2DRect(depthTex, gl_TexCoord[0].xy * colorTexScale).x;
+ */
+ //gl_FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);
+ //return;
+
+ //gl_FragColor.w = max(0.0, min((thickness)*5.0, 1.0));
+ //gl_FragColor.w = 1.0;
+
+
+}
+);
+
+const char *texture2DPS = STRINGIFY(
+ uniform sampler2D tex; \n
+ void main() \n
+{ \n
+gl_FragColor = texture2D(tex, gl_TexCoord[0].xy); \n
+} \n
+);
+
+#if TECHNICAL_MODE
+
+const char *particleSmokeUseFOMPS = STRINGIFY(
+uniform sampler2DArrayShadow stex;
+uniform float shadowAmbient = 0.3;
+
+float shadowCoef()
+{
+ const int index = 0;
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[2].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+uniform float ispotMaxDist;
+uniform vec3 spotOriginEye;
+uniform sampler2D spot_a0123;
+uniform sampler2D spot_b123;
+
+uniform sampler2D smokeTex;
+
+const float PI = 3.1415926535897932384626433832795;
+const vec3 _2pik = vec3(2.0) * vec3(PI,2.0*PI,3.0*PI);
+const vec3 factor_a = vec3(2.0*PI)*vec3(1.0,2.0,3.0);
+const vec3 factor_b = vec3(2.0*PI)*vec3(1.0,2.0,3.0);
+const vec3 value_1 = vec3(1.0);
+
+uniform mat4 eyeToSpotMatrix;
+void main()
+{
+ //gl_FragColor = gl_Color;
+ //return;
+
+ // calculate eye-space normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float mag = dot(N.xy, N.xy);
+ if (mag > 1.0) discard; // kill pixels outside circle
+
+ float falloff = pow(1.0-mag,1.0);//exp(-mag);
+ //falloff = 1.0f;
+ float shadowC = shadowCoef();
+
+ vec3 shadowColor = vec3(0.4, 0.4, 0.4)*0.8;
+
+ // Also FOM
+
+// vec4 projectionCoordinate = eyeToSpotMatrix*vec4(gl_TexCoord[2].xyz, 1.0f);
+ vec4 projectionCoordinate = eyeToSpotMatrix*vec4(gl_TexCoord[2].xyz, 1.0f);
+ //gl_FragColor.xyz = gl_TexCoord[3].xyz*0.25f;
+ //gl_FragColor.xyz = projectionCoordinate.xyz / projectionCoordinate.w;
+ //gl_FragColor.w = 1.0f;
+
+ //read Fourier series coefficients for color extinction on RGB
+ vec4 sR_a0123 = texture2DProj(spot_a0123,projectionCoordinate);
+ vec3 sR_b123 = texture2DProj(spot_b123,projectionCoordinate).rgb;
+
+ //gl_FragColor.xyz = sR_a0123.xyz;
+ //gl_FragColor.w = 1.0f;
+ //return;
+ //compute absolute and normalized distance (in spot depth range)
+ float distance2spotCenter = length(spotOriginEye-gl_TexCoord[2].xyz);//distance from spot origin to surfel in world space
+ float d = distance2spotCenter*ispotMaxDist;
+
+
+ //compute some value to recover the extinction coefficient using the Fourier series
+ vec3 sin_a123 = sin(factor_a*vec3(d));
+ vec3 cos_b123 = value_1-cos(factor_b*vec3(d));
+
+ //compute the extinction coefficients using Fourier
+ float att = (sR_a0123.r*d/2.0) + dot(sin_a123*(sR_a0123.gba/_2pik) ,value_1) + dot(cos_b123*(sR_b123.rgb/_2pik) ,value_1);
+
+ att = max(0.0f, att);
+ att = min(1.0f, att);
+ shadowC *= (1.0f-att);
+ float inS = shadowC;
+ shadowC = (shadowAmbient + (1.0f -shadowAmbient)*shadowC);
+ //....
+ if (gl_TexCoord[0].z > 1) shadowC = 1;
+ vec4 texColor = texture2D(smokeTex, gl_TexCoord[0].xy*0.25+gl_TexCoord[1].xy);
+
+ gl_FragColor.xyz = (texColor.x)*gl_Color.xyz*(shadowColor + (vec3(1.0f,1,1) -shadowColor)*shadowC);//*falloff;
+ gl_FragColor.w = gl_Color.w*texColor.r;
+
+
+ //float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[2].z), 0.0, 1.0);
+ //float fog = exp(-gl_Fog.density*(gl_TexCoord[0].z*gl_TexCoord[0].z));
+ //gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);
+
+ gl_FragColor.xyz *= 1.6f;
+ gl_FragColor.w *= max(min(falloff,1.0f),0.0f) * max(min(gl_TexCoord[0].w,1.0f),0.0f);
+ //gl_FragColor.w = 1;
+ //gl_FragColor.xyz = vec3(shadowC, shadowC, shadowC);
+// gl_FragColor.w = 0.2f;
+ //gl_FragColor.w = falloff * gl_TexCoord[0].w;
+ //gl_FragColor.xyz = sR_a0123.xyz;
+ gl_FragColor.xyz *= ((gl_TexCoord[0].z)+inS*0.3)*0.7;
+ //gl_FragDepth = gl_FragCoord.z - (1-mag)*0.00002;
+
+}
+);
+
+#else
+const char *particleSmokeUseFOMPS = STRINGIFY(
+uniform sampler2DArrayShadow stex;
+uniform float shadowAmbient = 0.3;
+
+float shadowCoef()
+{
+ const int index = 0;
+ /*
+ int index = 3;
+
+ // find the appropriate depth map to look up in based on the depth of this fragment
+ if(gl_FragCoord.z < far_d.x)
+ index = 0;
+ else if(gl_FragCoord.z < far_d.y)
+ index = 1;
+ else if(gl_FragCoord.z < far_d.z)
+ index = 2;
+ */
+
+ // transform this fragment's position from view space to scaled light clip space
+ // such that the xy coordinates are in [0;1]
+ // note there is no need to divide by w for othogonal light sources
+ vec4 shadow_coord = gl_TextureMatrix[index]*vec4(gl_TexCoord[2].xyz, 1);
+
+ shadow_coord.w = shadow_coord.z;
+
+ // tell glsl in which layer to do the look up
+ shadow_coord.z = float(index);
+
+
+ // Gaussian 3x3 filter
+ return shadow2DArray(stex, shadow_coord).x;
+}
+uniform float ispotMaxDist;
+uniform vec3 spotOriginEye;
+uniform sampler2D spot_a0123;
+uniform sampler2D spot_b123;
+
+uniform sampler2D smokeTex;
+
+const float PI = 3.1415926535897932384626433832795;
+const vec3 _2pik = vec3(2.0) * vec3(PI,2.0*PI,3.0*PI);
+const vec3 factor_a = vec3(2.0*PI)*vec3(1.0,2.0,3.0);
+const vec3 factor_b = vec3(2.0*PI)*vec3(1.0,2.0,3.0);
+const vec3 value_1 = vec3(1.0);
+
+uniform mat4 eyeToSpotMatrix;
+void main()
+{
+ //gl_FragColor = gl_Color;
+ //return;
+/*
+ gl_FragColor = texture2D(smokeTex, gl_TexCoord[0].xy);
+ gl_FragColor.w = gl_FragColor.r;
+ gl_FragColor.xyz = vec3(1,1,1);
+ return;
+*/
+// gl_FragColor = vec4(1,0,0,1);
+// return;
+
+ // calculate eye-space normal from texture coordinates
+ vec3 N;
+ N.xy = gl_TexCoord[0].xy*vec2(2.0, -2.0) + vec2(-1.0, 1.0);
+ float mag = dot(N.xy, N.xy);
+ if (mag > 1.0) discard; // kill pixels outside circle
+
+ float falloff = pow(1.0-mag,1.0);//exp(-mag);
+ //falloff = 1.0f;
+ float shadowC = shadowCoef();
+
+ vec3 shadowColor = vec3(0.4, 0.4, 0.9)*0.8;
+
+ // Also FOM
+
+// vec4 projectionCoordinate = eyeToSpotMatrix*vec4(gl_TexCoord[2].xyz, 1.0f);
+ vec4 projectionCoordinate = eyeToSpotMatrix*vec4(gl_TexCoord[2].xyz, 1.0f);
+ //gl_FragColor.xyz = gl_TexCoord[3].xyz*0.25f;
+ //gl_FragColor.xyz = projectionCoordinate.xyz / projectionCoordinate.w;
+ //gl_FragColor.w = 1.0f;
+
+ //read Fourier series coefficients for color extinction on RGB
+ vec4 sR_a0123 = texture2DProj(spot_a0123,projectionCoordinate);
+ vec3 sR_b123 = texture2DProj(spot_b123,projectionCoordinate).rgb;
+
+ //gl_FragColor.xyz = sR_a0123.xyz;
+ //gl_FragColor.w = 1.0f;
+ //return;
+ //compute absolute and normalized distance (in spot depth range)
+ float distance2spotCenter = length(spotOriginEye-gl_TexCoord[2].xyz);//distance from spot origin to surfel in world space
+ float d = distance2spotCenter*ispotMaxDist;
+
+
+ //compute some value to recover the extinction coefficient using the Fourier series
+ vec3 sin_a123 = sin(factor_a*vec3(d));
+ vec3 cos_b123 = value_1-cos(factor_b*vec3(d));
+
+ //compute the extinction coefficients using Fourier
+ float att = (sR_a0123.r*d/2.0) + dot(sin_a123*(sR_a0123.gba/_2pik) ,value_1) + dot(cos_b123*(sR_b123.rgb/_2pik) ,value_1);
+
+ att = max(0.0f, att);
+ att = min(1.0f, att);
+ shadowC *= (1.0f-att);
+ float inS = shadowC;
+ shadowC = (shadowAmbient + (1.0f -shadowAmbient)*shadowC);
+ //....
+ if (gl_TexCoord[0].z > 1) shadowC = 1;
+ vec4 texColor = texture2D(smokeTex, gl_TexCoord[0].xy*0.25+gl_TexCoord[1].xy);
+
+ gl_FragColor.xyz = (texColor.x)*gl_Color.xyz*(shadowColor + (vec3(1.0f,1,1) -shadowColor)*shadowC);//*falloff;
+ gl_FragColor.w = gl_Color.w*texColor.r;
+
+
+ //float fog = clamp(gl_Fog.scale*(gl_Fog.end+gl_TexCoord[2].z), 0.0, 1.0);
+ //float fog = exp(-gl_Fog.density*(gl_TexCoord[0].z*gl_TexCoord[0].z));
+ //gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog);
+
+ gl_FragColor.xyz *= 1.6f;
+ gl_FragColor.w *= max(min(falloff,1.0f),0.0f) * max(min(gl_TexCoord[0].w,1.0f),0.0f);
+ //gl_FragColor.w = 1;
+ //gl_FragColor.xyz = vec3(shadowC, shadowC, shadowC);
+// gl_FragColor.w = 0.2f;
+ //gl_FragColor.w = falloff * gl_TexCoord[0].w;
+ //gl_FragColor.xyz = sR_a0123.xyz;
+ gl_FragColor.xyz *= ((gl_TexCoord[0].z)+inS*0.3)*0.7;
+ //gl_FragDepth = gl_FragCoord.z - (1-mag)*0.00002;
+
+}
+);
+
+#endif
+// sky box
+const char *skyboxVS = STRINGIFY(
+ uniform vec3 projectionCenter = vec3(0,0,0);
+
+void main()
+{
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ // gl_Position = gl_Vertex;
+ // gl_Position = gl_ProjectionMatrix * gl_Vertex;
+ gl_TexCoord[0].xyz = (gl_Vertex.xyz + projectionCenter);
+ // gl_TexCoord[0].xyz = (mat3) gl_ModelViewMatrix * gl_Vertex.xyz;
+ gl_FrontColor = gl_Color;
+}
+);
+
+const char *skyboxPS = STRINGIFY(
+ uniform samplerCube cubemap;
+
+void main()
+{
+ gl_FragColor = textureCube(cubemap, gl_TexCoord[0].xyz * vec3(1, 1, 1));
+
+ gl_FragColor.x = 1.5 * pow(gl_FragColor.x, 2.2);
+ gl_FragColor.y = 1.5 * pow(gl_FragColor.y, 2.2);
+ gl_FragColor.z = 1.5 * pow(gl_FragColor.z, 2.2);
+ gl_FragColor.w = 1.5 * pow(gl_FragColor.w, 2.2);
+}
+);
diff --git a/KaplaDemo/samples/sampleViewer3/Render/MyShaders.h b/KaplaDemo/samples/sampleViewer3/Render/MyShaders.h
new file mode 100644
index 00000000..55ad55c2
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/MyShaders.h
@@ -0,0 +1,21 @@
+extern const char *particleVS,*particleVSNoKill;
+extern const char *particleSpherePS, *particleDebugPS, *particleDensityPS, *particleFoamPS, *particleFoamVS, *particleBubblePS;
+extern const char *particleSurfacePS, *particleThicknessPS;
+extern const char *mblurVS, *mblurGS, *mblurGSNoKill, *particleSprayPS;
+extern const char *passThruVS;
+extern const char *depthBlurPS , *depthBlur2DPS, *depthBlurSymPS, *displaySurfacePS, *displaySurfaceNewPS, *displaySurfaceChromePS, *displaySurfaceSolidPS;
+extern const char *depthBlurViewIDPS, *depthBlurViewIDNonSepPS;
+extern const char *textureRectPS, *dilatePS, *copyPS;
+
+// Nutt
+extern const char *depthToInitThicknessPS;
+extern const char *hfDepthPS, *hfDepthVS, *hfThicknessVS, *hfThicknessPS;
+extern const char *debugPS, *debugTriVS, *debugTriPS;
+extern const char *hfThicknessAddPS, *displaySurfaceNutPS, *particleDumbFoamVS, *particleDumbFoamGS, *particleDumbFoamPS, *displaySurfaceNutEscapePS, *displaySurfaceNutEscapeDiffusePS, *particleSprayUseFOMPS, *particleSprayGenFOMPS ;
+
+extern const char *texture2DPS;
+
+extern const char *particleSmokeUseFOMPS;
+
+extern const char *skyboxVS;
+extern const char *skyboxPS; \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Render/glmesh.cpp b/KaplaDemo/samples/sampleViewer3/Render/glmesh.cpp
new file mode 100644
index 00000000..c35a0af4
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/glmesh.cpp
@@ -0,0 +1,271 @@
+
+#include "glmesh.h"
+#include <windows.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <vector>
+#include <iostream>
+using namespace std;
+GLMesh::GLMesh(GLuint elementTypei) {
+ firstTimeBO = true;
+ vbo = ibo = 0;
+ withTexture = withColor = withNormal = withTangent = false;
+ elementType = elementTypei;
+}
+GLMesh::~GLMesh() {
+ firstTimeBO = true;
+ if (vbo) {
+ glDeleteBuffersARB(1, &vbo);
+ }
+ if (ibo) {
+ glDeleteBuffersARB(1, &ibo);
+ }
+}
+void GLMesh::reset() {
+ firstTimeBO = true;
+ if (vbo) {
+ glDeleteBuffersARB(1, &vbo);
+ }
+ if (ibo) {
+ glDeleteBuffersARB(1, &ibo);
+ }
+ vbo = ibo = 0;
+ withTexture = withColor = withNormal = withTangent = false;
+
+ indices.clear();
+ vertices.clear();
+ normals.clear();
+ colors.clear();
+ texCoords.clear(); // treats as u v
+ tangents.clear();
+ bitangents.clear();
+
+ // For raw
+ rawVertices.clear();
+ rawNormals.clear();
+
+}
+void GLMesh::genVBOIBO() {
+ glGenBuffersARB(1, &vbo);
+ glGenBuffersARB(1, &ibo);
+}
+void GLMesh::updateVBOIBO(bool dynamicVB) {
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo);
+ int bytesv = 0;
+ if (firstTimeBO) {
+ //if (!((vertices.size() > 0) && (indices.size() > 0) && (normals.size() == 0) && (texCoords.size() > 0) && (colors.size() > 0))) {
+ // // Only support pos, texcoord, color, no normal for now :P
+ // exit(-129);
+ //}
+ bytesv = vertices.size()*sizeof(float)*(3); //position 3, color 3, tex coord 2
+ withColor = (colors.size() != 0);
+ withTexture = (texCoords.size() != 0);
+ withNormal = (normals.size() != 0);
+ withTangent = (tangents.size() != 0) && (bitangents.size() != 0);
+ if (withColor) bytesv += vertices.size()*sizeof(float)*(3);
+ if (withTexture) bytesv += vertices.size()*sizeof(float)*(2);
+ if (withNormal) bytesv += vertices.size()*sizeof(float)*(3);
+ if (withTangent) bytesv += vertices.size()*sizeof(float)*(6);
+
+ vector<char> dummy(bytesv, 0);
+
+
+ if (dynamicVB) {
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, bytesv, (const void*)&dummy[0], GL_DYNAMIC_DRAW_ARB);
+ } else {
+ //glBufferDataARB(GL_ARRAY_BUFFER_ARB, bytesv, (const void*)&dummy[0], GL_STATIC_DRAW_ARB);
+ }
+
+ int bytesi = indices.size()*sizeof(PxU32);
+
+ dummy.resize(bytesi, 0);
+ glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bytesi, (const void*)&indices[0], GL_STATIC_DRAW_ARB); // index never change
+ firstTimeBO = 0;
+
+ }
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+
+
+ float* vb = 0;
+
+ if (dynamicVB) vb = (float*)glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); else {
+ vb = new float[bytesv / sizeof(float)];
+
+ }
+
+
+ int numV = vertices.size();
+ int pos = 0;
+
+
+ memcpy(vb, &vertices[0], sizeof(PxVec3)*numV);
+ pos+=3*numV;
+
+ if (withColor) {
+ memcpy(&vb[pos], &colors[0], sizeof(PxVec3)*numV);
+ pos+=3*numV;
+ }
+
+ if (withTexture) {
+ memcpy(&vb[pos], &texCoords[0], sizeof(float)*numV*2);
+ pos+=2*numV;
+ }
+
+ if (withNormal) {
+ memcpy(&vb[pos], &normals[0], sizeof(float)*numV*3);
+ pos+=3*numV;
+ }
+
+
+ if (withTangent) {
+
+ memcpy(&vb[pos], &tangents[0], sizeof(float)*numV*3);
+ pos+=3*numV;
+ memcpy(&vb[pos], &bitangents[0], sizeof(float)*numV*3);
+ pos+=3*numV;
+ }
+ if (dynamicVB) {
+ glUnmapBuffer(GL_ARRAY_BUFFER_ARB);
+ } else {
+ glBufferDataARB(GL_ARRAY_BUFFER_ARB, bytesv, (const void*)vb, GL_STATIC_DRAW_ARB);
+ delete vb;
+
+ }
+
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+
+}
+void GLMesh::drawVBOIBO(bool enable, bool draw, bool disable, bool drawpoints) {
+
+ if ((vbo == 0) || (ibo == 0)) return;
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo);
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ibo);
+
+
+ // Only support pos, texcoord, color, no normal for now :P
+ int numV = vertices.size();
+ if(enable) glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, sizeof(PxVec3), 0);
+ GLuint pos = 3*sizeof(float)*numV;
+ if (withColor) {
+ if(enable) glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(3, GL_FLOAT, 0, (const GLvoid*) (pos));
+ pos+=3*sizeof(float)*numV;
+ }
+ if (withTexture) {
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ if(enable) glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 0, (const GLvoid*) (pos));
+ pos+=2*sizeof(float)*numV;
+ }
+ if (withNormal) {
+ if(enable) glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT, sizeof(PxVec3), (const GLvoid*) (pos));
+ pos+=3*sizeof(float)*numV;
+ }
+
+ if (withTangent) {
+
+
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ if(enable) {
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ glTexCoordPointer(3, GL_FLOAT, 0, (const GLvoid*) (pos));
+ pos+=3*sizeof(float)*numV;
+ glClientActiveTextureARB(GL_TEXTURE2_ARB);
+ if(enable) {
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ glTexCoordPointer(3, GL_FLOAT, 0, (const GLvoid*) (pos));
+ pos+=3*sizeof(float)*numV;
+ }
+
+ if (draw) {
+ if (!drawpoints) {
+ glDrawElements(elementType, indices.size(), GL_UNSIGNED_INT, 0);
+ } else {
+ glDrawArrays(GL_POINTS, 0, numV);
+ }
+ }
+
+ if (disable) {
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glClientActiveTextureARB(GL_TEXTURE2_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glClientActiveTextureARB(GL_TEXTURE1_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ glDisableClientState(GL_NORMAL_ARRAY);
+
+ glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
+ glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+ }
+
+}
+
+void GLMesh::draw() {
+ if ((vertices.size() > 0) && (indices.size() > 0)) {
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, sizeof(PxVec3), &vertices[0]);
+
+ if (normals.size() > 0) {
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT, sizeof(PxVec3), &normals[0]);
+ }
+
+ if (texCoords.size() > 0) {
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glTexCoordPointer(2, GL_FLOAT, 0, &texCoords[0]);
+ }
+
+ if (colors.size() > 0) {
+ glEnableClientState(GL_COLOR_ARRAY);
+ glColorPointer(3, GL_FLOAT, 0, &colors[0]);
+ }
+
+ //if (mTexId > 0) {
+ // glColor3f(1.0f, 1.0f, 1.0f);
+ // glEnable(GL_TEXTURE_2D);
+ // glBindTexture(GL_TEXTURE_2D, mTexId);
+ //}
+ //else {
+ // glColor3f(0.5f, 0.5f, 0.5f);
+ // glDisable(GL_TEXTURE_2D);
+ //}
+
+ glDrawElements(elementType, indices.size(), GL_UNSIGNED_INT, &indices[0]);
+ }
+ if (texCoords.size() > 0) {
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ }
+ if (colors.size() > 0) {
+ glDisableClientState(GL_COLOR_ARRAY);
+ }
+ if (rawVertices.size() > 0) {
+ // Also draw raw buffer
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(3, GL_FLOAT, sizeof(PxVec3), &rawVertices[0]);
+ if (rawNormals.size() > 0) {
+ glEnableClientState(GL_NORMAL_ARRAY);
+ glNormalPointer(GL_FLOAT, sizeof(PxVec3), &rawNormals[0]);
+ }
+ glDrawArrays(elementType, 0, rawVertices.size());
+
+
+ }
+ glDisableClientState(GL_VERTEX_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+
+
+ //glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ //glDisable(GL_TEXTURE_2D);
+
+
+}
+
diff --git a/KaplaDemo/samples/sampleViewer3/Render/glmesh.h b/KaplaDemo/samples/sampleViewer3/Render/glmesh.h
new file mode 100644
index 00000000..87097ab9
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/glmesh.h
@@ -0,0 +1,42 @@
+
+#ifndef __GLMESH_H__
+#define __GLMESH_H__
+#include <GL/glew.h>
+
+#include "PxPhysics.h"
+#include <vector>
+using namespace physx;
+class GLMesh{
+public:
+ GLMesh(GLuint elementTypei = GL_TRIANGLES);
+ ~GLMesh();
+ void draw();
+
+ // For indices
+ std::vector<PxU32> indices;
+ std::vector<PxVec3> vertices;
+ std::vector<PxVec3> normals;
+ std::vector<PxVec3> colors;
+ std::vector<float> texCoords; // treats as u v
+ std::vector<PxVec3> tangents;
+ std::vector<PxVec3> bitangents;
+
+ // For raw
+ std::vector<PxVec3> rawVertices;
+ std::vector<PxVec3> rawNormals;
+
+ void reset();
+ void genVBOIBO();
+ void updateVBOIBO(bool dynamicVB = true);
+ void drawVBOIBO(bool enable = true, bool draw = true, bool disable = true, bool drawpoints = false);
+
+ // For vertex buffer
+ GLuint vbo;
+ GLuint ibo;
+ bool firstTimeBO;
+ bool withTexture, withColor, withNormal, withTangent;
+ GLuint elementType;
+
+
+};
+#endif
diff --git a/KaplaDemo/samples/sampleViewer3/Render/newParameters.cpp b/KaplaDemo/samples/sampleViewer3/Render/newParameters.cpp
new file mode 100644
index 00000000..64b712ee
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/newParameters.cpp
@@ -0,0 +1,46 @@
+float seedDustRadius = 0.02f;
+//float seedDustNumPerSite = 15;
+//float seedDustNumPerSiteCollisionEvent = 3;
+float seedDustNumPerSite = 20;
+float seedDustNumPerSiteCollisionEvent = 4.5f;
+
+float applyForcePointAreaPerSample = 0.005f;
+float applyForceFromPointsDrag = 0.1f;
+//float noise3DScale = 1.5f;
+//float noise2DScale = 0.5f;
+float noiseKIsoDecay = 0.99f;
+float noiseKAniDecay = 0.99f;
+float noise3DScale = 0.75f*0.5f;
+float noise2DScale = 0.32f*0.5f;
+float dustMaxLife = 5.0f;
+float dustMinLife = 1.0f;
+float dustParticleOpacity = 0.1f;
+float dustParticleRenderRadius = 0.1f;
+float particleStartFade = 5.0f;
+float octaveScaling = 7.0f;
+float divStrength = 5.0f;
+float curDivStrength = 0.0f;
+float divStrengthReductionRate = 8.0f/30;
+
+bool doGaussianBlur = false;
+float blurVelSigmaFDX = 1.0f;
+float blurVelCenterFactor = 30.0f;
+float curlScale = 10.0f;
+
+float areaPerDustSample = 0.005f;
+float areaPerDebris = 0.02f;
+
+float minSizeDecayRate = 1.0f;
+float explodeVel = 3.0f;
+float numParPerMeteor = 3;
+
+float minMeteorDustLife = 2.0f;
+float maxMeteorDustLife = 2.3f;
+float minMeteorDustSize = 0.5f;
+float maxMeteorDustSize = 1.5f;
+float minMeteorSizeDecayRate = 1.0f;
+
+int maxNumDebrisPerType = 500; // Maximum number of debris per each type of debris
+float sleepingThresholdRB = 0.1f;
+float sleepingThresholdParticles = 0.1f;
+int maxNumDebrisToAdd = 100; \ No newline at end of file
diff --git a/KaplaDemo/samples/sampleViewer3/Render/newParameters.h b/KaplaDemo/samples/sampleViewer3/Render/newParameters.h
new file mode 100644
index 00000000..b1d26722
--- /dev/null
+++ b/KaplaDemo/samples/sampleViewer3/Render/newParameters.h
@@ -0,0 +1,42 @@
+#pragma once
+extern float seedDustRadius;
+extern float seedDustNumPerSite;
+extern float seedDustNumPerSiteCollisionEvent;
+extern float applyForcePointAreaPerSample;
+extern float applyForceFromPointsDrag;
+extern float noiseKIsoDecay;
+extern float noiseKAniDecay;
+extern float noise3DScale;
+extern float noise2DScale;
+extern float dustMaxLife;
+extern float dustMinLife;
+extern float dustParticleOpacity;
+extern float dustParticleRenderRadius;
+extern float particleStartFade;
+extern float octaveScaling;
+extern float divStrength;
+extern float curDivStrength;
+extern float divStrengthReductionRate;
+
+
+extern bool doGaussianBlur;
+extern float blurVelSigmaFDX;
+extern float blurVelCenterFactor;
+extern float curlScale;
+extern float areaPerDustSample;
+extern float areaPerDebris;
+extern float minSizeDecayRate;
+
+extern float explodeVel; // Velocity of debris
+extern float numParPerMeteor;
+
+extern float minMeteorDustLife;
+extern float maxMeteorDustLife;
+extern float minMeteorDustSize;
+extern float maxMeteorDustSize;
+
+extern int maxNumDebrisPerType;
+extern float sleepingThresholdRB;
+extern float sleepingThresholdParticles;
+extern int maxNumDebrisToAdd;
+extern float minMeteorSizeDecayRate; \ No newline at end of file