8Observer8 Posted January 11, 2023 Author Share Posted January 11, 2023 My Snake2D game in pure WebGL1, Rollup, JS, FreeTexturePacker, WebAudioAPI, and HTML5/CSS for GUI: https://8observer8.github.io/webgl10-js/boomers-snake2d-webgl1-js/ Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted January 15, 2023 Author Share Posted January 15, 2023 (edited) To create a desktop application from WebGL, you can rewrite it to OpenGL. Python is one of the easiest languages to build desktop applications. Drawing Box2D physics engine colliders with b2Draw, OpenGL1, PyQt6 and Python The example shows how to draw colliders using b2Draw. Uses OpenGL version 1 for simplicity. pyBox2D works with Python 3.8. Download and install Python 3.8 from here: https://www.python.org/downloads/ Install the required packages with this command from CMD: pip install Box2D PyQt6 PyOpenGL Download the source code: https://github.com/8Observer8/edit-gravity-debug-drawer-opengl1-pyqt6 Go to your project folder and type this command to run the application: python main.py (or double click on main.py) Install the very useful isort module (pip install isort), which allows you to sort plugins alphabetically with the command: isort . (dot means to sort in all files in the current directory) The Notepad++ code editor has syntax highlighting for Python, JavaScript, HTML, C++, and more by default. There is a plugin (https://github.com/danielscherzer/NotepaddPP-glsl-integration) for syntax highlighting GLSL (OpenGL Shading Language). You can make the working directory the directory of the current file, which will open in the left pane. To do this, right-click on the file in the editor tab and select "Open into" -> "Open Containing Folder as Workspace". You can invoke the CMD (console) on Windows from Notapad++ by opening a code file in the editor, right-clicking on the file in the editor tab and selecting "Open into" -> "Open Containing Folder in cmd". Edited January 17, 2023 by 8Observer8 Quote Link to comment Share on other sites More sharing options...
Nikhil Sharma Posted February 2, 2023 Share Posted February 2, 2023 Here are two examples of using WebGL to create simple graphics in a web browser: Drawing a Triangle: <!DOCTYPE html> <html> <head> <script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.js"></script> <script> // Set up the scene const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // Create the triangle const geometry = new THREE.Geometry(); geometry.vertices.push( new THREE.Vector3(-1, -1, 0), new THREE.Vector3(0, 1, 0), new THREE.Vector3(1, -1, 0) ); geometry.faces.push(new THREE.Face3(0, 1, 2)); const material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); const triangle = new THREE.Mesh(geometry, material); scene.add(triangle); // Render the scene camera.position.z = 5; renderer.render(scene, camera); </script> </head> <body> </body> </html> Rotating a Cube: <!DOCTYPE html> <html> <head> <script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.js"></script> <script> // Set up the scene const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 ); const renderer = new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // Create the cube const geometry = new THREE.BoxGeometry(1, 1, 1); const material = new THREE.MeshBasicMaterial({ color: 0xff0000 }); const cube = new THREE.Mesh(geometry, material); scene.add(cube); // Render the scene camera.position.z = 5; renderer.render(scene, camera); const render = function () { requestAnimationFrame(render); cube.rotation.x += 0.01; cube.rotation.y += 0.01; renderer.render(scene, camera); }; render(); </script> </head> <body> </body> </html> These examples show the basics of setting up a scene, creating objects, and rendering them in a web browser using Three.js. Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted February 3, 2023 Author Share Posted February 3, 2023 (edited) @Nikhil Sharma sorry but this topic for pure WebGL and OpenGL examples. If you want you can create another topic for Three.js examples. Edited February 3, 2023 by 8Observer8 Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted February 9, 2023 Author Share Posted February 9, 2023 Translated a platformer with self-written physics from Olga28 to WebGL Demo in browser: https://8observer8.github.io/webgl10-js/olga28s-platformer-2d/ Controls: left/right arrows and up arrow - jump. Forum topic: https://www.cyberforum.ru/javascript-canvas/thread3075879.html Right-click in Chrome and select "Translate to English" Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted February 9, 2023 Author Share Posted February 9, 2023 (edited) Calculation of points of a five-pointed star. Sandbox demo on WebGL and JavaScript: https://plnkr.co/edit/W49ndxcQemMgkAoP I made the video: https://www.youtube.com/watch?v=0fu4X8xbOuY Edited February 9, 2023 by 8Observer8 Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted February 21, 2023 Author Share Posted February 21, 2023 I have a slight angle offset between the object and the borders of the colliders: https://github.com/Lusito/box2d.ts/issues/36#issuecomment-1438368875 - PlayCode: https://playcode.io/1211513 - Plunker: https://plnkr.co/edit/zTthXbGVITITERkL Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted March 3, 2023 Author Share Posted March 3, 2023 Some progress in pure WebGL. Placed tiles and colliders in Tiled. Packed tiles and sprites into one texture atlas using Free Texture Packer. Physics at OimoPhysics. Drawn with pure WebGL 1.0 and linear algebra with glMatrix Demo in browser: https://8observer8.github.io/webgl10-js/mario-2d-jumps-oimophysics-webgl-js/ Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted May 29, 2023 Author Share Posted May 29, 2023 I implemented the simplest multiplayer using WebSockets (package ws - npm) and Node.js. I send keyboard input to the server, which relays it to other clients. Used by WebGL 1.0, glMatrix and OimoPhysics. Extracted original models, textures and animations using RE1MV. Created a non-skinned skeletal animation using the Blender Python API. Skinning is expensive in terms of resources and is not needed for the models in this game, in which all parts of the animation models are separate objects. Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted May 29, 2023 Author Share Posted May 29, 2023 All extracted animations for Jill and Barry. Rotate the camera with the mouse wheel pressed. Moving the camera with the right mouse button: Demo for Jill Demo for Barry Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted May 30, 2023 Author Share Posted May 30, 2023 I extracted the original skeletal animations from RE1MV and wrote a plugin in the Blender Python API to load animations into Blender: Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted June 2, 2023 Author Share Posted June 2, 2023 My multiplayer above is not working properly. The idea was to have the same physics world on the clients and apply the same keyboard event (to apply the same pulses) without the physics world on the server for smooth movements. The server simply forwards the array of keys pressed to other clients. But after a while, the physical worlds on the clients are no longer the same. I should have an authoritarian server, that is, a physical world on the server to synchronize the positions and rotation angles of the clients. Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted June 6, 2023 Author Share Posted June 6, 2023 (edited) I completed the first version of the demo with an authoritarian server, where you can navigate in cooperative and single player modes from the first and third person. Made to show models, animations made in Blender and interactive interactions on WebGL. Demo in browser: https://8observer8.github.io/webgl10-js/room-webgl-js/ Edited June 6, 2023 by 8Observer8 Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted July 4, 2023 Author Share Posted July 4, 2023 Ray casting from fixture using box2d-core and WebGL 1.0 Sandboxes: PlayCode: https://playcode.io/1523196 Plunker: https://plnkr.co/edit/Zwz0EcTnFOQazZgL?preview This example with Rollup on GitHub and a step-by-step instruction to run it: https://github.com/8Observer8/ray-casting-box2dcore-webgl-js Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted July 4, 2023 Author Share Posted July 4, 2023 (edited) This example shows how to load the spritesheet files (png and json) from Free TexturePacker Online (https://www.codeandweb.com/tp-online) using Fetch API: index.js import loadTexture from "./load-texture.js"; async function init() { const characterTexturePath = "assets/spritesheets/character.png"; const characterTexture = await loadTexture(characterTexturePath); const characterJSONPath = "assets/spritesheets/character.json"; const characterResponse = await fetch(characterJSONPath); const characterContent = await characterResponse.text(); console.log(characterContent); } init(); load-texture.js import { gl } from "./webgl-context.js"; export default function loadTexture(url, minType = gl.NEAREST, magType = gl.NEAREST) { return new Promise(resolve => { const image = new Image(); image.onload = () => { const texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minType); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magType); gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); resolve(texture); }; image.src = url; }); } index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Example</title> <link rel="stylesheet" type="text/css" href="./css/style.css"> </head> <body> <canvas id="renderCanvas" width="300" height="300"></canvas> <!-- Since importmap is not yet supported by all browsers, it is necessary to add the polyfill es-module-shims.min.js --> <script async src="https://unpkg.com/[email protected]/dist/es-module-shims.min.js"></script> <script type="importmap"> { "imports": { "gl-matrix": "https://cdn.skypack.dev/[email protected]" } } </script> <script type="module" src="./js/index.js"></script> </body> </html> Edited July 4, 2023 by 8Observer8 Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted July 24, 2023 Author Share Posted July 24, 2023 (edited) Sprite in SFML style using FreeTexturePacker, pure WebGL 1.0, and JavaScript This example loads sprites from the FreeTexturePacker sprite sheet and uses a sprite in SFML style Playgrounds: Plunker Replit Edited July 24, 2023 by 8Observer8 Quote Link to comment Share on other sites More sharing options...
codyjohnson1416 Posted December 19, 2023 Share Posted December 19, 2023 document.addEventListener("DOMContentLoaded", function () { // Get the WebGL context const canvas = document.getElementById("webgl-canvas"); const gl = canvas.getContext("webgl"); // Check if WebGL is available if (!gl) { console.error("Unable to initialize WebGL. Your browser may not support it."); return; } // Vertex shader program const vsSource = ` attribute vec4 aVertexPosition; uniform mat4 uModelViewMatrix; uniform mat4 uProjectionMatrix; void main(void) { gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition; } `; // Fragment shader program const fsSource = ` void main(void) { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); } `; // Initialize shaders const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource); const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource); // Create program and link shaders const shaderProgram = createProgram(gl, vertexShader, fragmentShader); // Set up the buffers for the cube's vertices const vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); const vertices = [ // Front face -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, // Back face -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); // Set up the position attribute const position = gl.getAttribLocation(shaderProgram, "aVertexPosition"); gl.vertexAttribPointer(position, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(position); // Set the clear color and enable depth testing gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clearDepth(1.0); gl.enable(gl.DEPTH_TEST); // Set up the perspective matrix const projectionMatrix = mat4.create(); mat4.perspective(projectionMatrix, Math.PI / 4, canvas.width / canvas.height, 0.1, 100.0); // Set up the model-view matrix const modelViewMatrix = mat4.create(); // Set up animation variables let then = 0; // Draw the scene function drawScene(now) { now *= 0.001; // convert to seconds const deltaTime = now - then; then = now; // Rotate the cube mat4.rotateY(modelViewMatrix, modelViewMatrix, deltaTime); // Set the uniform matrices const uModelViewMatrix = gl.getUniformLocation(shaderProgram, "uModelViewMatrix"); const uProjectionMatrix = gl.getUniformLocation(shaderProgram, "uProjectionMatrix"); gl.uniformMatrix4fv(uModelViewMatrix, false, modelViewMatrix); gl.uniformMatrix4fv(uProjectionMatrix, false, projectionMatrix); // Clear the canvas and draw the cube gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.drawArrays(gl.TRIANGLE_FAN, 0, 4); gl.drawArrays(gl.TRIANGLE_FAN, 4, 4); gl.drawArrays(gl.LINE_LOOP, 0, 4); gl.drawArrays(gl.LINE_LOOP, 4, 4); // Request the next animation frame requestAnimationFrame(drawScene); } // Start the animation requestAnimationFrame(drawScene); }); // Helper function to create shaders function createShader(gl, type, source) { const shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { console.error("Shader compilation error:", gl.getShaderInfoLog(shader)); gl.deleteShader(shader); return null; } return shader; } // Helper function to create shader program function createProgram(gl, vertexShader, fragmentShader) { const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { console.error("Shader program linking error:", gl.getProgramInfoLog(program)); gl.deleteProgram(program); return null; } gl.useProgram(program); return program; } mca leads Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted December 20, 2023 Author Share Posted December 20, 2023 (edited) I copied codyjohnson1416's example on Plunker: https://plnkr.co/edit/frieLjHeWBwGPcJt?preview index.html <!DOCTYPE html> <html> <head> <title>codyjohnson1416's Example</title> </head> <body> <canvas id="webgl-canvas"></canvas> <!-- Since import maps are not yet supported by all browsers, its is necessary to add the polyfill es-module-shims.js --> <script async src="https://unpkg.com/[email protected]/dist/es-module-shims.js"></script> <script type="importmap"> { "imports": { "gl-matrix": "https://cdn.jsdelivr.net/npm/[email protected]/+esm" } } </script> <script type="module" src="./js/index.js"></script> </body> </html> index.js import { mat4 } from "gl-matrix"; document.addEventListener("DOMContentLoaded", function () { // Get the WebGL context const canvas = document.getElementById("webgl-canvas"); const gl = canvas.getContext("webgl"); // Check if WebGL is availablea if (!gl) { console.error("Unable to initialize WebGL. Your browser may not support it."); return; } // Vertex shader program const vsSource = ` attribute vec4 aVertexPosition; uniform mat4 uModelViewMatrix; uniform mat4 uProjectionMatrix; void main(void) { gl_Position = uProjectionMatrix * uModelViewMatrix * aVertexPosition; } `; // Fragment shader program const fsSource = ` void main(void) { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); } `; // Initialize shaders const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource); const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource); // Create program and link shaders const shaderProgram = createProgram(gl, vertexShader, fragmentShader); // Set up the buffers for the cube's vertices const vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); const vertices = [ // Front face -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, // Back face -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); // Set up the position attribute const position = gl.getAttribLocation(shaderProgram, "aVertexPosition"); gl.vertexAttribPointer(position, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(position); // Set the clear color and enable depth testing gl.clearColor(0.0, 0.0, 0.0, 1.0); gl.clearDepth(1.0); gl.enable(gl.DEPTH_TEST); // Set up the perspective matrix const projectionMatrix = mat4.create(); mat4.perspective(projectionMatrix, Math.PI / 4, canvas.width / canvas.height, 0.1, 100.0); // Set up the model-view matrix const modelViewMatrix = mat4.create(); // Set up animation variables let then = 0; // Draw the scene function drawScene(now) { now *= 0.001; // convert to seconds const deltaTime = now - then; then = now; // Rotate the cube mat4.rotateY(modelViewMatrix, modelViewMatrix, deltaTime); // Set the uniform matrices const uModelViewMatrix = gl.getUniformLocation(shaderProgram, "uModelViewMatrix"); const uProjectionMatrix = gl.getUniformLocation(shaderProgram, "uProjectionMatrix"); gl.uniformMatrix4fv(uModelViewMatrix, false, modelViewMatrix); gl.uniformMatrix4fv(uProjectionMatrix, false, projectionMatrix); // Clear the canvas and draw the cube gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.drawArrays(gl.TRIANGLE_FAN, 0, 4); gl.drawArrays(gl.TRIANGLE_FAN, 4, 4); gl.drawArrays(gl.LINE_LOOP, 0, 4); gl.drawArrays(gl.LINE_LOOP, 4, 4); // Request the next animation frame requestAnimationFrame(drawScene); } // Start the animation requestAnimationFrame(drawScene); }); // Helper function to create shaders function createShader(gl, type, source) { const shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { console.error("Shader compilation error:", gl.getShaderInfoLog(shader)); gl.deleteShader(shader); return null; } return shader; } // Helper function to create shader program function createProgram(gl, vertexShader, fragmentShader) { const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { console.error("Shader program linking error:", gl.getProgramInfoLog(program)); gl.deleteProgram(program); return null; } gl.useProgram(program); return program; } Edited December 20, 2023 by 8Observer8 Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted June 2 Author Share Posted June 2 (edited) Perspective camera with mat4.perspective https://plnkr.co/edit/Uzjsuj2e0LyGTnxm?preview <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Perspective camera using pure WebGL 1.0 and JavaScript</title> <style> html, body { overflow: hidden; width: 100%; height: 100%; margin: 0; padding: 0; } #renderCanvas { width: 100%; height: 100%; } </style> </head> <body> <canvas id="renderCanvas" width="300" height="300"></canvas> <script type="importmap"> { "imports": { "gl-matrix": "https://8observer8.github.io/libs/[email protected]/gl-matrix.min.js" } } </script> <script type="module"> import { glMatrix, mat4, } from "gl-matrix"; // Get the WebGL context const canvas = document.getElementById("renderCanvas"); const gl = canvas.getContext("webgl"); // Vertex shader program const vertexShaderSource = ` attribute vec2 aPosition; uniform mat4 uMvpMatrix; void main() { gl_Position = uMvpMatrix * vec4(aPosition, 0.0, 1.0); } `; // Fragment shader program const fragmentShaderSource = ` precision mediump float; void main() { gl_FragColor = vec4(0.058, 0.615, 0.345, 1.0); } `; gl.clearColor(153/255, 220/255, 236/255, 1); // Initialize shaders const vertexShader = createShader(gl.VERTEX_SHADER, vertexShaderSource); const fragmentShader = createShader(gl.FRAGMENT_SHADER, fragmentShaderSource); // Create program and link shaders const shaderProgram = createProgram(vertexShader, fragmentShader); const vertPositions = [ -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, 0.5 ]; const vertPosBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertPosBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertPositions), gl.STATIC_DRAW); // Set up the position attribute const aPositionLocation = gl.getAttribLocation(shaderProgram, "aPosition"); gl.vertexAttribPointer(aPositionLocation, 2, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(aPositionLocation); const uMvpMatrixLocation = gl.getUniformLocation(shaderProgram, "uMvpMatrix"); // Set up the model-view-projection matrix const mvpMatrix = mat4.create(); const modelMatrix = mat4.create(); const viewMatrix = mat4.create(); const projMatrix = mat4.create(); const projViewMatrix = mat4.create(); mat4.lookAt(viewMatrix, [0, 2, 3], [0, 0, 0], [0, 1, 0]); window.onresize = () => { const w = gl.canvas.clientWidth; const h = gl.canvas.clientHeight; gl.canvas.width = w; gl.canvas.height = h; gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); mat4.perspective(projMatrix, glMatrix.toRadian(50), w / h, 0.1, 100); draw(); }; window.onresize(null); function draw() { mat4.identity(modelMatrix); mat4.mul(projViewMatrix, projMatrix, viewMatrix); mat4.rotateX(modelMatrix, modelMatrix, glMatrix.toRadian(90)); mat4.mul(mvpMatrix, projViewMatrix, modelMatrix); gl.uniformMatrix4fv(uMvpMatrixLocation, false, mvpMatrix); gl.clear(gl.COLOR_BUFFER_BIT); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); } // Helper function to create shaders function createShader(type, source) { const shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { console.error("Shader compilation error:", gl.getShaderInfoLog(shader)); gl.deleteShader(shader); return null; } return shader; } // Helper function to create shader program function createProgram(vertexShader, fragmentShader) { const program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { console.error("Shader program linking error:", gl.getProgramInfoLog(program)); gl.deleteProgram(program); return null; } gl.useProgram(program); return program; } </script> </body> </html> Edited June 2 by 8Observer8 Quote Link to comment Share on other sites More sharing options...
8Observer8 Posted July 3 Author Share Posted July 3 Simple triangle using OpenGL ES 2.0, C++, SDL3, and WebAssembly WASM demo How to run SDL3 app on Web with WebAssembly Convert rendering using the SDL3 API to rendering using OpenGL ES 2.0 main.cpp #include <SDL3/SDL.h> #include <SDL3/SDL_main.h> #include <SDL3/SDL_opengles2.h> #include <iostream> #ifdef __EMSCRIPTEN__ #include <emscripten.h> #include <emscripten/html5.h> #endif // __EMSCRIPTEN__ struct AppContext { SDL_Window *window; SDL_GLContext glcontext; SDL_bool app_quit = SDL_FALSE; }; const char *vertexShaderSource = "attribute vec2 aPosition;\n" "void main()\n" "{\n" " gl_Position = vec4(aPosition, 0.0, 1.0);\n" "}\n"; const char *fragmentShaderSource = "void main()\n" "{\n" " gl_FragColor = vec4(0.2, 0.7, 0.3, 1.0);\n" "}\n"; // Helper function for creating shaders GLuint createShader(const char *shaderSource, int shaderType) { GLuint shader = glCreateShader(shaderType); glShaderSource(shader, 1, &shaderSource, NULL); glCompileShader(shader); GLint status; glGetShaderiv(shader, GL_COMPILE_STATUS, &status); if (status == GL_FALSE) { GLint maxLength = 0; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength); std::vector<GLchar> errorLog(maxLength); glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]); glDeleteShader(shader); // Don't leak the shader std::cout << &(errorLog[0]) << std::endl; std::cout << shaderSource << std::endl; } return shader; } // Helper function for creating a shader program GLuint createShaderProgram() { GLuint program = glCreateProgram(); GLuint vShader = createShader(vertexShaderSource, GL_VERTEX_SHADER); GLuint fShader = createShader(fragmentShaderSource, GL_FRAGMENT_SHADER); glAttachShader(program, vShader); glAttachShader(program, fShader); glLinkProgram(program); glUseProgram(program); return program; } // Load a triangle to the video card void initVertexBuffers(GLuint program) { float vertPositions[] = { -0.5f, -0.5f, 0.5f, -0.5f, 0.f, 0.5f }; GLuint vertPosBuffer; glGenBuffers(1, &vertPosBuffer); glBindBuffer(GL_ARRAY_BUFFER, vertPosBuffer); int amount = sizeof(vertPositions) / sizeof(vertPositions[0]); glBufferData(GL_ARRAY_BUFFER, amount * sizeof(GLfloat), vertPositions, GL_STATIC_DRAW); GLint aPositionLocation = glGetAttribLocation(program, "aPosition"); glVertexAttribPointer(aPositionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(aPositionLocation); } int SDL_Fail() { SDL_LogError(SDL_LOG_CATEGORY_CUSTOM, "Error %s", SDL_GetError()); return -1; } int SDL_AppInit(void **appstate, int argc, char *argv[]) { // init the library, here we make a window so we only need the Video capabilities. if (SDL_Init(SDL_INIT_VIDEO)) { return SDL_Fail(); } // create a window SDL_Window *window = SDL_CreateWindow("Window", 352, 430, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); if (!window) { return SDL_Fail(); } SDL_GLContext glcontext = SDL_GL_CreateContext(window); if (!glcontext) { return SDL_Fail(); } // Create a shader program and load a triangle to the video card GLuint program = createShaderProgram(); initVertexBuffers(program); // print some information about the window SDL_ShowWindow(window); { int width, height, bbwidth, bbheight; SDL_GetWindowSize(window, &width, &height); SDL_GetWindowSizeInPixels(window, &bbwidth, &bbheight); SDL_Log("Window size: %ix%i", width, height); SDL_Log("Backbuffer size: %ix%i", bbwidth, bbheight); if (width != bbwidth) { SDL_Log("This is a highdpi environment."); } } // set up the application data *appstate = new AppContext { window, glcontext, }; SDL_Log("Application started successfully!"); return 0; } int SDL_AppEvent(void *appstate, const SDL_Event *event) { auto *app = (AppContext *)appstate; switch (event->type) { case SDL_EVENT_QUIT: { app->app_quit = SDL_TRUE; break; } default: { break; } } return 0; } int SDL_AppIterate(void *appstate) { auto *app = (AppContext *)appstate; glClearColor(0.188f, 0.22f, 0.255f, 1.f); glClear(GL_COLOR_BUFFER_BIT); glDrawArrays(GL_TRIANGLES, 0, 3); SDL_GL_SwapWindow(app->window); return app->app_quit; } void SDL_AppQuit(void *appstate) { auto *app = (AppContext *)appstate; if (app) { SDL_GL_DeleteContext(app->glcontext); SDL_DestroyWindow(app->window); delete app; } SDL_Quit(); SDL_Log("Application quit successfully!"); } Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.