2014-11-21 8 views
11

Ich versuche, this tutorial zu arbeiten, aber ich lief in zwei Probleme, von denen einer der folgenden ist.Warum muss ich einen Genauigkeitswert in Webgl-Shadern definieren?

Wenn ich den Code ausführen, wie es ist, bekomme ich einen Fehler in der Fragment-Shader sagen: THREE.WebGLShader: gl.getShaderInfoLog() ERROR: 0:2: '' : No precision specified for (float). Also was ich getan habe, war eine Genauigkeit für jeden Float/Vektor, den ich so definiere, zu spezifizieren varying highp vec3 vNormal. Dies beseitigt den Fehler, aber ich verstehe nicht warum? Ich kann kein anderes Beispiel finden, wo Präzisionswerte zu Variablendeklarationen hinzugefügt werden. Kann jemand erklären, warum das passiert? Hat es etwas mit meinem Browser zu tun (Chrome 38)?

+2

Liefert dieser Beitrag etwas Licht? http://stackoverflow.com/questions/5366416 – vabada

+0

In Antwort auf den Titel Ihrer Frage ist die Antwort im Grunde "weil die Spezifikation so sagt". WebGL basiert auf der OpenGL ES 2.0-Spezifikation und für diese Spezifikation müssen Sie die Genauigkeit angeben. – gman

Antwort

5

Jessys Antwort ist korrekt, dass die meisten Fragment-Shader eine Standard-Genauigkeit am oberen Rand des Fragment-Shader-Codes festlegen.

Sie verwenden jedoch die RawShaderMaterial von Three.js, die keine der integrierten Uniformen, Attribute und Präzisionsdeklarationen vorgibt. Sie müssen es also selbst definieren.

Auf der anderen Seite verwendet das Tutorial, das Sie verknüpft haben, Three.js's ShaderMaterial für sein Material, so dass Three.js die Genauigkeitserklärung automatisch vorangestellt wird.

Wenn Sie die Standard-Uniformen/Attribute aus Ihrem Shader-Code entfernen und stattdessen ShaderMaterial verwenden, funktioniert es ohne den Präzisionscode.

Vertex Shader

varying vec3 vNormal; 

void main() { 
    vNormal = normal; 
    gl_Position = projectionMatrix * 
       modelViewMatrix * 
       vec4(position,1.0); 
} 

Fragment Shader

varying vec3 vNormal; 

void main() { 
    vec3 light = vec3(0.5, 0.2, 1.0); 

    // ensure it's normalized 
    light = normalize(light); 

    // calculate the dot product of 
    // the light to the vertex normal 
    float dProd = max(0.0, dot(vNormal, light)); 

    // feed into our frag colour 
    gl_FragColor = vec4(dProd, // R 
         dProd, // G 
         dProd, // B 
         1.0); // A 
} 

Update auf das Material

// create the sphere's material 
var shaderMaterial = new THREE.ShaderMaterial({ 
    vertexShader: document.getElementById('vertex-shader').innerHTML, 
    fragmentShader: document.getElementById('fragment-shader').innerHTML 
}); 

Here ist eine Geige Ihres Codes ohne die Genauigkeitsdeklarationen.

+0

Ooh Mann Ich fühle mich ziemlich albern, nachdem ich mehrere Stunden damit verbracht habe herauszufinden, was los ist. Ich habe keine Ahnung, warum ich 'RawShaderMaterial()' verwendet habe, das war nicht meine Absicht. Vielen Dank für deine Hilfe! – Flavio

+0

@Flavio kein Problem Ich bin froh, dass ich helfen kann :) – Anton

9

In WebGL-Fragment-Shadern ist keine Standardpräzision vorhanden. (Hohe Präzision ist Standard für Vertex-Shader.) Die einfachste Lösung ist

precision highp float; 

, um alle Ihre Fragment-Shader zu schreiben, die die Notwendigkeit zu beseitigen, die Genauigkeit für alle Floating-Point-Vektorvariablen zu definieren, aber im Allgemeinen,

precision mediump float; 

wird für die Leistung vorzuziehen sein. Ich rate nicht Tief; Die gute mobile Hardware von heute unterstützt es nicht einmal mehr, und entspricht dem Typus von Lowp bis Mediump.

+0

Cool Vielen Dank für die Antwort, das erklärt viel. Was ich jedoch immer noch nicht verstehe, ist, warum ich keine dieser Präzisionsdeklarationen in anderen Shaderprogrammen sehe. Sie sind nicht einmal in [Tutorial] (http://aerotwist.com/tutorials/an-introduction-to-shaders-part-2/) Ich habe versucht, zur Arbeit zu kommen. – Flavio

+1

Sie sollten 'highp' nicht verwenden, außer Sie wissen, dass Sie es brauchen. Die meisten Telefone können 'highp' nicht unterstützen, damit Ihr Shader nicht auf dem Telefon läuft. Einige Shader benötigen 'highp', also' mediump'.Warum du es nicht in den Shadern siehst, liegt daran, dass three.js es zu den Shadern hinzufügt, die du schreibst. Installieren Sie den [WebGL Inspector] (http://benvanik.github.io/WebGL-Inspector/), führen Sie eine three.js App aus, klicken Sie auf "capture" und "ui" und dann auf "programs" und sehen Sie sich die tatsächlichen Shader an wurden WebGL von three.js übergeben. Sie werden sehen, dass sie Genauigkeit angeben. – gman

+0

@gman Was POS geht so weit, einen Shader vollständig zu deaktivieren, anstatt highp als mediump zu laufen? – Jessy