$source, "type" => $type, "id" => $id, "severity" => $severity, "message" => $message, "gl" => GL::$lastCall]); }, null); // GL::debugMessageCallback($callback, null); GL::enable(GL::DEBUG_OUTPUT); GL::enable(GL::DEBUG_OUTPUT_SYNCHRONOUS); GL::enable(GL::BLEND); GL::blendFunc(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA); $vertexShader = GL::createShader(GL::VERTEX_SHADER); $vertexShaderSource = file_get_contents(__DIR__ . "/../shaders/vertex.glsl"); GL::shaderSource($vertexShader, 1, $vertexShaderSource, null); GL::compileShader($vertexShader); GL::getShaderiv($vertexShader, GL::COMPILE_STATUS, $success); if ( ! $success) { GL::getShaderiv($vertexShader, GL::INFO_LOG_LENGTH, $logLength); GL::getShaderInfoLog($vertexShader, $infoLog, $logLength); die("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n\t$infoLog"); } $fragmentShader = GL::createShader(GL::FRAGMENT_SHADER); $fragmentShaderSource = file_get_contents( __DIR__ . "/../shaders/fragment.glsl" ); GL::shaderSource($fragmentShader, 1, $fragmentShaderSource, null); GL::compileShader($fragmentShader); GL::getShaderiv($fragmentShader, GL::COMPILE_STATUS, $success); if ( ! $success) { GL::getShaderiv($fragmentShader, GL::INFO_LOG_LENGTH, $logLength); GL::GetShaderInfoLog($fragmentShader, $infoLog, $logLength); die("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n\t$infoLog"); } $shaderProgram = GL::createProgram(); GL::attachShader($shaderProgram, $vertexShader); GL::attachShader($shaderProgram, $fragmentShader); GL::linkProgram($shaderProgram); GL::deleteShader($vertexShader); GL::deleteShader($fragmentShader); $vertices = [ -0.5, -0.5, 0.0, 0.5, -0.5, 0.0, 0.0, 0.5, 0.0, ]; $float = Utils::arrayOf('float', $vertices); GL::genVertexArrays(1, $VAO); GL::genBuffers(1, $VBO); GL::bindVertexArray($VAO); GL::bindBuffer(GL::ARRAY_BUFFER, $VBO); GL::bufferData( GL::ARRAY_BUFFER, FFI::sizeof($float), $float, GL::STATIC_DRAW ); GL::vertexAttribPointer( 0, 3, GL::FLOAT, false, 12, 0 ); GL::enableVertexAttribArray(0); GL::bindBuffer(GL::ARRAY_BUFFER, 0); GL::bindVertexArray(0); $textureRow = Cairo::format_stride_for_width(Cairo::FORMAT_RGB24, 400); $textureData = FFI::new(FFI::arrayType(FFI::type("unsigned char"), [$textureRow * 400])); $surface = Cairo::image_surface_create_for_data($textureData, Cairo::FORMAT_RGB24, 400, 400, $textureRow); $cairo = Cairo::create($surface); Cairo::select_font_face($cairo, "sans-serif", Cairo::FONT_SLANT_NORMAL, Cairo::FONT_SLANT_NORMAL); Cairo::set_font_size($cairo, 50); Cairo::move_to($cairo, 50, 50); Cairo::show_text($cairo, "Hello PHP!"); Cairo::rectangle($cairo, 0, 0, 50, 50); Cairo::fill($cairo); Cairo::surface_flush($surface); Gl::genTextures(1, $texture); GL::bindTexture(GL::TEXTURE_2D, $texture); gl::texParameteri(GL::TEXTURE_2D, GL::TEXTURE_WRAP_S, GL::REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method) gl::texParameteri(GL::TEXTURE_2D, GL::TEXTURE_WRAP_T, GL::REPEAT); // set texture filtering parameters gl::texParameteri(GL::TEXTURE_2D, GL::TEXTURE_MIN_FILTER, GL::LINEAR); gl::texParameteri(GL::TEXTURE_2D, GL::TEXTURE_MAG_FILTER, GL::LINEAR); GL::texImage2D(GL::TEXTURE_2D, 0, GL::RGBA, 400, 400, 0, GL::BGRA, GL::UNSIGNED_BYTE, $textureData); $vertexShader = GL::createShader(GL::VERTEX_SHADER); $vertexShaderSource = file_get_contents(__DIR__ . "/../shaders/sq_vertex_shader.glsl"); GL::shaderSource( $vertexShader, 1, $vertexShaderSource, null ); GL::compileShader($vertexShader); GL::getShaderiv($vertexShader, GL::COMPILE_STATUS, $success); if ( ! $success) { GL::getShaderiv($vertexShader, GL::INFO_LOG_LENGTH, $logLength); GL::getShaderInfoLog($vertexShader, $infoLog, $logLength); die("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n\t$infoLog"); } $fragmentShader = GL::createShader(GL::FRAGMENT_SHADER); $fragmentShaderSource = file_get_contents( __DIR__ . "/../shaders/sq_fragment_shader.glsl" ); GL::shaderSource( $fragmentShader, 1, $fragmentShaderSource, null ); GL::compileShader($fragmentShader); GL::getShaderiv($fragmentShader, GL::COMPILE_STATUS, $success); if ( ! $success) { GL::getShaderiv($fragmentShader, GL::INFO_LOG_LENGTH, $logLength); GL::GetShaderInfoLog($fragmentShader, $infoLog, $logLength); die("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n\t$infoLog"); } $squareProgram = GL::createProgram(); GL::attachShader($squareProgram, $vertexShader); GL::attachShader($squareProgram, $fragmentShader); GL::linkProgram($squareProgram); GL::deleteShader($vertexShader); GL::deleteShader($fragmentShader); $sq = [ // positions // colors // texture coords 0.5, 0.5, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, // top right 0.5, -0.5, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, // bottom right -0.5, -0.5, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, // bottom left -0.5, 0.5, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0 // top left ]; $float = Utils::arrayOf('float', $sq); GL::genVertexArrays(1, $SQUARE_VAO); GL::genBuffers(1, $VBO); GL::genBuffers(1, $EBO); GL::bindVertexArray($SQUARE_VAO); GL::bindBuffer(GL::ARRAY_BUFFER, $VBO); GL::bufferData( GL::ARRAY_BUFFER, FFI::sizeof($float), $float, GL::STATIC_DRAW ); $indices = Utils::arrayOf("unsigned int", [0, 1, 3, 1, 2, 3]); GL::bindBuffer(GL::ELEMENT_ARRAY_BUFFER, $EBO); GL::bufferData( GL::ELEMENT_ARRAY_BUFFER, FFI::sizeof($indices), $indices, GL::STATIC_DRAW, ); GL::vertexAttribPointer(0, 3, GL::FLOAT, false, 8 * 4, 0); GL::enableVertexAttribArray(0); GL::vertexAttribPointer(1, 3, GL::FLOAT, false, 8 * 4, 3 * 4); GL::enableVertexAttribArray(1); GL::vertexAttribPointer(2, 2, GL::FLOAT, false, 8 * 4, 6 * 4); GL::enableVertexAttribArray(2); GL::useProgram($squareProgram); $location = GL::getUniformLocation($squareProgram, "ourTexture"); GL::uniform1i($location, 0); $viewportSizeLocation = GL::getUniformLocation($squareProgram, "viewportSize"); while ( ! GLFW::windowShouldClose($window)) { processInput($window); GL::clearColor(0.2, 0.3, 0.3, 1.0); GL::clear(GL::COLOR_BUFFER_BIT); GL::useProgram($shaderProgram); GL::bindVertexArray($VAO); GL::drawArrays(GL::TRIANGLES, 0, 3); GL::activeTexture(GL::TEXTURE0); GL::bindTexture(GL::TEXTURE_2D, $texture); GL::useProgram($squareProgram); GL::uniform2i($viewportSizeLocation, $viewportWidth, $viewportHeight); GL::bindVertexArray($SQUARE_VAO); $f = FFI::new("long long"); $f->cdata = 0; GL::drawElements(GL::TRIANGLES, 6, GL::UNSIGNED_INT, FFI::cast('void *', $f)); GLFW::pollEvents(); GLFW::swapBuffers($window); } GLFW::terminate(); } function processInput($window) { if (GLFW::getKey($window, GLFW::KEY_ESCAPE) === GLFW::PRESS) { GLFW::setWindowShouldClose($window, 1); } } main();