Hello, sfml, long time no see!
This is the first time I explore sfml 2 in FreeBSD, Because it's a little late for me to know it was in FreeBSD.
I share two programs.
1. The first program, uses std::chrono to calculate FPS.// main.cpp
#include <chrono>
#include <iostream>
#include <string>
#include <SFML/Graphics.hpp>
#include <GLES3/gl3.h>
double getTime() {
static auto start = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::high_resolution_clock::now()-start
).count()*1.0/1000000000;
}
int main() {
sf::ContextSettings cs;
cs.depthBits = 32;
sf::RenderWindow window(sf::VideoMode(800, 500), "FreeBSD & SFML & OpenGL",
sf::Style::Default, cs);
window.setVerticalSyncEnabled(true);
window.setActive();
glClearColor(0.3, 0.4, 0.6, 1.0);
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glClearDepthf(1.0f);
sf::Font font;
font.loadFromFile("./sansation.ttf");
sf::Text text("Pending FPS Calculating ...", font);
text.setPosition(250.0f, 235.0f);
text.setColor(sf::Color(255.0f, 0.0f, 0.0f, 255.0f));
double t1, t2;
t1 = t2 = getTime();
while (window.isOpen()) {
static sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
}
static double fps = 0.0;
static int counter = 0;
++counter;
t2 = getTime();
if (t2-t1 >= 1.0) {
fps = counter/(t2-t1);
t1 = t2;
counter = 0;
text.setString(std::string("FPS: ")+std::to_string(fps));
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
window.draw(text);
window.display();
}
}
// Makefile (Please Install devel/bmake)
CC = clang
CXX = clang++
PROG = practise
SRCS = main.cpp
CXXFLAGS += -stdlib=libc++ -std=c++1y `pkgconf --cflags sfml-all glesv2`
LDFLAGS += -stdlib=libc++ -lc++ -lm `pkgconf --libs sfml-all glesv2`
.include <prog.mk>
2. The second program, EGL and OpenGL ES 3// main.cpp
#include <glm/glm.hpp>
#define GLM_FORCE_RADIANS
#include <glm/ext.hpp>
#include <SFML/Graphics.hpp>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h>
#include <cmath>
#include <cassert>
#include <iostream>
#include <vector>
const int w = 640;
const int h = 480;
GLubyte image[h][w][4];
GLuint texture;
glm::mat4 mMatrix, vMatrix, pMatrix;
GLuint mLocation, vLocation, pLocation;
GLuint vShader, fShader, program;
GLuint vBuffer, iBuffer, array;
inline void makeImage() {
/*
cx = w/2 - 1;
cy = h/2 - 1;
dd = 255/std::max(w, h)
Distance: sqrt( (i-cx)^2 + (j-cy)^2 )
) * dd
*/
float cx = w/2.0f-1.0f;
float cy = h/2.0f-1.0f;
float max_r = std::min(w, h)/2.0f;
float dd = 255.0f/max_r;
for (int j=0; j<h; ++j) {
for (int i=0; i<w; ++i) {
float r = (GLfloat)sqrt( (i-cx)*(i-cx) + (j-cy)*(j-cy) );
if (r < max_r) {
image[j][i][0] = (GLubyte)(255.0f-r*dd);
} else {
image[j][i][0] = GLubyte(0);
}
image[j][i][1] = GLubyte(0);
image[j][i][2] = GLubyte(0);
image[j][i][3] = GLubyte(255);
}
}
}
void loadTexture() {
makeImage();
sf::Image image1;
assert(image1.loadFromFile("./hello.png"));
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
image1.getSize().x, image1.getSize().y, 0,
GL_RGBA,
GL_UNSIGNED_BYTE, image1.getPixelsPtr());
glBindTexture(GL_TEXTURE_2D, 0);
}
void loadMatrices() {
mMatrix = glm::mat4(1.0f);
vMatrix = glm::lookAt(glm::vec3(5.0f, 1.6f, 5.0f), glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 1.0f, 0.0f));
pMatrix = glm::perspective(75.0f, 1.6f, 0.08f, 50.0f);
mLocation = glGetUniformLocation(program, "mMatrix");
vLocation = glGetUniformLocation(program, "vMatrix");
pLocation = glGetUniformLocation(program, "pMatrix");
glUseProgram(program);
glUniformMatrix4fv(mLocation, 1, GL_FALSE, &mMatrix[0][0]);
glUniformMatrix4fv(vLocation, 1, GL_FALSE, &vMatrix[0][0]);
glUniformMatrix4fv(pLocation, 1, GL_FALSE, &pMatrix[0][0]);
glUseProgram(0);
}
void loadShaders() {
const char * vs_code =
"#version 300 es\n"
"layout(location=0) in vec4 inPosition;\n"
"layout(location=1) in vec2 inUV;\n"
"out vec2 exUV;\n"
"uniform mat4 mMatrix, vMatrix, pMatrix;\n"
"void main() {\n"
" gl_Position = pMatrix * vMatrix * mMatrix * inPosition;\n"
" exUV = inUV;\n"
"}\n";
const char * fs_code =
"#version 300 es\n"
"in vec2 exUV;\n"
"out vec3 outColor;\n"
"uniform sampler2D sampler;\n"
"void main() {\n"
" outColor = texture(sampler, exUV).rgb;\n"
"}\n";
vShader = glCreateShader(GL_VERTEX_SHADER);
fShader = glCreateShader(GL_FRAGMENT_SHADER);
program = glCreateProgram();
glShaderSource(vShader, 1, &vs_code, nullptr);
glShaderSource(fShader, 1, &fs_code, nullptr);
glCompileShader(vShader);
glCompileShader(fShader);
glAttachShader(program, vShader);
glAttachShader(program, fShader);
glLinkProgram(program);
}
inline void * offset(int i) {
return (void *)((char *)nullptr + i);
}
void loadBuffers() {
glGenBuffers(1, &vBuffer);
glGenBuffers(1, &iBuffer);
glGenVertexArrays(1, &array);
std::vector<GLfloat> vertices = {
-1.6f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
1.6f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
1.6f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
-1.6f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f
};
std::vector<GLubyte> indices = {
0, 1, 2, 2, 3, 0
};
glBindBuffer(GL_ARRAY_BUFFER, vBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*vertices.size(), &vertices[0],
GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLubyte)*indices.size(),
&indices[0], GL_STATIC_DRAW);
glBindVertexArray(array);
glBindBuffer(GL_ARRAY_BUFFER, vBuffer);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6,
offset(0));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6,
offset(sizeof(GLfloat)*4));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iBuffer);
glBindVertexArray(0);
}
void init() {
loadTexture();
loadShaders();
loadTexture();
loadBuffers();
loadMatrices();
glEnable(GL_DEPTH_TEST);
glClearDepthf(1.0f);
glClearColor(0.3f, 0.5f, 0.7f, 1.0f);
}
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(array);
glBindTexture(GL_TEXTURE_2D, texture);
glUseProgram(program);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, offset(0));
glUseProgram(0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindVertexArray(0);
}
void reshape(int w, int h) {
double w_ratio = w*1.0/h;
int glx, gly, glw, glh;
if (w_ratio > 1.6) {
glw = h*1.6;
glh = h;
glx = (w-glw)/2;
gly = 0;
} else {
glw = w;
glh = w/1.6;
glx = 0;
gly = (h-glh)/2;
}
glViewport(glx, gly, glw, glh);
}
int main() {
sf::RenderWindow window(sf::VideoMode(800, 500), "SFML Window & EGL & FreeBSD");
window.setActive();
EGLBoolean egl_result = EGL_FALSE;
EGLDisplay egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
EGLint egl_major, egl_minor;
egl_result = eglInitialize(egl_display, &egl_major, &egl_minor);
assert(egl_result == EGL_TRUE);
std::clog << "EGL Version " << egl_major << "." << egl_minor << std::endl;
egl_result = eglBindAPI(EGL_OPENGL_ES_API);
assert(egl_result == EGL_TRUE);
std::clog << "Bind OpenGL ES API OK!" << std::endl;
EGLConfig egl_config;
EGLint egl_configNum;
const EGLint egl_configAttribList[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 8,
EGL_NONE
};
egl_result = eglChooseConfig(egl_display, egl_configAttribList,
&egl_config, 1, &egl_configNum);
assert(egl_result == EGL_TRUE && egl_configNum == 1);
EGLSurface egl_surface = eglCreateWindowSurface(egl_display, egl_config,
(EGLNativeWindowType)window.getSystemHandle(), nullptr);
assert(egl_surface != EGL_NO_SURFACE);
const EGLint egl_contextAttribList[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
EGLContext egl_context = eglCreateContext(egl_display, egl_config,
EGL_NO_CONTEXT, egl_contextAttribList);
assert(egl_context != EGL_NO_CONTEXT);
eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
init();
while (window.isOpen()) {
static sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed) {
window.close();
}
if (event.type == sf::Event::Resized) {
reshape(event.size.width, event.size.height);
}
display();
eglSwapBuffers(egl_display, egl_surface);
}
}
eglTerminate(egl_display);
}
// Makefile (Please install devel/bmake)
PROG = egl
SRCS = main.cpp
CC = clang
CXX = clang++
sfmod = sfml-all
CXXFLAGS += -stdlib=libc++ -std=c++1y `pkgconf --cflags egl glesv2 ${sfmod}`
LDFLAGS += -stdlib=libc++ `pkgconf --libs egl glesv2 ${sfmod}` -lc++ -lm
.include <bsd.prog.mk>