2016-07-16 10 views
0

gezoomt Ich verwende cocos2d-js webgl Modus eine sehr einfache Shader-Effekt zu erzeugen:Fragment-Shader-Position ändert sich, wenn Browser

einen gefüllten Kreis mit einer Position geben Zentrum ziehen und einen Radius.

Die Fragment-Shader:

uniform vec2 position; 
uniform vec3 lightColor; 
uniform float lightSize; 

    void main() 
    { 
     float distance = distance(gl_FragCoord.xy, position); 
     if (distance <= lightSize) { 
      gl_FragColor = vec4(lightColor, 1.0); 
     } 
     else { 
      gl_FragColor = vec4(lightColor, 0.0); 
     } 
    } 

Dieser Code funktioniert gut, wenn der Browser nicht (100%) skaliert wird.

Aber wenn ich versuche, den Browser auf 80% oder 120% zu zoomen, habe ich festgestellt, dass der Kreis mit einem Versatz von der eingestellten Mittelposition gezeichnet wurde.

Ich bin mir nicht sicher, wie Sie dieses Problem beheben können, um sicherzustellen, dass der Kreis immer auf der MITTLERE POSITION eingestellt ist, egal wie ich den Browser zoome.

Jede Beratung geschätzt wird, Dank :)

+0

Welchen Wert setzen Sie für 'position'? Es ist eine Uniform und der gepostete Code zeigt nicht, auf welchen Wert Sie ihn setzen. –

Antwort

0

Wenn das Fenster (200, 200) war, dann war das Zentrum (100, 100). Aber wenn dein Fenster plötzlich (400, 400) wird, ist (100, 100) nicht mehr das Zentrum, richtig? Das bedeutet "Fensterplatz": der Raum relativ zum Fenster.

Wenn Sie Berechnungen in einem Bereich ausführen möchten, der nicht von den Eigenschaften des Fensters abhängig ist, müssen Sie gl_FragCoord in diesen Raum transformieren. Und natürlich muss Ihre position auch im selben Raum sein.

Eine allgemeine Lösung wäre, die Größe des Fensters zu erhalten und es als eine Einheit zu übergeben. Dann teilen Sie gl_FragCoord.xy durch diese Größe. Die Mitte des Fensters in diesem Raum wäre immer (0,5, 0,5). Aber Sie müssen sicherstellen, diese einheitliche zu aktualisieren, wann immer das Fenster Abmessungen ändert.

0

Der Versuch, Shader unten ich keine Probleme

var fs = ` 
 
precision mediump float; 
 
uniform vec2 position; 
 
uniform vec3 lightColor; 
 
uniform float lightSize; 
 

 
    void main() 
 
    { 
 
     float distance = distance(gl_FragCoord.xy, position); 
 
     if (distance <= lightSize) { 
 
      gl_FragColor = vec4(lightColor, 1.0); 
 
     } 
 
     else { 
 
      gl_FragColor = vec4(lightColor, 0.0); 
 
     } 
 
    } 
 
`; 
 
var vs = ` 
 
attribute vec4 a_position; 
 
void main() { 
 
    gl_Position = a_position; 
 
} 
 
`; 
 

 
var gl = document.querySelector("canvas").getContext("webgl"); 
 
var programInfo = twgl.createProgramInfo(gl, [vs, fs]); 
 
var bufferInfo = twgl.createBufferInfoFromArrays(gl, { 
 
    a_position: { 
 
    numComponents: 2, 
 
    data: [ 
 
     -1, -1, 
 
     -1, 1, 
 
     1, -1, 
 
     1, -1, 
 
     -1, 1, 
 
     1, 1, 
 
    ], 
 
    }, 
 
}); 
 

 
function render(time) { 
 
    time *= 0.001; 
 
    twgl.resizeCanvasToDisplaySize(gl.canvas); 
 
    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); 
 

 
    var uniforms = { 
 
    position: [gl.canvas.width/2, gl.canvas.height/2], 
 
    lightColor: [0.5 + Math.sin(time * 10) * 0.25, 0, 0], 
 
    lightSize: 100, 
 
    };  
 
     
 
    gl.useProgram(programInfo.program); 
 
    twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo); 
 
    twgl.setUniforms(programInfo, uniforms); 
 
    twgl.drawBufferInfo(gl, gl.TRIANGLES, bufferInfo); 
 
    requestAnimationFrame(render); 
 
} 
 
requestAnimationFrame(render); 
 
    
body { margin: 0; } 
 
canvas { display: block; width: 100vw; height: 100vh; }
<script src="https://twgljs.org/dist/twgl.min.js"></script> 
 
<canvas></canvas>

sehen, was Sie Position einstellen werden? Der obige Code setzt es auf gl.canvas.width/2, gl.canvas.height/2, was die Mitte der Leinwand ist.

Verwandte Themen