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

Author Topic: How to use sf::Shader with multiple textures as a raw shader for OpenGL?  (Read 2857 times)

0 Members and 2 Guests are viewing this topic.

XCemaXX

  • Newbie
  • *
  • Posts: 3
    • View Profile
My shader requires diffuse and normal map textures. How to implement it? I didn't find answer in previous topic.
Is it possible to use sf::Shader with multiple textures as a raw shader for custom OpenGL geometry?

Now I can only load 1 texture, and if I comment sf::Texture::bind(), I will recive black model.
//staff with vertices
std::vector<GLfloat> vertices(3 * 3 * model->nfaces(), 0);
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glEnableVertexAttribArray(0);
GLuint vertexbuffer = 0;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*vertices.size(), vertices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);

//textures
sf::Texture texdif= model->diffusemapT;
sf::Texture::bind(&texdif);
sf::Texture texnormal = model->normalmapT;
glEnable(GL_TEXTURE_2D);
sf::Texture::bind(&texnormal);

//shader
sf::Shader shader;
if (!shader.loadFromFile("Vertex_shader.glsl", "Fragment_shader.glsl")) return 0;
sf::Shader::bind(&shader);

//drawning
shader.setUniform("diffuse", texdif);
shader.setUniform("tangentnm", texnormal);
glDrawArrays(GL_TRIANGLES, 0, vertices.size());
window.display();

Now I use shader only with 1 texture. For code above I get normal map on my model, because it was loaded later. But I want to use this shader:
#version 330 core

out vec3 color;
// Interpolated values from the vertex shaders
in vec3 Normal_cameraspace;
in vec3 LightDirection_cameraspace;
in vec3 tangent_cameraspace;
in vec3 bitangent_cameraspace;
in vec2 UV;

// Textures
uniform sampler2D tangentnm;
uniform sampler2D diffuse;

void main() {
    vec3 n = normalize(Normal_cameraspace);  
    mat3 D = mat3(normalize(tangent_cameraspace), normalize(bitangent_cameraspace), n);
    n = normalize((D*normalize(texture(tangentnm, UV).rgb * 2 - 1)));
    vec3 l = normalize(LightDirection_cameraspace);
    float cosTheta = clamp(dot(n,l), 0, 1);

    color = texture(diffuse, UV).xyz*(0.1 + 1.3*cosTheta);
}

SFML 2.5.1, OpenGL 4.6
« Last Edit: April 03, 2019, 05:46:17 pm by XCemaXX »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Do you ever call sf::Shader::bind(&shader)? That's where textures are bound and mapped to sampler2D variables.
Laurent Gomila - SFML developer

XCemaXX

  • Newbie
  • *
  • Posts: 3
    • View Profile
Yes, I call.
sf::Shader shader;
if (!shader.loadFromFile("Vertex_shader.glsl", "Fragment_shader.glsl")) return 0;
sf::Shader::bind(&shader);
p.s. I have add it to the first post.
« Last Edit: April 03, 2019, 05:45:51 pm by XCemaXX »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
You should definitely provide a complete and minimal example that reproduces the problem, so that we don't have to guess ;)
Laurent Gomila - SFML developer

XCemaXX

  • Newbie
  • *
  • Posts: 3
    • View Profile
Thank you for your advice. I found my mistake.
I called sf::Shader::bind(&shader) before shader.setUniform("diffuse", texdif).
I changed code to:
sf::Texture texdif= model->diffusemapT;
sf::Texture texnormal = model->normalmapT;
glEnable(GL_TEXTURE_2D);
sf::Shader shader;
if (!shader.loadFromFile("Vertex_shader.glsl", "Fragment_shader.glsl")) return 0;
shader.setUniform("diffuse", texdif);
shader.setUniform("tangentnm", texnormal);
sf::Shader::bind(&shader);
But it is strange that I can call other "setUniform" rows after sf::Shader::bind, and it works. For example:
sf::Glsl::Mat4 M1(tmp);
shader.setUniform("M", M1);
And vertex shader uses:
uniform mat4 M;
« Last Edit: April 03, 2019, 05:45:43 pm by XCemaXX »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Uniforms are sent to the shader directly, but textures also need to be bound when the shader runs, which is done in sf::Shader::bind.
Laurent Gomila - SFML developer