Welcome, Guest. Please login or register. Did you miss your activation email?

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - jokoon

Pages: [1]
1
General / Making SFML work with WSL2
« on: November 13, 2021, 12:59:04 pm »
WSL2 now supports gui applications!

Since I was quite annoyed by visual studio, I decided to use WSL2 and make as a dev environnement. I've read it works on win10 not only win11.

Installing WSL is pretty straightforward, I'll let you do it. I reinstalled my WSL image and added the WSL kernel update provided by microsoft.

sudo apt install libsfml-dev
works.


My make script builds fine.

I'm now getting:

Failed to open X11 display; make sure the DISPLAY environment variable is set correctly
Aborted

I tried
export DISPLAY=:0
and other things, I installed vcxsrv.exe, and I still get the error.

Then you must do

export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0
export LIBGL_ALWAYS_INDIRECT=0

In your WSL terminal.

Then run xlaunch.exe and tick the right boxes like in the linked image.



It works!

2
The goal here is to create noise, render on a framebuffer, pull the data on the CPU (done in pull()). I don't need to do further rendering with opengl in the loop, I only need it at the beginning.

I load glad after initializing my SFML window, and my opengl code works fine.

The problem is drawing things with SFML again.

I've read the example and the tutorial but I fail to understand what is going wrong...

Here is the code.

Shader class

#ifndef SHADER_H
#define SHADER_H

#include <glad/glad.h>
#include <glm/glm.hpp>

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
namespace gl_things {
    class Shader
    {
    public:
        unsigned int ID;
        // constructor generates the shader on the fly
        // ------------------------------------------------------------------------
        Shader() {}
        Shader(const char* vertexPath, const char* fragmentPath)
        {
            // 1. retrieve the vertex/fragment source code from filePath
            std::string vertexCode;
            std::string fragmentCode;
            std::ifstream vShaderFile;
            std::ifstream fShaderFile;
            // ensure ifstream objects can throw exceptions:
            vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
            fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
            try
            {
                // open files
                vShaderFile.open(vertexPath);
                fShaderFile.open(fragmentPath);
                std::stringstream vShaderStream, fShaderStream;
                // read file's buffer contents into streams
                vShaderStream << vShaderFile.rdbuf();
                fShaderStream << fShaderFile.rdbuf();
                // close file handlers
                vShaderFile.close();
                fShaderFile.close();
                // convert stream into string
                vertexCode = vShaderStream.str();
                fragmentCode = fShaderStream.str();
            }
            catch (std::ifstream::failure e)
            {
                std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
            }
            const char* vShaderCode = vertexCode.c_str();
            const char * fShaderCode = fragmentCode.c_str();
            // 2. compile shaders
            unsigned int vertex, fragment;
            int success;
            char infoLog[512];
            // vertex shader
            vertex = glCreateShader(GL_VERTEX_SHADER);
            glShaderSource(vertex, 1, &vShaderCode, NULL);
            glCompileShader(vertex);
            checkCompileErrors(vertex, "VERTEX");
            // fragment Shader
            fragment = glCreateShader(GL_FRAGMENT_SHADER);
            glShaderSource(fragment, 1, &fShaderCode, NULL);
            glCompileShader(fragment);
            checkCompileErrors(fragment, "FRAGMENT");
            // shader Program
            ID = glCreateProgram();
            glAttachShader(ID, vertex);
            glAttachShader(ID, fragment);
            glLinkProgram(ID);
            checkCompileErrors(ID, "PROGRAM");
            // delete the shaders as they're linked into our program now and no longer necessery
            glDeleteShader(vertex);
            glDeleteShader(fragment);

        }
        // activate the shader
        // ------------------------------------------------------------------------
        void use() const
        {
            glUseProgram(ID);
        }
        // utility uniform functions
        // ------------------------------------------------------------------------
        void setBool(const std::string &name, bool value) const
        {
            glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
        }
        // ------------------------------------------------------------------------
        void setInt(const std::string &name, int value) const
        {
            glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
        }
        // ------------------------------------------------------------------------
        void setFloat(const std::string &name, float value) const
        {
            glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
        }
        // ------------------------------------------------------------------------
        void setVec2(const std::string &name, const glm::vec2 &value) const
        {
            glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
        }
        void setVec2(const std::string &name, float x, float y) const
        {
            glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y);
        }
        // ------------------------------------------------------------------------
        void setVec3(const std::string &name, const glm::vec3 &value) const
        {
            glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
        }
        void setVec3(const std::string &name, float x, float y, float z) const
        {
            glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z);
        }
        // ------------------------------------------------------------------------
        void setVec4(const std::string &name, const glm::vec4 &value) const
        {
            glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
        }
        void setVec4(const std::string &name, float x, float y, float z, float w) const
        {
            glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w);
        }
        // ------------------------------------------------------------------------
        void setMat2(const std::string &name, const glm::mat2 &mat) const
        {
            glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
        }
        // ------------------------------------------------------------------------
        void setMat3(const std::string &name, const glm::mat3 &mat) const
        {
            glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
        }
        // ------------------------------------------------------------------------
        void setMat4(const std::string &name, const glm::mat4 &mat) const
        {
            glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
        }

    private:
        // utility function for checking shader compilation/linking errors.
        // ------------------------------------------------------------------------
        void checkCompileErrors(GLuint shader, std::string type)
        {
            GLint success;
            GLchar infoLog[1024];
            if (type != "PROGRAM")
            {
                glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
                if (!success)
                {
                    glGetShaderInfoLog(shader, 1024, NULL, infoLog);
                    std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
                }
            }
            else
            {
                glGetProgramiv(shader, GL_LINK_STATUS, &success);
                if (!success)
                {
                    glGetProgramInfoLog(shader, 1024, NULL, infoLog);
                    std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
                }
            }
        }
    };
}
#endif

