Pas2JS_WebGL.pas 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. program Hello;
  2. uses
  3. Vectors, Mat4, MemoryBuffer, GLUtils, GLTypes,
  4. BrowserConsole, Web, WebGL, WebGL2, JS, Math;
  5. type
  6. GLVertex2 = record
  7. pos: TVec2;
  8. color: TRGBAb;
  9. end;
  10. const
  11. kSIZEOF_VERTEX = 12;
  12. function GetVertexData: TJSUInt8Array;
  13. var
  14. buffer: TMemoryBuffer;
  15. verts: TJSArray;
  16. v: GLVertex2;
  17. i: integer;
  18. begin
  19. verts := TJSArray.new;
  20. v.pos := V2(0, 0);
  21. v.color := RGBAb(255, 0, 0, 255);
  22. verts.push(v);
  23. v.pos := V2(0, 100);
  24. v.color := RGBAb(0, 255, 0, 255);
  25. verts.push(v);
  26. v.pos := V2(100, 100);
  27. v.color := RGBAb(0, 0, 255, 255);
  28. verts.push(v);
  29. // pack the array of verticies into a byte buffer
  30. buffer := TMemoryBuffer.Create(kSIZEOF_VERTEX * verts.length);
  31. for i := 0 to verts.length - 1 do
  32. begin
  33. v := GLVertex2(verts[i]);
  34. buffer.AddFloats(2, v.pos);
  35. buffer.AddBytes(4, v.color);
  36. end;
  37. result := buffer.GetBytes;
  38. end;
  39. var
  40. nextTime: single = 0;
  41. deltaTime: single = 0;
  42. var
  43. gl: TJSWebGLRenderingContext;
  44. shader: TShader;
  45. projTransform: TMat4;
  46. viewTransform: TMat4;
  47. modelTransform: TMat4;
  48. var
  49. rotateAngle: double = 0;
  50. procedure UpdateCanvas(time: TDOMHighResTimeStamp);
  51. var
  52. now: single;
  53. list: TScalarArray;
  54. begin
  55. now := time * 0.001;
  56. deltaTime := now - nextTime;
  57. nextTime := now;
  58. modelTransform := TMat4.Identity;
  59. modelTransform := modelTransform.Multiply(TMat4.Translate(100, 100, 0));
  60. modelTransform := modelTransform.Multiply(TMat4.RotateZ(DegToRad(rotateAngle)));
  61. //fullTransform := projTransform.Multiply(viewTransform);
  62. //fullTransform := fullTransform.Multiply(modelTransform);
  63. rotateAngle := rotateAngle + (20 * deltaTime);
  64. list := modelTransform.CopyList;
  65. shader.SetUniformMat4('modelTransform', TJSFloat32List(list));
  66. //writeln(deltaTime);
  67. gl.clear(gl.COLOR_BUFFER_BIT);
  68. gl.drawArrays(gl.TRIANGLES, 0, 3);
  69. window.requestAnimationFrame(@UpdateCanvas);
  70. end;
  71. var
  72. canvas: TJSHTMLCanvasElement;
  73. i: integer;
  74. offset: integer;
  75. stride: integer;
  76. vertexShaderSource: string;
  77. fragmentShaderSource: string;
  78. buffer: TJSWebGLBuffer;
  79. list: TScalarArray;
  80. begin
  81. // make webgl context
  82. canvas := TJSHTMLCanvasElement(document.createElement('canvas'));
  83. canvas.width := 300;
  84. canvas.height := 300;
  85. document.body.appendChild(canvas);
  86. gl := TJSWebGLRenderingContext(canvas.getContext('webgl'));
  87. if gl = nil then
  88. begin
  89. writeln('failed to load webgl!');
  90. exit;
  91. end;
  92. // create shaders from source in html
  93. vertexShaderSource := document.getElementById('vertex.glsl').textContent;
  94. fragmentShaderSource := document.getElementById('fragment.glsl').textContent;
  95. shader := TShader.Create(gl, vertexShaderSource, fragmentShaderSource);
  96. shader.Compile;
  97. shader.BindAttribLocation(0, 'in_position');
  98. shader.BindAttribLocation(1, 'in_color');
  99. shader.Link;
  100. shader.Use;
  101. // prepare context
  102. gl.clearColor(0.9, 0.9, 0.9, 1);
  103. gl.viewport(0, 0, canvas.width, canvas.height);
  104. gl.clear(gl.COLOR_BUFFER_BIT);
  105. // setup transform matricies
  106. projTransform := TMat4.Ortho(0, gl.canvas.width, gl.canvas.height, 0, -1, 1);
  107. viewTransform := TMat4.Identity;
  108. modelTransform := TMat4.Identity;
  109. // TODO: parser bug typecasting to TJSFloat32List(projTransform.CopyList)
  110. // so we need to assign to a variable first
  111. list := projTransform.CopyList;
  112. shader.SetUniformMat4('projTransform', TJSFloat32List(list));
  113. list := viewTransform.CopyList;
  114. shader.SetUniformMat4('viewTransform', TJSFloat32List(list));
  115. list := modelTransform.CopyList;
  116. shader.SetUniformMat4('modelTransform', TJSFloat32List(list));
  117. // create buffer
  118. buffer := gl.createBuffer;
  119. gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  120. gl.bufferData(gl.ARRAY_BUFFER, GetVertexData, gl.STATIC_DRAW);
  121. // TODO: vertex array objects were added in webgl2
  122. offset := 0;
  123. stride := kSIZEOF_VERTEX;
  124. // position
  125. gl.enableVertexAttribArray(0);
  126. gl.vertexAttribPointer(0, 2, gl.FLOAT, false, stride, offset);
  127. offset := offset + TVec2_Sizeof;
  128. // color (normalized = true since we're using unsigned byte)
  129. gl.enableVertexAttribArray(1);
  130. gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, stride, offset);
  131. offset := offset + TRGBAb_Sizeof;
  132. //gl.drawArrays(gl.TRIANGLES, 0, 3);
  133. // fire off the timer to draw
  134. window.requestAnimationFrame(@UpdateCanvas);
  135. end.