2
0

Pas2JS_WebGL.pas 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. program Pas2JS_WebGL;
  2. uses
  3. Mat4, MemoryBuffer, GLUtils, GLTypes, SysUtils,
  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; // vec2 + RGBAb
  12. function GetVertexData: TJSUInt8Array;
  13. var
  14. buffer: TMemoryBuffer;
  15. verts: TJSArray;
  16. v: GLVertex2;
  17. i: integer;
  18. begin
  19. // there's really no reason to build the array
  20. // as vectors first then pack into bytes but
  21. // we're doing it anyways because this how most
  22. // will be familar with vertex data from standard
  23. // OpenGL
  24. verts := TJSArray.new;
  25. v.pos := V2(0, 0);
  26. v.color := RGBAb(255, 0, 0, 255);
  27. verts.push(v);
  28. v.pos := V2(0, 100);
  29. v.color := RGBAb(0, 255, 0, 255);
  30. verts.push(v);
  31. v.pos := V2(100, 100);
  32. v.color := RGBAb(0, 0, 255, 255);
  33. verts.push(v);
  34. // pack the array of verticies into a byte buffer
  35. buffer := TMemoryBuffer.Create(kSIZEOF_VERTEX * verts.length);
  36. for i := 0 to verts.length - 1 do
  37. begin
  38. v := GLVertex2(verts[i]);
  39. buffer.AddFloats(2, {v.pos}ToFloats(v.pos));
  40. buffer.AddBytes(4, v.color);
  41. end;
  42. result := buffer.GetBytes;
  43. end;
  44. var
  45. nextTime: single = 0;
  46. deltaTime: single = 0;
  47. var
  48. gl: TJSWebGLRenderingContext;
  49. shader: TShader;
  50. projTransform: TMat4;
  51. viewTransform: TMat4;
  52. modelTransform: TMat4;
  53. var
  54. rotateAngle: double = 0;
  55. procedure UpdateCanvas(time: TDOMHighResTimeStamp);
  56. var
  57. now: single;
  58. begin
  59. now := time * 0.001;
  60. deltaTime := now - nextTime;
  61. nextTime := now;
  62. modelTransform := TMat4.Identity;
  63. modelTransform := modelTransform.Multiply(TMat4.Translate(100, 100, 0));
  64. modelTransform := modelTransform.Multiply(TMat4.RotateZ(DegToRad(rotateAngle)));
  65. rotateAngle := rotateAngle + (20 * deltaTime);
  66. shader.SetUniformMat4('modelTransform', modelTransform);
  67. //writeln(deltaTime);
  68. gl.clear(gl.COLOR_BUFFER_BIT);
  69. gl.drawArrays(gl.TRIANGLES, 0, 3);
  70. window.requestAnimationFrame(@UpdateCanvas);
  71. end;
  72. var
  73. canvas: TJSHTMLCanvasElement;
  74. i: integer;
  75. stride: integer;
  76. offset: integer;
  77. vertexShaderSource: string;
  78. fragmentShaderSource: string;
  79. buffer: TJSWebGLBuffer;
  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. shader.SetUniformMat4('projTransform', projTransform);
  110. shader.SetUniformMat4('viewTransform', viewTransform);
  111. shader.SetUniformMat4('modelTransform', modelTransform);
  112. // create buffer
  113. buffer := gl.createBuffer;
  114. gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  115. gl.bufferData(gl.ARRAY_BUFFER, GetVertexData, gl.STATIC_DRAW);
  116. offset := 0;
  117. stride := kSIZEOF_VERTEX;
  118. // position
  119. gl.enableVertexAttribArray(0);
  120. gl.vertexAttribPointer(0, 2, gl.FLOAT, false, stride, offset);
  121. offset += GLSizeof(gl.FLOAT) * 2;
  122. // color (normalized = true since we're using unsigned byte)
  123. gl.enableVertexAttribArray(1);
  124. gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, stride, offset);
  125. offset += GLSizeof(gl.UNSIGNED_BYTE) * 4;
  126. // fire off the timer to draw
  127. window.requestAnimationFrame(@UpdateCanvas);
  128. end.