|
|
|
@ -6,7 +6,14 @@ use Cijber\GraphicsToolkit\GLFW;
|
|
|
|
|
use Cijber\GraphicsToolkit\Utils;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
set_error_handler(function($severity, $message, $file, $line) {
|
|
|
|
|
global $error;
|
|
|
|
|
$error = new RuntimeException("$severity: $message [$file($line)]");
|
|
|
|
|
Fiber::suspend();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
include(__DIR__ . "/../vendor/autoload.php");
|
|
|
|
|
|
|
|
|
|
function main() {
|
|
|
|
|
GL::init();
|
|
|
|
|
|
|
|
|
@ -31,63 +38,66 @@ function main() {
|
|
|
|
|
$window,
|
|
|
|
|
function($window, $width, $height) use (&$viewportHeight, &$viewportWidth) {
|
|
|
|
|
echo "Size: $width x $height\n";
|
|
|
|
|
GL::viewport(0, 0, $viewportWidth = $width, $viewportHeight = $height);
|
|
|
|
|
glViewport(0, 0, $viewportWidth = $width, $viewportHeight = $height);
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
GL::viewport(0, 0, 800, 600);
|
|
|
|
|
glViewport(0, 0, 800, 600);
|
|
|
|
|
|
|
|
|
|
GL::debugMessageCallback(function($source, $type, $id, $severity, $length, $message, $user) {
|
|
|
|
|
glDebugMessageCallback(function($source, $type, $id, $severity, $length, $message, $user) {
|
|
|
|
|
$message = substr($message, 0, $length);
|
|
|
|
|
|
|
|
|
|
var_dump(["source" => $source, "type" => $type, "id" => $id, "severity" => $severity, "message" => $message, "gl" => GL::$lastCall]);
|
|
|
|
|
var_dump(["source" => $source, "type" => $type, "id" => $id, "severity" => $severity, "message" => $message, "call" => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)[2]]);
|
|
|
|
|
}, null);
|
|
|
|
|
|
|
|
|
|
// GL::debugMessageCallback($callback, null);
|
|
|
|
|
// glDebugMessageCallback($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);
|
|
|
|
|
glEnable(GL::DEBUG_OUTPUT);
|
|
|
|
|
glEnable(GL::DEBUG_OUTPUT_SYNCHRONOUS);
|
|
|
|
|
|
|
|
|
|
$vertexShader = GL::createShader(GL::VERTEX_SHADER);
|
|
|
|
|
$vertexShaderSource = file_get_contents(__DIR__ . "/../shaders/vertex.glsl");
|
|
|
|
|
glEnable(GL::BLEND);
|
|
|
|
|
|
|
|
|
|
// glEnable(GL::BLEND);
|
|
|
|
|
glBlendFunc(GL::SRC_ALPHA, GL::ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
|
|
|
|
|
GL::shaderSource($vertexShader, 1, $vertexShaderSource, null);
|
|
|
|
|
$vertexShader = \glCreateShader(GL::VERTEX_SHADER);
|
|
|
|
|
$vertexShaderSource = file_get_contents(__DIR__ . "/../shaders/vertex.glsl");
|
|
|
|
|
|
|
|
|
|
GL::shaderSource($vertexShader, [$vertexShaderSource]);
|
|
|
|
|
|
|
|
|
|
GL::compileShader($vertexShader);
|
|
|
|
|
GL::getShaderiv($vertexShader, GL::COMPILE_STATUS, $success);
|
|
|
|
|
glCompileShader($vertexShader);
|
|
|
|
|
glGetShaderiv($vertexShader, GL::COMPILE_STATUS, Utils::pointer($success, "int32_t"));
|
|
|
|
|
|
|
|
|
|
if ( ! $success) {
|
|
|
|
|
GL::getShaderiv($vertexShader, GL::INFO_LOG_LENGTH, $logLength);
|
|
|
|
|
GL::getShaderInfoLog($vertexShader, $infoLog, $logLength);
|
|
|
|
|
if ( ! $success->cdata) {
|
|
|
|
|
glGetShaderiv($vertexShader, GL::INFO_LOG_LENGTH, Utils::pointer($logLength, "int32_t"));
|
|
|
|
|
glGetShaderInfoLog($vertexShader, $logLength, Utils::null(), Utils::stringBuffer($infoLog, $logLength->cdata));
|
|
|
|
|
die("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n\t$infoLog");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$fragmentShader = GL::createShader(GL::FRAGMENT_SHADER);
|
|
|
|
|
$fragmentShader = glCreateShader(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);
|
|
|
|
|
GL::shaderSource($fragmentShader, [$fragmentShaderSource]);
|
|
|
|
|
glCompileShader($fragmentShader);
|
|
|
|
|
glGetShaderiv($fragmentShader, GL::COMPILE_STATUS, FFI::addr($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");
|
|
|
|
|
if ( ! $success->cdata) {
|
|
|
|
|
glGetShaderiv($fragmentShader, GL::INFO_LOG_LENGTH, Utils::pointer($logLength, "int32_t"));
|
|
|
|
|
glGetShaderInfoLog($fragmentShader, $logLength->cdata, Utils::pointer($result, 'int32_t'), Utils::stringBuffer($infoLog, $logLength->cdata));
|
|
|
|
|
$infoLog = FFI::string($infoLog, $result->cdata);
|
|
|
|
|
die("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n\t{$infoLog}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$shaderProgram = GL::createProgram();
|
|
|
|
|
GL::attachShader($shaderProgram, $vertexShader);
|
|
|
|
|
GL::attachShader($shaderProgram, $fragmentShader);
|
|
|
|
|
GL::linkProgram($shaderProgram);
|
|
|
|
|
$shaderProgram = glCreateProgram();
|
|
|
|
|
glAttachShader($shaderProgram, $vertexShader);
|
|
|
|
|
glAttachShader($shaderProgram, $fragmentShader);
|
|
|
|
|
glLinkProgram($shaderProgram);
|
|
|
|
|
|
|
|
|
|
GL::deleteShader($vertexShader);
|
|
|
|
|
GL::deleteShader($fragmentShader);
|
|
|
|
|
glDeleteShader($vertexShader);
|
|
|
|
|
glDeleteShader($fragmentShader);
|
|
|
|
|
|
|
|
|
|
$vertices = [
|
|
|
|
|
-0.5,
|
|
|
|
@ -102,20 +112,21 @@ function main() {
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$float = Utils::arrayOf('float', $vertices);
|
|
|
|
|
GL::genVertexArrays(1, $VAO);
|
|
|
|
|
GL::genBuffers(1, $VBO);
|
|
|
|
|
|
|
|
|
|
GL::bindVertexArray($VAO);
|
|
|
|
|
|
|
|
|
|
GL::bindBuffer(GL::ARRAY_BUFFER, $VBO);
|
|
|
|
|
GL::bufferData(
|
|
|
|
|
glGenVertexArrays(1, Utils::pointer($VAO, 'uint32_t'));
|
|
|
|
|
glGenBuffers(1, Utils::pointer($VBO, 'uint32_t'));
|
|
|
|
|
$VAO = $VAO->cdata;
|
|
|
|
|
$VBO = $VBO->cdata;
|
|
|
|
|
|
|
|
|
|
glBindVertexArray($VAO);
|
|
|
|
|
glBindBuffer(GL::ARRAY_BUFFER, $VBO);
|
|
|
|
|
glBufferData(
|
|
|
|
|
GL::ARRAY_BUFFER,
|
|
|
|
|
FFI::sizeof($float),
|
|
|
|
|
$float,
|
|
|
|
|
GL::STATIC_DRAW
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
GL::vertexAttribPointer(
|
|
|
|
|
glVertexAttribPointer(
|
|
|
|
|
0,
|
|
|
|
|
3,
|
|
|
|
|
GL::FLOAT,
|
|
|
|
@ -124,10 +135,10 @@ function main() {
|
|
|
|
|
0
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
GL::enableVertexAttribArray(0);
|
|
|
|
|
glEnableVertexAttribArray(0);
|
|
|
|
|
|
|
|
|
|
GL::bindBuffer(GL::ARRAY_BUFFER, 0);
|
|
|
|
|
GL::bindVertexArray(0);
|
|
|
|
|
glBindBuffer(GL::ARRAY_BUFFER, 0);
|
|
|
|
|
glBindVertexArray(0);
|
|
|
|
|
|
|
|
|
|
$textureRow = Cairo::format_stride_for_width(Cairo::FORMAT_RGB24, 400);
|
|
|
|
|
$textureData = FFI::new(FFI::arrayType(FFI::type("unsigned char"), [$textureRow * 400]));
|
|
|
|
@ -142,65 +153,57 @@ function main() {
|
|
|
|
|
Cairo::fill($cairo);
|
|
|
|
|
Cairo::surface_flush($surface);
|
|
|
|
|
|
|
|
|
|
Gl::genTextures(1, $texture);
|
|
|
|
|
GL::bindTexture(GL::TEXTURE_2D, $texture);
|
|
|
|
|
glGenTextures(1, Utils::pointer($texture, "uint32_t"));
|
|
|
|
|
$texture = $texture->cdata;
|
|
|
|
|
glBindTexture(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);
|
|
|
|
|
glTexParameteri(GL::TEXTURE_2D, GL::TEXTURE_WRAP_S, GL::REPEAT); // set texture wrapping to GL_REPEAT (default wrapping method)
|
|
|
|
|
glTexParameteri(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);
|
|
|
|
|
glTexParameteri(GL::TEXTURE_2D, GL::TEXTURE_MIN_FILTER, GL::LINEAR);
|
|
|
|
|
glTexParameteri(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);
|
|
|
|
|
glTexImage2D(GL::TEXTURE_2D, 0, GL::RGBA, 400, 400, 0, GL::BGRA, GL::UNSIGNED_BYTE, $textureData);
|
|
|
|
|
|
|
|
|
|
$vertexShader = GL::createShader(GL::VERTEX_SHADER);
|
|
|
|
|
$vertexShader = glCreateShader(GL::VERTEX_SHADER);
|
|
|
|
|
$vertexShaderSource = file_get_contents(__DIR__ . "/../shaders/sq_vertex_shader.glsl");
|
|
|
|
|
|
|
|
|
|
GL::shaderSource(
|
|
|
|
|
$vertexShader,
|
|
|
|
|
1,
|
|
|
|
|
$vertexShaderSource,
|
|
|
|
|
null
|
|
|
|
|
);
|
|
|
|
|
GL::shaderSource($vertexShader, [$vertexShaderSource]);
|
|
|
|
|
|
|
|
|
|
glCompileShader($vertexShader);
|
|
|
|
|
glGetShaderiv($vertexShader, GL::COMPILE_STATUS, Utils::pointer($success, 'int32_t'));
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
if ( ! $success->cdata) {
|
|
|
|
|
glGetShaderiv($vertexShader, GL::INFO_LOG_LENGTH, Utils::pointer($logLength, "int32_t"));
|
|
|
|
|
glGetShaderInfoLog($vertexShader, $logLength, Utils::null(), Utils::stringBuffer($infoLog, $logLength->cdata));
|
|
|
|
|
die("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n\t$infoLog");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$fragmentShader = GL::createShader(GL::FRAGMENT_SHADER);
|
|
|
|
|
$fragmentShader = glCreateShader(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);
|
|
|
|
|
GL::shaderSource($fragmentShader, [$fragmentShaderSource]);
|
|
|
|
|
glCompileShader($fragmentShader);
|
|
|
|
|
glGetShaderiv($fragmentShader, GL::COMPILE_STATUS, FFI::addr($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");
|
|
|
|
|
|
|
|
|
|
if ( ! $success->cdata) {
|
|
|
|
|
glGetShaderiv($fragmentShader, GL::INFO_LOG_LENGTH, Utils::pointer($logLength, "int32_t"));
|
|
|
|
|
glGetShaderInfoLog($fragmentShader, $logLength->cdata, Utils::pointer($result, 'int32_t'), Utils::stringBuffer($infoLog, $logLength->cdata));
|
|
|
|
|
$infoLog = FFI::string($infoLog, $result->cdata);
|
|
|
|
|
die("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n\t{$infoLog}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$squareProgram = GL::createProgram();
|
|
|
|
|
GL::attachShader($squareProgram, $vertexShader);
|
|
|
|
|
GL::attachShader($squareProgram, $fragmentShader);
|
|
|
|
|
GL::linkProgram($squareProgram);
|
|
|
|
|
$squareProgram = glCreateProgram();
|
|
|
|
|
glAttachShader($squareProgram, $vertexShader);
|
|
|
|
|
glAttachShader($squareProgram, $fragmentShader);
|
|
|
|
|
glLinkProgram($squareProgram);
|
|
|
|
|
|
|
|
|
|
GL::deleteShader($vertexShader);
|
|
|
|
|
GL::deleteShader($fragmentShader);
|
|
|
|
|
glDeleteShader($vertexShader);
|
|
|
|
|
glDeleteShader($fragmentShader);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
$sq = [
|
|
|
|
@ -240,15 +243,18 @@ function main() {
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$float = Utils::arrayOf('float', $sq);
|
|
|
|
|
GL::genVertexArrays(1, $SQUARE_VAO);
|
|
|
|
|
GL::genBuffers(1, $VBO);
|
|
|
|
|
GL::genBuffers(1, $EBO);
|
|
|
|
|
glGenVertexArrays(1, Utils::pointer($SQUARE_VAO, 'uint32_t'));
|
|
|
|
|
$SQUARE_VAO = $SQUARE_VAO->cdata;
|
|
|
|
|
glGenBuffers(1, Utils::pointer($VBO, 'uint32_t'));
|
|
|
|
|
$VBO = $VBO->cdata;
|
|
|
|
|
glGenBuffers(1, Utils::pointer($EBO, 'uint32_t'));
|
|
|
|
|
$EBO = $EBO->cdata;
|
|
|
|
|
|
|
|
|
|
GL::bindVertexArray($SQUARE_VAO);
|
|
|
|
|
glBindVertexArray($SQUARE_VAO);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GL::bindBuffer(GL::ARRAY_BUFFER, $VBO);
|
|
|
|
|
GL::bufferData(
|
|
|
|
|
glBindBuffer(GL::ARRAY_BUFFER, $VBO);
|
|
|
|
|
glBufferData(
|
|
|
|
|
GL::ARRAY_BUFFER,
|
|
|
|
|
FFI::sizeof($float),
|
|
|
|
|
$float,
|
|
|
|
@ -256,46 +262,48 @@ function main() {
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$indices = Utils::arrayOf("unsigned int", [0, 1, 3, 1, 2, 3]);
|
|
|
|
|
GL::bindBuffer(GL::ELEMENT_ARRAY_BUFFER, $EBO);
|
|
|
|
|
GL::bufferData(
|
|
|
|
|
glBindBuffer(GL::ELEMENT_ARRAY_BUFFER, $EBO);
|
|
|
|
|
glBufferData(
|
|
|
|
|
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);
|
|
|
|
|
glVertexAttribPointer(0, 3, GL::FLOAT, 0, 8 * 4, 0);
|
|
|
|
|
glEnableVertexAttribArray(0);
|
|
|
|
|
glVertexAttribPointer(1, 3, GL::FLOAT, 0, 8 * 4, 3 * 4);
|
|
|
|
|
glEnableVertexAttribArray(1);
|
|
|
|
|
glVertexAttribPointer(2, 2, GL::FLOAT, 0, 8 * 4, 6 * 4);
|
|
|
|
|
glEnableVertexAttribArray(2);
|
|
|
|
|
|
|
|
|
|
GL::useProgram($squareProgram);
|
|
|
|
|
$location = GL::getUniformLocation($squareProgram, "ourTexture");
|
|
|
|
|
GL::uniform1i($location, 0);
|
|
|
|
|
$viewportSizeLocation = GL::getUniformLocation($squareProgram, "viewportSize");
|
|
|
|
|
glUseProgram($squareProgram);
|
|
|
|
|
$location = glGetUniformLocation($squareProgram, "ourTexture");
|
|
|
|
|
glUniform1i($location, 0);
|
|
|
|
|
$viewportSizeLocation = glGetUniformLocation($squareProgram, "viewportSize");
|
|
|
|
|
|
|
|
|
|
while ( ! GLFW::windowShouldClose($window)) {
|
|
|
|
|
processInput($window);
|
|
|
|
|
|
|
|
|
|
GL::clearColor(0.2, 0.3, 0.3, 1.0);
|
|
|
|
|
GL::clear(GL::COLOR_BUFFER_BIT);
|
|
|
|
|
glClearColor(0.2, 0.3, 0.3, 1.0);
|
|
|
|
|
glClear(GL::COLOR_BUFFER_BIT);
|
|
|
|
|
|
|
|
|
|
glUseProgram($squareProgram);
|
|
|
|
|
|
|
|
|
|
GL::useProgram($shaderProgram);
|
|
|
|
|
GL::bindVertexArray($VAO);
|
|
|
|
|
GL::drawArrays(GL::TRIANGLES, 0, 3);
|
|
|
|
|
glActiveTexture(GL::TEXTURE0);
|
|
|
|
|
glBindTexture(GL::TEXTURE_2D, $texture);
|
|
|
|
|
|
|
|
|
|
GL::activeTexture(GL::TEXTURE0);
|
|
|
|
|
GL::bindTexture(GL::TEXTURE_2D, $texture);
|
|
|
|
|
glBindVertexArray($VAO);
|
|
|
|
|
glDrawArrays(GL::TRIANGLES, 0, 3);
|
|
|
|
|
|
|
|
|
|
GL::useProgram($squareProgram);
|
|
|
|
|
GL::uniform2i($viewportSizeLocation, $viewportWidth, $viewportHeight);
|
|
|
|
|
GL::bindVertexArray($SQUARE_VAO);
|
|
|
|
|
glActiveTexture(GL::TEXTURE0);
|
|
|
|
|
glBindTexture(GL::TEXTURE_2D, $texture);
|
|
|
|
|
|
|
|
|
|
$f = FFI::new("long long");
|
|
|
|
|
$f->cdata = 0;
|
|
|
|
|
GL::drawElements(GL::TRIANGLES, 6, GL::UNSIGNED_INT, FFI::cast('void *', $f));
|
|
|
|
|
glUseProgram($squareProgram);
|
|
|
|
|
glUniform2i($viewportSizeLocation, $viewportWidth, $viewportHeight);
|
|
|
|
|
glBindVertexArray($SQUARE_VAO);
|
|
|
|
|
|
|
|
|
|
glDrawElements(GL::TRIANGLES, 6, GL::UNSIGNED_INT, 0);
|
|
|
|
|
|
|
|
|
|
GLFW::pollEvents();
|
|
|
|
|
GLFW::swapBuffers($window);
|
|
|
|
@ -310,4 +318,11 @@ function processInput($window) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
main();
|
|
|
|
|
global $error;
|
|
|
|
|
$error = null;
|
|
|
|
|
$fiber = new Fiber(fn() => main());
|
|
|
|
|
$fiber->start();
|
|
|
|
|
|
|
|
|
|
if ($error !== null) {
|
|
|
|
|
throw $error;
|
|
|
|
|
}
|
|
|
|
|