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


我一直在拼凑在线示例,以制作Mandelbrot Set片段着色器。顶点着色器基本上什么也没做,它指定 gl_Position 并且片段着色器会进行一些数学计算以计算图像。

但是,我有一些 #define我想用JavaScript控制的变量替换,我不知道如何做到这一点。如果可以显示如何说替换的示例 #define MAX_ITERATIONS 200 在下面的代码中使用JavaScript指定的变量,我可能会弄清楚其余部分。我相信我需要指定一个 uniform 要么 varying 但我不确定如何管理从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);
}

片段着色器MAX_ITERATIONSXMINYMIN,和 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);
    }
}

8556
2017-09-29 04:31


起源



答案:


简短的回答是你基本上有两个选择

  1. 通过统一将值从JavaScript传递到GLSL。

    例如,如果要传递浮点,请创建浮点均匀

    uniform float foo;
    

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

    var locationOfFoo = gl.getUniformLocation(someProgram "foo");
    

    您现在可以将值传递给GLSL

    gl.useProgram(someProgram)
    gl.uniform1f(locationOfFoo, valueToPass);
    
  2. 在编译着色器之前处理字符串

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

    ...

    var maxIterations = 123;
    var xMin = 4.5;
    shaderSource = shaderSource.replace(/%maxIterations%/g, maxIterations);
    shaderSource = shaderSource.replace(/%xMin%/g, xMin);
    

(1)以上是为了传递经常变化的东西。 #2用于在编译之前更改着色器。 #1是几乎100%的WebGL程序中使用的技术。 #2经常在生成许多游戏引擎的着色器时使用。


15
2017-09-29 07:21





我花了大约45分钟来实施 GMAN的 回答因为 我一直犯下愚蠢的小错误。所以这是一个 完整的工作代码 样品 这会创建一个可调整的瓷砖地图。

测试中: Chrome,Internet Explorer和Edge:

<!DOCTYPE HTML >
<html lang="en">
<head>
<meta charset="UTF-8">
<title>         GL_TILE_TESTBED           </title>
<!-- AUTHOR: John Mark Isaac Madison           -->
<!-- EMAIL : J4M4I5M7@hotmail.com              -->
<!-- SSSSSSSSS SHADER_SECTION START  SSSSSSSSS -->
<!-- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS -->
<!-- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS -->
<style>

    p{ font-size:12pt;}
    h3,p,input,button,br{ 
        padding:0px; 
        margin:0px; 
        font-family:"Andale Mono";
    }
    button,input{
        padding:10px;
    }
</style>
<script id="VERT_SHADER" type="NOT_JAVASCRIPT">
  precision highp float;

  attribute vec2 a_position;
  void main() {
    gl_Position = vec4(a_position, 0, 1);
  }
</script>


<script id="FRAG_SHADER" type="NOT_JAVASCRIPT">

  //Must declare precision before declaring
  //any uniforms:
  ////////////////////////////////////////////////
  #ifdef GL_FRAGMENT_PRECISION_HIGH
    precision highp float;
  #else
    precision mediump float;
  #endif
  precision mediump int;
  ////////////////////////////////////////////////

  #define CANVAS_WID  640.0
  #define CANVAS_HIG  480.0

  #define TIL_WID     64.0
  #define TIL_HIG     64.0

  //Uniforms exposed to HTML/JAVASCRIPT:
  uniform float TIL_WID_EDIT;
  uniform float TIL_HIG_EDIT;

  float til_wid;
  float til_hig;


  void main() {

    //If uniforms have not set by user,
    //use the default values set by the #define(s)
    //==========================================//
    if(TIL_WID_EDIT > 0.0){
      til_wid = TIL_WID_EDIT;
    }else{
      til_wid = TIL_WID;
    }

    if(TIL_HIG_EDIT > 0.0){
      til_hig = TIL_HIG_EDIT;
    }else{
      til_hig = TIL_HIG;
    }
    //==========================================//

    //NOTE: on "gl_FragCoord" range:
    //******************************************//
    //web-gl: In terms of pixel/canvas coords.
    //OpenGL: In terms of 0 to 1.
    //******************************************//

    //:Calculate number of tiles shown on screen:
    //:This may be fractional:
    float NUM_TIL_X = CANVAS_WID / til_wid;
    float NUM_TIL_Y = CANVAS_HIG / til_hig;


    vec2 FC_MOD;
    FC_MOD.x = gl_FragCoord.x;
    FC_MOD.y = gl_FragCoord.y;

    //You want all tiles to have the full range 
    //of colors, so you always modulate by 
    //CANVAS_WID and CANVAS_HIG, You scale by the 
    //# of tiles on each axis which means the 
    //gradient becomes steeper as the # of tiles
    //increases.
    FC_MOD.x = mod( gl_FragCoord.x*NUM_TIL_X, CANVAS_WID );
    FC_MOD.y = mod( gl_FragCoord.y*NUM_TIL_Y, CANVAS_HIG );

    //[N]ormalize values into range 0 to 1:
    //NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN//
    float norm_X = (FC_MOD.x) / CANVAS_WID;
    float norm_Y = (FC_MOD.y) / CANVAS_HIG;
    //NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN//

    //Use [B]lue channel because why not?
    //BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB//
    float GRAD_X = gl_FragCoord.x / CANVAS_WID;
    //BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB//

    //Set the final [F]ragment colors:
    //FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF//
    gl_FragColor = vec4(norm_X, norm_Y, GRAD_X, 1.0);
    //FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF//
  }
