nv-shader-noperspective-interpolation.html (8659B)
1 <!-- 2 Copyright (c) 2023 The Khronos Group Inc. 3 Use of this source code is governed by an MIT-style license that can be 4 found in the LICENSE.txt file. 5 --> 6 7 <!DOCTYPE html> 8 <html> 9 <head> 10 <meta charset="utf-8"> 11 <title>WebGL NV_shader_noperspective_interpolation Conformance Tests</title> 12 <link rel="stylesheet" href="../../resources/js-test-style.css"/> 13 <script src="../../js/js-test-pre.js"></script> 14 <script src="../../js/webgl-test-utils.js"></script> 15 </head> 16 <body> 17 <canvas width="128" height="128" id="c"></canvas> 18 <div id="description"></div> 19 <div id="console"></div> 20 <script> 21 "use strict"; 22 description("This test verifies the functionality of the NV_shader_noperspective_interpolation extension, if it is available."); 23 24 debug(""); 25 26 var wtu = WebGLTestUtils; 27 var gl = wtu.create3DContext("c", null, 2); 28 var ext; 29 30 function runShaderTests(extensionEnabled) { 31 debug(""); 32 debug("Testing various shader compiles with extension " + (extensionEnabled ? "enabled" : "disabled")); 33 34 const macroVertex = `#version 300 es 35 in vec4 vPosition; 36 void main() { 37 #ifdef GL_NV_shader_noperspective_interpolation 38 gl_Position = vPosition; 39 #else 40 #error no GL_NV_shader_noperspective_interpolation; 41 #endif 42 }`; 43 44 const macroFragment = `#version 300 es 45 precision highp float; 46 out vec4 my_FragColor; 47 void main() { 48 #ifdef GL_NV_shader_noperspective_interpolation 49 my_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 50 #else 51 #error no GL_NV_shader_noperspective_interpolation; 52 #endif 53 }`; 54 55 for (const shaders of [[wtu.simpleVertexShaderESSL300, macroFragment], 56 [macroVertex, wtu.simpleColorFragmentShaderESSL300]]) { 57 // Expect the macro shader to succeed ONLY if enabled 58 if (wtu.setupProgram(gl, shaders)) { 59 if (extensionEnabled) { 60 testPassed("Macro defined in shaders when extension is enabled"); 61 } else { 62 testFailed("Macro defined in shaders when extension is disabled"); 63 } 64 } else { 65 if (extensionEnabled) { 66 testFailed("Macro not defined in shaders when extension is enabled"); 67 } else { 68 testPassed("Macro not defined in shaders when extension is disabled"); 69 } 70 } 71 } 72 73 const missingVertex = `#version 300 es 74 noperspective out float interpolant; 75 in vec4 vPosition; 76 void main() { 77 gl_Position = vPosition; 78 }`; 79 80 const missingFragment = `#version 300 es 81 precision highp float; 82 noperspective in float interpolant; 83 out vec4 my_FragColor; 84 void main() { 85 my_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 86 }`; 87 88 // Always expect the shader missing the #extension pragma to fail (whether enabled or not) 89 for (const shaders of [[missingVertex, wtu.simpleColorFragmentShaderESSL300], 90 [wtu.simpleVertexShaderESSL300, missingFragment], 91 [missingVertex, missingFragment]]) { 92 if (wtu.setupProgram(gl, shaders)) { 93 testFailed("Noperspective interpolation qualifier allowed without #extension pragma"); 94 } else { 95 testPassed("Noperspective interpolation qualifier disallowed without #extension pragma"); 96 } 97 } 98 99 const validVertex = `#version 300 es 100 #extension GL_NV_shader_noperspective_interpolation : enable 101 noperspective out float interpolant; 102 in vec4 vPosition; 103 void main() { 104 gl_Position = vPosition; 105 }`; 106 107 const validFragment = `#version 300 es 108 #extension GL_NV_shader_noperspective_interpolation : enable 109 precision highp float; 110 noperspective in float interpolant; 111 out vec4 my_FragColor; 112 void main() { 113 my_FragColor = vec4(1.0, 0.0, 0.0, 1.0); 114 }`; 115 116 // Try to compile a shader using a noperspective qualifier that should only succeed if enabled 117 if (wtu.setupProgram(gl, [validVertex, validFragment])) { 118 if (extensionEnabled) { 119 testPassed("Noperspective interpolation qualifier compiled successfully when extension enabled"); 120 } else { 121 testFailed("Noperspective interpolation qualifier compiled successfully when extension disabled"); 122 } 123 } else { 124 if (extensionEnabled) { 125 testFailed("Noperspective interpolation qualifier failed to compile when extension enabled"); 126 } else { 127 testPassed("Noperspective interpolation qualifier failed to compile when extension disabled"); 128 } 129 } 130 131 debug(""); 132 } 133 134 function runInterpolationTest() { 135 function draw(program, skew) { 136 gl.useProgram(program); 137 138 const posLoc = gl.getAttribLocation(program, "position"); 139 const colLoc = gl.getAttribLocation(program, "color"); 140 141 const buf = gl.createBuffer(); 142 gl.bindBuffer(gl.ARRAY_BUFFER, buf); 143 gl.bufferData( 144 gl.ARRAY_BUFFER, 145 new Float32Array([ 146 -1.0, -1.0, 0.0, 1.0, 147 +1.0, -1.0, 0.0, 1.0, 148 0.0, +1.0 * skew, 0.0, skew, 149 150 1.0, 0.0, 0.0, 1.0, 151 0.0, 1.0, 0.0, 1.0, 152 0.0, 0.0, 1.0, 1.0]), 153 gl.STATIC_DRAW); 154 155 gl.vertexAttribPointer(posLoc, 4, gl.FLOAT, false, 0, 0); 156 gl.vertexAttribPointer(colLoc, 4, gl.FLOAT, false, 0, 48); 157 gl.enableVertexAttribArray(posLoc); 158 gl.enableVertexAttribArray(colLoc); 159 gl.drawArrays(gl.TRIANGLES, 0, 3); 160 } 161 162 const vertexSmooth = `#version 300 es 163 in vec4 position; 164 in vec4 color; 165 smooth out vec4 interp_color; 166 void main() { 167 gl_Position = position; 168 interp_color = color; 169 }`; 170 171 const fragmentSmooth = `#version 300 es 172 precision highp float; 173 smooth in vec4 interp_color; 174 out vec4 fragColor; 175 void main() { 176 fragColor = interp_color; 177 }`; 178 const programSmooth = wtu.setupProgram(gl, [vertexSmooth, fragmentSmooth]); 179 180 debug("Get non-skewed value with smooth interpolation"); 181 gl.clearColor(0.0, 0.0, 0.0, 1.0); 182 gl.clear(gl.COLOR_BUFFER_BIT); 183 draw(programSmooth, 1.0); 184 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); 185 186 const smoothColor = new Uint8Array(4); 187 gl.readPixels(64, 64, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, smoothColor); 188 189 const vertexNoperspective = `#version 300 es 190 #extension GL_NV_shader_noperspective_interpolation : require 191 in vec4 position; 192 in vec4 color; 193 noperspective out vec4 interp_color; 194 void main() { 195 gl_Position = position; 196 interp_color = color; 197 }`; 198 199 const fragmentNoperspective = `#version 300 es 200 #extension GL_NV_shader_noperspective_interpolation : require 201 precision highp float; 202 noperspective in vec4 interp_color; 203 out vec4 fragColor; 204 void main() { 205 fragColor = interp_color; 206 }`; 207 const programNoperspective = wtu.setupProgram(gl, [vertexNoperspective, fragmentNoperspective]); 208 209 debug(""); 210 debug("Check non-skewed value with noperspective interpolation"); 211 gl.clear(gl.COLOR_BUFFER_BIT); 212 draw(programNoperspective, 1.0); 213 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); 214 wtu.checkCanvasRect(gl, 64, 64, 1, 1, smoothColor, "Non-skewed noperspective should match smooth"); 215 216 debug(""); 217 debug("Check skewed value with noperspective interpolation"); 218 gl.clear(gl.COLOR_BUFFER_BIT); 219 draw(programNoperspective, 2.0); 220 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); 221 wtu.checkCanvasRect(gl, 64, 64, 1, 1, smoothColor, "Skewed noperspective should match smooth"); 222 } 223 224 function runTest() { 225 if (!gl) { 226 testFailed("WebGL context does not exist"); 227 return; 228 } 229 testPassed("WebGL context exists"); 230 231 runShaderTests(false); 232 233 ext = gl.getExtension("NV_shader_noperspective_interpolation"); 234 wtu.runExtensionSupportedTest(gl, "NV_shader_noperspective_interpolation", ext !== null); 235 236 if (!ext) { 237 testPassed("No NV_shader_noperspective_interpolation support -- this is legal"); 238 } else { 239 testPassed("Successfully enabled NV_shader_noperspective_interpolation extension"); 240 runShaderTests(true); 241 runInterpolationTest(); 242 } 243 } 244 245 runTest(); 246 247 var successfullyParsed = true; 248 </script> 249 <script src="../../js/js-test-post.js"></script> 250 </body> 251 </html>