Added julia set shader example.
This commit is contained in:
parent
561c486ceb
commit
49a49e492a
4 changed files with 300 additions and 0 deletions
86
examples/shaders/resources/shaders/glsl330/julia_shader.fs
Normal file
86
examples/shaders/resources/shaders/glsl330/julia_shader.fs
Normal file
|
@ -0,0 +1,86 @@
|
|||
#version 330
|
||||
|
||||
// Input vertex attributes (from vertex shader)
|
||||
|
||||
uniform vec2 screenDims; // Dimensions of the screen
|
||||
uniform vec2 c; // c.x = real, c.y = imaginary component. Equation done is z^2 + c
|
||||
uniform vec2 offset; // Offset of the scale.
|
||||
uniform float zoom; // Zoom of the scale.
|
||||
|
||||
// Output fragment color
|
||||
out vec4 finalColor;
|
||||
|
||||
const int MAX_ITERATIONS = 255; // Max iterations to do.
|
||||
|
||||
// Square a complex number
|
||||
vec2 complexSquare(vec2 z)
|
||||
{
|
||||
return vec2(
|
||||
z.x * z.x - z.y * z.y,
|
||||
z.x * z.y * 2.0
|
||||
);
|
||||
}
|
||||
|
||||
// Convert Hue Saturation Value color into RGB
|
||||
vec3 hsv2rgb(vec3 c)
|
||||
{
|
||||
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
||||
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
||||
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// The pixel coordinates scaled so they are on the mandelbrot scale.
|
||||
vec2 z = vec2(((gl_FragCoord.x + offset.x)/screenDims.x) * 2.5 * zoom,
|
||||
((screenDims.y - gl_FragCoord.y + offset.y)/screenDims.y) * 1.5 * zoom); // y also flipped due to opengl
|
||||
int iterations = 0;
|
||||
|
||||
/*
|
||||
Julia sets use a function z^2 + c, where c is a constant.
|
||||
This function is iterated until the nature of the point is determined.
|
||||
|
||||
If the magnitude of the number becomes greater than 2, then from that point onward
|
||||
the number will get bigger and bigger, and will never get smaller (tends towards infinity).
|
||||
2^2 = 4, 4^2 = 8 and so on.
|
||||
So at 2 we stop iterating.
|
||||
|
||||
If the number is below 2, we keep iterating.
|
||||
But when do we stop iterating if the number is always below 2 (it converges)?
|
||||
That is what MAX_ITERATIONS is for.
|
||||
Then we can divide the iterations by the MAX_ITERATIONS value to get a normalized value that we can
|
||||
then map to a color.
|
||||
|
||||
We use dot product (z.x * z.x + z.y * z.y) to determine the magnitude (length) squared.
|
||||
And once the magnitude squared is > 4, then magnitude > 2 is also true (saves computational power).
|
||||
*/
|
||||
for (iterations = 0; iterations < MAX_ITERATIONS; iterations++)
|
||||
{
|
||||
z = complexSquare(z) + c; // Iterate function
|
||||
if (dot(z, z) > 4.0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Another few iterations decreases errors in the smoothing calculation.
|
||||
// See http://linas.org/art-gallery/escape/escape.html for more information.
|
||||
z = complexSquare(z) + c;
|
||||
z = complexSquare(z) + c;
|
||||
|
||||
// This last part smooths the color (again see link above).
|
||||
float smoothVal = float(iterations) + 1.0 - (log(log(length(z)))/log(2.0));
|
||||
|
||||
// Normalize the value so it is between 0 and 1.
|
||||
float norm = smoothVal/float(MAX_ITERATIONS);
|
||||
|
||||
// If in set, color black. 0.999 allows for some float accuracy error.
|
||||
if (norm > 0.999)
|
||||
{
|
||||
finalColor = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
} else
|
||||
{
|
||||
finalColor = vec4(hsv2rgb(vec3(norm, 1.0, 1.0)), 1.0);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue