Initial Query

Draw an image of a house with a chimney using WebGL in a single HTML file. Make the canvas take the full page.

LLM Generation

Query

Draw an image of a house with a chimney using WebGL in a single HTML file. Make the canvas take the full page.

Output

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>
**How to use it:** 1. Save the code above as an HTML file (e.g., `webgl_house.html`). 2. Open the file in a modern web browser that supports WebGL (like Chrome, Firefox, Edge, Safari). **Explanation:** 1. **HTML Structure:** Sets up a basic HTML page with a `<canvas>` element where the drawing will happen. 2. **CSS Styling:** Makes the `html`, `body`, and `canvas` elements fill the entire viewport without margins or scrollbars. 3. **Shaders:** * **Vertex Shader (`vertex-shader-2d`):** Takes 2D vertex positions (`a_position`) and outputs them as 4D positions (`gl_Position`) required by WebGL. It simply passes the 2D coordinates through, setting Z to 0 and W to 1. * **Fragment Shader (`fragment-shader-2d`):** Takes a uniform color (`u_color`) set from JavaScript and outputs it as the final pixel color (`gl_FragColor`). This allows us to draw different parts of the house in different solid colors. 4. **JavaScript (`main` function):** * Gets the canvas and the WebGL rendering context. * Compiles the shaders and links them into a WebGL program using the helper functions `initShaderProgram` and `loadShader`. * Looks up the memory locations (attribute and uniform locations) within the GPU program for `a_position` and `u_color`. * Creates a `positionBuffer` on the GPU to hold vertex data. * Defines the vertex coordinates for the house body (a rectangle), the roof (a triangle), and the chimney (a rectangle). Coordinates are in WebGL's Normalized Device Coordinates (NDC), ranging from -1 to +1 in both X and Y. Rectangles are defined using two triangles. * **`drawScene` Function:** * Calls `resizeCanvasToDisplaySize` to ensure the drawing buffer matches the canvas element's displayed size. * Sets the WebGL viewport to match the canvas size. * Clears the canvas with a light blue background color. * Tells WebGL to use the compiled shader program. * Enables the vertex position attribute. * Binds the `positionBuffer`. * Tells the position attribute how to read data from the buffer (`vertexAttribPointer`). * **Draws each part:** * Loads the specific vertices for the part (body, roof, chimney) into the `positionBuffer` using `gl.bufferData`. * Sets the desired color for that part using `gl.uniform4f`. * Calls `gl.drawArrays(gl.TRIANGLES, ...)` to draw the triangles defined by the vertices currently in the buffer. * **Initial Draw & Resize:** Calls `drawScene` once initially and sets up an event listener to call `drawScene` again whenever the browser window is resized. 5. **Helper Functions:** * `initShaderProgram`, `loadShader`: Standard boilerplate for compiling/linking shaders. * `resizeCanvasToDisplaySize`: A common utility to handle canvas resizing correctly, ensuring the drawing resolution matches the display size.

Extract Code

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>

Check if all of the following conditions are true:

HTML Render

Rendering the webpage gives the following image:

LLM Generation

Query

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?

Output

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.

LLM Generation

Query

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".

Output

Yes it does.

Substring Evaluation

Testing if the previous output contains the string es it does: True

Check this condition is not true:

Substring Evaluation

Testing if the previous output contains the string THREE.: False

Final Answer: True

Final Answer: True