[英]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點,這可能是您不想做的。 除此以外,您想使用法線。 但是,從着色器(負責繪制)的角度來看,法線,頂點以及諸如紋理坐標之類的其他東西僅是數據,而您是由誰來決定的,即數據是指頂點,法線,紋理坐標還是其他任何東西。
如果我理解的很好,您希望自定義對象而不添加太多額外的數據。 我認為法線或紋理無法幫助您。
您幾乎不需要面對紋理問題...
...和法線用於這樣的光反射 。
我對問題的思考方式。 您可以用很少的參數,半徑和中心定義圓。 使用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 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.