actual code

//#include "stdafx.h"
#include <algorithm>

#include <iostream>
#include <string>
#include <vector>
#include <map>

#include <SFML/Graphics.hpp>

//#include <SFML/OpenGL.hpp>
//#include <Box2D\Box2D.h>
using namespace std;
using namespace sf;

#include "glad\glad.h"
//#define GLAD_GL_IMPLEMENTATION
//#include "gl.h"

#include "shader_m.h"
#include <SFML\Window\ContextSettings.hpp>

typedef Vector2f Vec2;
typedef Vector2<double> Vec2d;
typedef Vector2i Vec2i;

#define msg(s) cout<< #s << " " << s << endl;

RenderWindow * window;
Vec2i windowsize;

namespace perlin_shading {
    gl_things::Shader ourShader;

    float vertices[] = {
        // positions          // colors           // texture coords
        // 0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
        // 0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
        //-0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
        //-0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left
         1.f,  1.f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 1.0f, // top right
         1.f, -1.f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 0.0f, // bottom right
        -1.f, -1.f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 0.0f, // bottom left
        -1.f,  1.f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 1.0f  // top left
    };
    unsigned int indices[] = {
        0, 1, 3, // first triangle
        1, 2, 3  // second triangle
    };
    unsigned int VBO, VAO, EBO;
    unsigned int texture, tex32F, fbo;

    void init_geom() {
        glGenVertexArrays(1, &VAO);
        glGenBuffers(1, &VBO);
        glGenBuffers(1, &EBO);

        glBindVertexArray(VAO);

        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

        // position attribute
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
        glEnableVertexAttribArray(0);
        // color attribute
        glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
        glEnableVertexAttribArray(1);
        // texture coord attribute
        glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
        glEnableVertexAttribArray(2);

    }
    void init_framebuffer() {
        // texture with internal format `GL_RGBA32F`
        //GLuint tex32F = texture;
        glGenTextures(1, &tex32F);
        glBindTexture(GL_TEXTURE_2D, tex32F);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 300, 300, 0, GL_RED, GL_FLOAT, nullptr);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

        // framebuffer with attached texture
        //fbo = 0;
        glGenFramebuffers(1, &fbo);
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex32F, 0);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);

        {
            // In both cases you should validate the completeness of the frambuffer glCheckFramebufferStatus:
            glBindFramebuffer(GL_FRAMEBUFFER, fbo);
            int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
            if (status != GL_FRAMEBUFFER_COMPLETE) {
                glBindFramebuffer(GL_FRAMEBUFFER, 0);
                msg("glCheckFramebufferStatus error");
            }
            glBindFramebuffer(GL_FRAMEBUFFER, 0);
        }

    }

    void pull() {
        //glBindFramebuffer(GL_FRAMEBUFFER, 0);
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
        {
            glViewport(0, 0, 300, 300);
            // bind Texture
            ourShader.use();
            glBindTexture(GL_TEXTURE_2D, texture);
            //glBindTexture(GL_TEXTURE_2D, tex32F);
            glBindVertexArray(VAO);
            glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
        }

        //glfwSwapBuffers(window);

        // Render the image after glBindFramebuffer(GL_FRAMEBUFFER, fbo). After the rendering by the shader the image is stored in the texture object, because the texture is attached to the color plane of fbo. So at this point the texture can be read by glGetTexImage
        glBindTexture(GL_TEXTURE_2D, tex32F);

        float values[300 * 300];
        //glFinish();
        glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, values);

        float min_val = 1e20, max_val = -1e20;

        for (int i = 0; i < 300; ++i) {
            for (int j = 0; j < 300; ++j) {
                float val = values[i + 300 * j];
                max_val = max(val, max_val);
                min_val = min(val, min_val);
            }
        }
        msg(max_val);
        msg(min_val);
        glBindFramebuffer(GL_FRAMEBUFFER, 0);

    }
    int do_things() {

        window->setActive(true);
        {
            if (!gladLoadGLLoader(reinterpret_cast<GLADloadproc>(sf::Context::getFunction)))
            //if (!gladLoadGL())
            {
                std::cout << "Failed to initialize GLAD" << std::endl;
                return -1;
            }
            ourShader = gl_things::Shader("shaders/quad.vs", "shaders/perlin2.fs");

            init_geom();
            init_framebuffer();
            pull();
        }
        window->setActive(false);

        window->resetGLStates();

    }
}

