@@ -6,8 +6,8 @@ import { mat4 } from 'gl-matrix';
66let uMVPLocation : WebGLUniformLocation | null = null ;
77
88let gl : WebGLRenderingContext | null = null ;
9- let program : WebGLProgram | null = null ;
10- let positionBuffer : WebGLBuffer | null = null ;
9+ let program : WebGLProgram ;
10+ let positionBuffer : WebGLBuffer ;
1111
1212export let vertices : number [ ] = [ ] ;
1313export let colors : number [ ] = [ ] ;
@@ -16,20 +16,20 @@ export let colors: number[] = [];
1616let matrixWidth : number = 1 ;
1717let matrixHeight : number = 1 ;
1818
19- let colorBuffer : WebGLBuffer | null = null ; // Buffer for color data
19+ let colorBuffer : WebGLBuffer ; // Buffer for color data
2020
2121export function createScene ( el : HTMLCanvasElement ) {
22- // Initialize WebGL
23- gl = el . getContext ( "webgl" ) ;
24- if ( ! gl ) {
25- console . error ( "WebGL not supported" ) ;
26- return ;
27- }
22+ // Initialize WebGL
23+ gl = el . getContext ( "webgl" ) ;
24+ if ( ! gl ) {
25+ console . error ( "WebGL not supported" ) ;
26+ return ;
27+ }
2828
29- clearVertices ( ) ;
29+ clearVertices ( ) ;
3030
31- // Set up shaders
32- const vertexShaderSource = `
31+ // Set up shaders
32+ const vertexShaderSource = `
3333 precision mediump float;
3434 attribute vec3 aPosition;
3535 attribute vec4 aColor; // Color attribute
@@ -42,7 +42,7 @@ export function createScene(el: HTMLCanvasElement) {
4242 vColor = aColor; // Pass the color to the fragment shader
4343 }
4444 ` ;
45- const fragmentShaderSource = `
45+ const fragmentShaderSource = `
4646 precision mediump float;
4747 varying vec4 vColor;
4848
@@ -51,47 +51,48 @@ export function createScene(el: HTMLCanvasElement) {
5151 }
5252 ` ;
5353
54- const vertexShader = createShader ( gl , gl . VERTEX_SHADER , vertexShaderSource ) ;
55- const fragmentShader = createShader ( gl , gl . FRAGMENT_SHADER , fragmentShaderSource ) ;
54+ const vertexShader = createShader ( gl , gl . VERTEX_SHADER , vertexShaderSource ) ;
55+ const fragmentShader = createShader ( gl , gl . FRAGMENT_SHADER , fragmentShaderSource ) ;
5656
57- program = createProgram ( gl , vertexShader , fragmentShader ) ;
58- gl . useProgram ( program ) ;
57+ program = createProgram ( gl , vertexShader , fragmentShader ) ;
58+ gl . useProgram ( program ) ;
5959
60- uMVPLocation = gl . getUniformLocation ( program , "uMVP" ) ;
60+ uMVPLocation = gl . getUniformLocation ( program , "uMVP" ) ;
6161
62- // Set up position buffer
63- positionBuffer = gl . createBuffer ( ) ;
64- const positionAttributeLocation = gl . getAttribLocation ( program , "aPosition" ) ;
65- gl . bindBuffer ( gl . ARRAY_BUFFER , positionBuffer ) ;
66- gl . enableVertexAttribArray ( positionAttributeLocation ) ;
67- gl . vertexAttribPointer ( positionAttributeLocation , 3 , gl . FLOAT , false , 0 , 0 ) ;
62+ // Set up position buffer
63+ positionBuffer = gl . createBuffer ( ) ;
64+ const positionAttributeLocation = gl . getAttribLocation ( program , "aPosition" ) ;
65+ gl . bindBuffer ( gl . ARRAY_BUFFER , positionBuffer ) ;
66+ gl . enableVertexAttribArray ( positionAttributeLocation ) ;
67+ gl . vertexAttribPointer ( positionAttributeLocation , 3 , gl . FLOAT , false , 0 , 0 ) ;
6868
69- // Set up color buffer
70- colorBuffer = gl . createBuffer ( ) ;
71- const colorAttributeLocation = gl . getAttribLocation ( program , "aColor" ) ;
72- gl . bindBuffer ( gl . ARRAY_BUFFER , colorBuffer ) ;
73- gl . enableVertexAttribArray ( colorAttributeLocation ) ;
74- gl . vertexAttribPointer ( colorAttributeLocation , 4 , gl . FLOAT , false , 0 , 0 ) ;
69+ // Set up color buffer
70+ colorBuffer = gl . createBuffer ( ) ;
71+ const colorAttributeLocation = gl . getAttribLocation ( program , "aColor" ) ;
72+ gl . bindBuffer ( gl . ARRAY_BUFFER , colorBuffer ) ;
73+ gl . enableVertexAttribArray ( colorAttributeLocation ) ;
74+ gl . vertexAttribPointer ( colorAttributeLocation , 4 , gl . FLOAT , false , 0 , 0 ) ;
7575
76- // Set up WebGL viewport
77- gl . viewport ( 0 , 0 , gl . canvas . width , gl . canvas . height ) ;
78- gl . clearColor ( 0 , 0 , 0 , 1 ) ;
79- gl . enable ( gl . DEPTH_TEST ) ;
76+ // Set up WebGL viewport
77+ gl . viewport ( 0 , 0 , gl . canvas . width , gl . canvas . height ) ;
78+ gl . clearColor ( 0 , 0 , 0 , 1 ) ;
79+ gl . enable ( gl . DEPTH_TEST ) ;
8080}
8181
8282const createShader = ( gl : WebGLRenderingContext , type : number , source : string ) : WebGLShader => {
8383 const shader = gl . createShader ( type ) ;
84- if ( ! shader ) {
85- throw new Error ( "Unable to create shader" ) ;
86- }
87- gl . shaderSource ( shader , source ) ;
88- gl . compileShader ( shader ) ;
89- if ( ! gl . getShaderParameter ( shader , gl . COMPILE_STATUS ) ) {
84+ if ( shader ) {
85+ gl . shaderSource ( shader , source ) ;
86+ gl . compileShader ( shader ) ;
87+ if ( ! gl . getShaderParameter ( shader , gl . COMPILE_STATUS ) ) {
9088 console . error ( gl . getShaderInfoLog ( shader ) ) ;
9189 gl . deleteShader ( shader ) ;
9290 throw new Error ( "Shader compilation failed" ) ;
91+ }
92+ return shader ;
9393 }
94- return shader ;
94+ else
95+ throw new Error ( "Unable to create shader" ) ;
9596} ;
9697
9798const createProgram = ( gl : WebGLRenderingContext , vertexShader : WebGLShader , fragmentShader : WebGLShader ) : WebGLProgram => {
@@ -100,9 +101,9 @@ const createProgram = (gl: WebGLRenderingContext, vertexShader: WebGLShader, fra
100101 gl . attachShader ( program , fragmentShader ) ;
101102 gl . linkProgram ( program ) ;
102103 if ( ! gl . getProgramParameter ( program , gl . LINK_STATUS ) ) {
103- console . error ( gl . getProgramInfoLog ( program ) ) ;
104- gl . deleteProgram ( program ) ;
105- throw new Error ( "Program linking failed" ) ;
104+ console . error ( gl . getProgramInfoLog ( program ) ) ;
105+ gl . deleteProgram ( program ) ;
106+ throw new Error ( "Program linking failed" ) ;
106107 }
107108 return program ;
108109} ;
@@ -122,13 +123,11 @@ export function setMatrixDimensions(width: number, height: number) {
122123}
123124
124125export const updateScene = ( vertices : number [ ] , colors : number [ ] ) => {
125- if ( ! gl || ! positionBuffer || ! colorBuffer ) return ;
126+ if ( ! gl ) return ;
126127
127- // Set the MVP matrix
128+ // Set the MVP matrix
128129 const mvp = getMVPMatrix ( ) ;
129- if ( uMVPLocation ) {
130- gl . uniformMatrix4fv ( uMVPLocation , false , mvp ) ;
131- }
130+ gl . uniformMatrix4fv ( uMVPLocation , false , mvp ) ;
132131
133132 // Bind the position buffer and upload the vertex data
134133 gl . bindBuffer ( gl . ARRAY_BUFFER , positionBuffer ) ;
@@ -148,45 +147,42 @@ export const updateScene = (vertices: number[], colors: number[]) => {
148147function getMVPMatrix ( ) : mat4 {
149148 const canvas = gl ! . canvas as HTMLCanvasElement ;
150149 const canvasAspect = canvas . width / canvas . height ;
150+
151151 const fov = Math . PI / 6 ; // 30 degrees
152152 const near = 0.1 ;
153153 const far = 100.0 ;
154154
155155 const projection = mat4 . create ( ) ;
156156 mat4 . perspective ( projection , fov , canvasAspect , near , far ) ;
157157
158+ // Normalize the matrix dimensions to a unit square/rectangle
159+ // Use the larger dimension as the base
160+ const maxDim = Math . max ( matrixWidth , matrixHeight ) ;
161+ const normalizedWidth = matrixWidth / maxDim ;
162+ const normalizedHeight = matrixHeight / maxDim ;
163+
158164 // Calculate the required camera distance to fit the matrix in view
159- const matrixAspect = matrixWidth / matrixHeight ;
160-
161- // The object will be scaled by matrixAspect in X direction and 1 in Y direction
162- // We need to fit the larger dimension in the view
163- // Calculate the size of the object after scaling
164- const objectWidth = matrixAspect ;
165- const objectHeight = 1 ;
166-
167165 // Determine which dimension is limiting based on canvas aspect
168- // The vertical FOV determines how much we see vertically
169- // The horizontal FOV is: horizontal = 2 * atan(tan(vertical/2) * aspect)
170- const verticalSize = objectHeight ;
171- const horizontalSize = objectWidth ;
172-
166+ const verticalSize = normalizedHeight ;
167+ const horizontalSize = normalizedWidth ;
168+
173169 // Calculate required distance for vertical fit
174170 const distanceForHeight = verticalSize / ( 2 * Math . tan ( fov / 2 ) ) ;
175-
171+
176172 // Calculate required distance for horizontal fit
177173 const horizontalFov = 2 * Math . atan ( Math . tan ( fov / 2 ) * canvasAspect ) ;
178174 const distanceForWidth = horizontalSize / ( 2 * Math . tan ( horizontalFov / 2 ) ) ;
179-
175+
180176 // Use the larger distance to ensure both dimensions fit
181177 const cameraDistance = Math . max ( distanceForHeight , distanceForWidth ) * 2.5 ; // 1.2 adds some padding
182178
183179 const view = mat4 . create ( ) ;
184180 mat4 . lookAt ( view , [ 0 , 0 , cameraDistance ] , [ 0 , 0 , 0 ] , [ 0 , 1 , 0 ] ) ;
185181
186182 const model = mat4 . create ( ) ;
187-
188- // Scale by the matrix aspect ratio to get correct proportions
189- mat4 . scale ( model , model , [ matrixAspect , 1 , 1 ] ) ;
183+
184+ // Scale by the normalized dimensions to get correct proportions
185+ mat4 . scale ( model , model , [ normalizedWidth , normalizedHeight , 1 ] ) ;
190186
191187 const mvp = mat4 . create ( ) ;
192188 mat4 . multiply ( mvp , projection , view ) ;
0 commit comments