Pobierałem razem przykłady online, aby utworzyć moduł cieniujący Mandelbrot. Wirtualny moduł cieniujący w zasadzie nic nie daje, przypisuje on gl_Position
, a moduł cieniujący fragmentuje trochę matematyki, aby obliczyć obraz.Wysyłanie zmiennych JavaScript w celu fragmentacji modułu cieniującego
Jednak mam kilka #define
s, które chcę zastąpić zmiennymi sterowanymi JavaScript i nie wiem jak to zrobić. Jeśli można podać przykład, w jaki sposób zastąpić #define MAX_ITERATIONS 200
zmienną przypisaną do JavaScript w poniższym kodzie, prawdopodobnie mógłbym znaleźć resztę z nich. Uważam, że muszę określić uniform
lub varying
, ale nie jestem pewien jak zarządzać komunikacją z JavaScript do GLSL.
Nie rozumiem również, jak działa aPosition
między JavaScriptem a vertexowym shaderem, ale to, co mam, jest zasadniczo takie samo jak w przykładach.
JavaScript, to sobie wyobrazić tylko init()
spraw dla tak czytelników, reszta jest zamieszczona w razie potrzeby:
var canvas, gl, shaderProgram;
function draw() {
window.requestAnimationFrame(draw, canvas);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}
function init() {
canvas = document.getElementById("theCanvas");
gl = initGl(canvas);
if (!gl) {
alert("Could not initialize WebGL");
return;
}
shaderProgram = initShaders();
if (!shaderProgram) {
alert("Could not initialize shaders");
return;
}
var vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
-1.0, -1.0,
1.0, -1.0,
-1.0, 1.0,
1.0, 1.0,
]),
gl.STATIC_DRAW
);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.viewportWidth = canvas.width;
gl.viewportHeight = canvas.height;
var aPosition = gl.getAttribLocation(shaderProgram, "aPosition");
gl.enableVertexAttribArray(aPosition);
gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0);
draw();
}
function initGl(inCanvas) {
gl = false;
try { gl = inCanvas.getContext("webgl") || inCanvas.getContext("experimental-webgl"); }
catch (e) {}
return !gl ? false : gl;
}
function initShaders() {
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, document.getElementById("vertexShader").text);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(vertexShader));
return false;
}
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, document.getElementById("fragmentShader").text);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(fragmentShader));
return false;
}
shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) return false;
gl.useProgram(shaderProgram);
return shaderProgram;
}
Vertex Shader:
attribute vec2 aPosition;
void main() {
gl_Position = vec4(aPosition, 0.0, 1.0);
}
Fragment Shader, MAX_ITERATIONS
, XMIN
, YMIN
i WH
powinna być kontrolowana w JavaScript:
#ifdef GL_FRAGEMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
precision mediump int;
#define MAX_ITERATIONS 200
#define XMIN -2.5
#define YMIN -2.0
#define WH 4.0
#define LOG_TWO log(2.0)
#define LOG_MAX log(200.0)
void main() {
// Normalized pixel position to complex plane position
float maxPwh = max(640.0, 480.0);
float x = XMIN+(gl_FragCoord.x/maxPwh)*WH;
float y = YMIN+(gl_FragCoord.y/maxPwh)*WH;
// Complex plane window offsets for pixel windows that are not square
float halfDelta = WH/maxPwh*0.5;
x -= min((640.0-480.0)*halfDelta, 0.0);
y -= min((480.0-640.0)*halfDelta, 0.0);
// Mandelbrot Set code
float zr = x;
float zi = y;
int iterations = 0;
for (int i = 0; i < MAX_ITERATIONS; i++) {
iterations = i;
float sqZr = zr*zr;
float sqZi = zi*zi;
float twoZri = 2.0*zr*zi;
zr = sqZr-sqZi+x;
zi = twoZri+y;
if (sqZr+sqZi > 16.0) break;
}
if (iterations == MAX_ITERATIONS-1) gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
else {
float fn = float(iterations)+1.0-log(log(sqrt(zr*zr+zi*zi)))/LOG_TWO;
float logVal = log(fn)/LOG_MAX;
gl_FragColor = vec4(logVal, logVal, logVal, 1.0);
}
}