// initializing the window
void init_window() {
    Vec2i screen_resolution = { int(VideoMode::getDesktopMode().width), int(VideoMode::getDesktopMode().height) };

    windowsize = Vec2i(0.5f*screen_resolution.x, 0.9f*screen_resolution.y);

    // placing the window on the desktop
    Vec2i windowpos;
    VideoMode::getDesktopMode().height;

    windowpos = Vec2i(
        screen_resolution.x - windowsize.x - 10,
        screen_resolution.y - windowsize.y - 40
    );
    //auto opengl = cfg.getvar<Vec2i>("opengl");
    // ContextSettings::Core
    //ContextSettings settings(0, 0, 0, 4, 5);
    ContextSettings settings(0, 0, 0, 3, 3);

    window = new sf::RenderWindow(sf::VideoMode(windowsize.x, windowsize.y), "perlin shader");
    //window = new sf::RenderWindow(sf::VideoMode(windowsize.x, windowsize.y), "perlin shader", 7, settings);
    window->setFramerateLimit(60);
    //frame_duration = 1.0f / 60;
    window->setPosition(windowpos);
}
RectangleShape dadaism;

void draw() {

    window->pushGLStates();
    window->draw(dadaism);
    window->popGLStates();
}

void loop() {

    while (window->isOpen())
    {
        sf::Event event;
        while (window->pollEvent(event))
        {
            switch (event.type)
            {
            case sf::Event::KeyPressed:
                if (event.key.code == sf::Keyboard::Escape)
                    window->close();
                break;
            case sf::Event::Closed:
                window->close();
                break;
            default:
                break;
            }
        }

        window->clear(Color(16, 16, 16));
       
        window->pushGLStates();
        draw();
        window->popGLStates();
       
        window->display();
    }
}
int main(int argc, char*argv[]) {

    dadaism = RectangleShape({ 50,50 });
    init_window();
    perlin_shading::do_things();


    loop();
    return 0;
}
 
fragment shader
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;

out vec3 ourColor;
out vec2 TexCoord;

void main()
{
    gl_Position = vec4(aPos, 1.0);
    ourColor = aColor;
    TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}
 
vertex shader
#version 330 core
out vec4 FragColor;
// out float FragColor;

in vec3 ourColor;
in vec2 TexCoord;


void main(){
    vec3 debugged = vec3(TexCoord.xy,0);
    FragColor = vec4(0.34,0,0, 1.0f);
    // FragColor = 0.34;
}
 



3
I wrote a shader that generates noise, it uses gl_TexCoord[0].xy (a thing generated by SFML) as input and outputs a float for every pixel.

I want the data on the CPU, as an array of 32bits float.

Here is what I'm doing:

    //using opengl 3.0 (I also tried 3.2)
    ContextSettings settings(0, 0, 0, 3, 0);
    sf::RenderWindow window(sf::VideoMode(windowsize.x, windowsize.y),
        "yada", 7, settings
    );


Here I overwrite the texture after the texture is created:

 
#ifndef GL_R32F
#define GL_R32F 0x822E // found this in glad.h for opengl 3.0, easy guess is that this value doesn't change across opengl versions
#endif
auto handle = sprite_perlin.getTexture()->getNativeHandle();
glBindTexture(GL_TEXTURE_2D, handle);
auto size = sprite_perlin.getTexture()->getSize();
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, size.x, size.y, 0, GL_RED, GL_FLOAT, NULL);
        }

Here I read the texture data into values:

       
float values[4096];
// whole_size is the size of the texture, here it is 60
if(whole_size*whole_size < 4096)
    glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, values);

Image brought_back;
brought_back.create(whole_size, whole_size, Color::Red);

float mi = 1e20, ma = -1e20;

for (int i = 0; i < whole_size; ++i) {
    for (int j = 0; j < whole_size; ++j) {
        brought_back.setPixel(i, j, { 0,Uint8(255.f*values[whole_size*i + j]),0 });
        ma = max(values[whole_size*i + j], ma);
        mi = min(values[whole_size*i + j], mi);
    }
}


 

mi and ma are both to 0.0f;

Here is the noise generated when showed on a sprite with the shader (with some color function that takes a float) The shader works as intended, I would just like to retrieve the data as float on the CPU.



Here is a simplified version of the shader:
uniform int texture_size;

float get_value_at(ivec2 pixel_coord) {
    //dummy value
    return 0.34f;
}

void main(){
    ivec2 pix_pos = ivec2(gl_TexCoord[0].xy*texture_size);

    float val = get_value_at(pix_pos);

    gl_FragColor = vec4(val,0,0,1);
}


