Mandelbrot设置缩放限制

时间:2017-12-11 18:34:27

标签: javascript webgl fractals mandelbrot

我最近开始学习Javascript / WebGL,并且我已经学到了足够的知识来组合一个简单的Mandelbrot分形渲染器。该程序工作正常,但由于某种原因,它不会让我放大超过20倍,如果我放大更多,它开始看像素化。我之前在其他分形绘图程序中遇到过这个问题,但它通常不会变得明显,直到大约2 ^ 45变焦。我想也许它与GLSL中的最大浮点数大小有关,但我真的不确定问题是什么,甚至不知道如何找到问题。我只是想知道是否有人知道这个缩放限制的原因是什么,以及是否有任何方法可以增加它?这是我的HTML / GLSL代码:

<html>
<head>

    <title>Mandelbrot Set</title>

    <style>

    body {
        margin = 0;
        padding = 0;
    }

    </style>

</head>


<body>

    <h3>Click on the fractal to zoom in.</h3>

    <canvas id = "canvas" width = "500" height = "500" onclick = "drawFractal();">
    Sorry, your browser does not support HTML5.
    </canvas>

    <script id = "vertexshader" type = "vertexshader">

    attribute vec2 a_position;

    void main(){
        gl_Position = vec4(a_position, 0, 0);
    }

    </script>

    <script id = "fragmentshader" type = "fragmentshader">

    precision mediump float;

    uniform vec2 u_resolution;
    uniform vec2 u_zoomCenter;
    uniform float u_zoom;
    uniform int u_maxIterations;
    uniform float u_colorDiversity;

    vec2 f(vec2 z, vec2 c)
    {
        return vec2(z.x*z.x - z.y*z.y, z.x*z.y*2.0) + c;
    }

    // Credit to hughsk on GitHub for this hsv to rgb converter
    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(){

        vec2 zeroToOne = gl_FragCoord.xy / u_resolution;

        vec2 c = u_zoomCenter + (zeroToOne * 4.0 - vec2(2.0)) / u_zoom;
        vec2 z = vec2(0.0);
        bool escaped = false;
        float iterations = 0.0;

        for (int i = 0; i < 100000; i++)
        {
            if (i > u_maxIterations) break;
            z = f(z, c);

            if (length(z) > 2.0)
            {
                escaped = true;
                iterations = float(i);
                break;
            }
        }

        gl_FragColor = escaped ? vec4(hsv2rgb(vec3(iterations * u_colorDiversity, 1.0, 1.0)), 1.0) : vec4(vec3(0.0), 1.0); 
    }

    </script>

    <script src = "webgl.js"></script>

</body>

</html>

这是我的&#34; webgl.js&#34;文件:

// Compile and link shaders and create program
function createShader(gl, type, source){
        var shader = gl.createShader(type);
        gl.shaderSource(shader, source);
        gl.compileShader(shader);

        if (gl.getShaderParameter(shader, gl.COMPILE_STATUS)) return shader;

        console.log(gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        alert("Error: failed to create shader. Check the console for more information.");
}

function createProgram(gl, vertexShader, fragmentShader){
    var program = gl.createProgram();
    gl.attachShader(program, vertexShader);
    gl.attachShader(program, fragmentShader);
    gl.linkProgram(program);

    if (gl.getProgramParameter(program, gl.LINK_STATUS)) return program;

    console.log(gl.getProgramInfoLog(program));
    gl.deleteProgram(program);
    alert("Error: failed to create program. Check the console for more information.");
}

// WebGL setup
var canvas = document.getElementById("canvas");
var gl = canvas.getContext("webgl");
if (!gl){
    var gl = canvas.getContext("experimental-webgl");
    console.log("WebGL not supported, falling back on experimental WebGL.");
}
if (!gl){
    console.log("Experimental WebGL not supported.");
    alert("Your browser does not support WebGL. Check the console for more information.");
}

// Create shaders and program
var vertexShaderSource = document.getElementById("vertexshader").text;
var fragmentShaderSource = document.getElementById("fragmentshader").text;

var vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
var fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);

var program = createProgram(gl, vertexShader, fragmentShader);
gl.useProgram(program);

// Set up position buffer
var screen = new Float32Array([
    -1, -1, 
    1, -1, 
    1, 1, 
    1, 1, 
    -1, 1, 
    -1, -1]);
var positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, screen, gl.STATIC_DRAW);

// Set up position attribute in vertex shader
var a_positionLocation = gl.getAttribLocation(program, "a_position");
gl.enableVertexAttribArray(a_positionLocation);
gl.vertexAttribPointer(a_positionLocation, 2, gl.FLOAT, false, 0, 0);

// Set up WebGL window
gl.viewport(0, 0, 500, 500);
gl.clearColor(0, 0, 0, 0);

// Set up uniforms in fragment shader
var u_resolutionLocation = gl.getUniformLocation(program, "u_resolution");
var u_zoomCenterLocation = gl.getUniformLocation(program, "u_zoomCenter");
var u_zoomLocation = gl.getUniformLocation(program, "u_zoom");
var u_maxIterationsLocation = gl.getUniformLocation(program, "u_maxIterations");
var u_colorDiversityLocation = gl.getUniformLocation(program, "u_colorDiversity");

gl.uniform2f(u_resolutionLocation, 500, 500);

// Set up some global variables
var offset_x = 0;
var offset_y = 0;
var zoom = 1;
var iterations = 10000;
var colorDiversity = 0.01;

// Update uniforms based on global variables
function updateUniforms()
{
    gl.uniform2f(u_zoomCenterLocation, offset_x, offset_y);
    gl.uniform1f(u_zoomLocation, zoom);
    gl.uniform1i(u_maxIterationsLocation, iterations);
    gl.uniform1f(u_colorDiversityLocation, colorDiversity);
}

// Get mouse position
function getMousePos() {
    var rect = canvas.getBoundingClientRect();
    return [(event.clientX - rect.left - 250) / 125, (event.clientY - rect.top - 250) / 125];
}

// Draw the fractal
function drawFractal() {
    mousePos = getMousePos();
    offset_x += mousePos[0] / zoom;
    offset_y -= mousePos[1] / zoom;
    zoom *= 2;

    updateUniforms();
    gl.drawArrays(gl.TRIANGLES, 0, 6);
}

// Draw fractal when the page loads
updateUniforms();
gl.drawArrays(gl.TRIANGLES, 0, 6);

1 个答案:

答案 0 :(得分:0)

最大可能缩放取决于您使用的the precision of the floating point number 和您的算法。

您可以使用任意精确数字来提高精确度,例如mpfrmpcarb library