Ich bin ein Anfänger bei WebGL-Programmierung.WebGL: glatt Linien aus Canvas verblassen
Ich habe eine Webanwendung in Three.JS gemacht, die mit gelegentlichem Rauschen eine Sinowelle auf eine Leinwand zeichnet. Nachdem sie gezeichnet wurden, verblasse ich sie. Der Endeffekt sieht ungefähr so aus:
Ich versuche, die Anwendung in WebGL wegen Geschwindigkeitsprobleme mit Three.js zu machen. Ich bin in der Lage, eine einfache Sinuswelle in WebGL zu zeichnen, aber ich weiß nicht, wie ich den gleichen Effekt erzielen kann, bei dem ich eine einzelne Welle zeichnen, sie irgendwie im Puffer behalten und verblassen kann.
Dies ist, was ich zur Zeit (in WebGL) haben:
Auch hier ist der entsprechende Code:
this.gl;
try {
this.gl = this.canvas.getContext('experimental-webgl',{antialias: false});
} catch (e) {
alert('WebGL not supported.');
}
//set position of vertices in clip coordinates
this.vtxShaderSrc = "\n\
attribute vec2 position;\n\
uniform vec2 viewport;\n\
\n\
void main(void){\n\
\n\
gl_Position = vec4((position/viewport)*2.0-1.0, 0.0, 1.0);\n\
}";
//fragment shader returns the color of pixel
this.fmtShaderSrc = "\n\
precision mediump float;\n\
\n\
\n\
\n\
void main(void){\n\
int r = 255;\n\
int g = 255;\n\
int b = 255;\n\
gl_FragColor = vec4(r/255,g/255,b/255,1.);\n\
}";
this.getShader = function(source, type){
var shader = this.gl.createShader(type);
this.gl.shaderSource(shader, source);
this.gl.compileShader(shader);
return shader;
}
this.vtxShader = this.getShader(this.vtxShaderSrc, this.gl.VERTEX_SHADER);
this.fmtShader = this.getShader(this.fmtShaderSrc, this.gl.FRAGMENT_SHADER);
this.program = this.gl.createProgram();
//attach fragment and vertex shader to program
this.gl.attachShader(this.program, this.vtxShader);
this.gl.attachShader(this.program, this.fmtShader);
//link program to WebGL
this.gl.linkProgram(this.program);
//get position attribute and enable it in vertex shader
this._position = this.gl.getAttribLocation(this.program, 'position');
this.gl.enableVertexAttribArray(this._position);
//tell WebGL to use this program
this.gl.useProgram(this.program);
//create buffers
this.vertexBuffer = this.gl.createBuffer();
this.facesBuffer = this.gl.createBuffer();
this.lineVertices = [];
this.faceCount = [];
//bind them to WebGL
this.bindVertexBuffer = function(){
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.vertexBuffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(this.lineVertices), this.gl.STREAM_DRAW);
}
this.bindFacesBuffer = function(){
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, this.facesBuffer);
this.gl.bufferData(this.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(this.faceCount), this.gl.STREAM_DRAW);
}
this.bindVertexBuffer();
this.bindFacesBuffer();
//set background color to black
this.gl.clearColor(0.0,0.0,0.0,1.0);
//draw on canvas
this.draw = function(){
this.gl.enable(this.gl.BLEND);
this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
this.gl.vertexAttribPointer(this._position, 2, this.gl.FLOAT, false, 8*2, 0);
var loc = this.gl.getUniformLocation(this.program, 'viewport');
this.gl.uniform2f(loc, this.canvas.width, this.canvas.height);
//draw only if number of lines is greater than 0
if(this.faceCount.length > 0){
this.gl.drawElements(this.gl.LINE_STRIP, this.faceCount.length/4, this.gl.UNSIGNED_SHORT, 0);
}
this.gl.disable(this.gl.BLEND);
}
//update vertices and faces so next call to this.draw() updates the wave
this.update = function(newPts){
this.lineVertices = newPts;
this.bindVertexBuffer();
var faces = [];
for(var i = 0; i < this.lineVertices.length; i++) faces.push(i);
this.faceCount = faces;
this.bindFacesBuffer();
}
Jede Hilfe/Zeiger geschätzt werden. Danke
Interessant. Was war der Engpass für die Implementierung von three.js, wenn ich fragen darf? – user01
@ user01 Die Methode, die ich zum Rendern der Linien in three.js verwende, zeichnet zusätzliche Linien und wendet eine niedrigere Deckkraft an, wenn mehr Linien gezeichnet werden. Es funktioniert gut für eine, sogar zwei Wellen (sagen sin und cos wave). Ich habe jedoch vor, viel mehr Wellen auf einer Leinwand zu haben. Dies führt dazu, dass der FPS deutlich sinkt, da die Anzahl der eingehenden Punkte auf Zehntausende steigt. Der direkte Umgang mit WebGL erhöht diese Leistung scheinbar um das 20- bis 50-fache. Ich versuche, die von dieser Person verwendete Rendermethode nachzuahmen: http://codeflow.org/entries/2013/feb/04/high-performance-js-heatmaps/ –
Verfolgen Sie eine Helligkeitsvariable oder etwas Ähnliches. Es sollte bei 1,0 beginnen und dann im Laufe der Zeit auf 0 verringern. Senden Sie es an die GPU und multiplizieren Sie 'gl_FragColor' mit der Helligkeit. Es ist auch möglich, die Helligkeitsverringerung ganz auf GPU zu verschieben, aber ich bin mir nicht sicher, ob das das ist, wonach Sie suchen. – user80667