簡體   English   中英

WebGL將矩形和圖像繪制到一個着色器

[英]WebGL draw rect & image to one shader

只是嘗試做一些我有兩個“游戲對象”的基本webgl。 一個簡單的精靈,和一個矩形。 基本上我想做的是繪制精靈圖像,然后繪制具有指定顏色的矩形。

兩個對象都有一個pos矢量,一個寬度和一個高度。 該子畫面具有一個圖像對象,而rect具有一個rgb值為0到1的顏色對象。

對不起所有代碼,但這是我的draw方法:

draw: function () {
  this.resize();
  var delta = this.getDeltaTime();

  gl.viewport(0, 0, gl.canvas.clientWidth, gl.canvas.clientHeight);
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

  var shaderProgram = this.shader.shaderProgram;

  var matrixLocation = gl.getUniformLocation(shaderProgram, "uMatrix");

  for (var i = 0; i < this.objects.length; i++) {
    var planePositionBuffer = gl.createBuffer();
    mat3.identity(this.mvMatrix);
    gl.bindBuffer(gl.ARRAY_BUFFER, planePositionBuffer);
    var object = this.objects[i];

    var x1 = object.pos.x;
    var y1 = object.pos.y;
    var x2 = object.pos.x + object.width;
    var y2 = object.pos.y + object.height;

    var vertices = [
      x1, y1,
      x2, y1,
      x1, y2,
      x1, y2,
      x2, y1,
      x2, y2
    ];

    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, 2, gl.FLOAT, false, 0, 0);

    var textureBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer);

    var textureCoords;
    if (object.image) {
      var dw = (object.width / object.image.image.width);
      var dh = 1.0 - (object.height / object.image.image.height);
      textureCoords = [
        0.0, 1.0,
        dw, 1.0,
        0.0, dh,
        0.0, dh,
        dw, 1.0,
        dw, dh
      ];

      gl.activeTexture(gl.TEXTURE0);
      gl.bindTexture(gl.TEXTURE_2D, this.objects[i].image);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(textureCoords), gl.STATIC_DRAW);
      gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
    }


    mat3.multiply(this.mvMatrix, this.mvMatrix, [
      2 / gl.canvas.clientWidth, 0, 0,
      0, -2 / gl.canvas.clientHeight, 0,
      -1, 1, 1
    ]);

    gl.uniformMatrix3fv(matrixLocation, false, this.mvMatrix);

    gl.uniform1i(shaderProgram.samplerUniform, 0);

    var colorLocation = gl.getUniformLocation(shaderProgram, "uColor");
    if (object.color) {
      var color = object.color;
      gl.uniform4f(colorLocation, color.r, color.g, color.b, 1);
    }
    else {
      gl.uniform4f(colorLocation, 1.0, 1.0, 1.0, 1);
    }

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

  requestAnimationFrame(this.draw.bind(this));
}

基本上我正在做的是將位置坐標放在一起以繪制圖像/矩形。

然后,我檢查對象是否有圖像。 如果是這樣,請根據其精靈寬度相對於圖像尺寸來計算紋理坐標。 並綁定紋理。

然后在下面,如果對象沒有顏色,則將統一顏色設置為白色。 如果對象確實具有顏色,它將設置該顏色的統一性。

現在,在我的列表中,圖像精靈是第一位,矩形是第二位,首先針對圖像調用bindTexture。 堅持進行抽獎。 OpenGL是一種狀態機,因此圖像首先繪制,保持綁定狀態,然后再次為rect坐標繪制。 它只使用我保存在矩形中的綠色。

因此,我的主要問題是: 是否有解決此問題的適當方法? 還是僅在某些情況下有辦法在頂點上繪制顏色,而在另一種情況下有紋理?

這是我的着色器:

<script id="shader-fs" type="x-shader/x-fragment">
  precision mediump float;

  varying vec2 vTextureCoord;
  uniform sampler2D uSampler;
  uniform vec4 uColor;

  void main(void) {
    gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)) * uColor;
  }
</script>

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

  uniform mat3 uMatrix;
  varying vec2 vTextureCoord;

  void main() {
    gl_Position = vec4((uMatrix * vec3(aVertexPosition, 1)).xy, 0, 1);
    vTextureCoord = aTextureCoord;
  }
</script>

很簡單 使用統一矩陣在片段坐標上的代碼中具有屏幕坐標。

使用單個着色器繪制紋理或顏色的典型方法是將不使用的着色器設置為白色,乘法或黑色和加法。 我更喜歡白色和乘法,這就是您已經擁有的。

因此,當您只想繪制紋理時

var whiteColor = [1, 1, 1, 1];

gl.bindTexture(gl.TEXTURE_2D, textureWithImageInIt);
gl.uniform4fv(uColorLocation, whiteColor);

當您只想用顏色繪制時,請綁定1x1像素的白色紋理

在初始化時間

var white1PixelTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, white1PixelTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
              new Uint8Array([255,255,255,255]));

在抽獎時

gl.bindTexture(gl.TEXTURE_2D, white1PixelTexture);
gl.uniform4fv(uColorLocation, someColor);  

之所以有效,是因為white = 11 * something = something使得texture * 1 = texture1 * color = color ;

它還使您可以為簡單的效果着色紋理。 設置顏色為紅色[1, 0.4, 0.4, 1] 1,0.4,0.4,1 [1, 0.4, 0.4, 1] ,您將獲得紅色的紋理。 隨時間調整[1, 0, 0, lerpColorOverTime]的alpha [1, 0, 0, lerpColorOverTime]您可以淡出紋理。

是的,有一種適當的方法,只需在完成紋理處理后將其解除綁定即可:

 gl.activeTexture(gl.TEXTURE0);
 gl.bindTexture(gl.TEXTURE_2D, null);

暫無
暫無

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

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