Projeto Virtual Worlds

Computação Gráfica 3D em C

Arquivos Mensais: junho 2017

Usando GLFW3

Ok… faz tempo que não escrevo por aqui… Quero só mostrar que o mudei o framework para inicilização do OpenGL para o GLFW3, que tem alguns recursos interessantes (suporte a múltiplos monitores, por exemplo). O código principal para inicialização do projeto é, agora, este:

/* glfw3_fullscreen.c */
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <GLFW/glfw3.h>
#include <GL/gl.h>

// Defina o "nome" de sua janela aqui...
#define WINDOW_TITLE "My Window"

// Usando FULLHD.
#define WINDOW_WIDTH 1920
#define WINDOW_HEIGHT 1080

// Se formos usar FSAA (ver abaixo).
#define FSAA_SAMPLES 16

// Callbacks.
static void error_callback(int, const char *);
static void key_callback(GLFWwindow *, int, int, int, int);

// A função de desenho de quadros.
static void draw(void);

int main(int argc, char *argv[])
{
  GLFWmonitor *primaryMonitor;
  GLFWwindow *mainWindow;

  glfwSetErrorCallback(error_callback);

  if (!glfwInit())
    return EXIT_FAILURE;

  // Ao sair, certifica-se de chamar glfwTerminate().
  atexit(glfwTerminate);

  // GLFW3 agora exige a criação ou uso do objeto "monitor".
  // Aqui seleciono o monitor principal.
  primaryMonitor = glfwGetPrimaryMonitor();

  // Vamos usar RGBA com 8 bits cada (32 bit planes).
  glfwWindowHint(GLFW_RED_BITS,   8);
  glfwWindowHint(GLFW_GREEN_BITS, 8);
  glfwWindowHint(GLFW_BLUE_BITS,  8);
  glfwWindowHint(GLFW_ALPHA_BITS, 8);

  // 60 fps, double buffering, janela not-resizeable e not decorated, 
  // OpenGL 3.3 context (4.3 não suportado em uma de minhas
  // máquinas de teste), core profile.
  //
  // Alguns desses parâmetros são default, mas ajusto assim mesmo.
  glfwWindowHint(GLFW_REFRESH_RATE,          60);
  glfwWindowHint(GLFW_DOUBLEBUFFER,          true);
  glfwWindowHint(GLFW_RESIZABLE,             false);
  glfwWindowHint(GLFW_DECORATED,             false);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  glfwWindowHint(GLFW_OPENGL_PROFILE,        GLFW_OPENGL_CORE_PROFILE);

  // Se você for usar FULL SCREEN ANTI-ALIASING, ajuste o número de
  // samples aqui:
  //glfwWindowHint(GLFW_SAMPLES, FSAA_SAMPLES);

  // Tenta criar a janela.
  mainWindow = glfwCreateWindow(
                WINDOW_WIDTH, WINDOW_HEIGHT,
                WINDOW_TITLE,
                primaryMonitor,
                NULL);

  if (mainWindow)
  { 
    glfwSetKeyCallback(mainWindow, key_callback);

    glfwMakeContextCurrent(mainWindow);

    glfwShowWindow(mainWindow);

    // Esconde o cursor do mouse.
    glfwSetInputMode(mainWindow, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

    // Loop principal...
    while (!glfwWindowShouldClose(mainWindow))
    {
      // Desenha um quadro aqui.
      draw();
      glfwSwapBuffers(mainWindow);

      // Verifica se há eventos (teclado, mouse, joystick, ...)
      // pendentes.
      glfwPollEvents();
    }

    // Destrói a janela.
    glfwDestroyWindow(mainWindow);
  }
  else
    return EXIT_FAILURE;

  return EXIT_SUCCESS;
}

void error_callback(int error, const char *description)
{
  fprintf(stderr, "Error: %s\n", description);
}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
  // Termina o loop principal se apertar ESC.
  if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
    glfwSetWindowShouldClose(window, true);
}

// Função simples: Limpa o buffer.
void draw(void)
{
  glClear(GL_COLOR_BUFFER_BIT);
  glFlush();
}

Não mudou grandes coisas em relação ao GLFW2. Para compilar esse cara é necessário instalar o pacote libglfw3-dev e usar o seguinte Makefile:

CFLAGS=-O2 -fno-stack-protector -march=native `pkg-config --cflags glfw3 gl`
LDFLAGS=-O2 -s
LIBS=`pkg-config --libs glfw3 gl`

all: glfw3_fullscreen

glfw3_fullscreen: glfw3_fullscreen.o
	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)

glfw3_fullscreen.o: glfw3_fullscreen.c

Obviamente que as opções -fno-stack-protector e -march=native são opcionais e só as coloquei ai para gerar código mais otimizado.