Here is an updated code, which is using rendertexture to test things out (sorry it's 417 lines, but it should work as is):

//#include "stdafx.h"
#include <random>
#include <algorithm>

#include <iostream>
#include <string>
#include <vector>
#include <map>

#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <SFML/OpenGL.hpp>
//#include <Box2D\Box2D.h>
using namespace std;
using namespace sf;

typedef Vector2f Vec2;
typedef Vector2<double> Vec2d;
typedef Vector2i Vec2i;

float interp(float start, float end, float coef) { return (end - start)*coef + start; }
Vec2 interp(Vec2 start, Vec2 end, float coef) { return coef * (end - start) + start; }

vector<float> seeded_rand_float(unsigned int seed, int many) {
    vector<float> ret;
    std::mt19937 rr;
    std::uniform_real_distribution<float> dist(0, 1.0);

    rr.seed(seed);

    for (int j = 0; j < many; ++j)
        ret.push_back(dist(rr));
    return ret;
}
vector<Vec2> seeded_rand_vec2(unsigned int seed, int many) {
    auto coeffs1 = seeded_rand_float(seed, many * 2);
    vector<Vec2> pushere;
    for (int i = 0; i < many; ++i)
        pushere.push_back(Vec2(coeffs1[2 * i], coeffs1[2 * i + 1]));
    return pushere;
}
#define msg(s) cout<< #s << " " << s << endl;

RenderWindow * window;
RenderTarget * target;
namespace labground {
    Vec2 winsize, wincenter;
    Vec2i windowsize;
    Vec2 mpos_abs, mpos;


    //logfile lf;
    //configfile cfg;
    Transform transf_glob;

    Vec2 tr(Vec2 p) {
        return transf_glob.transformPoint(p);
    };
    Vec2 untr(Vec2 p) {
        return transf_glob.getInverse().transformPoint(p);
    };

    View view, ui_view;
   
    // zooming
    float zoom_mult = 1.5f;
    float zoom_div = 1.0f / zoom_mult;
    float zoomlevel = 1;

    void zoom (Event&e) {
        using namespace labground;
        mpos_abs = window->mapPixelToCoords(Vec2i(mpos), view);

        // msg(view.getSize());
        // msg(view.getCenter());

        //view = window->getView();
        if (e.mouseWheel.delta < 0) {
            zoomlevel *= zoom_mult;
            view.setSize(view.getSize()*zoom_mult);
            auto center = interp(mpos_abs, view.getCenter(), zoom_mult);
            center = Vec2(Vec2i(center));
            view.setCenter(center);
        }
        if (e.mouseWheel.delta > 0) {
            zoomlevel *= zoom_div;
            view.setSize(view.getSize()*zoom_div);
            auto center = interp(mpos_abs, view.getCenter(), zoom_div);
            view.setCenter(center);
        }
        window->setView(view);
    };
}

namespace perlin_shading {
    Shader perlin_shader;

    sf::Texture texture_shader, texture_broughtback;
    sf::Sprite sprite_perlin, sprite_broughtback, sprite_rtext;
    Image img_back;
    typedef Vec2i ivec2;
    typedef Vec2 vec2;

    float sprite_scale;

    int grad_size, grad_quant, whole_size;
    Vec2 gradients[16];
    Vec2 gradients_ctype[4096];
    RenderTexture rtext;

    void init_perlin() {
        perlin_shader.loadFromFile("shaders/perlin-better.frag", sf::Shader::Fragment);
        //perlin_shader.loadFromFile("shaders/" + cfg.getstr("shader_file"), sf::Shader::Fragment);
        //perlin_shader.loadFromFile("shaders/noisebench.vert", "shaders/" + cfg.getstr("shader_file"));
        perlin_shader.setUniform("grad_size", grad_size);
        perlin_shader.setUniform("grad_quant", grad_quant);

        //perlin_shader.setUniformArray("gradients", gradients, grad_quant*grad_quant);
        perlin_shader.setUniformArray("gradients", gradients_ctype, grad_quant*grad_quant);

        //texture.loadFromFile("pics/orxqx6B.png");

        //sprite_perlin.move(wincenter);

        Image img;
        //img.create(400, 400, Color::Black);
        img.create(whole_size, whole_size, Color::Red);
        for (int i = 0; i < 10; ++i) {
            img.setPixel(i * 2, i, Color::Green);
            img.setPixel(i, i * 2, Color::Red);
            img.setPixel(i, i, Color::Yellow);
            img.setPixel(i / 2, i, Color::Cyan);
            img.setPixel(i, i / 2, Color::Magenta);
        }
        texture_shader.loadFromImage(img);
        //shader.setUniform("texture", sf::Shader::CurrentTexture);
        //perlin_shader.setUniform("v_texCoord4D", Glsl::Vec4(1,1,1,1));

        sprite_perlin.setTexture(texture_shader);
        {
#ifndef GL_R32F
#define GL_R32F 0x822E
#endif
            auto handle = sprite_perlin.getTexture()->getNativeHandle();
            glBindTexture(GL_TEXTURE_2D, handle);
            auto size = sprite_perlin.getTexture()->getSize();
            glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, size.x, size.y, 0, GL_RED, GL_FLOAT, NULL);
        }
        sprite_perlin.move(labground::wincenter);
        sprite_perlin.setScale(sprite_scale, sprite_scale);


        //sprite_perlin.setScale(sprite_scale, sprite_scale);
    }

    void pull_data() {
        using namespace perlin_shading;

        float values[4096];
        /*
        void glGetTexImage(
            GLenum target,
            GLint level,
            GLenum format,
            GLenum type,
            GLvoid * pixels);

        void glTexImage2D(      GLenum target,
            GLint level,
            GLint internalformat,
            GLsizei width,
            GLsizei height,
            GLint border,
            GLenum format,
            GLenum type,
            const GLvoid * data);

        void glReadPixels(      GLint x,
            GLint y,
            GLsizei width,
            GLsizei height,
            GLenum format,
            GLenum type,
            GLvoid * data);


            */

        float mi = 1e20, ma = -1e20;

        // format = GL_RED, type = GL_FLOAT
        //window->clear();
        //window->draw(sprite_broughtback);
        if (false) {
            if (whole_size*whole_size < 4096)
            {
                //glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, values);
                //glReadPixels(0, 0, whole_size, whole_size, GL_RED, GL_FLOAT, values);
            }
            Image brought_back;
            brought_back.create(whole_size, whole_size, Color::Red);


            for (int i = 0; i < whole_size; ++i) {
                for (int j = 0; j < whole_size; ++j) {
                    ma = max(values[whole_size*i + j], ma);
                    mi = min(values[whole_size*i + j], mi);
                }
            }
            msg(ma);
            msg(mi);
       
        }

        //texture_broughtback.loadFromImage(brought_back);
        rtext.create(whole_size, whole_size);
       
        {
            rtext.clear();
            rtext.display();
            rtext.draw(sprite_perlin, &perlin_shader);

            sprite_rtext.setTexture(rtext.getTexture());

            glGetTexImage(GL_TEXTURE_2D, 0, GL_RED, GL_FLOAT, values);
        }

        for (int i = 0; i < whole_size; ++i) {
            for (int j = 0; j < whole_size; ++j) {
                ma = max(values[whole_size*i + j], ma);
                mi = min(values[whole_size*i + j], mi);
            }
        }
        msg(ma);
        msg(mi);

        //img_back = rtext.getTexture().copyToImage();
        //texture_broughtback.loadFromImage(img_back);

        //sprite_broughtback.setTexture(texture_broughtback);
       
        // scales and positions
        sprite_broughtback.setScale(sprite_scale, sprite_scale);
        sprite_rtext.setScale(sprite_scale, sprite_scale);
       
        sprite_broughtback.move({ 0,labground::wincenter.y });
        sprite_rtext.move({ labground::wincenter.x,0 });
       
        auto error = glGetError();
        msg(error);
    }

    void init() {
        grad_size = 20;
        grad_quant = 4;
        whole_size = grad_size * (grad_quant - 1);

        if (grad_quant*grad_quant > 4096) { msg("can't send gradients, please allocate a large C-type array in the code below!"); return; }
        {
            int seed = 43123;
            auto rand_v = seeded_rand_vec2(seed, grad_quant*grad_quant);
            for (int i = 0; i < grad_quant*grad_quant; ++i) {
                gradients_ctype[i] = 2.0f*rand_v[i] - Vec2{ 1.f, 1.0f };
            }

        }

        msg(grad_size);
        msg(grad_quant);
        msg(whole_size);

        auto smallest_size = min(labground:: windowsize.x, labground::windowsize.y);
        sprite_scale = 0.5f* smallest_size / whole_size;
        init_perlin();
        pull_data();
    }

    void draw(RenderTarget * target) {
        //target->draw(sprite_perlin, &perlin_shader);
        target->draw(sprite_perlin, &perlin_shader);
        target->draw(sprite_broughtback);
        target->draw(sprite_rtext);
    }
    void mouse_moved(Vec2 mpos_abs) {
        auto pixel = ivec2(mpos_abs / sprite_scale);
        pixel.x = max(0, min(whole_size - 1, pixel.x));
        pixel.y = max(0, min(whole_size - 1, pixel.y));
    }
}

