簡體   English   中英

着色器:存儲它們的最佳實踐

[英]Shaders : Best practice to store them

我正在學習webgl並從此站點上汲取教訓

為了存儲着色器,作者在<script>標記中聲明了它們:

<script id="shader-vs" type="x-shader/x-vertex">
attribute vec3 aVertexPosition;

uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;

void main(void) {
  gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
}
</script>

然后使用一些javascript代碼檢索它們:

 function getShader(gl, id) {
  var shaderScript = document.getElementById(id);
  if (!shaderScript) {
      return null;
  }

  var str = "";
  var k = shaderScript.firstChild;
  while (k) {
      if (k.nodeType == 3)
          str += k.textContent;
      k = k.nextSibling;
  }

  var shader;
  if (shaderScript.type == "x-shader/x-fragment") {
      shader = gl.createShader(gl.FRAGMENT_SHADER);
  } else if (shaderScript.type == "x-shader/x-vertex") {
      shader = gl.createShader(gl.VERTEX_SHADER);
  } else {
      return null;
  }

  gl.shaderSource(shader, str);
  gl.compileShader(shader);

  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
      alert(gl.getShaderInfoLog(shader));
      return null;
  }

  return shader;
}

我發現檢索着色器非常復雜,因此問題很簡單:

檢索和編譯着色器的最佳實踐是什么? 這是標准方式嗎? 我希望能夠將着色器存儲在其他文件中。

我在webGL中不太好,但是我做了一些事情。 我也在問自己這個問題。 我知道有3種常見方法。 第一個是您在此處介紹的基本內容。 是的,它很雜亂,很復雜,但是有一些優點。 着色器代碼易於維護。

我發現的第二種方法是將着色器代碼放入數組中,然后立即加入數組,使其成為字符串。 之后,您可以將字符串傳遞給gl.createShader函數。

這種技術在three.js javascript庫中非常普遍,該庫中有很多着色器代碼。 它使着色器易於閱讀,而不像第一個那樣混亂,但是如您所見,維護着色器代碼會有點困難。 要點是,它將使您可以將所有內容保存在一個javascript文件中,這是每個好的庫都需要的行為。

一個小例子,這是我們的頂點着色器:

var vertexShader = [
    "attribute vec3 aVertexPosition;",

    "uniform mat4 uMVMatrix;",
    "uniform mat4 uPMatrix;",

    "void main(void) {",
        "gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);",
    "}"
].join( "\n" );

編輯

有人找到了一種更好的方法!

var vertexShader = `attribute vec3 aVertexPosition;

uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;

void main(void) {
    gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
}`;

編輯結束

可以處理着色器的功能

function getShader(gl, source, type) {

    var shader;
    if (type == "fragment") {
        shader = gl.createShader(gl.FRAGMENT_SHADER);
    } else if (type == "vertex") {
        shader = gl.createShader(gl.VERTEX_SHADER);
    } else {
        return null;
    }

    gl.shaderSource(shader, source);
    gl.compileShader(shader);

    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
        alert(gl.getShaderInfoLog(shader));
        return null;
    }

    return shader;
}

簡單函數調用

// var fragmentShader = getShader(gl, fragmentShader, "fragment");
var vertexShader = getShader(gl, vertexShader, "vertex");

但是您可能正在尋找與眾不同的東西。 因此,對您來說最好的選擇是制作“ myvertexshader”之類的文件,然后調用ajax將文件加載到變量中。 jQuery是一個不錯的選擇。

jQuery.get('myvertexshader', callback);

function callback(source) {
    var shader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(shader, source);
    gl.compileShader(shader);

    ...
}

然后將您的着色器代碼與javascript分開。 您還可以設置自己的文件擴展名,並在IDE中為着色器開發制定不同的規則,這對於豐富的着色器來說是個好主意。

PS:我聽說有一些謠言稱Blob文件將能夠編譯着色器(也許我已經知道了)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM