/* MIT License Copyright (c) 2022 railgunSR Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* THIS MAKES USE OF OPENSIMPLEX2, A NOISE ALGORITHM CREATED BY THE FINE FOLKS OVER AT https://github.com/KdotJPG/OpenSimplex2 PLEASE GIVE THEM SOME LOVE. IT ALSO MAKES USE OF FUNCTIONS FROM THE_FORCE, A SHADER IDE https://github.com/shawnlawson/The_Force */ //version #version 330 core //output // out vec4 fragColor; layout (location = 0) out vec4 accum; layout (location = 1) out float reveal; //input in vec3 FragPos; in vec3 Normal; in vec2 TexCoord; in vec4 projCoord; in vec4 modelCoord; //uniforms uniform float time; //layout uniforms uniform sampler2D shadowMap; uniform sampler2D volumeDepthFrontface; uniform sampler2D volumeDepthBackface; //transform matrices uniforms uniform mat4 model; uniform mat4 view; uniform mat4 projection; //function declarations vec4 openSimplex2_Conventional(vec3 X); vec4 openSimplex2_ImproveXY(vec3 X); float flameTex(float x, float y); float getNoise(float scale, float timeScale); float voronoi(vec2 point); vec3 voronoi(vec3 x); float linearCenterAroundPoint(float inputPt, float centerpoint, float falloff); /* Main method */ void main(){ float timeS = time * 0.003; // Normalized pixel coordinates (from 0 to 1) vec3 projCoordNorm = projCoord.xyz / projCoord.w / 2.0 + 0.5; //make vec2 vec2 finalProd = projCoordNorm.xy; //grab depth values float closeDepth = texture(volumeDepthFrontface, finalProd.xy).r; float farDepth = texture(volumeDepthBackface, finalProd.xy).r; //distance between the two float volume = min(abs(farDepth - closeDepth),1); //based on distance of model coords from center float dist = length(modelCoord.xyz); //https://stackoverflow.com/questions/38938498/how-do-i-convert-gl-fragcoord-to-a-world-space-point-in-a-fragment-shader vec4 ndcPos; ndcPos.xy = ((2.0 * gl_FragCoord.xy) - (2.0 * projCoord.xy)) / (projCoord.zw) - 1; ndcPos.z = (2.0 * gl_FragCoord.z - gl_DepthRange.near - gl_DepthRange.far) / (gl_DepthRange.far - gl_DepthRange.near); ndcPos.w = 1.0; vec4 clipPos = ndcPos / gl_FragCoord.w; // vec4 eyePos = inverse(model) * inverse(view) * inverse(projection) * clipPos; vec4 eyePos = inverse(projection) * inverse(view) * inverse(model) * clipPos; float red = 0.1984; float green = 0.6464; float blue = 0.7366; float alpha = volume * 7.0; vec4 noiseVal = openSimplex2_Conventional(vec3( projCoordNorm.x * 20, projCoordNorm.y * 20, projCoordNorm.z * 20 + timeS * 3)); vec4 color = vec4( FragPos.x / 10, FragPos.y / 10, FragPos.z / 10, alpha * volume ); // weight function float weight = clamp(pow(min(1.0, color.a * 10.0) + 0.01, 3.0) * 1e8 * pow(1.0 - gl_FragCoord.z * 0.9, 3.0), 1e-2, 3e3); // store pixel color accumulation accum = vec4(color.rgb,1); // store pixel revealage threshold reveal = volume; // reveal = 1.0; // if(val < 0.3){ // discard; // } // Output to screen // fragColor = color; } float getNoise(float scale, float time){ float noiseInX = modelCoord.x * scale; float noiseInZ = FragPos.y * scale - time; float noiseInY = modelCoord.y * scale; float noise = openSimplex2_ImproveXY(vec3(noiseInX,noiseInY,noiseInZ)).x; return noise; } //////////////// K.jpg's Re-oriented 4-Point BCC Noise (OpenSimplex2) //////////////// ////////////////////// Output: vec4(dF/dx, dF/dy, dF/dz, value) ////////////////////// // Inspired by Stefan Gustavson's noise vec4 permute(vec4 t) { return t * (t * 34.0 + 133.0); } // Gradient set is a normalized expanded rhombic dodecahedron vec3 grad(float hash) { // Random vertex of a cube, +/- 1 each vec3 cube = mod(floor(hash / vec3(1.0, 2.0, 4.0)), 2.0) * 2.0 - 1.0; // Random edge of the three edges connected to that vertex // Also a cuboctahedral vertex // And corresponds to the face of its dual, the rhombic dodecahedron vec3 cuboct = cube; cuboct[int(hash / 16.0)] = 0.0; // In a funky way, pick one of the four points on the rhombic face float type = mod(floor(hash / 8.0), 2.0); vec3 rhomb = (1.0 - type) * cube + type * (cuboct + cross(cube, cuboct)); // Expand it so that the new edges are the same length // as the existing ones vec3 grad = cuboct * 1.22474487139 + rhomb; // To make all gradients the same length, we only need to shorten the // second type of vector. We also put in the whole noise scale constant. // The compiler should reduce it into the existing floats. I think. grad *= (1.0 - 0.042942436724648037 * type) * 32.80201376986577; return grad; } // BCC lattice split up into 2 cube lattices vec4 openSimplex2Base(vec3 X) { // First half-lattice, closest edge vec3 v1 = round(X); vec3 d1 = X - v1; vec3 score1 = abs(d1); vec3 dir1 = step(max(score1.yzx, score1.zxy), score1); vec3 v2 = v1 + dir1 * sign(d1); vec3 d2 = X - v2; // Second half-lattice, closest edge vec3 X2 = X + 144.5; vec3 v3 = round(X2); vec3 d3 = X2 - v3; vec3 score2 = abs(d3); vec3 dir2 = step(max(score2.yzx, score2.zxy), score2); vec3 v4 = v3 + dir2 * sign(d3); vec3 d4 = X2 - v4; // Gradient hashes for the four points, two from each half-lattice vec4 hashes = permute(mod(vec4(v1.x, v2.x, v3.x, v4.x), 289.0)); hashes = permute(mod(hashes + vec4(v1.y, v2.y, v3.y, v4.y), 289.0)); hashes = mod(permute(mod(hashes + vec4(v1.z, v2.z, v3.z, v4.z), 289.0)), 48.0); // Gradient extrapolations & kernel function vec4 a = max(0.5 - vec4(dot(d1, d1), dot(d2, d2), dot(d3, d3), dot(d4, d4)), 0.0); vec4 aa = a * a; vec4 aaaa = aa * aa; vec3 g1 = grad(hashes.x); vec3 g2 = grad(hashes.y); vec3 g3 = grad(hashes.z); vec3 g4 = grad(hashes.w); vec4 extrapolations = vec4(dot(d1, g1), dot(d2, g2), dot(d3, g3), dot(d4, g4)); // Derivatives of the noise vec3 derivative = -8.0 * mat4x3(d1, d2, d3, d4) * (aa * a * extrapolations) + mat4x3(g1, g2, g3, g4) * aaaa; // Return it all as a vec4 return vec4(derivative, dot(aaaa, extrapolations)); } // Use this if you don't want Z to look different from X and Y vec4 openSimplex2_Conventional(vec3 X) { // Rotate around the main diagonal. Not a skew transform. vec4 result = openSimplex2Base(dot(X, vec3(2.0/3.0)) - X); return vec4(dot(result.xyz, vec3(2.0/3.0)) - result.xyz, result.w); } // Use this if you want to show X and Y in a plane, then use Z for time, vertical, etc. vec4 openSimplex2_ImproveXY(vec3 X) { // Rotate so Z points down the main diagonal. Not a skew transform. mat3 orthonormalMap = mat3( 0.788675134594813, -0.211324865405187, -0.577350269189626, -0.211324865405187, 0.788675134594813, -0.577350269189626, 0.577350269189626, 0.577350269189626, 0.577350269189626); vec4 result = openSimplex2Base(orthonormalMap * X); return vec4(result.xyz * orthonormalMap, result.w); } const mat2 myt = mat2(.12121212,.13131313,-.13131313,.12121212); const vec2 mys = vec2(1e4, 1e6); vec2 rhash(vec2 uv) { uv *= myt; uv *= mys; return fract(fract(uv/mys)*uv); } vec3 hash( vec3 p ){ return fract(sin(vec3( dot(p,vec3(1.0,57.0,113.0)), dot(p,vec3(57.0,113.0,1.0)), dot(p,vec3(113.0,1.0,57.0))))*43758.5453); } float voronoi(vec2 point){ vec2 p = floor( point ); vec2 f = fract( point ); float res = 0.0; for( int j=-1; j<=1; j++ ) { for( int i=-1; i<=1; i++ ) { vec2 b = vec2( i, j ); vec2 r = vec2( b ) - f + rhash( p + b); res += 1./pow(dot(r,r),8.); } } return pow(1./res, 0.0625); } vec3 voronoi(vec3 x) { vec3 p = floor( x ); vec3 f = fract( x ); float id = 0.0; vec2 res = vec2( 100.0 ); for( int k=-1; k<=1; k++ ) { for( int j=-1; j<=1; j++ ) { for( int i=-1; i<=1; i++ ) { vec3 b = vec3( float(i), float(j), float(k) ); vec3 r = vec3( b ) - f + hash( p + b ); float d = dot( r, r ); if( d < res.x ) { id = dot( p+b, vec3(1.0,57.0,113.0 ) ); res = vec2( d, res.x ); } else if( d < res.y ) { res.y = d; } } } } return vec3( sqrt( res ), abs(id) ); } //////////////////////////////// End noise code //////////////////////////////// float linearCenterAroundPoint(float inputPt, float centerpoint, float falloff){ return max(((-abs(inputPt - centerpoint)) + centerpoint)*falloff,0); }