// treating SFML events
void mouse_moved(Vec2 pos) {
};
void mouse_click (sf::Mouse::Button button) {
};
void mouse_release (sf::Mouse::Button button) {
    if (button == Mouse::Button::Left) {
    }
};
void treat_other_event (Event&e) {
    if (e.type == Event::MouseWheelMoved && e.mouseWheel.delta){
        labground::zoom(e);
    }
};
void treat_key_event(Keyboard::Key k) {
    switch (k)
    {
    case Keyboard::E:
        break;
    case Keyboard::I:

        break;
    case Keyboard::Q:
        break;
    case Keyboard::BackSpace:
        break;

    case Keyboard::Space:
        break;

    case Keyboard::S:
        break;
    case Keyboard::Num1:
        break;
    case Keyboard::Num2:
    case Keyboard::Num3:
    case Keyboard::Num4:
    case Keyboard::Num5:
        break;
    }
};
#include <SFML\Window\ContextSettings.hpp>
// initializing the window
void init_window() {
    using namespace labground;
    Vec2i screen_resolution = { int(VideoMode::getDesktopMode().width), int(VideoMode::getDesktopMode().height) };

    windowsize = Vec2i(0.5f*screen_resolution.x, 0.9f*screen_resolution.y);
    //winsize = Vec2(windowsize);
    wincenter = 0.5f*Vec2(windowsize);
   
    // placing the window on the desktop
    Vec2i windowpos;
    VideoMode::getDesktopMode().height;

    windowpos = Vec2i(
        screen_resolution.x - windowsize.x - 10,
        screen_resolution.y - windowsize.y - 40
    );
    //auto opengl = cfg.getvar<Vec2i>("opengl");
    // ContextSettings::Core
    //ContextSettings settings(0, 0, 0, 4, 5);
    ContextSettings settings(0, 0, 0, 3, 0);

    //sf::RenderWindow window(sf::VideoMode(windowsize.x, windowsize.y), "perlin shader");
    window = new sf::RenderWindow(sf::VideoMode(windowsize.x, windowsize.y), "perlin shader", 7, settings);
    window->setFramerateLimit(60);
    //frame_duration = 1.0f / 60;

    window->setPosition(windowpos);

    ui_view = view = window->getDefaultView();

}

