2014-09-22 110 views
1

我是WebGL的新手,我試圖在這個綠色圓圈的中間創建一個黑色的圓環,而不會增加額外的圓圈。我相信我可以通過使這些三角形的法線變成另一種方式來做到這一點,但我不確定如何做到這一點。我的朋友建議更改紋理座標,但我不太明白這將如何幫助。任何人都可以對這些想法和可能的直覺發出一些光芒嗎?在圓圈中間改變顏色

_______HTML File__________

<!DOCTYPE html> 
<html> 
<head> 

<script id="vertex-shader" type="x-shader/x-vertex"> 
attribute vec4 vPosition; 

void 
main() 
{ 
    gl_Position = vPosition; 
} 
</script> 

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

void 
main() 
{ 
    gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 
} 
</script> 

<script type="text/javascript" src="../Common/webgl-utils.js"></script> 
<script type="text/javascript" src="../Common/initShaders.js"></script> 
<script type="text/javascript" src="../Common/MV.js"></script> 
<script type="text/javascript" src="Circle.js"></script> 
</head> 

<body> 
<canvas id="gl-canvas" width="512" height="512"> 
Oops ... your browser doesn't support the HTML5 canvas element 
</canvas> 
</body> 
</html> 

_____Javascript File______

var gl; 
var points; 


window.onload = function init() 
{ 
    var canvas = document.getElementById("gl-canvas"); 

    gl = WebGLUtils.setupWebGL(canvas); 
    if (!gl) { alert("WebGL isn't available"); } 


    // The Vertices 
    var pi = 3.14159; 
    var x = 2*pi/100; 
    var y = 2*pi/100; 
    var r = 0.9; 

    points = [ vec2(0.0, 0.0) ]; //establish origin 

    //for loop to push points 
    for(var i = 0; i < 100; i++){ 
     points.push(vec2(r*Math.cos(x*i), r*Math.sin(y*i))); 
     points.push(vec2(r*Math.cos(x*(i+1)), r*Math.sin(y*(i+1)))); 
    } 

    // 
    // Configure WebGL 
    // 
    gl.viewport(0, 0, canvas.width, canvas.height); 
    gl.clearColor(0.3, 0.3, 0.3, 1.0); 

    // Load shaders and initialize attribute buffers 

    var program = initShaders(gl, "vertex-shader", "fragment-shader"); 
    gl.useProgram(program); 

    // Load the data into the GPU 

    var bufferId = gl.createBuffer(); 
    gl.bindBuffer(gl.ARRAY_BUFFER, bufferId); 
    gl.bufferData(gl.ARRAY_BUFFER, flatten(points), gl.STATIC_DRAW); 

    // Associate out shader variables with our data buffer 

    var vPosition = gl.getAttribLocation(program, "vPosition"); 
    gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0); 
    gl.enableVertexAttribArray(vPosition); 

    render(); 
}; 


function render() { 
    gl.clear(gl.COLOR_BUFFER_BIT); 
    gl.drawArrays(gl.TRIANGLE_FAN, 0, points.length); 
} 
+0

