Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将JavaScript变量发送到片段着色器_Javascript_Glsl_Webgl - Fatal编程技术网

将JavaScript变量发送到片段着色器

将JavaScript变量发送到片段着色器,javascript,glsl,webgl,Javascript,Glsl,Webgl,我一直在拼凑在线示例来制作Mandelbrot集片段着色器。顶点着色器基本上什么都不做,它指定gl\u位置,片段着色器执行一些数学运算来计算图像 但是,我有许多#define要用JavaScript控制变量替换,我不知道如何做到这一点。如果可以举一个例子,说明如何在下面的代码中用JavaScript指定的变量替换#定义MAX_迭代200,那么我可能会找出其余的例子。我认为我需要指定一个统一的或变化的,但不确定如何管理从JavaScript到GLSL的通信 另外,我不明白aPosition是如何在

我一直在拼凑在线示例来制作Mandelbrot集片段着色器。顶点着色器基本上什么都不做,它指定
gl\u位置
,片段着色器执行一些数学运算来计算图像

但是,我有许多
#define
要用JavaScript控制变量替换,我不知道如何做到这一点。如果可以举一个例子,说明如何在下面的代码中用JavaScript指定的变量替换
#定义MAX_迭代200
,那么我可能会找出其余的例子。我认为我需要指定一个
统一的
变化的
,但不确定如何管理从JavaScript到GLSL的通信

另外,我不明白
aPosition
是如何在JavaScript和顶点着色器之间工作的,我得到的与示例基本相同

JavaScript,我想只有
init()
对SO读者来说是重要的,如果需要,其余的都会发布:

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;
}
顶点着色器

attribute vec2 aPosition;

void main() {
    gl_Position = vec4(aPosition, 0.0, 1.0);
}
片段着色器
最大迭代次数
XMIN
YMIN
WH
应在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);
    }
}
\ifdef GL\u FRAGEMENT\u精度高
高精度浮点;
#否则
精密中泵浮子;
#恩迪夫
精密中泵;
#定义最大迭代次数200次
#定义XMIN-2.5
#定义YMIN-2.0
#定义WH4.0
#定义两个日志(2.0)
#定义LOG_MAX LOG(200.0)
void main(){
//将像素位置归一化为复平面位置
浮动最大值=最大值(640.0480.0);
浮点x=XMIN+(gl_FragCoord.x/maxPwh)*;
浮动y=YMIN+(gl_FragCoord.y/maxPwh)*WH;
//非正方形像素窗口的复杂平面窗口偏移
浮动半三角形=WH/maxPwh*0.5;
x-=最小值((640.0-480.0)*半三角形,0.0);
y-=最小值((480.0-640.0)*半三角形,0.0);
//Mandelbrot集码
浮动zr=x;
浮点数zi=y;
int迭代次数=0;
对于(int i=0;i16.0)断裂;
}
如果(迭代次数==最大迭代次数-1)gl\u FragColor=vec4(1.0,1.0,1.0,1.0);
否则{
float fn=float(迭代)+1.0-log(log(sqrt(zr*zr+zi*zi)))/logtwo;
float logVal=log(fn)/log_MAX;
gl_FragColor=vec4(logVal,logVal,logVal,1.0);
}
}

简而言之,您基本上有两种选择

  • 通过统一将值从JavaScript传递到GLSL

    例如,如果要传递一个浮点,请创建一个浮点统一

    uniform float foo;
    
    在JavaScript中,编译并链接该着色器,然后查找制服的位置

    var locationOfFoo = gl.getUniformLocation(someProgram, "foo");
    
    现在,您可以使用将值传递给GLSL

    gl.useProgram(someProgram)
    gl.uniform1f(locationOfFoo, valueToPass);
    
  • 在编译着色器之前操纵字符串

    #define MAX_INTERATIONS %maxIterations%
    #define XMIN %xMin%
    


  • (1) 上面是用来传递经常变化的东西的#2用于在编译着色器之前更改着色器#1是几乎100%的WebGL程序中使用的一种技术#2在动态生成着色器时经常使用,许多游戏引擎都是这样做的。

    我花了大约45分钟来实现gman的回答,因为 我一直犯愚蠢的小错误。下面是一个完整的工作代码 创建可调整平铺贴图的示例

    测试地点:Chrome、Internet Explorer和Edge:

    
    GL_瓷砖_试验台
    p{font size:12pt;}
    h3,p,输入,按钮,br{
    填充:0px;
    边际:0px;
    字体系列:“安达勒单声道”;
    }
    按钮,输入{
    填充:10px;
    }
    高精度浮点;
    属性向量2 a_位置;
    void main(){
    gl_位置=vec4(a_位置,0,1);
    }
    //必须在声明前声明精度
    //任何制服:
    ////////////////////////////////////////////////
    #ifdef GL_碎片_精度_高
    高精度浮点;
    #否则
    精密中泵浮子;
    #恩迪夫
    精密中泵;
    ////////////////////////////////////////////////
    #定义画布WID640.0
    #定义CANVAS_HIG 480.0
    #定义TIL_WID 64.0
    #定义直到64.0
    //暴露于HTML/JAVASCRIPT的制服:
    均匀浮动直到编辑;
    均匀浮动直到高编辑;
    浮动至宽;
    浮到高处;
    void main(){
    //如果用户未设置制服,
    //使用#定义设置的默认值
    //==========================================//
    如果(直到宽度编辑>0.0){
    til_wid=til_wid_编辑;
    }否则{
    til_wid=til_wid;
    }
    如果(直到高编辑>0.0){
    til_hig=til_hig_EDIT;
    }否则{
    til_hig=til_hig;
    }
    //==========================================//
    //注:在“gl_FragCoord”范围内:
    //******************************************//
    //web gl:在像素/画布坐标方面。
    //OpenGL:从0到1。
    //******************************************//
    //:计算屏幕上显示的瓷砖数量:
    //:这可能是分数:
    float NUM_TIL_X=画布宽度/TIL宽度;
    float NUM_TIL_Y=画布高度/高度;
    vec2-FC_-MOD;
    FC_MOD.x=gl_FragCoord.x;
    FC_MOD.y=gl_FragCoord.y;
    //您希望所有磁贴都具有完整的范围
    //颜色,所以你总是通过
    //画布宽和画布高,按
    //#每个轴上的瓷砖数量,表示
    //随着瓷砖厚度的增加,坡度变得更陡
    //增加。
    FC_MOD.x=MOD(
    
    var maxIterations = 123;
    var xMin = 4.5;
    shaderSource = shaderSource.replace(/%maxIterations%/g, maxIterations);
    shaderSource = shaderSource.replace(/%xMin%/g, xMin);