void draw() {
    using namespace labground;
    window->setView(view);
    //////////////// OBJECTS THAT CAN BE ZOOMED ////////////////

    perlin_shading::draw(window);

    //////////////// OBJECTS THAT CANNOT BE ZOOMED ////////////////
   
    window->setView(ui_view);
}
void loop() {
    using namespace labground;
    while (window->isOpen())
    {
        sf::Event event;
        while (window->pollEvent(event))
        {
            switch (event.type)
            {
            case sf::Event::KeyPressed:
                if (event.key.code == sf::Keyboard::Escape)
                    window->close();
                treat_key_event(event.key.code);
                break;
            case sf::Event::Closed:
                window->close();
                break;
            case sf::Event::MouseButtonPressed:
                mouse_click(event.mouseButton.button);
                break;
            case sf::Event::MouseButtonReleased:
                mouse_release(event.mouseButton.button);
                break;
            case sf::Event::MouseMoved:
                mpos = Vec2(event.mouseMove.x, event.mouseMove.y);
                mpos_abs = window->mapPixelToCoords(Vec2i(mpos), view);
                mouse_moved(mpos);
                break;
            default:
                treat_other_event(event);
                break;
            }
        }

        window->clear(Color(16,16,16));
        //update();
        draw();
        window->display();
    }

}
int main(int argc, char*argv[]) {
    init_window();
    perlin_shading::init();
    loop();
}

4
Python / Building pysfml on windows?
« on: May 12, 2018, 04:45:37 pm »
Since python is one of my favorite languages and I use it for quick prototyping, I wanted to build pysfml on windows.

I did this on windows 10, with visual studio 2015 and python 3.5.something.

WARNING I am not a maintainer and by no means a build system guru, so if this sounds dirty, it's normal.

swig http://www.swig.org/download.html (windows version) (add its directory in your path so that setup.py can later call it) (required to build cython)

a pre compiled version of sfml, I chose the 64 version

Installing cython

pip install cython

cloning the pysfml repo

git clone https://github.com/Sonkun/python-sfml

and building it

python setup.py install

Editing setup.py

The script needs a few adjustments

line 60 add the include folder line this:

self.compiler.include_dirs.append(os.path.join(self.build_temp, 'C:\\_code\\libs\\SFML-2.5.0\\include'))

and line 81:

library_dirs=[os.path.join('extlibs', 'libs-msvc-universal', arch)]+[os.path.join('C:\\_code\\libs\\SFML-2.5.0\\lib')] if sys.hexversion >= 0x03050000 else [],

Everything builds fine when I run:

python setup.py install

when importing sf, I now have

ImportError: DLL load failed: The specified module could not be found.

5
Feature requests / Making SFML work with web assembly?
« on: November 14, 2017, 02:54:01 pm »
Have anybody tried to build SFML to the WASM format? I've seen that wasm allows opengl calls.

It would be really cool to have SFML run in a browser :)

6
Feature requests / C++ modules for SFML
« on: March 12, 2016, 02:49:59 pm »
I've seen some video presentations of modules. It seems they're available in VS2015, and I guess they are also available with clang.

I just wanted to know if some of you guys tried them, and to poke around to see how cumbersome it would be to build sfml as modules (for VS2015 is seems to revolve around those .ifc files) for vs2015, clang or both. No idea if GCC support them though...

Reminder: modules essentially allows for much faster building times, and in some way are a "standardized" precompiled header.

Usually, instead of

#include <vector>
#include "SFML/Graphics.hpp"

you do

import std.vector
import sf.graphics

I did not try them yet, so I don't know how trivial it would be to use them for a library like SFML...

What do you think?

7
General / Are the examples supposed to work?
« on: November 06, 2014, 03:55:35 pm »
I was trying to learn how to use shader in SFML, I encountered the Effect virtual class, and I wanted to know what were the argument of the update() function and where was it called.

