Draw an image of a house with a chimney using WebGL in a single HTML file. Make the canvas take the full page.
Draw an image of a house with a chimney using WebGL in a single HTML file. Make the canvas take the full page.
Okay, here is a single HTML file containing WebGL code to draw a simple house with a chimney. The canvas is styled to take up the full browser window and will resize dynamically.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>WebGL House</title> <style> /* Basic reset and full-page canvas styling */ html, body { margin: 0; padding: 0; overflow: hidden; /* Prevent scrollbars */ height: 100%; background-color: #f0f0f0; /* Optional background for behind canvas */ } canvas { display: block; /* Remove potential space below canvas */ width: 100vw; /* 100% of viewport width */ height: 100vh; /* 100% of viewport height */ } </style> </head> <body> <canvas id="webgl-canvas"></canvas> <!-- Vertex Shader --> <script id="vertex-shader-2d" type="notjs"> // An attribute will receive data from a buffer attribute vec2 a_position; // All shaders have a main function void main() { // gl_Position is a special variable a vertex shader // is responsible for setting. It needs vec4 (x, y, z, w). // We use 0 for z (since it's 2D) and 1 for w (standard for positions). gl_Position = vec4(a_position, 0.0, 1.0); } </script> <!-- Fragment Shader --> <script id="fragment-shader-2d" type="notjs"> // Fragment shaders don't have a default precision so we need // to pick one. mediump is a good default. precision mediump float; // We need to declare a uniform for the color uniform vec4 u_color; // All shaders have a main function void main() { // gl_FragColor is a special variable a fragment shader // is responsible for setting. It determines the pixel's color. gl_FragColor = u_color; } </script> <script> function main() { // --- 1. Setup --- const canvas = document.getElementById('webgl-canvas'); const gl = canvas.getContext('webgl'); if (!gl) { alert('WebGL is not supported by your browser.'); return; } // --- 2. Compile Shaders & Link Program --- const vsSource = document.getElementById('vertex-shader-2d').text; const fsSource = document.getElementById('fragment-shader-2d').text; const shaderProgram = initShaderProgram(gl, vsSource, fsSource); if (!shaderProgram) { return; // Error already logged in initShaderProgram } // --- 3. Look up attribute and uniform locations --- const positionAttributeLocation = gl.getAttribLocation(shaderProgram, 'a_position'); const colorUniformLocation = gl.getUniformLocation(shaderProgram, 'u_color'); // --- 4. Create Buffers --- // We'll use one buffer and update it for each shape part const positionBuffer = gl.createBuffer(); // --- 5. Define Geometry (Normalized Device Coordinates: -1 to +1) --- // House Body (Rectangle made of 2 triangles) const houseBodyVertices = new Float32Array([ -0.5, -0.5, // bottom-left 0.5, -0.5, // bottom-right -0.5, 0.3, // top-left -0.5, 0.3, // top-left (repeat for second triangle) 0.5, -0.5, // bottom-right (repeat for second triangle) 0.5, 0.3, // top-right ]); // Roof (Triangle) const roofVertices = new Float32Array([ -0.6, 0.3, // bottom-left 0.6, 0.3, // bottom-right 0.0, 0.8, // top-middle ]); // Chimney (Rectangle made of 2 triangles) const chimneyVertices = new Float32Array([ 0.2, 0.4, // bottom-left 0.4, 0.4, // bottom-right 0.2, 0.7, // top-left 0.2, 0.7, // top-left (repeat) 0.4, 0.4, // bottom-right (repeat) 0.4, 0.7, // top-right ]); // --- 6. Drawing Function --- function drawScene() { resizeCanvasToDisplaySize(gl.canvas); gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); // Clear the canvas gl.clearColor(0.8, 0.9, 1.0, 1.0); // Light sky blue gl.clear(gl.COLOR_BUFFER_BIT); // Tell WebGL to use our program gl.useProgram(shaderProgram); // Turn on the attribute gl.enableVertexAttribArray(positionAttributeLocation); // Bind the position buffer. gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); // Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER) const size = 2; // 2 components per iteration (x, y) const type = gl.FLOAT; // the data is 32bit floats const normalize = false; // don't normalize the data const stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position const offset = 0; // start at the beginning of the buffer gl.vertexAttribPointer( positionAttributeLocation, size, type, normalize, stride, offset); // --- Draw the House Body --- gl.bufferData(gl.ARRAY_BUFFER, houseBodyVertices, gl.STATIC_DRAW); gl.uniform4f(colorUniformLocation, 0.8, 0.5, 0.2, 1.0); // Brownish color gl.drawArrays(gl.TRIANGLES, 0, 6); // 6 vertices for the rectangle // --- Draw the Roof --- gl.bufferData(gl.ARRAY_BUFFER, roofVertices, gl.STATIC_DRAW); gl.uniform4f(colorUniformLocation, 0.6, 0.2, 0.2, 1.0); // Dark red color gl.drawArrays(gl.TRIANGLES, 0, 3); // 3 vertices for the triangle // --- Draw the Chimney --- gl.bufferData(gl.ARRAY_BUFFER, chimneyVertices, gl.STATIC_DRAW); gl.uniform4f(colorUniformLocation, 0.4, 0.4, 0.4, 1.0); // Grey color gl.drawArrays(gl.TRIANGLES, 0, 6); // 6 vertices for the rectangle } // --- 7. Initial Draw and Resize Handling --- drawScene(); // Initial draw // Redraw scene when window is resized window.addEventListener('resize', drawScene); } // --- Helper Functions --- // Initialize a shader program, so WebGL knows how to draw our data function initShaderProgram(gl, vsSource, fsSource) { const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource); const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource); // Create the shader program const shaderProgram = gl.createProgram(); gl.attachShader(shaderProgram, vertexShader); gl.attachShader(shaderProgram, fragmentShader); gl.linkProgram(shaderProgram); // If creating the shader program failed, alert if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { console.error('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram)); gl.deleteProgram(shaderProgram); gl.deleteShader(vertexShader); gl.deleteShader(fragmentShader); return null; } return shaderProgram; } // Creates a shader of the given type, uploads the source and compiles it. function loadShader(gl, type, source) { const shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); // See if it compiled successfully if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { console.error('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); gl.deleteShader(shader); return null; } return shader; } // Resize canvas drawing buffer to match display size function resizeCanvasToDisplaySize(canvas) { // Lookup the size the browser is displaying the canvas. const displayWidth = canvas.clientWidth; const displayHeight = canvas.clientHeight; // Check if the canvas is not the same size. if (canvas.width !== displayWidth || canvas.height !== displayHeight) { // Make the canvas the same size canvas.width = displayWidth; canvas.height = displayHeight; return true; // Yes, it was resized } return false; // No, it was already the right size } // --- Run the main function when the page loads --- window.onload = main; </script> </body> </html> |
I extracted the following code from that output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>WebGL House</title> <style> /* Basic reset and full-page canvas styling */ html, body { margin: 0; padding: 0; overflow: hidden; /* Prevent scrollbars */ height: 100%; background-color: #f0f0f0; /* Optional background for behind canvas */ } canvas { display: block; /* Remove potential space below canvas */ width: 100vw; /* 100% of viewport width */ height: 100vh; /* 100% of viewport height */ } </style> </head> <body> <canvas id="webgl-canvas"></canvas> <!-- Vertex Shader --> <script id="vertex-shader-2d" type="notjs"> // An attribute will receive data from a buffer attribute vec2 a_position; // All shaders have a main function void main() { // gl_Position is a special variable a vertex shader // is responsible for setting. It needs vec4 (x, y, z, w). // We use 0 for z (since it's 2D) and 1 for w (standard for positions). gl_Position = vec4(a_position, 0.0, 1.0); } </script> <!-- Fragment Shader --> <script id="fragment-shader-2d" type="notjs"> // Fragment shaders don't have a default precision so we need // to pick one. mediump is a good default. precision mediump float; // We need to declare a uniform for the color uniform vec4 u_color; // All shaders have a main function void main() { // gl_FragColor is a special variable a fragment shader // is responsible for setting. It determines the pixel's color. gl_FragColor = u_color; } </script> <script> function main() { // --- 1. Setup --- const canvas = document.getElementById('webgl-canvas'); const gl = canvas.getContext('webgl'); if (!gl) { alert('WebGL is not supported by your browser.'); return; } // --- 2. Compile Shaders & Link Program --- const vsSource = document.getElementById('vertex-shader-2d').text; const fsSource = document.getElementById('fragment-shader-2d').text; const shaderProgram = initShaderProgram(gl, vsSource, fsSource); if (!shaderProgram) { return; // Error already logged in initShaderProgram } // --- 3. Look up attribute and uniform locations --- const positionAttributeLocation = gl.getAttribLocation(shaderProgram, 'a_position'); const colorUniformLocation = gl.getUniformLocation(shaderProgram, 'u_color'); // --- 4. Create Buffers --- // We'll use one buffer and update it for each shape part const positionBuffer = gl.createBuffer(); // --- 5. Define Geometry (Normalized Device Coordinates: -1 to +1) --- // House Body (Rectangle made of 2 triangles) const houseBodyVertices = new Float32Array([ -0.5, -0.5, // bottom-left 0.5, -0.5, // bottom-right -0.5, 0.3, // top-left -0.5, 0.3, // top-left (repeat for second triangle) 0.5, -0.5, // bottom-right (repeat for second triangle) 0.5, 0.3, // top-right ]); // Roof (Triangle) const roofVertices = new Float32Array([ -0.6, 0.3, // bottom-left 0.6, 0.3, // bottom-right 0.0, 0.8, // top-middle ]); // Chimney (Rectangle made of 2 triangles) const chimneyVertices = new Float32Array([ 0.2, 0.4, // bottom-left 0.4, 0.4, // bottom-right 0.2, 0.7, // top-left 0.2, 0.7, // top-left (repeat) 0.4, 0.4, // bottom-right (repeat) 0.4, 0.7, // top-right ]); // --- 6. Drawing Function --- function drawScene() { resizeCanvasToDisplaySize(gl.canvas); gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); // Clear the canvas gl.clearColor(0.8, 0.9, 1.0, 1.0); // Light sky blue gl.clear(gl.COLOR_BUFFER_BIT); // Tell WebGL to use our program gl.useProgram(shaderProgram); // Turn on the attribute gl.enableVertexAttribArray(positionAttributeLocation); // Bind the position buffer. gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); // Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER) const size = 2; // 2 components per iteration (x, y) const type = gl.FLOAT; // the data is 32bit floats const normalize = false; // don't normalize the data const stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position const offset = 0; // start at the beginning of the buffer gl.vertexAttribPointer( positionAttributeLocation, size, type, normalize, stride, offset); // --- Draw the House Body --- gl.bufferData(gl.ARRAY_BUFFER, houseBodyVertices, gl.STATIC_DRAW); gl.uniform4f(colorUniformLocation, 0.8, 0.5, 0.2, 1.0); // Brownish color gl.drawArrays(gl.TRIANGLES, 0, 6); // 6 vertices for the rectangle // --- Draw the Roof --- gl.bufferData(gl.ARRAY_BUFFER, roofVertices, gl.STATIC_DRAW); gl.uniform4f(colorUniformLocation, 0.6, 0.2, 0.2, 1.0); // Dark red color gl.drawArrays(gl.TRIANGLES, 0, 3); // 3 vertices for the triangle // --- Draw the Chimney --- gl.bufferData(gl.ARRAY_BUFFER, chimneyVertices, gl.STATIC_DRAW); gl.uniform4f(colorUniformLocation, 0.4, 0.4, 0.4, 1.0); // Grey color gl.drawArrays(gl.TRIANGLES, 0, 6); // 6 vertices for the rectangle } // --- 7. Initial Draw and Resize Handling --- drawScene(); // Initial draw // Redraw scene when window is resized window.addEventListener('resize', drawScene); } // --- Helper Functions --- // Initialize a shader program, so WebGL knows how to draw our data function initShaderProgram(gl, vsSource, fsSource) { const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource); const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource); // Create the shader program const shaderProgram = gl.createProgram(); gl.attachShader(shaderProgram, vertexShader); gl.attachShader(shaderProgram, fragmentShader); gl.linkProgram(shaderProgram); // If creating the shader program failed, alert if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { console.error('Unable to initialize the shader program: ' + gl.getProgramInfoLog(shaderProgram)); gl.deleteProgram(shaderProgram); gl.deleteShader(vertexShader); gl.deleteShader(fragmentShader); return null; } return shaderProgram; } // Creates a shader of the given type, uploads the source and compiles it. function loadShader(gl, type, source) { const shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); // See if it compiled successfully if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { console.error('An error occurred compiling the shaders: ' + gl.getShaderInfoLog(shader)); gl.deleteShader(shader); return null; } return shader; } // Resize canvas drawing buffer to match display size function resizeCanvasToDisplaySize(canvas) { // Lookup the size the browser is displaying the canvas. const displayWidth = canvas.clientWidth; const displayHeight = canvas.clientHeight; // Check if the canvas is not the same size. if (canvas.width !== displayWidth || canvas.height !== displayHeight) { // Make the canvas the same size canvas.width = displayWidth; canvas.height = displayHeight; return true; // Yes, it was resized } return false; // No, it was already the right size } // --- Run the main function when the page loads --- window.onload = main; </script> </body> </html> |
Rendering the webpage gives the following image:
This is a screenshot of a webpage that draws something with webgl. I'm trying to see if it drew what I wanted. Describe what is drawn in this image?
The image depicts a simple drawing of a house. It features a brown rectangular base representing the main structure of the house. On top, there is a red triangular roof. Additionally, there is a gray rectangle on the roof, which resembles a chimney. The background is a light blue color.
Does this answer say that there is a picture of a house with a chimney "The image depicts a simple drawing of a house. It features a brown rectangular base representing the main structure of the house. On top, there is a red triangular roof. Additionally, there is a gray rectangle on the roof, which resembles a chimney. The background is a light blue color."? Answer "Yes it does" or "No it does not".
Yes it does.
Testing if the previous output contains the string es it does
: True
Testing if the previous output contains the string THREE.
: False