Browse Source

glsl debugging

Gregg Tavares 6 years ago
parent
commit
14e1c82e2e

BIN
threejs/lessons/resources/images/inspect-matrices.gif


BIN
threejs/lessons/resources/images/standard-primitive-normals.jpg


BIN
threejs/lessons/resources/images/standard-primitive-uvs.jpg


+ 105 - 13
threejs/lessons/threejs-debugging-glsl.md

@@ -1,19 +1,111 @@
 Title: Debugging Three.js - GLSL
 Description: How to debug GLSL Shaders
 
-Check your shaders
-  Use the shader inspector OR
-  Add a shader dumper
-  Use WEBGL_Debug_Shaders
-
-Change fragment shader
-  color = red
-  show normals
-  show texture coordinates
-  show lighting
-
-Change Vertex Shader
-  simplest shader
+This site so far does not teach GLSL just like it does not teach JavaScript.
+Those are really large topics. If you want to learn GLSL consider checking out
+[these articles](https://webglfundamentals.org) as a starting place.
+
+If you already know GLSL then here are a few tips for debugging.
+
+When I'm making a new GLSL shader and nothing appears generally
+the first thing I do is change the fragment shader to return a solid
+color. For example at the very bottom of the shader I might put
+
+```glsl
+void main() {
+
+  ...
+
+  gl_FragColor = vec4(1, 0, 0, 1);  // red
+}
+```
+
+If I see the object I was trying to draw then I know the issue is
+related to my fragment shader. It could be anything like bad textures,
+uninitialized uniforms, uniforms with the wrong values but at least
+I have a direction to look.
+
+To test some of those I might start trying to draw some of the inputs.
+For example if I'm using normals in the fragment shader then I might
+add
+
+```glsl
+gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1);
+```
+
+Normals go from -1 to +1 so by multiplying by 0.5 and adding 0.5 we get
+values that go from 0.0 to 1.0 which makes them useful for colors.
+
+Try this with some things you know work and you'll start getting an idea
+of what normals *normally* look like. If your normals don't look normal
+then you have some clue where to look. If you're manipulating normals
+in the fragments shader you can use the same technique to draw the
+result of that manipulation.
+
+<div class="threejs_center"><img src="resources/images/standard-primitive-normals.jpg" style="width: 650px;"></div>
+
+Similarly if we're using textures there will be texture coordinates and we
+can draw them with something like
+
+```glsl
+gl_FragColor = vec4(fract(vUv), 0, 1);
+```
+
+The `fract` is there in case we're using texture coordinates that go outside
+the 0 to 1 range. This is common if `texture.repeat` is set to something greater
+than 1.
+
+<div class="threejs_center"><img src="resources/images/standard-primitive-uvs.jpg" style="width: 650px;"></div>
+
+You can do similar things for all values in your fragment shader. Figure out
+what their range is likely to be, add some code to set `gl_FragColor` with
+that range scaled to 0.0 to 1.0
+
+To check textures try a `CanvasTexture` or a `DataTexture` that you 
+know works.
+
+Conversely, if after setting `gl_FragColor` to red I still see nothing
+then I have a hint my issue might be in the direction of the things
+related to the vertex shader. Some matrices might be wrong or my
+attributes might have bad data or be setup incorrectly.
+
+I'd first look at the matrices. I might put a breakpoint right after
+my call to `renderer.render(scene, camera)` and then start expanding
+things in the inspector. Is the camera's world matrix and projection
+matrix at least not full of `NaN`s? Expanding the scene and looking
+at its `children` I'd check that the world matrices look reasonable (no `NaN`s)
+and last 4 values of each matrix look reasonable for my scene. If I 
+expect my scene to be 50x50x50 units and some matrix shows 552352623.123 
+clearly something is wrong there.
+
+<div class="threejs_center"><img src="resources/images/inspect-matrices.gif"></div>
+
+Just like we did for the fragment shader we can also draw values from the
+vertex shader by passing them to the fragment shader. Declare a varying
+in both and pass the value you're not sure is correct. In fact if my
+shader use using normals I'll change the fragment shader to display them
+like is mentioned above and then just set `vNormal` to the value I want 
+to display but scaled so the values go from 0.0 to 1.0. I then look at the
+results and see if they fit my expectations.
+
+Another good thing to do is use a simpler shader. Can you draw your data
+with `MeshBasicMaterial`? If you can then try it and make sure it shows
+up as expected.
+
+If not what's the simplest vertex shader that will let you visualize your
+geometry? Usually it's as simple as
+
+```glsl
+gl_Position = projection * modelView * vec4(position.xyz, 1);
+```
+
+If that works start adding in your changes a little at a time.
+
+Yet another thing you can do is use the
+[Shader Editor extension for Chrome](https://chrome.google.com/webstore/detail/shader-editor/ggeaidddejpbakgafapihjbgdlbbbpob?hl=en)
+or similar for other browsers. It's a great way to look at how other shaders
+are working. It's also good as you can make some of the changes suggested above
+live while the code is running.
 
 
 

+ 2 - 1
threejs/lessons/toc.html

@@ -35,8 +35,9 @@
   </ul>
   <li>Tips</li>
   <ul>
-    <li><a href="/threejs/lessons/threejs-debugging-javascript.html">Debugging JavaScript</a></li>
     <li><a href="/threejs/lessons/threejs-rendering-on-demand.html">Rendering On Demand</a></li>
+    <li><a href="/threejs/lessons/threejs-debugging-javascript.html">Debugging JavaScript</a></li>
+    <li><a href="/threejs/lessons/threejs-debugging-glsl.html">Debugging GLSL</a></li>
   </ul>
   <li>Fundamentals</li>
   <ul>