Pas2JS_WebGL.pas 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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;
  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. begin
  54. now := time * 0.001;
  55. deltaTime := now - nextTime;
  56. nextTime := now;
  57. modelTransform := TMat4.Identity;
  58. modelTransform := modelTransform.Multiply(TMat4.Translate(100, 100, 0));
  59. modelTransform := modelTransform.Multiply(TMat4.RotateZ(DegToRad(rotateAngle)));
  60. rotateAngle := rotateAngle + (20 * deltaTime);
  61. shader.SetUniformMat4('modelTransform', modelTransform);
  62. //writeln(deltaTime);
  63. gl.clear(gl.COLOR_BUFFER_BIT);
  64. gl.drawArrays(gl.TRIANGLES, 0, 3);
  65. window.requestAnimationFrame(@UpdateCanvas);
  66. end;
  67. var
  68. canvas: TJSHTMLCanvasElement;
  69. i: integer;
  70. stride: integer;
  71. offset: integer;
  72. vertexShaderSource: string;
  73. fragmentShaderSource: string;
  74. buffer: TJSWebGLBuffer;
  75. begin
  76. // make webgl context
  77. canvas := TJSHTMLCanvasElement(document.createElement('canvas'));
  78. canvas.width := 300;
  79. canvas.height := 300;
  80. document.body.appendChild(canvas);
  81. gl := TJSWebGLRenderingContext(canvas.getContext('webgl'));
  82. if gl = nil then
  83. begin
  84. writeln('failed to load webgl!');
  85. exit;
  86. end;
  87. // create shaders from source in html
  88. vertexShaderSource := document.getElementById('vertex.glsl').textContent;
  89. fragmentShaderSource := document.getElementById('fragment.glsl').textContent;
  90. shader := TShader.Create(gl, vertexShaderSource, fragmentShaderSource);
  91. shader.Compile;
  92. shader.BindAttribLocation(0, 'in_position');
  93. shader.BindAttribLocation(1, 'in_color');
  94. shader.Link;
  95. shader.Use;
  96. // prepare context
  97. gl.clearColor(0.9, 0.9, 0.9, 1);
  98. gl.viewport(0, 0, canvas.width, canvas.height);
  99. gl.clear(gl.COLOR_BUFFER_BIT);
  100. // setup transform matricies
  101. projTransform := TMat4.Ortho(0, gl.canvas.width, gl.canvas.height, 0, -1, 1);
  102. viewTransform := TMat4.Identity;
  103. modelTransform := TMat4.Identity;
  104. shader.SetUniformMat4('projTransform', projTransform);
  105. shader.SetUniformMat4('viewTransform', viewTransform);
  106. shader.SetUniformMat4('modelTransform', modelTransform);
  107. // create buffer
  108. buffer := gl.createBuffer;
  109. gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  110. gl.bufferData(gl.ARRAY_BUFFER, GetVertexData, gl.STATIC_DRAW);
  111. offset := 0;
  112. // vec2 + RGBAb
  113. stride := kSIZEOF_VERTEX;
  114. // position
  115. gl.enableVertexAttribArray(0);
  116. gl.vertexAttribPointer(0, 2, gl.FLOAT, false, stride, offset);
  117. offset += GLSizeof(gl.FLOAT) * 2;
  118. // color (normalized = true since we're using unsigned byte)
  119. gl.enableVertexAttribArray(1);
  120. gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, stride, offset);
  121. offset += GLSizeof(gl.UNSIGNED_BYTE) * 4;
  122. // fire off the timer to draw
  123. window.requestAnimationFrame(@UpdateCanvas);
  124. end.