I tried to setup the examples using CMake, I got an error:

CMake Error at ftp/CMakeLists.txt:8 (sfml_add_example):
  Unknown CMake command "sfml_add_example".

I could not find the source of SFML 1.6 either.

So how are those effects class used ? Where can I see the full code of those examples, meaning the main() ?

8
General / Specializing the << operator for SFML types
« on: August 17, 2014, 08:31:36 pm »
I managed to specialize the operator<< for Vector2<> and Color on MSVC 2012, but my code doesn't work on xcode 5.

namespace sf {
    ostream & operator<< (ostream & os, const sf::Color &right)
    {
        os << right.r << " " << right.g << " " << right.b; return os;
    }
    template<typename Type>
    inline ostream& operator<<(ostream& os,const sf::Vector2<Type>& rhs)
    {
        os.precision(2);
        return os<<'['<<rhs.x<<", "<<rhs.y<<']';
    }
}
 

My code is inside a header and inside include guards. I tried with and without inline, with and without namespace sf{}.

I'm getting duplicate symbol error for each .o file that I'm linking.

I'm guessing I'm not the only one specializing this operator. clang and MSVC sure seem to not compile templates the same way. What is working for you ?

9
SFML projects / Some simple "perlin" noise
« on: June 23, 2014, 12:20:18 pm »
There are many noise generators: perlin, brownian, simplex, value noise, etc.

I made this function, it's not a lot of code and the result seems somehow fine. I'm not sure if I can call this perlin noise, it just looks random. It requires C++11, especially for the random generator. I'm not using the standard rand() function since it's not implementation defined, while minstd_rand is.

Here is the result:



Here is the code, you can get different results by changing the seed.

#include <random>
using namespace std;
using namespace sf;
typedef Vector2f Vec2; // I'm lazy
VertexArray glines(Lines); // to show gradients
Sprite spr;
Texture tx;
// this allows the code to generate the same image depending on an integer, and it will still look random. I'm not using a permutation table.
int seed = 23;
// simple dot product
float        prod(Vec2 a, Vec2 b)       { return a.x*b.x + a.y*b.y; }
// linear interpolation between 2 vectors
Vec2         interp(Vec2 start,Vec2 end,float coef){return coef*(end-start)+start;}
// generates an array of float between 0 and 1, depending on a unsigned int seed
vector<float> seeded_rand_float(unsigned int seed, int many){
        vector<float> ret;
        minstd_rand rr; // C++11 template of std::linear_congruential_engine
   
    if(seed%2147483647==0) // those values won't work and will break the generator (look at the definition of minstd_rand)
    {
        seed/=2; // dirty fix
        msg("bad seed !");
    }
        rr.seed(seed);

        for(int j = 0 ; j < many; ++j)
        ret.push_back(float(rr())/0x7fffffff); // making sure values are [0,1]
        return ret;
}

// generates a vector2f, taking two consecutive random float from the function above
vector<Vec2>seeded_rand_vec2(unsigned int seed, int many){
    auto coeffs1 = seeded_rand_float(seed, many*2); // twice as many values
    vector<Vec2> pushere;
    for(int i = 0; i < many; ++i)
        pushere.push_back(Vec2(coeffs1[2*i],coeffs1[2*i+1])); // using consecutive values from the array
    return pushere;
}
void init()
{
        // this is a lambda
   // [this](){ // removed the lambda,
        glines.clear();
        int pixels = 500; // number of pixels in a row
        int divisions = 10; // number of cells in a row
        float cellsize = float(pixels)/divisions; // the size of one cell where interpolation will occur.

        //generates the gradients vectors, gradients vector are random vector place at each corner of the square cells, (they're lattice). I've added +1 because there is one more at the end
        auto randv = seeded_rand_vec2(seed,(divisions+1)*(divisions+1));
        float factor=2.f;// that's not a very relevant variable, but nothing is perfect
        for(auto&a:randv){ // rewrite vector so their range can go from [0,1] to [-1,1] instead
            a*=factor;
            a-=factor*.5f*Vec2(1.f,1.f);
        }
        Image img;
        img.create(pixels,pixels,Color(0,0,0)); // black image of size pixels*pixels
        for(int jj=0;jj<=divisions;++jj){ // this loop just help visualize the gradient vectors using simple lines
            for(int ii=0;ii<=divisions;++ii)
            {
                Vec2
                A = randv[divisions*jj      +ii],
                glines.append(Vertex(Vec2(10,10)+cellsize*Vec2(ii,jj)));
                glines.append(Vertex(Vec2(10,10)+cellsize*Vec2(ii,jj)+A*cellsize*.5f));
            }
        }
       
        for(int j=0;j<=pixels;++j)
        {
            for(int i=0;i<=pixels;++i)
            {
                int ii = int(i/cellsize);
                int jj = int(j/cellsize);
                // here we create 4 vectors, each one describing a corner of the square cell
                // the indexing use is a little painful to understand
                Vec2
                &A = randv[divisions*jj      +ii],
                &B = randv[divisions*jj      +ii+1],
                &C = randv[divisions*(jj+1)  +ii],
                &D = randv[divisions*(jj+1)  +ii+1];

                // those steps generate x,y float values in [0,1], indicating the relative position of the pixel in a square cell
                // for example if the cellsize is 50, the pixel at (142,351), (x,y) will be (float(42/50),float(1/50))
                float x = float(i-cellsize*(i/int(cellsize)))/cellsize; // converting to int is like a floor() call
                float y = float(j-cellsize*(j/int(cellsize)))/cellsize; // (I guess?)
                // interpolate the 4 gradients into one vector, depending on the relative position of the pixel in the cell
                // note that you can change the interp function for smoother results (those weird white artifacts)
                Vec2 grad = interp(interp(A,B,x),interp(C,D,x),y);
                // calculate the pixel value, it's the sum of the dot products between the interpolated gradient, and 4 vectors, which are made with the difference between the pixel relative value, and the corresponding corners.
                float bright =
                prod(grad ,Vec2(x     ,y))+
                prod(grad ,Vec2(1.f-x ,y))+
                prod(grad ,Vec2(x     ,1.f-y))+
                prod(grad ,Vec2(1.f-x ,1.f-y));
               
                bright=abs(bright);//making it positive
                bright*=.25f; // divides by four, since the value is in [0.0,4.0]

                img.setPixel(i,j,Color(255.f*bright,255.f*bright,255.f*bright)); // sets the pixel
            }
        }
        tx.loadFromImage(img);
        spr.setPosition(Vec2(10,10));// shifts the sprite
        spr.setTexture(tx);
       
    //}();
}

