kopia lustrzana https://github.com/jameshball/osci-render
63 wiersze
1.8 KiB
GLSL
63 wiersze
1.8 KiB
GLSL
std::string lineFragmentShader = R"(
|
|
|
|
#define EPS 1E-6
|
|
#define TAU 6.283185307179586
|
|
#define TAUR 2.5066282746310002
|
|
#define SQRT2 1.4142135623730951
|
|
|
|
uniform float uSize;
|
|
uniform float uIntensity;
|
|
uniform vec2 uOffset;
|
|
uniform vec2 uScale;
|
|
uniform float uScreenOverlay;
|
|
uniform float uFishEye;
|
|
uniform sampler2D uScreen;
|
|
varying float vSize;
|
|
varying vec4 uvl;
|
|
varying vec2 vTexCoord;
|
|
|
|
// A standard gaussian function, used for weighting samples
|
|
float gaussian(float x, float sigma) {
|
|
return exp(-(x * x) / (2.0 * sigma * sigma)) / (TAUR * sigma);
|
|
}
|
|
|
|
// This approximates the error function, needed for the gaussian integral
|
|
float erf(float x) {
|
|
float s = sign(x), a = abs(x);
|
|
x = 1.0 + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a;
|
|
x *= x;
|
|
return s - s / (x * x);
|
|
}
|
|
|
|
void main() {
|
|
// fish eye distortion
|
|
vec2 uv = vTexCoord - vec2(0.5);
|
|
float uva = atan(uv.x, uv.y);
|
|
float uvd = sqrt(dot(uv, uv));
|
|
uvd = uvd * (1.0 - uFishEye * uvd * uvd);
|
|
vec2 texCoord = vec2(0.5) + vec2(sin(uva), cos(uva)) * uvd;
|
|
|
|
texCoord = (texCoord - uOffset - 0.5) * uScale + 0.5;
|
|
|
|
float len = uvl.z;
|
|
vec2 xy = uvl.xy;
|
|
float brightness;
|
|
|
|
float sigma = vSize/5.0;
|
|
if (len < EPS) {
|
|
// If the beam segment is too short, just calculate intensity at the position.
|
|
brightness = gaussian(length(xy), sigma);
|
|
} else {
|
|
// Otherwise, use analytical integral for accumulated intensity.
|
|
brightness = erf(xy.x/SQRT2/sigma) - erf((xy.x-len)/SQRT2/sigma);
|
|
brightness *= exp(-xy.y*xy.y/(2.0*sigma*sigma))/2.0/len;
|
|
}
|
|
|
|
brightness *= uvl.w;
|
|
|
|
gl_FragColor = 2.0 * texture2D(uScreen, texCoord) * brightness;
|
|
gl_FragColor.a = 1.0;
|
|
}
|
|
|
|
)";
|