【问题标题】:WebGL Drawing Multiple Shapes of Different ColourWebGL 绘制多种不同颜色的形状
【发布时间】:2017-02-07 01:59:38
【问题描述】:

我目前正在学习 WebGL 和 Javascript。一项任务要求我使用 WebGL 创建多个形状,并且它们都是不同的颜色,但是,我无法弄清楚如何设置它,以便每个形状都有自己的颜色。

// HelloTriangle.js (c) 2012 matsuda
// Vertex shader program
var VSHADER_SOURCE =
  'attribute vec4 a_Position;\n' +
  'void main() {\n' +
  '  gl_Position = a_Position;\n' +
  '}\n';
 
// Fragment shader program
var FSHADER_SOURCE =
  'precision mediump float;\n' +
  'uniform vec4 u_FragColor;\n' +
  'void main() {\n' +
  '  gl_FragColor = u_FragColor;\n' +
  '}\n';
 
function main() {
  // Retrieve <canvas> element
  var canvas = document.getElementById('webgl');
 
  // Get the rendering context for WebGL
  var gl = getWebGLContext(canvas);
  if (!gl) {
    console.log('Failed to get the rendering context for WebGL');
    return;
  }
 
  // Initialize shaders
  if (!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)) {
    console.log('Failed to intialize shaders.');
    return;
  }
 
  // Write the positions of vertices to a vertex shader
  var n = initVertexBuffers(gl);
  if (n < 0) {
    console.log('Failed to set the positions of the vertices');
    return;
  }
 
  // Specify the color for clearing <canvas>
  gl.clearColor(0, 0, 0, 1);
 
  // Clear <canvas>
  gl.clear(gl.COLOR_BUFFER_BIT);
 
  // Draw the rectangle
  gl.drawArrays(gl.TRIANGLES, 0, 3); // Triangle One
  gl.drawArrays(gl.TRIANGLES, 3, 3); // Triangle Two
  gl.drawArrays(gl.TRIANGLE_FAN, 6, 6); // Triangle Fan
}
 
function randColor() // Assign Random color values
{
    setR = Math.random();
    setG = Math.random();
    setB = Math.random();
}
 
function initVertexBuffers(gl) {
  var vertices = new Float32Array([
    0.1,   0.1,   -0.1,  -0.1,   0.1,  -0.1,  // First Triangle
    0.15,  0.25,   0.1,   0.2,  -0.1,   0.2,  // Second Triangle
    0.75,  0.65,   0.35,  0.25,  0.65,  0.55,
    0.65,  0.25,   0.35,  0.45,  0.25,  0.15  // Triangle Fan
  ]);
  var n = 6; // The number of vertices
 
  // Create a buffer object
  var vertexBuffer = gl.createBuffer();
  if (!vertexBuffer) {
    console.log('Failed to create the buffer object');
    return -1;
  }
 
  // Bind the buffer object to target
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
  // Write date into the buffer object
  gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
 
  var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
  if (a_Position < 0) {
    console.log('Failed to get the storage location of a_Position');
    return -1;
  }
 
  // Get the storage location of u_FragColor
  var u_FragColor = gl.getUniformLocation(gl.program, 'u_FragColor');
  if (!u_FragColor) {
    console.log('Failed to get the storage location of u_FragColor');
    return;
  }
 
  //Pass color of point to u_FragColor
  randColor();
  gl.uniform4f(u_FragColor, setR, setG, setB, 1.0);
 
  // Assign the buffer object to a_Position variable
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
 
  // Enable the assignment to a_Position variable
  gl.enableVertexAttribArray(a_Position);
 
  return n;
}
<canvas id="webgl" width="400" height="400">
  Please use a browser that supports "canvas"
</canvas>

<script src="../lib/webgl-utils.js"></script>
<script src="../lib/webgl-debug.js"></script>
<script src="../lib/cuon-utils.js"></script>

我很确定我应该修改的代码如下:

//Pass color of point to u_FragColor
randColor();
gl.uniform4f(u_FragColor, setR, setG, setB, 1.0);

但是,我不知道如何制作它,以便它为我尝试绘制的每个形状存储一个值。我认为通过让它在每次绘制之前随机更改颜色,可以解决它,但事实并非如此。任何对此的见解将不胜感激。

谢谢。

【问题讨论】:

标签: javascript html webgl fragment-shader


【解决方案1】:

你尝试了什么?该代码存在很多问题,并且在尝试运行它时会出错。

首先initShaders 返回gl.program 上的着色器,这使得零意义。 WebGL 应用程序通常有多个着色器程序。相反,您希望 initShaders 返回一个程序,以便您可以执行类似的操作

var program1 = initShaders(gl, vertex1ShaderSource, fragment1ShaderSource);
var program2 = initShaders(gl, vertex2ShaderSource, fragment2ShaderSource);
var program3 = initShaders(gl, vertex3ShaderSource, fragment3ShaderSource);
..etc...

接下来initVertexBuffers 引用了一个名为program 的变量,但不存在这样的变量。

initVertexBuffers 正在设置制服,但您想在开始绘制之前设置制服,而不是在初始化顶点时。

initVertexBuffers 也在查找属性和统一位置并检查错误。一方面,检查这些类型的错误本身还不错,但它会使您的代码更难以其他方式调试。在大多数 WebGL 程序中,如果您没有收到错误但屏幕上没有出现某些内容,那么首先要做的就是让您的片段着色器返回纯色

precision mediump float;
uniform vec4 u_FragColor;
void main() {
  //gl_FragColor = u_FragColor;
  gl_FragColor = vec4(1, 0, 0, 1); // return red
}

当您这样做时,WebGL 将优化未使用的u_FragColor,并且您检查您是否获得u_FragColor 位置的代码将失败,从而无法调试您的着色器。

我建议reading some other tutorials on WebGL。

绘制相同形状的多个副本的过程一般是

在初始化时

 set up program
 look up attribute locations and uniform locations
 setup vertices for shape

在绘制时

 setup attributes for shape
 gl.useProgram(program for shape)
 for each instance of shape
   set uniforms
     set a matrix uniform to position and orient the shape
     set a color uniform for the color
   drawArrays/drawElements

绘制多个不同形状的过程通常是

在初始化时

 set up programs
 look up attribute locations and uniform locations
 for each shape
   setup vertices for shape

在绘制时

 for each shape
   gl.useProgram(program for shape) (if different from last shape)
   setup attributes for shape (if different from last shape)
   set uniforms
     set a matrix uniform to position and orient the shape
     set a color uniform for the color
   drawArrays/drawElements

关于定位和定向形状的矩阵see this article

【讨论】:

    猜你喜欢
    • 2019-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    • 2016-02-23
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多