簡體   English   中英

更改圓圈中間的顏色

[英]Change color in middle of circle

我是WebGL的新手,我正嘗試在此綠色圓圈的中間創建一個黑環,而無需再添加其他圓圈。 我相信我可以通過使這些三角形的法線相反來做到這一點,但是我不確定到底該怎么做。 我的朋友建議更改紋理坐標,但是我真的不知道這會有什么幫助。 任何人都可以對這些想法和可能的直覺有所了解嗎?

_______HTML文件__________

<!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文件______

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 );
}

我按照您的要求整理了部分任務。 我嘗試不對代碼進行太多更改,因此您可以了解我所做的所有更改。 第一場小秀:

您以100點(頂點)為單位繪制了一個圓。 現在,您想在內部制作另一個形狀。 這意味着要再使用100點,這可能是您不想做的。 除此以外,您想使用法線。 但是,從着色器(負責繪制)的角度來看,法線,頂點以及諸如紋理坐標之類的其他東西僅是數據,而您是由誰來決定的,即數據是指頂點,法線,紋理坐標還是其他任何東西。

如果我理解的很好,您希望自定義對象而不添加太多額外的數據。 我認為法線或紋理無法幫助您。

您幾乎不需要面對紋理問題...

  • 首先是,如果圓過大(靠近您),那么僅以100分就不會那么好。
  • 如果圓圈太小(離您較遠),但是圓圈很多,您將用太多的點數來降低性能。
  • 如果將紋理用於內部的黑色環,則如果靠近將變得模糊。
  • 而且,如果對許多小圓圈使用過大的紋理,則會再次降低性能。

...和法線用於這樣的光反射

我對問題的思考方式。 您可以用很少的參數,半徑和中心定義圓。 使用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);

然后,我將以與您相同的方式進行渲染,除了需要允許Alpha繪制外,因為三角形的某些部分將是不可見的,因此它將看起來像圓形:

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;

我的片段着色器只需要做一件事,就可以確定像素是否在圓圈中。 簡單方程式: 在此處輸入圖片說明

如果左側小於右側,則像素在圓內。 如果不是,那么它就在外面,所以看不見:

    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);
    }

結束

所以現在您可能只知道幾個點就可以畫一個圓。 您可以使用類似的方法在內部繪制圓環。 然后,您可以在任何距離上繪制成千上萬的圖形,並使它們移動。 程序將仍然快速並且形狀將盡可能清晰。

最后一件事。 通常,您不會像這樣簡化形狀,但有時您可能會簡化。 貝塞爾曲線就是一個很好的例子,它可以幫助您僅用很少的點就能完成瘋狂的尖銳形狀。 但這很重要,您想做什么。 一種技術不能解決所有問題,您必須繼續尋找更多的解決方案。

編輯1: “什么是var middle = vec2(0.0,0.0)?我知道是vec2嗎?”

我在解決方案中復制了這個問題中的其他3個腳本(在左側的jsfiddle中: External Resources )。 這不是這個問題的一部分,但是很容易找到它們的起源:

<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]; vec2 var middle = [0.0, 0.0]; 是完全一樣的東西。 它不是本機javascript的一部分,因此您需要一些庫(您不需要它,但是它非常有用)。 我使用glmatrix

另一方面,在着色器中,向量和矩陣是本機的。 在第4.1章“ 基本類型”中自行查找。

暫無
暫無

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

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