some new things, mostly not working or finished
This commit is contained in:
50
math/LaunchProcess0279191077.debugTarget
Normal file
50
math/LaunchProcess0279191077.debugTarget
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TargetConfig Name="C:\Users\Sebastian\Desktop\INF6B\math\mandelbrot.exe" LastUsed="2025-11-06T09:04:37.9520296Z">
|
||||
<EngineConfig />
|
||||
<EngineOptions>
|
||||
<Property name="DebugChildProcesses" value="false" />
|
||||
</EngineOptions>
|
||||
<TargetOptions>
|
||||
<Option name="LaunchProcess">
|
||||
<Property name="Executable" value="C:\Users\Sebastian\Desktop\INF6B\math\mandelbrot.exe" />
|
||||
<Property name="Arguments" value="" />
|
||||
</Option>
|
||||
<Option name="RestoreCommandHistory">
|
||||
<Property name="History">
|
||||
<Property value="gn" />
|
||||
<Property value="g" />
|
||||
<Property value="p" />
|
||||
<Property value=".restart" />
|
||||
<Property value="uf mandelbrot!Render" />
|
||||
<Property value="x mandelbrot!Render" />
|
||||
<Property value="dv" />
|
||||
<Property value="!heap" />
|
||||
<Property value="x mandelbrot!*" />
|
||||
<Property value="u 0x507cc0" />
|
||||
<Property value="uf 0x507cc0" />
|
||||
<Property value="uf mandelbrot!Complex" />
|
||||
<Property value="x mandelbrot!complex" />
|
||||
<Property value="x mandelbrot!complex_scale" />
|
||||
<Property value="u 0x508360" />
|
||||
</Property>
|
||||
</Option>
|
||||
<Option name="RestoreBreakpoints">
|
||||
<Property name="Breakpoints">
|
||||
<Property>
|
||||
<Property name="Id" value="0" />
|
||||
<Property name="IsEnabled" value="true" />
|
||||
<Property name="OffsetExpression" value="mandelbrot!color_mandelbrot" />
|
||||
<Property name="Command" value="" />
|
||||
<Property name="PassCount" value="1" />
|
||||
<Property name="SymbolName" value="mandelbrot!color_mandelbrot" />
|
||||
<Property name="Location" value="mandelbrot!color_mandelbrot" />
|
||||
<Property name="Address" value="0" />
|
||||
<Property name="Module" value="mandelbrot" />
|
||||
<Property name="Filename" value="C:\Users\Sebastian\Desktop\INF6B\math\mandelbrot.c" />
|
||||
<Property name="Line" value="47" />
|
||||
<Property name="Type" value="Software" />
|
||||
</Property>
|
||||
</Property>
|
||||
</Option>
|
||||
</TargetOptions>
|
||||
</TargetConfig>
|
||||
98
math/complex.c
Normal file
98
math/complex.c
Normal file
@@ -0,0 +1,98 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "complex.h"
|
||||
|
||||
// Constructors
|
||||
Complex complex_new(double re, double im) {
|
||||
Complex z;
|
||||
z.re = re;
|
||||
z.im = im;
|
||||
return z;
|
||||
}
|
||||
|
||||
// Add
|
||||
Complex complex_add(Complex a, Complex b) {
|
||||
return complex_new(a.re + b.re, a.im + b.im);
|
||||
}
|
||||
|
||||
// Subtract
|
||||
Complex complex_sub(Complex a, Complex b) {
|
||||
return complex_new(a.re - b.re, a.im - b.im);
|
||||
}
|
||||
|
||||
// Multiply
|
||||
Complex complex_mul(Complex a, Complex b) {
|
||||
return complex_new(a.re * b.re - a.im * b.im,
|
||||
a.re * b.im + a.im * b.re);
|
||||
}
|
||||
|
||||
// Divide
|
||||
Complex complex_div(Complex a, Complex b) {
|
||||
double denom = b.re * b.re + b.im * b.im;
|
||||
return complex_new((a.re * b.re + a.im * b.im) / denom,
|
||||
(a.im * b.re - a.re * b.im) / denom);
|
||||
}
|
||||
|
||||
// Scalar multiply
|
||||
Complex complex_scale(Complex a, double alpha) {
|
||||
return complex_new(a.re * alpha, a.im * alpha);
|
||||
}
|
||||
|
||||
// Conjugate
|
||||
Complex complex_conjugate(Complex a) {
|
||||
return complex_new(a.re, -a.im);
|
||||
}
|
||||
|
||||
// Reciprocal
|
||||
Complex complex_reciprocal(Complex a) {
|
||||
double scale = a.re * a.re + a.im * a.im;
|
||||
return complex_new(a.re / scale, -a.im / scale);
|
||||
}
|
||||
|
||||
// Magnitude (faster than hypot)
|
||||
double complex_abs(Complex a) {
|
||||
return sqrt(a.re * a.re + a.im * a.im);
|
||||
}
|
||||
|
||||
// Phase
|
||||
double complex_phase(Complex a) {
|
||||
return atan2(a.im, a.re);
|
||||
}
|
||||
|
||||
// Exponential
|
||||
Complex complex_exp(Complex a) {
|
||||
double exp_re = exp(a.re);
|
||||
return complex_new(exp_re * cos(a.im),
|
||||
exp_re * sin(a.im));
|
||||
}
|
||||
|
||||
// Sine
|
||||
Complex complex_sin(Complex a) {
|
||||
return complex_new(sin(a.re) * cosh(a.im),
|
||||
cos(a.re) * sinh(a.im));
|
||||
}
|
||||
|
||||
// Cosine
|
||||
Complex complex_cos(Complex a) {
|
||||
return complex_new(cos(a.re) * cosh(a.im),
|
||||
-sin(a.re) * sinh(a.im));
|
||||
}
|
||||
|
||||
// Tangent
|
||||
Complex complex_tan(Complex a) {
|
||||
Complex s = complex_sin(a);
|
||||
Complex c = complex_cos(a);
|
||||
return complex_div(s, c);
|
||||
}
|
||||
|
||||
// Print function
|
||||
void complex_print(Complex a) {
|
||||
if (a.im == 0)
|
||||
printf("%g", a.re);
|
||||
else if (a.re == 0)
|
||||
printf("%gi", a.im);
|
||||
else if (a.im < 0)
|
||||
printf("%g - %gi", a.re, -a.im);
|
||||
else
|
||||
printf("%g + %gi", a.re, a.im);
|
||||
}
|
||||
25
math/complex.h
Normal file
25
math/complex.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef COMPLEX_H
|
||||
#define COMPLEX_H
|
||||
|
||||
typedef struct {
|
||||
double re;
|
||||
double im;
|
||||
} Complex;
|
||||
|
||||
Complex complex_new(double re, double im);
|
||||
Complex complex_add(Complex a, Complex b);
|
||||
Complex complex_sub(Complex a, Complex b);
|
||||
Complex complex_mul(Complex a, Complex b);
|
||||
Complex complex_div(Complex a, Complex b);
|
||||
Complex complex_scale(Complex a, double alpha);
|
||||
Complex complex_conjugate(Complex a);
|
||||
Complex complex_reciprocal(Complex a);
|
||||
double complex_abs(Complex a);
|
||||
double complex_phase(Complex a);
|
||||
Complex complex_exp(Complex a);
|
||||
Complex complex_sin(Complex a);
|
||||
Complex complex_cos(Complex a);
|
||||
Complex complex_tan(Complex a);
|
||||
void complex_print(Complex a);
|
||||
|
||||
#endif
|
||||
227
math/main.cpp
Normal file
227
math/main.cpp
Normal file
@@ -0,0 +1,227 @@
|
||||
#include <windows.h>
|
||||
#include <d3d11.h>
|
||||
#include <d3dcompiler.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#pragma comment(lib, "d3d11.lib")
|
||||
#pragma comment(lib, "D3DCompiler.lib")
|
||||
|
||||
HWND hwnd = nullptr;
|
||||
ID3D11Device* device = nullptr;
|
||||
ID3D11DeviceContext* context = nullptr;
|
||||
IDXGISwapChain* swapChain = nullptr;
|
||||
ID3D11RenderTargetView* rtv = nullptr;
|
||||
ID3D11VertexShader* vs = nullptr;
|
||||
ID3D11PixelShader* ps = nullptr;
|
||||
ID3D11InputLayout* inputLayout = nullptr;
|
||||
ID3D11Buffer* vertexBuffer = nullptr;
|
||||
|
||||
// Vertex struct
|
||||
struct Vertex { float x, y; };
|
||||
|
||||
// Vertex shader
|
||||
const char* vsSrc = R"(
|
||||
struct VS_INPUT { float2 pos : POSITION; };
|
||||
struct PS_INPUT { float4 pos : SV_POSITION; float2 uv : TEXCOORD; };
|
||||
PS_INPUT main(VS_INPUT input) {
|
||||
PS_INPUT output;
|
||||
output.pos = float4(input.pos,0,1);
|
||||
output.uv = input.pos*0.5+0.5;
|
||||
return output;
|
||||
}
|
||||
)";
|
||||
|
||||
char psSrc[2048]; // Pixel shader
|
||||
|
||||
// Mandelbrot view presets
|
||||
struct View { float xMin, xMax, yMin, yMax; };
|
||||
View views[] = {
|
||||
{-2.5f, 1.0f, -1.2f, 1.2f}, // Full set
|
||||
{-0.748f, -0.743f, 0.1f, 0.105f}, // Seahorse Valley
|
||||
{-0.74877f, -0.74872f, 0.06505f, 0.06510f}, // Mini zoom
|
||||
};
|
||||
int currentView = 0;
|
||||
|
||||
// Forward declarations
|
||||
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
||||
bool InitWindow(HINSTANCE, int);
|
||||
bool InitD3D();
|
||||
void CleanUp();
|
||||
bool CompileShaders();
|
||||
void Render();
|
||||
|
||||
// Main
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) {
|
||||
if (!InitWindow(hInstance, nCmdShow)) return 0;
|
||||
if (!InitD3D()) return 0;
|
||||
|
||||
CompileShaders();
|
||||
|
||||
MSG msg = {};
|
||||
while (msg.message != WM_QUIT) {
|
||||
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
else {
|
||||
Render(); // non-blocking rendering
|
||||
}
|
||||
}
|
||||
|
||||
CleanUp();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// --- Window ---
|
||||
bool InitWindow(HINSTANCE hInstance, int nCmdShow) {
|
||||
const char CLASS_NAME[] = "MandelbrotDX11";
|
||||
WNDCLASS wc = {};
|
||||
wc.lpfnWndProc = WndProc;
|
||||
wc.hInstance = hInstance;
|
||||
wc.lpszClassName = CLASS_NAME;
|
||||
RegisterClass(&wc);
|
||||
|
||||
hwnd = CreateWindowEx(0, CLASS_NAME, "DX11 Mandelbrot", WS_OVERLAPPEDWINDOW,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, nullptr, nullptr, hInstance, nullptr);
|
||||
if (!hwnd) return false;
|
||||
ShowWindow(hwnd, nCmdShow);
|
||||
return true;
|
||||
}
|
||||
|
||||
// --- WinProc ---
|
||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||
switch (msg) {
|
||||
case WM_DESTROY: PostQuitMessage(0); return 0;
|
||||
case WM_KEYDOWN:
|
||||
if (wParam == VK_ESCAPE) PostQuitMessage(0);
|
||||
if (wParam == VK_LEFT) currentView = (currentView + 2) % 3;
|
||||
if (wParam == VK_RIGHT) currentView = (currentView + 1) % 3;
|
||||
CompileShaders();
|
||||
return 0;
|
||||
}
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
// --- D3D11 Init ---
|
||||
bool InitD3D() {
|
||||
DXGI_SWAP_CHAIN_DESC scd = {};
|
||||
scd.BufferCount = 1;
|
||||
scd.BufferDesc.Width = 800;
|
||||
scd.BufferDesc.Height = 600;
|
||||
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
scd.BufferDesc.RefreshRate.Numerator = 60;
|
||||
scd.BufferDesc.RefreshRate.Denominator = 1;
|
||||
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
scd.OutputWindow = hwnd;
|
||||
scd.SampleDesc.Count = 1;
|
||||
scd.Windowed = TRUE;
|
||||
|
||||
D3D_FEATURE_LEVEL featureLevel;
|
||||
if (FAILED(D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr,
|
||||
0, nullptr, 0, D3D11_SDK_VERSION, &scd,
|
||||
&swapChain, &device, &featureLevel, &context))) return false;
|
||||
|
||||
ID3D11Texture2D* backBuffer = nullptr;
|
||||
swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&backBuffer);
|
||||
device->CreateRenderTargetView(backBuffer, nullptr, &rtv);
|
||||
backBuffer->Release();
|
||||
context->OMSetRenderTargets(1, &rtv, nullptr);
|
||||
|
||||
D3D11_VIEWPORT vp = {};
|
||||
vp.Width = 800; vp.Height = 600; vp.MinDepth = 0; vp.MaxDepth = 1;
|
||||
context->RSSetViewports(1, &vp);
|
||||
|
||||
Vertex verts[] = { {-1,-1},{-1,1},{1,-1},{1,1} };
|
||||
D3D11_BUFFER_DESC bd = {};
|
||||
bd.Usage = D3D11_USAGE_DEFAULT;
|
||||
bd.ByteWidth = sizeof(verts);
|
||||
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
D3D11_SUBRESOURCE_DATA initData = {};
|
||||
initData.pSysMem = verts;
|
||||
device->CreateBuffer(&bd, &initData, &vertexBuffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// --- Compile shaders ---
|
||||
bool CompileShaders() {
|
||||
// Pixel shader template with smooth coloring
|
||||
snprintf(psSrc, sizeof(psSrc),
|
||||
R"(struct PS_INPUT { float4 pos:SV_POSITION; float2 uv: TEXCOORD; };
|
||||
float mandelbrot(float2 c){
|
||||
float2 z=0;
|
||||
float iter=0;
|
||||
const int MAX_ITER=256;
|
||||
for(int i=0;i<MAX_ITER;i++){
|
||||
float x=z.x*z.x - z.y*z.y + (c.x*%.8f+%.8f);
|
||||
float y=2*z.x*z.y + (c.y*%.8f+%.8f);
|
||||
z=float2(x,y);
|
||||
if(dot(z,z)>4){iter=i; break;}
|
||||
}
|
||||
return iter;
|
||||
}
|
||||
float4 main(PS_INPUT input):SV_TARGET{
|
||||
float iter=mandelbrot(input.uv);
|
||||
const float MAX_ITER=256.0;
|
||||
// Original color mapping (smooth)
|
||||
float t = iter / MAX_ITER;
|
||||
float r = clamp(9.0*(1.0-t)*t*t*t,0,1);
|
||||
float g = clamp(15.0*(1.0-t)*(1.0-t)*t*t,0,1);
|
||||
float b = clamp(8.5*(1.0-t)*(1.0-t)*(1.0-t)*t,0,1);
|
||||
return float4(r,g,b,1.0);
|
||||
})",
|
||||
(views[currentView].xMax - views[currentView].xMin), views[currentView].xMin,
|
||||
(views[currentView].yMax - views[currentView].yMin), views[currentView].yMin
|
||||
);
|
||||
|
||||
ID3DBlob* vsBlob = nullptr, * psBlob = nullptr, * err = nullptr;
|
||||
|
||||
if (FAILED(D3DCompile(vsSrc, strlen(vsSrc), nullptr, nullptr, nullptr, "main", "vs_5_0", 0, 0, &vsBlob, &err))) {
|
||||
if (err) { OutputDebugStringA((char*)err->GetBufferPointer()); err->Release(); } return false;
|
||||
}
|
||||
if (FAILED(D3DCompile(psSrc, strlen(psSrc), nullptr, nullptr, nullptr, "main", "ps_5_0", 0, 0, &psBlob, &err))) {
|
||||
if (err) { OutputDebugStringA((char*)err->GetBufferPointer()); err->Release(); } return false;
|
||||
}
|
||||
|
||||
if (vs) vs->Release();
|
||||
if (ps) ps->Release();
|
||||
if (inputLayout) inputLayout->Release();
|
||||
|
||||
device->CreateVertexShader(vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), nullptr, &vs);
|
||||
device->CreatePixelShader(psBlob->GetBufferPointer(), psBlob->GetBufferSize(), nullptr, &ps);
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC layout[] = { {"POSITION",0,DXGI_FORMAT_R32G32_FLOAT,0,0,D3D11_INPUT_PER_VERTEX_DATA,0} };
|
||||
device->CreateInputLayout(layout, 1, vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), &inputLayout);
|
||||
|
||||
vsBlob->Release(); psBlob->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
// --- Render ---
|
||||
void Render() {
|
||||
float clear[4] = { 0,0,0,1 };
|
||||
context->ClearRenderTargetView(rtv, clear);
|
||||
|
||||
UINT stride = sizeof(Vertex), offset = 0;
|
||||
context->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
|
||||
context->IASetInputLayout(inputLayout);
|
||||
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
|
||||
context->VSSetShader(vs, nullptr, 0);
|
||||
context->PSSetShader(ps, nullptr, 0);
|
||||
|
||||
context->Draw(4, 0);
|
||||
swapChain->Present(0, 0); // non-blocking present
|
||||
}
|
||||
|
||||
// --- Cleanup ---
|
||||
void CleanUp() {
|
||||
if (vertexBuffer) vertexBuffer->Release();
|
||||
if (inputLayout) inputLayout->Release();
|
||||
if (vs) vs->Release();
|
||||
if (ps) ps->Release();
|
||||
if (rtv) rtv->Release();
|
||||
if (swapChain) swapChain->Release();
|
||||
if (context) context->Release();
|
||||
if (device) device->Release();
|
||||
}
|
||||
61
math/mandelbrot.c
Normal file
61
math/mandelbrot.c
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "mandelbrot.h"
|
||||
#include <math.h>
|
||||
|
||||
// Clamp helper
|
||||
static int clamp(int val) {
|
||||
if (val < 0) return 0;
|
||||
if (val > 255) return 255;
|
||||
return val;
|
||||
}
|
||||
|
||||
// Mandelbrot iterations
|
||||
int mandelbrot(Complex z0, int max_iter) {
|
||||
Complex z = z0;
|
||||
for (int i = 0; i < max_iter; i++) {
|
||||
if (complex_abs(z) > 2.0) return i;
|
||||
z = complex_add(complex_mul(z, z), z0);
|
||||
}
|
||||
return max_iter;
|
||||
}
|
||||
|
||||
// Simple HSV -> RGB helper
|
||||
static Color hsv_to_rgb(double h, double s, double v) {
|
||||
double r = 0, g = 0, b = 0;
|
||||
|
||||
int i = (int)(h * 6);
|
||||
double f = h * 6 - i;
|
||||
double p = v * (1 - s);
|
||||
double q = v * (1 - f * s);
|
||||
double t = v * (1 - (1 - f) * s);
|
||||
|
||||
switch (i % 6) {
|
||||
case 0: r = v; g = t; b = p; break;
|
||||
case 1: r = q; g = v; b = p; break;
|
||||
case 2: r = p; g = v; b = t; break;
|
||||
case 3: r = p; g = q; b = v; break;
|
||||
case 4: r = t; g = p; b = v; break;
|
||||
case 5: r = v; g = p; b = q; break;
|
||||
}
|
||||
|
||||
Color c = { (unsigned char)clamp((int)(r * 255)),
|
||||
(unsigned char)clamp((int)(g * 255)),
|
||||
(unsigned char)clamp((int)(b * 255)) };
|
||||
return c;
|
||||
}
|
||||
|
||||
// Color Mandelbrot
|
||||
Color color_mandelbrot(Complex z0, int max_iter) {
|
||||
int iter = mandelbrot(z0, max_iter);
|
||||
|
||||
if (iter == max_iter)
|
||||
return (Color) { 0, 0, 0 }; // black inside the set
|
||||
|
||||
// Map iteration to color hue
|
||||
double t = (double)iter / max_iter;
|
||||
double hue = 0.95 + 10 * t; // arbitrary scaling for more variation
|
||||
hue = fmod(hue, 1.0);
|
||||
double sat = 0.6; // saturation
|
||||
double val = 1.0; // brightness
|
||||
|
||||
return hsv_to_rgb(hue, sat, val);
|
||||
}
|
||||
12
math/mandelbrot.h
Normal file
12
math/mandelbrot.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef MANDELBROT_H
|
||||
#define MANDELBROT_H
|
||||
|
||||
#include "complex.h"
|
||||
|
||||
typedef struct { unsigned char r, g, b; } Color;
|
||||
|
||||
int mandelbrot(Complex z0, int max_iter);
|
||||
Color grey_mandelbrot(Complex z0, int max_iter); // optional, for backward compatibility
|
||||
Color color_mandelbrot(Complex z0, int max_iter);
|
||||
|
||||
#endif
|
||||
24
math/mandelbrot.hlsl
Normal file
24
math/mandelbrot.hlsl
Normal file
@@ -0,0 +1,24 @@
|
||||
cbuffer ViewportBuffer : register(b0)
|
||||
{
|
||||
float xmin;
|
||||
float xmax;
|
||||
float ymin;
|
||||
float ymax;
|
||||
int max_iter;
|
||||
};
|
||||
|
||||
struct PS_IN { float4 pos : SV_POSITION; };
|
||||
|
||||
float4 PSMain(PS_IN input) : SV_TARGET
|
||||
{
|
||||
float2 uv = input.pos.xy * 0.5 + 0.5; // [-1,1] -> [0,1]
|
||||
float2 c = float2(xmin,ymin) + uv * float2(xmax-xmin, ymax-ymin);
|
||||
float2 z = c;
|
||||
int i;
|
||||
for(i=0;i<max_iter;i++){
|
||||
if(dot(z,z)>4) break;
|
||||
z = float2(z.x*z.x - z.y*z.y, 2*z.x*z.y)+c;
|
||||
}
|
||||
float t = i/(float)max_iter;
|
||||
return float4(t,0.5*t,1.0-t,1);
|
||||
}
|
||||
Reference in New Issue
Block a user