ay OpenGL in python aint bad
This commit is contained in:
Generated
+8
@@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.11" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredPackages">
|
||||
<value>
|
||||
<list size="11">
|
||||
<item index="0" class="java.lang.String" itemvalue="notebook_shim" />
|
||||
<item index="1" class="java.lang.String" itemvalue="jupyter_server" />
|
||||
<item index="2" class="java.lang.String" itemvalue="jupyterlab_widgets" />
|
||||
<item index="3" class="java.lang.String" itemvalue="automium_web" />
|
||||
<item index="4" class="java.lang.String" itemvalue="jupyterlab_pygments" />
|
||||
<item index="5" class="java.lang.String" itemvalue="jupyter_client" />
|
||||
<item index="6" class="java.lang.String" itemvalue="typing_extensions" />
|
||||
<item index="7" class="java.lang.String" itemvalue="jupyter_server_terminals" />
|
||||
<item index="8" class="java.lang.String" itemvalue="prometheus_client" />
|
||||
<item index="9" class="java.lang.String" itemvalue="jupyter_core" />
|
||||
<item index="10" class="java.lang.String" itemvalue="jupyterlab_server" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredIdentifiers">
|
||||
<list>
|
||||
<option value="statsmodels.tsa.arima.model.*" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
Generated
+7
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="C:\Users\0piet\miniconda3" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
Generated
+8
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/Mandelbrot.iml" filepath="$PROJECT_DIR$/.idea/Mandelbrot.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
Generated
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,199 @@
|
||||
import os
|
||||
import pygame
|
||||
import numpy as np
|
||||
import pyopencl as cl
|
||||
import threading
|
||||
from queue import Queue as ThreadQueue
|
||||
os.environ['PYOPENCL_COMPILER_OUTPUT'] = '1'
|
||||
os.environ['PYOPENCL_NO_CACHE'] = '1'
|
||||
|
||||
# Constants
|
||||
WIDTH, HEIGHT = 800, 600
|
||||
INITIAL_MAX_ITER = 256
|
||||
ZOOM_FACTOR = 1.2
|
||||
MIN_RENDER_WIDTH, MIN_RENDER_HEIGHT = 100, 75
|
||||
MAX_RENDER_WIDTH, MAX_RENDER_HEIGHT = WIDTH, HEIGHT
|
||||
|
||||
# Initialize Pygame
|
||||
pygame.init()
|
||||
screen = pygame.display.set_mode((WIDTH, HEIGHT))
|
||||
pygame.display.set_caption("Mandelbrot Set Zoom")
|
||||
|
||||
# OpenCL setup
|
||||
platform = cl.get_platforms()[0]
|
||||
device = platform.get_devices()[0]
|
||||
context = cl.Context([device])
|
||||
queue = cl.CommandQueue(context)
|
||||
program_src = """
|
||||
__kernel void mandelbrot(
|
||||
const int width, const int height,
|
||||
const float xmin, const float xmax,
|
||||
const float ymin, const float ymax,
|
||||
const int max_iter, __global int* output) {
|
||||
|
||||
int gid = get_global_id(0);
|
||||
int x = gid % width;
|
||||
int y = gid / width;
|
||||
|
||||
float real = xmin + (xmax - xmin) * x / (float) width;
|
||||
float imag = ymin + (ymax - ymin) * y / (float) height;
|
||||
float c_real = real;
|
||||
float c_imag = imag;
|
||||
|
||||
int iter;
|
||||
for (iter = 0; iter < max_iter; iter++) {
|
||||
float real2 = real * real;
|
||||
float imag2 = imag * imag;
|
||||
if (real2 + imag2 > 4.0f) break;
|
||||
imag = 2.0f * real * imag + c_imag;
|
||||
real = real2 - imag2 + c_real;
|
||||
}
|
||||
output[gid] = iter;
|
||||
}
|
||||
"""
|
||||
program = cl.Program(context, program_src).build()
|
||||
|
||||
# Functions to calculate Mandelbrot set using OpenCL
|
||||
def mandelbrot_set(xmin, xmax, ymin, ymax, width, height, max_iter):
|
||||
output = np.empty((height, width), dtype=np.int32)
|
||||
output_buffer = cl.Buffer(context, cl.mem_flags.WRITE_ONLY, output.nbytes)
|
||||
|
||||
program.mandelbrot(queue, (width * height,), None,
|
||||
np.int32(width), np.int32(height),
|
||||
np.float32(xmin), np.float32(xmax),
|
||||
np.float32(ymin), np.float32(ymax),
|
||||
np.int32(max_iter), output_buffer)
|
||||
|
||||
cl.enqueue_copy(queue, output, output_buffer).wait()
|
||||
return output
|
||||
|
||||
# Function to draw the Mandelbrot set with colors
|
||||
def draw_mandelbrot(surface, mandelbrot_image, width, height, max_iter):
|
||||
for x in range(width):
|
||||
for y in range(height):
|
||||
iter_count = mandelbrot_image[y, x]
|
||||
if iter_count == max_iter:
|
||||
color = (0, 0, 0)
|
||||
else:
|
||||
color = (iter_count % 256, (iter_count * 5) % 256, (iter_count * 13) % 256)
|
||||
surface.set_at((x, y), color)
|
||||
|
||||
# Initial boundaries
|
||||
xmin, xmax = -2.0, 1.0
|
||||
ymin, ymax = -1.5, 1.5
|
||||
|
||||
# Initial resolution and iteration count
|
||||
RENDER_WIDTH, RENDER_HEIGHT = 800, 600
|
||||
MAX_ITER = INITIAL_MAX_ITER
|
||||
|
||||
# Create a surface for rendering
|
||||
render_surface = pygame.Surface((RENDER_WIDTH, RENDER_HEIGHT))
|
||||
|
||||
# Variables for pre-rendering
|
||||
next_mandelbrot_image = None
|
||||
next_render_surface = None
|
||||
needs_update = False
|
||||
is_rendering = False
|
||||
|
||||
# Render queue setup
|
||||
render_queue = ThreadQueue()
|
||||
render_thread = None
|
||||
|
||||
def render_worker():
|
||||
global next_mandelbrot_image, next_render_surface, is_rendering
|
||||
while True:
|
||||
task = render_queue.get()
|
||||
if task is None:
|
||||
break
|
||||
print("Pre-rendering started")
|
||||
is_rendering = True
|
||||
next_mandelbrot_image = mandelbrot_set(xmin, xmax, ymin, ymax, RENDER_WIDTH, RENDER_HEIGHT, MAX_ITER)
|
||||
next_render_surface = pygame.Surface((RENDER_WIDTH, RENDER_HEIGHT))
|
||||
draw_mandelbrot(next_render_surface, next_mandelbrot_image, RENDER_WIDTH, RENDER_HEIGHT, MAX_ITER)
|
||||
is_rendering = False
|
||||
print("Pre-rendering finished")
|
||||
render_queue.task_done()
|
||||
|
||||
def start_new_render():
|
||||
global render_thread, needs_update
|
||||
if render_thread is None or not render_thread.is_alive():
|
||||
render_thread = threading.Thread(target=render_worker)
|
||||
render_thread.start()
|
||||
render_queue.put(True)
|
||||
needs_update = True
|
||||
|
||||
def auto_zoom(zoom_factor, mouse_x, mouse_y):
|
||||
global xmin, xmax, ymin, ymax, RENDER_WIDTH, RENDER_HEIGHT, MAX_ITER
|
||||
# Convert screen coordinates to fractal coordinates
|
||||
x_center = xmin + (xmax - xmin) * mouse_x / WIDTH
|
||||
y_center = ymin + (ymax - ymin) * mouse_y / HEIGHT
|
||||
width = (xmax - xmin) / zoom_factor
|
||||
height = (ymax - ymin) / zoom_factor
|
||||
xmin, xmax = x_center - width / 2, x_center + width / 2
|
||||
ymin, ymax = y_center - height / 2, y_center + height / 2
|
||||
RENDER_WIDTH = min(MAX_RENDER_WIDTH, int(RENDER_WIDTH * zoom_factor))
|
||||
RENDER_HEIGHT = min(MAX_RENDER_HEIGHT, int(RENDER_HEIGHT * zoom_factor))
|
||||
MAX_ITER = min(2048, int(MAX_ITER * zoom_factor))
|
||||
return pygame.Surface((RENDER_WIDTH, RENDER_HEIGHT))
|
||||
|
||||
# Start pre-rendering the first frame
|
||||
start_new_render()
|
||||
|
||||
# Main loop
|
||||
running = True
|
||||
auto_zooming = False
|
||||
mouse_x, mouse_y = WIDTH // 2, HEIGHT // 2 # Default to center
|
||||
|
||||
while running:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
elif event.type == pygame.KEYDOWN:
|
||||
if event.key == pygame.K_SPACE:
|
||||
auto_zooming = not auto_zooming
|
||||
print("Auto-zooming:", "ON" if auto_zooming else "OFF")
|
||||
elif event.type == pygame.MOUSEMOTION:
|
||||
mouse_x, mouse_y = event.pos
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN:
|
||||
if event.button == 1 and not is_rendering: # Left mouse button for zoom in
|
||||
render_surface = auto_zoom(ZOOM_FACTOR, *event.pos)
|
||||
start_new_render()
|
||||
print(f"Zoom in at {event.pos}: needs_update set to True")
|
||||
elif event.button == 3 and not is_rendering: # Right mouse button for zoom out
|
||||
render_surface = auto_zoom(1/ZOOM_FACTOR, *event.pos)
|
||||
start_new_render()
|
||||
print(f"Zoom out at {event.pos}: needs_update set to True")
|
||||
elif event.type == pygame.MOUSEWHEEL and not is_rendering:
|
||||
if event.y > 0: # Scroll up for zoom in
|
||||
render_surface = auto_zoom(ZOOM_FACTOR, mouse_x, mouse_y)
|
||||
start_new_render()
|
||||
print(f"Scroll up zoom at ({mouse_x}, {mouse_y}): needs_update set to True")
|
||||
elif event.y < 0: # Scroll down for zoom out
|
||||
render_surface = auto_zoom(1/ZOOM_FACTOR, mouse_x, mouse_y)
|
||||
start_new_render()
|
||||
print(f"Scroll down zoom at ({mouse_x}, {mouse_y}): needs_update set to True")
|
||||
|
||||
if auto_zooming and not is_rendering:
|
||||
render_surface = auto_zoom(ZOOM_FACTOR, mouse_x, mouse_y)
|
||||
start_new_render()
|
||||
print(f"Auto zoom at ({mouse_x}, {mouse_y}): needs_update set to True")
|
||||
|
||||
if next_render_surface is not None:
|
||||
print("Updating render_surface with pre-rendered surface")
|
||||
render_surface = next_render_surface
|
||||
next_render_surface = None
|
||||
next_mandelbrot_image = None
|
||||
needs_update = False
|
||||
if not is_rendering and not auto_zooming:
|
||||
start_new_render()
|
||||
|
||||
# Scale the render surface to the screen size and blit it
|
||||
scaled_surface = pygame.transform.scale(render_surface, (WIDTH, HEIGHT))
|
||||
screen.blit(scaled_surface, (0, 0))
|
||||
pygame.display.flip()
|
||||
|
||||
# Cleanup
|
||||
render_queue.put(None)
|
||||
if render_thread:
|
||||
render_thread.join()
|
||||
pygame.quit()
|
||||
@@ -0,0 +1,115 @@
|
||||
import pygame
|
||||
import numpy as np
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
# Constants
|
||||
WIDTH, HEIGHT = 800, 600
|
||||
MAX_ITER = 256
|
||||
ZOOM_FACTOR = 1.2
|
||||
RENDER_WIDTH, RENDER_HEIGHT = 400, 300 # Lower resolution for rendering
|
||||
|
||||
# Initialize Pygame
|
||||
pygame.init()
|
||||
screen = pygame.display.set_mode((WIDTH, HEIGHT))
|
||||
pygame.display.set_caption("Mandelbrot Set Zoom")
|
||||
|
||||
# Functions to calculate Mandelbrot set
|
||||
def mandelbrot(c, max_iter):
|
||||
z = c
|
||||
for n in range(max_iter):
|
||||
if abs(z) > 2:
|
||||
return n
|
||||
z = z * z + c
|
||||
return max_iter
|
||||
|
||||
def mandelbrot_row(xmin, xmax, ymin, ymax, width, height, max_iter, y):
|
||||
r1 = np.linspace(xmin, xmax, width)
|
||||
r2 = np.linspace(ymin, ymax, height)
|
||||
row = np.empty(width, dtype=np.int32)
|
||||
for i in range(width):
|
||||
row[i] = mandelbrot(r1[i] + 1j * r2[y], max_iter)
|
||||
return row
|
||||
|
||||
def mandelbrot_set(xmin, xmax, ymin, ymax, width, height, max_iter):
|
||||
with ThreadPoolExecutor() as executor:
|
||||
rows = list(executor.map(lambda y: mandelbrot_row(xmin, xmax, ymin, ymax, width, height, max_iter, y), range(height)))
|
||||
return np.array(rows)
|
||||
|
||||
def draw_mandelbrot(surface, mandelbrot_image, width, height):
|
||||
for x in range(width):
|
||||
for y in range(height):
|
||||
color_value = mandelbrot_image[y, x] / MAX_ITER * 255
|
||||
color = (int(color_value), int(color_value), int(color_value))
|
||||
surface.set_at((x, y), color)
|
||||
|
||||
# Initial boundaries
|
||||
xmin, xmax = -2.0, 1.0
|
||||
ymin, ymax = -1.5, 1.5
|
||||
|
||||
# Create a surface for rendering
|
||||
render_surface = pygame.Surface((RENDER_WIDTH, RENDER_HEIGHT))
|
||||
|
||||
# Main loop
|
||||
running = True
|
||||
needs_update = True
|
||||
|
||||
while running:
|
||||
for event in pygame.event.get():
|
||||
if event.type == pygame.QUIT:
|
||||
running = False
|
||||
elif event.type == pygame.MOUSEBUTTONDOWN:
|
||||
if event.button == 1: # Left mouse button for zoom in
|
||||
mouse_x, mouse_y = event.pos
|
||||
mouse_x = mouse_x * RENDER_WIDTH // WIDTH
|
||||
mouse_y = mouse_y * RENDER_HEIGHT // HEIGHT
|
||||
r1 = np.linspace(xmin, xmax, RENDER_WIDTH)
|
||||
r2 = np.linspace(ymin, ymax, RENDER_HEIGHT)
|
||||
x_center = r1[mouse_x]
|
||||
y_center = r2[mouse_y]
|
||||
width = (xmax - xmin) / ZOOM_FACTOR
|
||||
height = (ymax - ymin) / ZOOM_FACTOR
|
||||
xmin, xmax = x_center - width / 2, x_center + width / 2
|
||||
ymin, ymax = y_center - height / 2, y_center + height / 2
|
||||
needs_update = True
|
||||
elif event.button == 3: # Right mouse button for zoom out
|
||||
mouse_x, mouse_y = event.pos
|
||||
mouse_x = mouse_x * RENDER_WIDTH // WIDTH
|
||||
mouse_y = mouse_y * RENDER_HEIGHT // HEIGHT
|
||||
r1 = np.linspace(xmin, xmax, RENDER_WIDTH)
|
||||
r2 = np.linspace(ymin, ymax, RENDER_HEIGHT)
|
||||
x_center = r1[mouse_x]
|
||||
y_center = r2[mouse_y]
|
||||
width = (xmax - xmin) * ZOOM_FACTOR
|
||||
height = (ymax - ymin) * ZOOM_FACTOR
|
||||
xmin, xmax = x_center - width / 2, x_center + width / 2
|
||||
ymin, ymax = y_center - height / 2, y_center + height / 2
|
||||
needs_update = True
|
||||
elif event.type == pygame.MOUSEWHEEL:
|
||||
if event.y > 0: # Scroll up for zoom in
|
||||
x_center = (xmin + xmax) / 2
|
||||
y_center = (ymin + ymax) / 2
|
||||
width = (xmax - xmin) / ZOOM_FACTOR
|
||||
height = (ymax - ymin) / ZOOM_FACTOR
|
||||
xmin, xmax = x_center - width / 2, x_center + width / 2
|
||||
ymin, ymax = y_center - height / 2, y_center + height / 2
|
||||
needs_update = True
|
||||
elif event.y < 0: # Scroll down for zoom out
|
||||
x_center = (xmin + xmax) / 2
|
||||
y_center = (ymin + ymax) / 2
|
||||
width = (xmax - xmin) * ZOOM_FACTOR
|
||||
height = (ymax - ymin) * ZOOM_FACTOR
|
||||
xmin, xmax = x_center - width / 2, x_center + width / 2
|
||||
ymin, ymax = y_center - height / 2, y_center + height / 2
|
||||
needs_update = True
|
||||
|
||||
if needs_update:
|
||||
mandelbrot_image = mandelbrot_set(xmin, xmax, ymin, ymax, RENDER_WIDTH, RENDER_HEIGHT, MAX_ITER)
|
||||
draw_mandelbrot(render_surface, mandelbrot_image, RENDER_WIDTH, RENDER_HEIGHT)
|
||||
needs_update = False
|
||||
|
||||
# Scale the render surface to the screen size and blit it
|
||||
scaled_surface = pygame.transform.scale(render_surface, (WIDTH, HEIGHT))
|
||||
screen.blit(scaled_surface, (0, 0))
|
||||
pygame.display.flip()
|
||||
|
||||
pygame.quit()
|
||||
Reference in New Issue
Block a user