Naloga 2: C0 and C1
This commit is contained in:
		
							parent
							
								
									0671004a38
								
							
						
					
					
						commit
						4de1f25a6a
					
				| @ -13,8 +13,20 @@ | ||||
|         padding: 0; | ||||
|         overflow: hidden; | ||||
|     } | ||||
|     #menu { | ||||
|         position: fixed; | ||||
|         display: flex; | ||||
|         padding: 8px; | ||||
|         gap: 8px; | ||||
|     } | ||||
| </style> | ||||
| <body> | ||||
| <div id="menu"> | ||||
|     <button id="add">Dodaj zlepek</button> | ||||
|     <button id="remove">Izbriši zlepek</button> | ||||
|     <button id="c0">Zagotovi zveznost</button> | ||||
|     <button id="c1">Zagotovi gladkost</button> | ||||
| </div> | ||||
| <canvas></canvas> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										235
									
								
								naloga_2/main.js
									
									
									
									
									
								
							
							
						
						
									
										235
									
								
								naloga_2/main.js
									
									
									
									
									
								
							| @ -1,28 +1,91 @@ | ||||
| const addButton = document.getElementById('add'); | ||||
| const removeButton = document.getElementById('remove'); | ||||
| const c0Button = document.getElementById('c0'); | ||||
| const c1Button = document.getElementById('c1'); | ||||
| const canvas = document.querySelector('canvas'); | ||||
| const context = canvas.getContext('2d'); | ||||
| 
 | ||||
| /** @type {number[][]} */ | ||||
| const points = []; | ||||
| let adding = false; | ||||
| /** @type {number|null} */ | ||||
| let selected = null; | ||||
| let mouseDown = false; | ||||
| /** @type {number|null} */ | ||||
| let movePointIndex = null; | ||||
| 
 | ||||
| /** @type {number[][][]} */ | ||||
| const curves = []; | ||||
| 
 | ||||
| addButton.addEventListener('click', () => { | ||||
|     adding = true; | ||||
|     curves.push([]); | ||||
|     selected = curves.length - 1; | ||||
| }); | ||||
| 
 | ||||
| removeButton.addEventListener('click', () => { | ||||
|     if (selected === null) return; | ||||
|     curves.splice(selected, 1); | ||||
|     selected = null; | ||||
|     draw(); | ||||
| }); | ||||
| 
 | ||||
| c0Button.addEventListener('click', () => { | ||||
|     if (curves.length <= 1 || selected === null) return; | ||||
| 
 | ||||
|     let p = getClosestEndPoint(curves[selected][0][0], curves[selected][0][1]); | ||||
|     if (p === null) return; | ||||
|     let [curveIndex, pointIndex] = p; | ||||
|     curves[selected][0] = curves[curveIndex][pointIndex]; | ||||
| 
 | ||||
|     p = getClosestEndPoint(curves[selected][3][0], curves[selected][3][1]); | ||||
|     if (p === null) return; | ||||
|     [curveIndex, pointIndex] = p; | ||||
|     curves[selected][3] = curves[curveIndex][pointIndex]; | ||||
| 
 | ||||
|     draw(); | ||||
| }); | ||||
| 
 | ||||
| c1Button.addEventListener('click', () => { | ||||
|     if (curves.length <= 1 || selected === null) return; | ||||
| 
 | ||||
|     let [curveIndex, pointIndex] = getClosestEndPoint( | ||||
|         curves[selected][0][0], | ||||
|         curves[selected][0][1], | ||||
|     ); | ||||
|     // Move first point of selected curve to closest found point
 | ||||
|     curves[selected][0] = curves[curveIndex][pointIndex]; | ||||
|     // Get control point of found point
 | ||||
|     const h1 = curves[curveIndex][pointIndex === 0 ? 1 : 2]; | ||||
|     // Set control point to location mirrored over the first point
 | ||||
|     curves[selected][1] = [ | ||||
|         2 * curves[selected][0][0] - h1[0], | ||||
|         2 * curves[selected][0][1] - h1[1], | ||||
|     ]; | ||||
| 
 | ||||
|     [curveIndex, pointIndex] = getClosestEndPoint( | ||||
|         curves[selected][3][0], | ||||
|         curves[selected][3][1], | ||||
|     ); | ||||
|     curves[selected][3] = curves[curveIndex][pointIndex]; | ||||
|     const h2 = curves[curveIndex][pointIndex === 0 ? 1 : 2]; | ||||
|     curves[selected][2] = [ | ||||
|         2 * curves[selected][3][0] - h2[0], | ||||
|         2 * curves[selected][3][1] - h2[1], | ||||
|     ]; | ||||
| 
 | ||||
|     draw(); | ||||
| }); | ||||
| 
 | ||||
