Попытка создать набор Мандельброта с использованием пиксельного шейдера GLSL, но возникли проблемы с ветвлением - PullRequest
0 голосов
/ 08 марта 2020

Я пытаюсь закодировать набор Мандельброта в GLSL. Но это может показаться из-за ограничений ветвления внутри GLSL, это не работает должным образом. Вот мой код:

passthrough.v sh:

attribute vec4 a_color;
attribute vec3 a_position;
attribute vec2 a_texCoord0;

uniform mat4 u_projTrans;
varying vec4 v_color;
varying vec2 v_texCoord0;

void main() {
    v_color = a_color;
    v_texCoord0 = a_texCoord0;
    gl_Position = u_projTrans * vec4(a_position, 1);
}

mandelbrot.f sh:

varying vec4 v_color;
varying vec2 v_texCoord0;

uniform sampler2D u_sampler2D;

uniform int u_width;
uniform int u_height;

uniform float u_realCenter;
uniform float u_imagCenter;

uniform float u_realSpan;
uniform float u_imagSpan;

int maxIterations = 255;

vec2 squareComplex(vec2 z);
vec2 coordToComplexNumber(vec2 coord);

float getRed(int stability);
float getGreen(int stability);
float getBlue(int stability);

void main()
{
    vec2 c = coordToComplexNumber(gl_FragCoord.xy);
    vec2 z = vec2(0, 0);

    int stability = 0;
    int attempts = 0;

    for (int i = 0; i < maxIterations && z.x * z.x + z.y * z.y < 4.0; i++) {
        z = squareComplex(z) + c;
        stability = stability + 1;
    }

    gl_FragColor = vec4(getRed(stability), getGreen(stability), getBlue(stability), 1);
}

vec2 squareComplex(vec2 z)
{
    return vec2(z.x * z.x - z.y * z.y, 2.0 * z.x * z.y);
}

vec2 coordToComplexNumber(vec2 coord)
{
    float lowestReal = u_realCenter - u_realSpan / 2.0;
    float lowestImag = u_imagCenter - u_imagSpan / 2.0;

    float portionX = coord.x / float(u_width);
    float portionY = coord.y / float(u_height);

    float mappedX = lowestReal + portionX * u_realSpan;
    float mappedY = lowestImag + portionY * u_imagSpan;

    return vec2(mappedX, mappedY);
}

float getRed(int stability)
{
    return float(stability) / float(maxIterations) * 255.0;
}

float getGreen(int stability)
{
    return mod(float(stability), float(maxIterations)) * 255.0;
}

float getBlue(int stability)
{
    return 0.0;
}

Проблема, похоже, возникает здесь:

for (int i = 0; i < maxIterations && z.x * z.x + z.y * z.y <= 4.0; i++) {
    z = squareComplex(z) + c;
    stability = stability + 1;
}

Тестирование с использованием следующего кода показывает, что этот l oop запускает только 1 итерацию и затем завершается каждый раз.

gl_FragColor = vec4(stability == 1 ? 1 : 0, 0, 0, 1);

, что приводит к окрашиванию всего красного.

Я также пытался использовать оператор break внутри l oop вместо использования && z.x * z.x + z.y * z.y <= 4.0 внутри условия for l oop, например:

if (z.x * z.x + z.y * z.y > 4.0) break;

Это, кажется, не работает должным образом , Я читал об ограничениях в ветвлении в GLSL. Так что это может быть причиной в обоих случаях, но я не знаю, как кодировать множество Мандельброта в GLSL без ветвления, и я не могу найти никакого решения для этого, а также не могу найти способ заставить ветвление работать в GLSL .

Я тестировал этот код на ноутбуке Intel HD на Linux, ноутбуке NVidia на Windows и на Samsung Galaxy S9, и он не работает ни на одном из них.

Этот код реализован в Java LibGDX.

Может быть, эта ошибка как-то связана с ней:

LwjglGraphics: created OpenGL 3.2+ core profile (GLES 3.0) context. This is experimental!

Это из моего DesktopLauncherCode:

package mypackagename.desktop

import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import mypackagename.Mandelbrot;

public class DesktopLauncher {
    public static void main (String[] arg) {
        LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
        config.vSyncEnabled = true;
        config.useGL30 = true;
        config.title = "GLSL Shaders";
        config.width = 1280;
        config.height = 720;
        new LwjglApplication(new Mandelbrot(), config);
    }
}

А это из моего основного кода:

package mypackagename;

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;

public class Mandelbrot extends ApplicationAdapter {

    private SpriteBatch batch;
    private ShaderProgram shader;

    private Texture texture;

    @Override
    public void create () {
        batch = new SpriteBatch();

        ShaderProgram.pedantic = false;
        shader = new ShaderProgram(
                Gdx.files.internal("shaders/mandelbrot3.vsh"),
                Gdx.files.internal("shaders/mandelbrot3.fsh")
        );
        System.out.println(shader.isCompiled() ? "shader compiled, yay" : shader.getLog());
        batch.setShader(shader);

        shader.setUniformf("u_realCenter", 0);
        shader.setUniformf("u_imagCenter", 0);
        shader.setUniformf("u_realSpan", 6);
        shader.setUniformf("u_imagSpan", 6);
    }

    @Override
    public void render () {
        Gdx.gl.glClearColor(0, 0, 0, 1);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
        batch.begin();
        batch.draw(texture, 0, 0);
        batch.end();
    }

    @Override
    public void dispose () {
        batch.dispose();
        shader.dispose();
    }

    @Override
    public void resize(int width, int height) {
        super.resize(width, height);
        texture = new Texture(getPixmapRectangle(width, height, Color.BLUE));
        shader.setUniformi("u_width", width);
        shader.setUniformi("u_height", height);
    }

    public static Pixmap getPixmapRectangle(int width, int height, Color color) {
        Pixmap pixmap = new Pixmap(width, height, Pixmap.Format.RGBA8888);
        pixmap.setColor(color);
        pixmap.fillRectangle(0, 0, pixmap.getWidth(), pixmap.getHeight());
        return pixmap;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...