void draw(RenderWindow&window)
{
        window.draw(spr);
}

It's not a compile-and-work example, but I made it easier for you to test. It might require many other headers like vector.

The interpolation is linear hence the ghostly white line artifacts between some gradients.

It's not the best implementation you could find, I think there are many errors (for instance, the gradients seem to loop over, the one on the left comes back on the right), but it's short and simple, and sort of look like random noise, I commented so you can understand the steps, because I had quite a lot of trouble understanding online examples, code and explanations, especially how the dot products are calculated.

Tell me what you think and ask about !

I also intend to use this to get a contour as points to draw polygons, to generate forest/grass/lakes/mountain patterns. Noise is interesting, but it's costly.

10
General discussions / About the documentation
« on: March 15, 2014, 10:44:06 am »
I don't want to sound whiny, but why isn't there any downloadable API doc ? I found myself several times without internet, so no doxygen and going through the source code.

I know I could do it myself, but why not provide it in the zip packages ? Would save devs some time...


11
Graphics / Not sure if bug or not, getting division by zero...
« on: November 14, 2013, 03:10:49 pm »
Using SFML 2.1 with MSVC 2012 on windows 7 64 bits. Can't really remember if I'm using the 64 bits version of the SFML lib.

struct menu
{
    //map<string,Sprite> icons;
    vector<Sprite> icons;
    vector<Texture> tx;
    vector<Text> texts;
    Vec2 origin;
    vector<string> filenames;
    void init()
    {
        for(int i = 0; i < 50; ++i)
        {
            tx.push_back(Texture());
            if(!tx.back().loadFromFile("png/beans.png")) cout << "could not open breeagfdso" << endl;
            icons.push_back(Sprite(tx.back()));
        }
        cout << icons.size() << " elems" << endl;
        float
            c_x = icons.begin()->getTextureRect().width+2,
            c_y = icons.begin()->getTextureRect().height+2;
        cout << "cx cy = " << c_x << " " << c_y << endl;
        int i = 0;
        for(auto&a:icons)
        {
            a.setPosition(Vec2((i%4)*c_x, (i/4)*c_y)+origin);
            ++i;
        }

    }
    void draw(RenderWindow&window)
    {
        for(auto&a:icons)
            window.draw(a);
    }
};

I think the code is pretty straightforward. I instantiate a menu and initialize it like this:

struct game
{
menu m;
void init()
{
    m.origin=Vector2f(10,10);
    m.init();
}

This is the error: Integer division by zero.

This previous code crashes if I set i < 3, the third displays fine, and 2 others are white squares. If I use only one texture and many sprites by just putting those 2 lines out of the loop like this:
        tx.push_back(Texture());
        if(!tx.back().loadFromFile("png/beans.png")) cout << "could not open breeagfdso" << endl;
        for(int i = 0; i < 50; ++i)
        {
            icons.push_back(Sprite(tx.back()));
        }
It runs fine and I see those icons displayed many times in rows.

I had a discussion lately on IRC about this, I was told I should use unique_ptr, but I don't think that's a solution since I use plain vectors, not vectors of pointers.

Can somebody tell me if it's a bug, or if the Texture class should not be used plain in a vector ?

Here is the call stack : http://pastebin.com/47bJmH1c

I remember outputing the size of the sprite rectangle like it was advised in one thread, I got some very large int number, but I don't understand why.

Pages: [1]
anything