</script>
<!-- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS -->
<!-- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS -->
<!-- SSSSSSSSSS SHADER_SECTION END  SSSSSSSSSS -->
</head> 
<!-- HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH -->

<!-- BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -->                    
<body onload="ON_LOADED_FUNCTION()" >
<!-- BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -->

    <h3> Open GL Tile TestBed            <h3>
    <p> Author: John Mark Isaac Madison <p>
    <p> Email : J4M4I5M7@hotmail.com    <p>

    <canvas id="glCanvas"></canvas>

    </br>
    <button onClick="PUT_WID();">TILE_WIDTH__IN_PIXELS</button> 
    <input type="text" id="INPUT_WID" value="45">
    </br>

    </br>
    <button onClick="PUT_HIG();">TILE_HEIGHT_IN_PIXELS</button> 
    <input type="text" id="INPUT_HIG" value="45">
    </br>



<!-- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS -->   
<script id="BOILER_PLATE_CODE">
    function ON_LOADED_FUNCTION(){
        console.log("[ON_LOADED_FUNCTION]");
        main();
    }

    //:Takes the gl context object, if the input
    //:is null, we likely failed to get the
    //:context.
    function HAS_OPEN_GL_CHECK(gl){
      // Only continue if WebGL is 
      // available and working
      if (!gl) {
        var msg = "";
        msg += "[Unable to initialize WebGL.]";
        msg += "[your browser or machine may]";
        msg +=  "[not support it.]"
        alert( msg );
        return;
      }
    }

    function GET_INPUT_BOX_VALUE( elem_id ){
        var box; //DOM input box
        var val; //Value in input box.
        box = document.getElementById( elem_id );
        val = box.value;
        return (0 + val); //cast to number.
    }

    function PUT_WID(){
        assert_program_and_gl_exist();
        var val = GET_INPUT_BOX_VALUE("INPUT_WID");
        SET_ATTR("TIL_WID_EDIT", val);
    }

    function PUT_HIG(){
        assert_program_and_gl_exist();
        var val = GET_INPUT_BOX_VALUE("INPUT_HIG");
        SET_ATTR("TIL_HIG_EDIT", val); 
    }

    function SET_ATTR(gl_var_name, val){
        if(val < 0 || val > 256 ){
            alert("choose value between 0 to 256");
            return;
        }

        var loc; //<--location of variable.
        loc = gl.getUniformLocation(
            program    , 
            gl_var_name
        );
        gl.useProgram(program);
        gl.uniform1f(loc, val);
    }

    function assert_program_and_gl_exist(){
        if(!program){慌("[NO_PROGRAM_EXISTS]");}
        if(!gl     ){慌("[NO_GL_EXISTS]");}
    }

    //慌: "disconcerted, be confused, lose one's head"
    //慌: In Code: ~Panic~
    function 慌( panic_message ){
        console.log( panic_message );
        alert      ( panic_message );
        throw      ( panic_message );
    }

    function makeOpenGlContextUsingCanvas(c){

        //:Try what works in chrome and all the
        //:respectable browsers first:
        gl = c.getContext("webgl");

        if(!gl){
            console.log("[Probably_In_IE]");
            gl = c.getContext("experimental-webgl");
        }else{
            console.log("[Probably_NOT_IE]");
        }

        HAS_OPEN_GL_CHECK( gl );
        return gl;
    }

    //: No "var" prefix, making them global:
    function initGlobals(){
        canvas = document.querySelector("#glCanvas");
        if(!canvas){
            alert("FAILED_TO_GET_CANVAS");
        }else{
            console.log("[GOT_CANVAS]");
        }

        gl = makeOpenGlContextUsingCanvas(canvas);


        //These dimensions are hard-coded into
        //fragment shader code, so be careful
        //about changing them:
        canvas.width = 640;
        canvas.height= 480;

        buffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
        gl.bufferData(
        gl.ARRAY_BUFFER, 
        new Float32Array([
          -1.0, -1.0, 
           1.0, -1.0, 
          -1.0,  1.0, 
          -1.0,  1.0, 
           1.0, -1.0, 
           1.0,  1.0]), 
        gl.STATIC_DRAW
        );

        //G == Global Container.
        //To fix problems with rendering in I.E.
        //(Internet Explorer)
        //GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG//
        var G = {}; 
        G.canvas = canvas;
        G.gl     = gl;
        G.buffer = buffer;

        if( ! G.canvas ||
            ! G.gl     ||
            ! G.buffer  ){
            慌("[Global_Container_Broken]");
        }

        return G;
        //GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG//
    }

    function main(){

      G = initGlobals();
      HAS_OPEN_GL_CHECK( G );

      gl.viewport(0,0,gl.drawingBufferWidth, gl.drawingBufferHeight);

      setup();
      render();
    }

    function setup(){
        var frag_dom = document.getElementById("FRAG_SHADER");
        var frag_src = frag_dom.text;
        console.log( frag_src );

        F = createShader(
            gl,gl.FRAGMENT_SHADER, frag_src
        );

        var vert_dom = document.getElementById("VERT_SHADER");
        var vert_src = vert_dom.text;
        console.log( vert_src );

        V = createShader(
            gl, gl.VERTEX_SHADER, vert_src
        );

        //**** MAKE "program" a GLOBAL VAR  ****//
        program = createProgram(gl,V,F);
        gl.useProgram( program );

        if(!program){
            慌("PROGRAM_IS_NULL");
        }
    }

    function render(){
      window.requestAnimationFrame(render,canvas);

      // Set clear color to black, fully opaque
      gl.clearColor(0.0, 0.0, 0.5, 1.0);

      // Clear the color buffer with specified clear color
      gl.clear(gl.COLOR_BUFFER_BIT);

      //Directly before call to gl.drawArrays:
      positionLocation = gl.getAttribLocation(program, "a_position");
      gl.enableVertexAttribArray( positionLocation );
      gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);


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

    function createShader(gl,type,source){
        //:Error Check For Bad Inputs:
        if(!gl    ){慌("[NULL_GL]");}
        if(!type  ){慌("[NULL_TY]");}
        if(!source){慌("[NULL_SR]");}

        var shader = gl.createShader(type);
        gl.shaderSource(shader, source);
        gl.compileShader(shader);
        var res = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
        if( res ){
            console.log("[SHADER_COMPILED!]");
            return shader;
        }

        console.log(gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        慌("[FAILED_TO_COMPILE_SHADER]");
    }

    //:gl  : openGL context :
    //:vert: vertex shader  :
    //:frag: fragment shader:
    function createProgram(gl,vert, frag){
        var program = gl.createProgram();
        gl.attachShader(program, vert);
        gl.attachShader(program, frag);
        gl.linkProgram (program);
        var res = gl.getProgramParameter(program, gl.LINK_STATUS);
        if( res ){
            console.log("[PROGRAM_CREATED!]");
            return program;
        }

        console.log(gl.getProgramInfoLog(program));
        gl.deleteProgram(program);
    }

</script>
<!-- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS -->

<!-- BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -->
</body>
</html>

1
2017-11-30 04:19



codepen.io/kioikoikio/full/xazbbw - Greag.Deay


答案:


简短的回答是你基本上有两个选择

  1. 通过统一将值从JavaScript传递到GLSL。

    例如,如果要传递浮点,请创建浮点均匀

    uniform float foo;
    

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

    var locationOfFoo = gl.getUniformLocation(someProgram "foo");
    

    您现在可以将值传递给GLSL

    gl.useProgram(someProgram)
    gl.uniform1f(locationOfFoo, valueToPass);
    
  2. 在编译着色器之前处理字符串

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

    ...

    var maxIterations = 123;
    var xMin = 4.5;
    shaderSource = shaderSource.replace(/%maxIterations%/g, maxIterations);
    shaderSource = shaderSource.replace(/%xMin%/g, xMin);
    

(1)以上是为了传递经常变化的东西。 #2用于在编译之前更改着色器。 #1是几乎100%的WebGL程序中使用的技术。 #2经常在生成许多游戏引擎的着色器时使用。


15
2017-09-29 07:21





我花了大约45分钟来实施 GMAN的 回答因为 我一直犯下愚蠢的小错误。所以这是一个 完整的工作代码 样品 这会创建一个可调整的瓷砖地图。

测试中: Chrome,Internet Explorer和Edge:

<!DOCTYPE HTML >
<html lang="en">
<head>
<meta charset="UTF-8">
<title>         GL_TILE_TESTBED           </title>
<!-- AUTHOR: John Mark Isaac Madison           -->
<!-- EMAIL : J4M4I5M7@hotmail.com              -->
<!-- SSSSSSSSS SHADER_SECTION START  SSSSSSSSS -->
<!-- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS -->
<!-- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS -->
<style>

    p{ font-size:12pt;}
    h3,p,input,button,br{ 
        padding:0px; 
        margin:0px; 
        font-family:"Andale Mono";
    }
    button,input{
        padding:10px;
    }
</style>
<script id="VERT_SHADER" type="NOT_JAVASCRIPT">
  precision highp float;

  attribute vec2 a_position;
  void main() {
    gl_Position = vec4(a_position, 0, 1);
  }
</script>


<script id="FRAG_SHADER" type="NOT_JAVASCRIPT">

  //Must declare precision before declaring
  //any uniforms:
  ////////////////////////////////////////////////
  #ifdef GL_FRAGMENT_PRECISION_HIGH
    precision highp float;
  #else
    precision mediump float;
  #endif
  precision mediump int;
  ////////////////////////////////////////////////

  #define CANVAS_WID  640.0
  #define CANVAS_HIG  480.0

  #define TIL_WID     64.0
  #define TIL_HIG     64.0

  //Uniforms exposed to HTML/JAVASCRIPT:
  uniform float TIL_WID_EDIT;
  uniform float TIL_HIG_EDIT;

  float til_wid;
  float til_hig;


  void main() {

    //If uniforms have not set by user,
    //use the default values set by the #define(s)
    //==========================================//
    if(TIL_WID_EDIT > 0.0){
      til_wid = TIL_WID_EDIT;
    }else{
      til_wid = TIL_WID;
    }

    if(TIL_HIG_EDIT > 0.0){
      til_hig = TIL_HIG_EDIT;
    }else{
      til_hig = TIL_HIG;
    }
    //==========================================//

    //NOTE: on "gl_FragCoord" range:
    //******************************************//
    //web-gl: In terms of pixel/canvas coords.
    //OpenGL: In terms of 0 to 1.
    //******************************************//

    //:Calculate number of tiles shown on screen:
    //:This may be fractional:
    float NUM_TIL_X = CANVAS_WID / til_wid;
    float NUM_TIL_Y = CANVAS_HIG / til_hig;


    vec2 FC_MOD;
    FC_MOD.x = gl_FragCoord.x;
    FC_MOD.y = gl_FragCoord.y;

    //You want all tiles to have the full range 
    //of colors, so you always modulate by 
    //CANVAS_WID and CANVAS_HIG, You scale by the 
    //# of tiles on each axis which means the 
    //gradient becomes steeper as the # of tiles
    //increases.
    FC_MOD.x = mod( gl_FragCoord.x*NUM_TIL_X, CANVAS_WID );
    FC_MOD.y = mod( gl_FragCoord.y*NUM_TIL_Y, CANVAS_HIG );

    //[N]ormalize values into range 0 to 1:
    //NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN//
    float norm_X = (FC_MOD.x) / CANVAS_WID;
    float norm_Y = (FC_MOD.y) / CANVAS_HIG;
    //NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN//

    //Use [B]lue channel because why not?
    //BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB//
    float GRAD_X = gl_FragCoord.x / CANVAS_WID;
    //BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB//

    //Set the final [F]ragment colors:
    //FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF//
    gl_FragColor = vec4(norm_X, norm_Y, GRAD_X, 1.0);
    //FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF//
  }
</script>
<!-- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS -->
<!-- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS -->
<!-- SSSSSSSSSS SHADER_SECTION END  SSSSSSSSSS -->
</head> 
<!-- HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH -->

<!-- BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -->                    
<body onload="ON_LOADED_FUNCTION()" >
<!-- BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -->

    <h3> Open GL Tile TestBed            <h3>
    <p> Author: John Mark Isaac Madison <p>
    <p> Email : J4M4I5M7@hotmail.com    <p>

    <canvas id="glCanvas"></canvas>

    </br>
    <button onClick="PUT_WID();">TILE_WIDTH__IN_PIXELS</button> 
    <input type="text" id="INPUT_WID" value="45">
    </br>

    </br>
    <button onClick="PUT_HIG();">TILE_HEIGHT_IN_PIXELS</button> 
    <input type="text" id="INPUT_HIG" value="45">
    </br>



<!-- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS -->   
<script id="BOILER_PLATE_CODE">
    function ON_LOADED_FUNCTION(){
        console.log("[ON_LOADED_FUNCTION]");
        main();
    }

    //:Takes the gl context object, if the input
    //:is null, we likely failed to get the
    //:context.
    function HAS_OPEN_GL_CHECK(gl){
      // Only continue if WebGL is 
      // available and working
      if (!gl) {
        var msg = "";
        msg += "[Unable to initialize WebGL.]";
        msg += "[your browser or machine may]";
        msg +=  "[not support it.]"
        alert( msg );
        return;
      }
    }

    function GET_INPUT_BOX_VALUE( elem_id ){
        var box; //DOM input box
        var val; //Value in input box.
        box = document.getElementById( elem_id );
        val = box.value;
        return (0 + val); //cast to number.
    }

    function PUT_WID(){
        assert_program_and_gl_exist();
        var val = GET_INPUT_BOX_VALUE("INPUT_WID");
        SET_ATTR("TIL_WID_EDIT", val);
    }

    function PUT_HIG(){
        assert_program_and_gl_exist();
        var val = GET_INPUT_BOX_VALUE("INPUT_HIG");
        SET_ATTR("TIL_HIG_EDIT", val); 
    }

    function SET_ATTR(gl_var_name, val){
        if(val < 0 || val > 256 ){
            alert("choose value between 0 to 256");
            return;
        }

        var loc; //<--location of variable.
        loc = gl.getUniformLocation(
            program    , 
            gl_var_name
        );
        gl.useProgram(program);
        gl.uniform1f(loc, val);
    }

    function assert_program_and_gl_exist(){
        if(!program){慌("[NO_PROGRAM_EXISTS]");}
        if(!gl     ){慌("[NO_GL_EXISTS]");}
    }

    //慌: "disconcerted, be confused, lose one's head"
    //慌: In Code: ~Panic~
    function 慌( panic_message ){
        console.log( panic_message );
        alert      ( panic_message );
        throw      ( panic_message );
    }

    function makeOpenGlContextUsingCanvas(c){

        //:Try what works in chrome and all the
        //:respectable browsers first:
        gl = c.getContext("webgl");

        if(!gl){
            console.log("[Probably_In_IE]");
            gl = c.getContext("experimental-webgl");
        }else{
            console.log("[Probably_NOT_IE]");
        }

        HAS_OPEN_GL_CHECK( gl );
        return gl;
    }

    //: No "var" prefix, making them global:
    function initGlobals(){
        canvas = document.querySelector("#glCanvas");
        if(!canvas){
            alert("FAILED_TO_GET_CANVAS");
        }else{
            console.log("[GOT_CANVAS]");
        }

        gl = makeOpenGlContextUsingCanvas(canvas);


        //These dimensions are hard-coded into
        //fragment shader code, so be careful
        //about changing them:
        canvas.width = 640;
        canvas.height= 480;

        buffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
        gl.bufferData(
        gl.ARRAY_BUFFER, 
        new Float32Array([
          -1.0, -1.0, 
           1.0, -1.0, 
          -1.0,  1.0, 
          -1.0,  1.0, 
           1.0, -1.0, 
           1.0,  1.0]), 
        gl.STATIC_DRAW
        );

        //G == Global Container.
        //To fix problems with rendering in I.E.
        //(Internet Explorer)
        //GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG//
        var G = {}; 
        G.canvas = canvas;
        G.gl     = gl;
        G.buffer = buffer;

        if( ! G.canvas ||
            ! G.gl     ||
            ! G.buffer  ){
            慌("[Global_Container_Broken]");
        }

        return G;
        //GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG//
    }

    function main(){

      G = initGlobals();
      HAS_OPEN_GL_CHECK( G );

      gl.viewport(0,0,gl.drawingBufferWidth, gl.drawingBufferHeight);

      setup();
      render();
    }

    function setup(){
        var frag_dom = document.getElementById("FRAG_SHADER");
        var frag_src = frag_dom.text;
        console.log( frag_src );

        F = createShader(
            gl,gl.FRAGMENT_SHADER, frag_src
        );

        var vert_dom = document.getElementById("VERT_SHADER");
        var vert_src = vert_dom.text;
        console.log( vert_src );

        V = createShader(
            gl, gl.VERTEX_SHADER, vert_src
        );

        //**** MAKE "program" a GLOBAL VAR  ****//
        program = createProgram(gl,V,F);
        gl.useProgram( program );

        if(!program){
            慌("PROGRAM_IS_NULL");
        }
    }

    function render(){
      window.requestAnimationFrame(render,canvas);

      // Set clear color to black, fully opaque
      gl.clearColor(0.0, 0.0, 0.5, 1.0);

      // Clear the color buffer with specified clear color
      gl.clear(gl.COLOR_BUFFER_BIT);

      //Directly before call to gl.drawArrays:
      positionLocation = gl.getAttribLocation(program, "a_position");
      gl.enableVertexAttribArray( positionLocation );
      gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);


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

    function createShader(gl,type,source){
        //:Error Check For Bad Inputs:
        if(!gl    ){慌("[NULL_GL]");}
        if(!type  ){慌("[NULL_TY]");}
        if(!source){慌("[NULL_SR]");}

        var shader = gl.createShader(type);
        gl.shaderSource(shader, source);
        gl.compileShader(shader);
        var res = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
        if( res ){
            console.log("[SHADER_COMPILED!]");
            return shader;
        }

        console.log(gl.getShaderInfoLog(shader));
        gl.deleteShader(shader);
        慌("[FAILED_TO_COMPILE_SHADER]");
    }

    //:gl  : openGL context :
    //:vert: vertex shader  :
    //:frag: fragment shader:
    function createProgram(gl,vert, frag){
        var program = gl.createProgram();
        gl.attachShader(program, vert);
        gl.attachShader(program, frag);
        gl.linkProgram (program);
        var res = gl.getProgramParameter(program, gl.LINK_STATUS);
        if( res ){
            console.log("[PROGRAM_CREATED!]");
            return program;
        }

        console.log(gl.getProgramInfoLog(program));
        gl.deleteProgram(program);
    }

</script>
<!-- SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS -->

<!-- BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB -->
</body>
</html>

1
2017-11-30 04:19



codepen.io/kioikoikio/full/xazbbw - Greag.Deay