123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- <!DOCTYPE html><html lang="en"><head>
- <meta charset="utf-8">
- <title>Debugging - GLSL</title>
- <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
- <meta name="twitter:card" content="summary_large_image">
- <meta name="twitter:site" content="@threejs">
- <meta name="twitter:title" content="Three.js – Debugging - GLSL">
- <meta property="og:image" content="https://threejs.org/files/share.png">
- <link rel="shortcut icon" href="../../files/favicon_white.ico" media="(prefers-color-scheme: dark)">
- <link rel="shortcut icon" href="../../files/favicon.ico" media="(prefers-color-scheme: light)">
- <link rel="stylesheet" href="../resources/lesson.css">
- <link rel="stylesheet" href="../resources/lang.css">
- <script type="importmap">
- {
- "imports": {
- "three": "../../build/three.module.js"
- }
- }
- </script>
- </head>
- <body>
- <div class="container">
- <div class="lesson-title">
- <h1>Debugging - GLSL</h1>
- </div>
- <div class="lesson">
- <div class="lesson-main">
- <p>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
- <a href="https://webglfundamentals.org">these articles</a> as a starting place.</p>
- <p>If you already know GLSL then here are a few tips for debugging.</p>
- <p>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</p>
- <pre class="prettyprint showlinemods notranslate lang-glsl" translate="no">void main() {
- ...
- gl_FragColor = vec4(1, 0, 0, 1); // red
- }
- </pre>
- <p>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.</p>
- <p>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</p>
- <pre class="prettyprint showlinemods notranslate lang-glsl" translate="no">gl_FragColor = vec4(vNormal * 0.5 + 0.5, 1);
- </pre>
- <p>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.</p>
- <p>Try this with some things you know work and you'll start getting an idea
- of what normals <em>normally</em> 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.</p>
- <div class="threejs_center"><img src="../resources/images/standard-primitive-normals.jpg" style="width: 650px;"></div>
- <p>Similarly if we're using textures there will be texture coordinates and we
- can draw them with something like</p>
- <pre class="prettyprint showlinemods notranslate lang-glsl" translate="no">gl_FragColor = vec4(fract(vUv), 0, 1);
- </pre>
- <p>The <code class="notranslate" translate="no">fract</code> is there in case we're using texture coordinates that go outside
- the 0 to 1 range. This is common if <code class="notranslate" translate="no">texture.repeat</code> is set to something greater
- than 1.</p>
- <div class="threejs_center"><img src="../resources/images/standard-primitive-uvs.jpg" style="width: 650px;"></div>
- <p>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 <code class="notranslate" translate="no">gl_FragColor</code> with
- that range scaled to 0.0 to 1.0</p>
- <p>To check textures try a <a href="/docs/#api/en/textures/CanvasTexture"><code class="notranslate" translate="no">CanvasTexture</code></a> or a <a href="/docs/#api/en/textures/DataTexture"><code class="notranslate" translate="no">DataTexture</code></a> that you
- know works.</p>
- <p>Conversely, if after setting <code class="notranslate" translate="no">gl_FragColor</code> 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.</p>
- <p>I'd first look at the matrices. I might put a breakpoint right after
- my call to <code class="notranslate" translate="no">renderer.render(scene, camera)</code> and then start expanding
- things in the inspector. Is the camera's world matrix and projection
- matrix at least not full of <code class="notranslate" translate="no">NaN</code>s? Expanding the scene and looking
- at its <code class="notranslate" translate="no">children</code> I'd check that the world matrices look reasonable (no <code class="notranslate" translate="no">NaN</code>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.</p>
- <div class="threejs_center"><img src="../resources/images/inspect-matrices.gif"></div>
- <p>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 <code class="notranslate" translate="no">vNormal</code> 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.</p>
- <p>Another good thing to do is use a simpler shader. Can you draw your data
- with <a href="/docs/#api/en/materials/MeshBasicMaterial"><code class="notranslate" translate="no">MeshBasicMaterial</code></a>? If you can then try it and make sure it shows
- up as expected.</p>
- <p>If not what's the simplest vertex shader that will let you visualize your
- geometry? Usually it's as simple as</p>
- <pre class="prettyprint showlinemods notranslate lang-glsl" translate="no">gl_Position = projection * modelView * vec4(position.xyz, 1);
- </pre>
- <p>If that works start adding in your changes a little at a time.</p>
- <p>Yet another thing you can do is use the
- <a href="https://chrome.google.com/webstore/detail/shader-editor/ggeaidddejpbakgafapihjbgdlbbbpob?hl=en">Shader Editor extension for Chrome</a>
- 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.</p>
- </div>
- </div>
- </div>
- <script src="../resources/prettify.js"></script>
- <script src="../resources/lesson.js"></script>
- </body></html>
|