首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WebGL特指每个三角形的颜色图案

WebGL特指每个三角形的颜色图案
EN

Stack Overflow用户
提问于 2016-03-06 15:21:58
回答 1查看 347关注 0票数 0

我目前正在努力教自己WebGL,特别是创建一个Tessellate应用程序。

我玩过颜色,现在对整个三角形产生了彩虹效应,这种效果不会随着颜色的变化而改变:

代码语言:javascript
复制
<script id="vertex-shader" type="x-shader/x-vertex">
    attribute vec4 vPosition;  
    uniform vec4 u_offset;
    varying vec4 v_positionWithOffset;       
    void main() {
        gl_Position = vPosition + u_offset;
        v_positionWithOffset = vPosition + u_offset; 
    }
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
    precision mediump float;
    varying vec4 v_positionWithOffset;
    void main() {
        vec4 color = v_positionWithOffset * 0.99 + 0.75;
        gl_FragColor = color;      
    }
</script>

我真正想要做的是在每个三角形被分割时分别着色。由于块色的效果是不可见的,所以我想用一些任意的颜色方案对每个三角形进行着色,所以每个三角形的中心是一个阴影,而外部是另一个(可能更深)的颜色。

我将如何实现这一目标?

提前感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-03-07 08:54:37

首先,在WebGL中着色任何东西的最明显的方法是使用纹理和纹理坐标,但我相信您知道这一点。

否则,如果你想把中间的一种颜色和边缘涂上不同的颜色,这里有一个基于这篇文章的想法。

我们可以在每个三角形的每个顶点上加上他所说的重心。

代码语言:javascript
复制
triangle vertex 0:   1, 0, 0
triangle vertex 1:   0, 1, 0
triangle vertex 2:   0, 0, 1

现在我们有了在每个三角形上插值的值,每个点到它的相反的边缘都有一个。我们可以在着色器里用它。我有个主意。这个使中心变成白色。

代码语言:javascript
复制
precision mediump float;

#define PI radians(180.0)

varying vec4 v_color;
varying vec3 v_barycentric;

uniform float u_fudge;
uniform float u_sharpness;

void main() {
  vec3 t = sin(v_barycentric * PI);
  float center = pow(t.x * t.y * t.z * u_fudge, u_sharpness);
  gl_FragColor = mix(v_color, vec4(1,1,1,1), center);
}

示例:

代码语言:javascript
复制
var positions = [];
var colors = [];
var barycentrics = [];

var subDivisions = 3;
for (var yy = 0; yy < subDivisions; ++yy) {

  // making the positions in clip space so no extra
  // math needed in shader

  var y0 = (yy + 0) / subDivisions * 2 - 1;
  var y1 = (yy + 1) / subDivisions * 2 - 1;

  for (var xx = 0; xx < subDivisions; ++xx) {

    var x0 = (xx + 0) / subDivisions * 2 - 1;
    var x1 = (xx + 1) / subDivisions * 2 - 1;

    // pick a random color
    var r = Math.random();
    var g = Math.random();
    var b = Math.random();

    // make a triangle
    positions.push(x0, y0);
    positions.push(x1, y0);
    positions.push(x0, y1);

    // and it's colors, one for each triangle vertex
    colors.push(r, g, b);
    colors.push(r, g, b);
    colors.push(r, g, b);
    
    barycentrics.push(1, 0, 0);
    barycentrics.push(0, 1, 0);
    barycentrics.push(0, 0, 1);

    // pick a random color
    r = Math.random();
    g = Math.random();
    b = Math.random();

    // make a triangle
    positions.push(x0, y1);
    positions.push(x1, y0);
    positions.push(x1, y1);

    // and it's colors, one for each triangle vertex
    colors.push(r, g, b);
    colors.push(r, g, b);
    colors.push(r, g, b);
    
    barycentrics.push(1, 0, 0);
    barycentrics.push(0, 1, 0);
    barycentrics.push(0, 0, 1);
  }
}


var gl = twgl.getWebGLContext(document.getElementById("c"));
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);

var arrays = {
  position:    { numComponents: 2, data: positions },
  color:       { numComponents: 3, data: colors },
  barycentric: { numComponents: 3, data: barycentrics },
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);

var uniforms = {
  u_fudge: 1,
  u_sharpness: 1,
};

function render() {
  gl.useProgram(programInfo.program);
  twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
  twgl.setUniforms(programInfo, uniforms);
  twgl.drawBufferInfo(gl, gl.TRIANGLES, bufferInfo);
}
render();

document.querySelectorAll("input[type=range]").forEach(function(elem) {
  elem.addEventListener('input', function(event) {
    var id = event.target.id;
    uniforms["u_" + id] = event.target.value / 100;
    render();
  });
});
代码语言:javascript
复制
<script src="https://twgljs.org/dist/twgl.min.js"></script>
<script id="vs" type="notjs">
attribute vec4 position;
attribute vec4 color;
attribute vec3 barycentric;

varying vec4 v_color;
varying vec3 v_barycentric;

void main() {
  gl_Position = position;
  
  v_color = color;
  v_barycentric = barycentric;
}
</script>
<script id="fs" type="notjs">
precision mediump float;

#define PI radians(180.0)

varying vec4 v_color;
varying vec3 v_barycentric;

uniform float u_fudge;
uniform float u_sharpness;

void main() {
  vec3 t = sin(v_barycentric * PI);
  float center = pow(t.x * t.y * t.z * u_fudge, u_sharpness);
  gl_FragColor = mix(v_color, vec4(1,1,1,1), center);
}
  </script>
<canvas id="c"></canvas>
<div id="ui">
  <label for="fudge">fudge</label>
  <input id="fudge"     type="range" min="0" max="500" value="100" />
  <label for="sharpness">sharpness</label>
  <input id="sharpness" type="range" min="0" max="500" value="100" />
</div>

我们可以通过2套制服的2种颜色,或使用两套顶点颜色或样本从2个纹理。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35828674

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档