{$FPUTYPE SSE3}{$mode delphi}{$apptype gui}
program julia_fractal_cpu;
uses GL, GLU, GLEXT, Glut;
const
WIDTH = 512;
HEIGHT = 512;
type
TVec3 = record
R, G, B: Single;
end;
TSampler2D = array[0..255, 0..2] of Single;
var
FractalTexID: GLuint;
u_pal: TSampler2D;
FrameBufferRGB_F32: array[0..HEIGHT-1, 0..WIDTH-1, 0..2] of Single;
Cx: Single = -0.7;
Cy: Single = 0.27015;
Zoom: Single = 3.0;
procedure GenPalette;
var
i: Integer;
begin
//randomize;
for i := 0 to 255 do
begin
u_pal[i, 0] := random(1000) / 1000.0; // R (0.0 .. 1.0)
u_pal[i, 1] := random(1000) / 1000.0; // G (0.0 .. 1.0)
u_pal[i, 2] := random(1000) / 1000.0; // B (0.0 .. 1.0)
end;
end;
procedure InitFractalTexture;
begin
glGenTextures(1, @FractalTexID);
glBindTexture(GL_TEXTURE_2D, FractalTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, WIDTH, HEIGHT, 0, GL_RGB, GL_FLOAT, nil);
end;
function texture2D(const sampler: TSampler2D; TexCoordX, TexCoordY: Single): TVec3;inline;
var
RawValue: Single;
MapPos: Single;
Idx1, Idx2: Integer;
FracPart: Single;
begin
// vec2(x, y) * 0.5 + vec2(0.5, 0.5)
RawValue := TexCoordX * 0.5 + 0.5;
// Clamp
if RawValue < 0.0 then RawValue := 0.0;
if RawValue > 1.0 then RawValue := 1.0;
MapPos := RawValue * 255.0;
Idx1 := Trunc(MapPos);
Idx2 := Idx1 + 1;
if Idx2 > 255 then Idx2 := 255;
FracPart := MapPos - Idx1;
Result.R := sampler[Idx1, 0] + FracPart * (sampler[Idx2, 0] - sampler[Idx1, 0]);
Result.G := sampler[Idx1, 1] + FracPart * (sampler[Idx2, 1] - sampler[Idx1, 1]);
Result.B := sampler[Idx1, 2] + FracPart * (sampler[Idx2, 2] - sampler[Idx1, 2]);
end;
procedure RenderJuliaToFloatRGBBuffer;
var
px, py, i: Integer;
vTexCoordX, vTexCoordY: Single;
x, y, t: Single;
Color: TVec3;
begin
for py := 0 to HEIGHT - 1 do
begin
vTexCoordY := py / (HEIGHT - 1);
for px := 0 to WIDTH - 1 do
begin
vTexCoordX := px / (WIDTH - 1);
// float x = (vTexCoord.x - 0.5) * u_zoom;
x := (vTexCoordX - 0.5) * Zoom;
y := (vTexCoordY - 0.5) * Zoom;
for i := 0 to 19 do
begin // PLAZMA CUBE: (x * x) + (y * y)
t := (x * x) - (y * y) + Cx; // float t = (x * x) - (y * y) + u_cx;
y := (x + x) * y + Cy; // y = (x + x) * y + u_cy;
x := t; // x = t;
end;
// gl_FragColor = texture2D(u_pal, vec2(x, y) * 0.5 + vec2(0.5, 0.5));
Color := texture2D(u_pal, x, y);
FrameBufferRGB_F32[py, px, 0] := Color.R;
FrameBufferRGB_F32[py, px, 1] := Color.G;
FrameBufferRGB_F32[py, px, 2] := Color.B;
end;
end;
glBindTexture(GL_TEXTURE_2D, FractalTexID);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, WIDTH, HEIGHT, GL_RGB, GL_FLOAT, @FrameBufferRGB_F32);
end;
procedure DisplayProc; cdecl;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
RenderJuliaToFloatRGBBuffer;
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, FractalTexID);
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0);
glTexCoord2f(1.0, 0.0); glVertex2f( 1.0, -1.0);
glTexCoord2f(1.0, 1.0); glVertex2f( 1.0, 1.0);
glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, 1.0);
glEnd();
glDisable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
glutSwapBuffers();
end;
procedure ReshapeProc(w, h: Integer); cdecl;
begin
glViewport(0, 0, w, h);
end;
procedure PassiveMotionProc(x, y: Integer); cdecl;
begin
Cx := (x / glutGet(GLUT_WINDOW_WIDTH)) * 2.0 - 1.0;
Cy := ((glutGet(GLUT_WINDOW_HEIGHT) - y) / glutGet(GLUT_WINDOW_HEIGHT)) * 2.0 - 1.0;
glutPostRedisplay();
end;
procedure KeyboardProc(key: Byte; x, y: Integer); cdecl;
begin
case Chr(key) of
'+', '=': Zoom := Zoom * 0.85;
'-': Zoom := Zoom * 1.15;
'r','R': GenPalette;
#27: Halt(0);
end;
glutPostRedisplay();
end;
begin
glutInit(@argc, argv);
glutInitDisplayMode(GLUT_DOUBLE or GLUT_RGB or GLUT_DEPTH);
glutInitWindowSize(WIDTH, HEIGHT);
glutCreateWindow('Julia Set OpenGL 2.0 (CPU)'+' - FPC '+{$I %FPCVERSION%});
glutDisplayFunc(@DisplayProc);
glutReshapeFunc(@ReshapeProc);
glutKeyboardFunc(@KeyboardProc);
glutPassiveMotionFunc(@PassiveMotionProc);
GenPalette;
InitFractalTexture;
glClearColor(0.0, 0.0, 0.0, 1.0);
glutMainLoop();
end.