的可能重複[three.js所WebGL的繪製圓自定義填充和着色邊框顏色(http://stackoverflow.com/questions/18425201/three-js-webgl-draw-a-circle-custom-fill - 邊界顏色着色器) – davidcondrey 2014-09-22 07:36:43

回答

2

我組裝你的任務的某些部分按照您的要求。我試圖不改變你的代碼,所以你可以理解我所做的所有改變。首先小秀:

你讓圈出的100點(頂點)。現在你想在裏面做出另一個形狀。這意味着再用100分,這可能是你不想做的。而不是這個,你想使用法線。但從着色器(負責繪製)的角度來看,如果數據意味着頂點,法線,紋理座標或其他任何東西,法線,頂點和其他東西(如紋理座標)就是數據,您決定誰。

如果我理解的很好,你想定製你的對象而不添加太多的額外數據。我不認爲法線或紋理可以幫助你。

有幾個問題,你將不得不面對與質感...

  • 首先,如果圓圈將過大(靠近你),那麼這將是不是很好用只有100點。
  • 如果圈子太小(遠離你),但會有很多圈子,你會用太多的點數來降低性能。
  • 如果你在內部使用黑色環紋理,如果你會更近,它會變得模糊。
  • 而且如果你對很多小圓圈使用太大的紋理,它會再次降低性能。

...和法線用於做light reflection like this

我想到了這個問題。你可以用幾個參數,半徑和中心來定義圓。使用webgl,您只能繪製三角形(和點)。但是您可以例如自定義着色器在每個三角形中繪製內切圓。

所以我定義只是半徑和中心:

var r = 0.9; 
var middle = vec2(0.0, 0.0); 

然後我生成三角形的3個點周圍的圓(圓內接該新的三角形的圓):

function buildCircle(center, r) { 
    var points = []; 

    points.push(vec2((r * TRI_HEIGHT_MOD * Math.cos(0 * DEG_TO_RAD)) + center[0], (r * TRI_HEIGHT_MOD * Math.sin(0 * DEG_TO_RAD)) + center[1])); 
    points.push(vec2((r * TRI_HEIGHT_MOD * Math.cos(120 * DEG_TO_RAD)) + center[0], (r * TRI_HEIGHT_MOD * Math.sin(120 * DEG_TO_RAD) + center[1]))); 
    points.push(vec2((r * TRI_HEIGHT_MOD * Math.cos(240 * DEG_TO_RAD)) + center[0], (r * TRI_HEIGHT_MOD * Math.sin(240 * DEG_TO_RAD)) + center[1])); 

    vertexPositions = points; 
} 

然後我傳中間,半徑和三角形我的着色器:

var vPosition = gl.getAttribLocation(program, "vPosition"); 
gl.vertexAttribPointer(vPosition, 2, gl.FLOAT, false, 0, 0); 
gl.enableVertexAttribArray(vPosition); 

program.middle = gl.getUniformLocation(program, "middle"); 
gl.uniform2f(program.middle, middle[0], middle[1]); 

program.r = gl.getUniformLocation(program, "r"); 
gl.uniform1f(program.r, r); 

然後我只是用s AME爲你做什麼,只是我需要讓阿爾法繪圖,因爲三角形的某些部分將是不可見的,所以它看起來是圓:

gl.blendFunc(gl.SRC_ALPHA, gl.ONE); 
gl.enable(gl.BLEND); 
gl.disable(gl.DEPTH_TEST); 

現在好了着色器。

有你真的需要知道繼續下去,所以請閱讀在這裏幾件事情:http://webglfundamentals.org/webgl/lessons/webgl-how-it-works.html

我的頂點着色器是一樣的你,除了我需要通過插值頂點位置到片段着色器:

varying vec4 pos; 

... 

void main() { 
    pos = vPosition; 

我的片段着色器只需要做一件事情,它是要決定,如果像素是在圓或不。簡單的等式: enter image description here

如果左側比右側小,則像素在圓內。如果沒有,那麼它在外面,所以無形:

float inside = pow(pos.r - middle.r, 2.0) + pow(pos.g - middle.g, 2.0); 
    if (inside < pow(r, 2.0)) { 
     gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); 
    } else { 
     gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); 
    } 

所以,現在你可能知道如何使一個圓圈剛剛從幾個點。你可以用類似的方法在裏面畫一個戒指。然後你可以在任何距離上畫出成千上萬的圖片並讓它們移動。程序將仍然很快,形狀將盡可能的銳利。

只是最後一件事。通常你不會簡化這種形狀,但有時你可能會這樣做。很好的例子是Bézier curve這可能會幫助你用幾個點來做出瘋狂的尖銳形狀。但這一切都很重要,你想要做什麼。一種技術不能解決所有問題,你必須不斷尋找更多的解決方案。

編輯1:「什麼是var middle = vec2(0.0,0.0)?我是mec,vec2?」

有這個問題,我在我的解決方案複製其他3個腳本(在的jsfiddle左側:外部資源)。它不是這個問題的一部分,但它很容易找到他們的起源:

<script type="text/javascript" src="../Common/webgl-utils.js"></script> 
<script type="text/javascript" src="../Common/initShaders.js"></script> 
<script type="text/javascript" src="../Common/MV.js"></script> 

MV.js是一些供應JavaScript和基本的數學......或代數結構,如向量和矩陣。 vec2是返回數組長度爲2的函數。所以var middle = [0.0, 0.0];是完全一樣的東西。這不是原生JavaScript的一部分,所以你需要一些庫(你不需要它,但它非常有用)。我使用glmatrix

論着色器另一方面,向量和矩陣是天然的。在4.1 Basic Types一章中自行找出它。

+0

什麼是var middle = vec2(0.0,0.0)?我meam,vec2? – debeka 2014-10-16 00:42:31

+1

@debeka答案在編輯1;) – 2014-10-16 12:56:30