| /** | ||||
|  * @param {number} x | ||||
|  * @param {number} y | ||||
|  */ | ||||
| function addPoint(x, y) { | ||||
|     if (points.length === 0) { | ||||
|         points.push([x, y]); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (points.length === 1) { | ||||
|         const h1x = lerp(0.25, points[0][0], x); | ||||
|         const h1y = lerp(0.25, points[0][1], y); | ||||
|         const h2x = lerp(0.75, points[0][0], x); | ||||
|         const h2y = lerp(0.75, points[0][1], y); | ||||
| 
 | ||||
|         points.push([h1x, h1y], [h2x, h2y], [x, y]); | ||||
|         return; | ||||
|     const curve = curves[curves.length - 1]; | ||||
|     curve.push([x, y]); | ||||
|     if (curve.length === 4) { | ||||
|         adding = false; | ||||
|     } | ||||
|     draw(); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
| @ -40,13 +103,14 @@ function lerp(t, a, b) { | ||||
|  * @param {number} t | ||||
|  * @param {number[]} p array of points | ||||
|  */ | ||||
| function curve(t, p) { | ||||
| function lerpCurve(t, p) { | ||||
|     if (p.length === 1) return p[0]; | ||||
|     return lerp(t, curve(t, p.slice(0, -1)), curve(t, p.slice(1))); | ||||
|     return lerp(t, lerpCurve(t, p.slice(0, -1)), lerpCurve(t, p.slice(1))); | ||||
| } | ||||
| 
 | ||||
| function drawCircles() { | ||||
|     for (const [x, y] of points) { | ||||
|     if (selected === null) return; | ||||
|     for (const [x, y] of curves[selected]) { | ||||
|         context.beginPath(); | ||||
|         context.ellipse(x, y, 10, 10, 0, 0, Math.PI * 2); | ||||
|         context.stroke(); | ||||
| @ -54,35 +118,40 @@ function drawCircles() { | ||||
| } | ||||
| 
 | ||||
| function drawLines() { | ||||
|     for (let i = 0; i < points.length - 3; i += 3) { | ||||
|         const p1 = points[i]; | ||||
|         const p2 = points[i + 1]; | ||||
|         const p3 = points[i + 2]; | ||||
|         const p4 = points[i + 3]; | ||||
|     for (let i = 0; i < curves.length; i++) { | ||||
|         const curve = curves[i]; | ||||
|         for (let j = 0; j < curve.length - 3; j += 3) { | ||||
|             const p1 = curve[j]; | ||||
|             const p2 = curve[j + 1]; | ||||
|             const p3 = curve[j + 2]; | ||||
|             const p4 = curve[j + 3]; | ||||
| 
 | ||||
|             context.beginPath(); | ||||
| 
 | ||||
|             if (selected === i) { | ||||
|                 context.moveTo(p1[0], p1[1]); | ||||
|                 context.lineTo(p2[0], p2[1]); | ||||
| 
 | ||||
|                 context.moveTo(p3[0], p3[1]); | ||||
|                 context.lineTo(p4[0], p4[1]); | ||||
|             } | ||||
| 
 | ||||
|             context.moveTo(p1[0], p1[1]); | ||||
|         for (let t = 0; t <= 1; t += 0.01) { | ||||
|             const x = curve(t, [p1[0], p2[0], p3[0], p4[0]]); | ||||
|             const y = curve(t, [p1[1], p2[1], p3[1], p4[1]]); | ||||
|             for (let t = 0; t <= 100; t++) { | ||||
|                 const tt = t / 100; | ||||
|                 const x = lerpCurve(tt, [p1[0], p2[0], p3[0], p4[0]]); | ||||
|                 const y = lerpCurve(tt, [p1[1], p2[1], p3[1], p4[1]]); | ||||
| 
 | ||||
|                 context.lineTo(x, y); | ||||
|             } | ||||
| 
 | ||||
|             context.stroke(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function draw() { | ||||
|     context.clearRect(0, 0, canvas.width, canvas.height); | ||||
|     if (points.length <= 0) return; | ||||
| 
 | ||||
|     drawCircles(); | ||||
|     drawLines(); | ||||
| @ -94,10 +163,120 @@ function resizeCanvas() { | ||||
|     draw(); | ||||
| } | ||||
| 
 | ||||
| window.addEventListener('mousedown', (e) => { | ||||
| /** | ||||
|  * Gets the index of the closest curve to the point | ||||
|  * @param {number} x | ||||
|  * @param {number} y | ||||
|  * @returns {number|null} | ||||
|  */ | ||||
| function getClosestCurveIndex(x, y) { | ||||
|     /** @type {number|null} */ | ||||
|     let minDist = null; | ||||
|     /** @type {number|null} */ | ||||
|     let minIndex = null; | ||||
| 
 | ||||
|     for (let i = 0; i < curves.length; i++) { | ||||
|         for (const point of curves[i]) { | ||||
|             const dist = Math.abs( | ||||
|                 Math.sqrt((x - point[0]) ** 2 + (y - point[1]) ** 2), | ||||
|             ); | ||||
|             if (!minDist || dist < minDist) { | ||||
|                 minDist = dist; | ||||
|                 minIndex = i; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return minIndex; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Gets the selected curve point under the mouse | ||||
|  * @param {number} x | ||||
|  * @param {number} y | ||||
|  * @returns {number|null} | ||||
|  */ | ||||
| function getSelectedPoint(x, y) { | ||||
|     if (selected === null) return null; | ||||
|     for (let i = 0; i < curves[selected].length; i++) { | ||||
|         const point = curves[selected][i]; | ||||
|         const dist = Math.abs( | ||||
|             Math.sqrt((x - point[0]) ** 2 + (y - point[1]) ** 2), | ||||
|         ); | ||||
|         if (dist <= 10) { | ||||
|             return i; | ||||
|         } | ||||
|     } | ||||
|     return null; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Gets the closest end point | ||||
|  * @param {number} x | ||||
|  * @param {number} y | ||||
|  * @returns {number[]|null} | ||||
|  */ | ||||
| function getClosestEndPoint(x, y) { | ||||
|     /** @type {number|null} */ | ||||
|     let minDist = null, | ||||
|         minCurveIndex = null, | ||||
|         minPointIndex = null; | ||||
| 
 | ||||
|     for (let i = 0; i < curves.length; i++) { | ||||
|         if (i === selected) continue; | ||||
|         let dist = Math.abs( | ||||
|             Math.sqrt((x - curves[i][0][0]) ** 2 + (y - curves[i][0][1]) ** 2), | ||||
|         ); | ||||
|         if (minDist === null || dist < minDist) { | ||||
|             minDist = dist; | ||||
|             minCurveIndex = i; | ||||
|             minPointIndex = 0; | ||||
|         } | ||||
| 
 | ||||
|         dist = Math.abs( | ||||
|             Math.sqrt((x - curves[i][3][0]) ** 2 + (y - curves[i][3][1]) ** 2), | ||||
|         ); | ||||
|         if (minDist === null || dist < minDist) { | ||||
|             minDist = dist; | ||||
|             minCurveIndex = i; | ||||
|             minPointIndex = 3; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return [minCurveIndex, minPointIndex]; | ||||
| } | ||||
| 
 | ||||
| canvas.addEventListener('mousedown', (e) => { | ||||
|     mouseDown = true; | ||||
| 
 | ||||
|     if (adding) { | ||||
|         addPoint(e.pageX, e.pageY); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const point = getSelectedPoint(e.pageX, e.pageY); | ||||
|     if (point !== null) { | ||||
|         movePointIndex = point; | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const i = getClosestCurveIndex(e.pageX, e.pageY); | ||||
|     if (i === null) return; | ||||
|     selected = i; | ||||
|     draw(); | ||||
| }); | ||||
| 
 | ||||
| canvas.addEventListener('mousemove', (e) => { | ||||
|     if (!mouseDown) return; | ||||
|     if (movePointIndex === null) return; | ||||
|     curves[selected][movePointIndex] = [e.pageX, e.pageY]; | ||||
|     draw(); | ||||
| }); | ||||
| 
 | ||||
| canvas.addEventListener('mouseup', () => { | ||||
|     mouseDown = false; | ||||
|     movePointIndex = null; | ||||
| }); | ||||
| 
 | ||||
| window.addEventListener('resize', resizeCanvas); | ||||
| resizeCanvas(); | ||||
|  | ||||
							
								
								
									
										6006
									
								
								vaja_1/glm.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6006
									
								
								vaja_1/glm.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										180
									
								
								vaja_1/main.js
									
									
									
									
									
								
							
							
						
						
									
										180
									
								
								vaja_1/main.js
									
									
									
									
									
								
							| @ -1,51 +1,33 @@ | ||||
| import { mat4 } from './glm.js'; | ||||
| 
 | ||||
| // Initialize WebGPU
 | ||||
| const adapter = await navigator.gpu.requestAdapter(); | ||||
| const device = await adapter.requestDevice(); | ||||
| const canvas = document.querySelector('canvas'); | ||||
| const context = canvas.getContext('webgpu'); | ||||
| 
 | ||||
| const format = 'rgba8unorm'; | ||||
| const format = navigator.gpu.getPreferredCanvasFormat(); | ||||
| context.configure({ device, format }); | ||||
| 
 | ||||
| // Create shaders
 | ||||
| const code = await fetch('shader.wgsl').then((res) => res.text()); | ||||
| const module = device.createShaderModule({ code }); | ||||
| 
 | ||||
| // Create vertex buffer layouts
 | ||||
| /** @type {GPUVertexBufferLayout} */ | ||||
| const vertexBufferLayout = { | ||||
|     arrayStride: 32, | ||||
|     attributes: [ | ||||
|         { | ||||
|             offset: 0, | ||||
|             format: 'float32x4', | ||||
|             shaderLocation: 0, | ||||
|         }, | ||||
|         { | ||||
|             offset: 16, | ||||
|             format: 'float32x4', | ||||
|             shaderLocation: 1, | ||||
|         }, | ||||
|     ], | ||||
| }; | ||||
| 
 | ||||
| // Create render pipeline
 | ||||
| const pipeline = device.createRenderPipeline({ | ||||
|     vertex: { | ||||
|         module, | ||||
|         buffers: [vertexBufferLayout], | ||||
|     }, | ||||
|     fragment: { | ||||
|         module, | ||||
|         targets: [{ format }], | ||||
|     }, | ||||
|     layout: 'auto', | ||||
| // Create depth texture
 | ||||
| const depthTexture = device.createTexture({ | ||||
|     size: [canvas.width, canvas.height], | ||||
|     usage: GPUTextureUsage.RENDER_ATTACHMENT, | ||||
|     format: 'depth24plus', | ||||
| }); | ||||
| 
 | ||||
| // Create vertex buffer
 | ||||
| // prettier-ignore
 | ||||
| const vertices = new Float32Array([ | ||||
|     0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, | ||||
|     1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, | ||||
|     // position       // color
 | ||||
|     -1, -1, -1,  1,   1, 0, 0, 1, | ||||
|      1, -1, -1,  1,   0, 1, 0, 1, | ||||
|     -1,  1, -1,  1,   0, 0, 1, 1, | ||||
|      1,  1, -1,  1,   1, 1, 0, 1, | ||||
| 
 | ||||
|     -1,  1,  1,  1,   1, 0, 0, 1, | ||||
|      1, -1,  1,  1,   0, 1, 0, 1, | ||||
|     -1,  1,  1,  1,   0, 0, 1, 1, | ||||
|      1,  1,  1,  1,   1, 1, 0, 1, | ||||
| ]); | ||||
| 
 | ||||
| const vertexBuffer = device.createBuffer({ | ||||
| @ -55,7 +37,16 @@ const vertexBuffer = device.createBuffer({ | ||||
| 
 | ||||
| device.queue.writeBuffer(vertexBuffer, 0, vertices); | ||||
| 
 | ||||
| const indices = new Uint32Array([0, 1, 2, 1, 2, 3]); | ||||
| // Create index buffer
 | ||||
| // prettier-ignore
 | ||||
| const indices = new Uint32Array([ | ||||
|     0, 1, 2,   1, 2, 3, | ||||
|     0, 1, 3,   1, 4, 5, | ||||
|     0, 4, 2,   4, 2, 5, | ||||
|     1, 5, 3,   5, 3, 7, | ||||
|     2, 3, 6,   3, 6, 7, | ||||
|     4, 5, 6,   5, 6, 7, | ||||
| ]); | ||||
| 
 | ||||
| const indexBuffer = device.createBuffer({ | ||||
|     size: indices.byteLength, | ||||
| @ -64,11 +55,86 @@ const indexBuffer = device.createBuffer({ | ||||
| 
 | ||||
| device.queue.writeBuffer(indexBuffer, 0, indices); | ||||
| 
 | ||||
| // Create command encoder
 | ||||
| const commandEncoder = device.createCommandEncoder(); | ||||
| // Fetch and compile shaders
 | ||||
| const code = await fetch('shader.wgsl').then((response) => response.text()); | ||||
| const module = device.createShaderModule({ code }); | ||||
| 
 | ||||
| // Encode render pass
 | ||||
| const renderPass = commandEncoder.beginRenderPass({ | ||||
| // Create the pipeline
 | ||||
| /** @type {GPUVertexBufferLayout} */ | ||||
| const vertexBufferLayout = { | ||||
|     arrayStride: 24, | ||||
|     attributes: [ | ||||
|         { | ||||
|             shaderLocation: 0, | ||||
|             offset: 0, | ||||
|             format: 'float32x2', | ||||
|         }, | ||||
|         { | ||||
|             shaderLocation: 1, | ||||
|             offset: 8, | ||||
|             format: 'float32x4', | ||||
|         }, | ||||
|     ], | ||||
| }; | ||||
| 
 | ||||
| const pipeline = device.createRenderPipeline({ | ||||
|     vertex: { | ||||
|         module, | ||||
|         buffers: [vertexBufferLayout], | ||||
|     }, | ||||
|     fragment: { | ||||
|         module, | ||||
|         targets: [{ format }], | ||||
|     }, | ||||
|     depthStencil: { | ||||
|         depthWriteEnabled: true, | ||||
|         depthCompare: 'less', | ||||
|         format: 'depth24plus', | ||||
|     }, | ||||
|     layout: 'auto', | ||||
| }); | ||||
| 
 | ||||
| // Create uniform buffer
 | ||||
| const uniformBuffer = device.createBuffer({ | ||||
|     size: 4 * 4 * 4, | ||||
|     usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST, | ||||
| }); | ||||
| 
 | ||||
| // Create the bind group
 | ||||
| const bindGroup = device.createBindGroup({ | ||||
|     layout: pipeline.getBindGroupLayout(0), | ||||
|     entries: [{ binding: 0, resource: { buffer: uniformBuffer } }], | ||||
| }); | ||||
| 
 | ||||
| function update() { | ||||
|     // Animate the square
 | ||||
|     const time = performance.now() / 1000; | ||||
| 
 | ||||
|     const modelMatrix = mat4 | ||||
|         .create() | ||||
|         .rotateX(time * 0.7) | ||||
|         .rotateY(time); | ||||
|     const viewMatrix = mat4.create().translate([0, 0, 5]).invert(); | ||||
|     const projectionMatrix = mat4.create().perspectiveZO(1, 1, 0.01, 100); | ||||
| 
 | ||||
|     const matrix = mat4 | ||||
|         .create() | ||||
|         .multiply(projectionMatrix) | ||||
|         .multiply(viewMatrix) | ||||
|         .multiply(modelMatrix); | ||||
| 
 | ||||
|     // const radius = 0.5;
 | ||||
|     // const frequency = 0.5;
 | ||||
|     // const x = radius * Math.cos(frequency * time * 2 * Math.PI);
 | ||||
|     // const y = radius * Math.sin(frequency * time * 2 * Math.PI);
 | ||||
| 
 | ||||
|     device.queue.writeBuffer(uniformBuffer, 0, matrix); | ||||
| } | ||||
| 
 | ||||
| function render() { | ||||
|     // Render the square
 | ||||
|     const commandEncoder = device.createCommandEncoder(); | ||||
|     const renderPass = commandEncoder.beginRenderPass({ | ||||
|         colorAttachments: [ | ||||
|             { | ||||
|                 view: context.getCurrentTexture().createView(), | ||||
| @ -77,14 +143,26 @@ const renderPass = commandEncoder.beginRenderPass({ | ||||
|                 storeOp: 'store', | ||||
|             }, | ||||
|         ], | ||||
| }); | ||||
| renderPass.setPipeline(pipeline); | ||||
| renderPass.setVertexBuffer(0, vertexBuffer); | ||||
| renderPass.setIndexBuffer(indexBuffer, 'uint32'); | ||||
| renderPass.drawIndexed(indices.length); | ||||
| renderPass.end(); | ||||
|         depthStencilAttachment: { | ||||
|             view: depthTexture.createView(), | ||||
|             depthLoadOp: 'clear', | ||||
|             depthClearValue: 1, | ||||
|             depthStoreOp: 'discard', | ||||
|         }, | ||||
|     }); | ||||
|     renderPass.setPipeline(pipeline); | ||||
|     renderPass.setVertexBuffer(0, vertexBuffer); | ||||
|     renderPass.setIndexBuffer(indexBuffer, 'uint32'); | ||||
|     renderPass.setBindGroup(0, bindGroup); | ||||
|     renderPass.drawIndexed(indices.length); | ||||
|     renderPass.end(); | ||||
|     device.queue.submit([commandEncoder.finish()]); | ||||
| } | ||||
| 
 | ||||
| const commandBuffer = commandEncoder.finish(); | ||||
| function frame() { | ||||
|     update(); | ||||
|     render(); | ||||
|     requestAnimationFrame(frame); | ||||
| } | ||||
| 
 | ||||
| // Send commands to GPU
 | ||||
| device.queue.submit([commandBuffer]); | ||||
| requestAnimationFrame(frame); | ||||
|  | ||||
| @ -1,17 +1,38 @@ | ||||
| struct VertexInput { | ||||
|     @location(0) position: vec4f, | ||||
|     @location(1) color: vec4f, | ||||
| } | ||||
| 
 | ||||
| struct VertexOutput { | ||||
|     @builtin(position) position: vec4f, | ||||
|     @location(0) color: vec4f, | ||||
| } | ||||
| 
 | ||||
| struct FragmentInput { | ||||
|     @location(0) color: vec4f, | ||||
| } | ||||
| 
 | ||||
| struct FragmentOutput { | ||||
|     @location(0) color: vec4f, | ||||
| } | ||||
| 
 | ||||
| @group(0) @binding(0) var<uniform> mtrx: mat4x4f; | ||||
| 
 | ||||
| @vertex | ||||
| fn vertex(@location(0) position: vec4f, @location(1) color: vec4f) -> VertexOutput { | ||||
| fn vertex(input: VertexInput) -> VertexOutput { | ||||
|     var output: VertexOutput; | ||||
|     output.position = position; | ||||
|     output.color = color; | ||||
| 
 | ||||
|     output.position = mtrx * input.position; | ||||
|     output.color = input.color; | ||||
| 
 | ||||
|     return output; | ||||
| } | ||||
| 
 | ||||
| @fragment | ||||
| fn fragment(@location(0) color: vec4f) -> @location(0) vec4f { | ||||
|     return color; | ||||
| fn fragment(input: FragmentInput) -> FragmentOutput { | ||||
|     var output: FragmentOutput; | ||||
| 
 | ||||
|     output.color = input.color; | ||||
| 
 | ||||
|     return output; | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user