Home > Enterprise >  OpenGL mix() fragment shader function not working and sample renaming messing with textures
OpenGL mix() fragment shader function not working and sample renaming messing with textures

Time:01-06

I have been going through the learnopengl tutorials recently and was on the texture tutorial. I was going through it and everything was working up until the mix() function was called in the fragment shader. For some reason, I can display both textures separately using texture() and just changing the sampler I use for it (so I know they both work), but can't get them to mix (I get a black screen).

Also, I wanted to rename the ourTexture sampler to something better, but whenever I rename it I get a black screen. I rename it both in the fragment shader and when I call the glGetUniformLocation() function, but for some reason nothing is working. No matter what I do, the texture only shows up if is call the sampler "ourTexture"

Here is the code:

#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#define SCREEN_WIDTH 1080
#define SCREEN_HEIGHT 1080

const char* vertexShaderSource = "#version 330 core\n"
"layout(location = 0) in vec4 positions;\n"
"layout(location = 1) in vec3 a_Colors;\n"
"layout(location = 2) in vec2 tex_Coords;\n"
"out vec4 colors;\n"
"out vec2 texCoords;\n"
"void main()\n"
"{\n"
"   gl_Position = positions;\n"
"   colors = vec4(a_Colors, 1.0);\n"
"   texCoords = tex_Coords;\n"
"}\n";

const char* fragmentShaderSource = "#version 330 core\n"
"in vec4 colors;\n"
"in vec2 texCoords;\n"
"out vec4 Frag_Color;\n"
"uniform sampler2D ourTexture;\n"
"uniform sampler2D smileyTexture;\n"
"void main()\n"
"{\n"
"   Frag_Color = texture(ourTexture, texCoords);\n"  //Mix doesn't work for some reason
"}\n";

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    
    #ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
    #endif

    GLFWwindow* window = glfwCreateWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "Multi-Color Square", NULL, NULL);
    if(window == NULL)
    {
        std::cout << "Failed to create window!" << std::endl;
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);

    int version = gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
    if(version == 0)
    {
        std::cout << "Failed to load glad!" << std::endl;
        glfwTerminate();
        return -1;
    }

    unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    glCompileShader(vertexShader);

    unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    glCompileShader(fragmentShader);

    unsigned int program = glCreateProgram();
    glAttachShader(program, vertexShader);
    glAttachShader(program, fragmentShader);
    glLinkProgram(program);

    glUseProgram(program);

    //Texture loading
    int width, height, nrChannels;
    unsigned char* data = stbi_load("container.jpeg", &width, &height, &nrChannels, 0);

    unsigned int texture;
    glGenTextures(1, &texture); //Generates the texture id
    glBindTexture(GL_TEXTURE_2D, texture);  //Binds the texture
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);   //Sets the texture data
    glGenerateMipmap(GL_TEXTURE_2D);    //Generate a mipmap for the currently bound 2d texture

    stbi_image_free(data);

    stbi_set_flip_vertically_on_load(true); 

    data = stbi_load("awesomeface.png", &width, &height, &nrChannels, 0);

    unsigned int smileyTexture;
    glGenTextures(1, &smileyTexture);
    glBindTexture(GL_TEXTURE_2D, smileyTexture);
    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
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);

    stbi_image_free(data);

    glBindTexture(GL_TEXTURE_2D, 0);

    float verticies[] = {
        //Coords        //Colors           //Textures
        -0.5f, -0.5f,    1.0f, 1.0f, 1.0f,  0.0f, 0.0f,
        0.5f, -0.5f,     0.0f, 1.0f, 0.0f,  1.0f, 0.0f,
        0.5f, 0.5f,      1.0f, 0.0f, 0.0f,  1.0f, 1.0f,
        -0.5f, 0.5f,     0.0f, 0.0f, 1.0f,  0.0f, 1.0f
    };

    unsigned int indicies[] = {
        0, 1, 2,
        0, 2, 3
    };

    unsigned int buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(verticies), verticies, GL_STATIC_DRAW);

    unsigned int vertexPointer;
    glGenVertexArrays(1, &vertexPointer);
    glBindVertexArray(vertexPointer);

    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)0);   //Positions
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(2 * sizeof(float))); //Colors
    glEnableVertexAttribArray(1);

    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)(5 * sizeof(float)));
    glEnableVertexAttribArray(2);

    unsigned int indexBuffer;
    glGenBuffers(1, &indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicies), indicies, GL_STATIC_DRAW);

    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

    glUniform1i(glGetUniformLocation(program, "ourTexture"), 0);    
    glUniform1i(glGetUniformLocation(program, "smileyTexture"), 1); 
    while(!glfwWindowShouldClose(window))
    {
        glClear(GL_COLOR_BUFFER_BIT);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texture);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, smileyTexture);

        glBindVertexArray(vertexPointer);
        glUseProgram(program);

        glDrawElements(GL_TRIANGLES, sizeof(indicies) / sizeof(unsigned int), GL_UNSIGNED_INT, NULL);

        glfwSwapBuffers(window);
        glfwPollEvents();
    }

    glDeleteBuffers(1, &buffer);
    glDeleteBuffers(1, &indexBuffer);
    glDeleteVertexArrays(1, &vertexPointer);
    glfwTerminate();

    return 0;
}

Edit: I call mix like mix(texture(ourTexture, texCoords), texture(smileyTexture, texCoords), 0.2);

However I've also tried mix(texture(ourTexture, texCoords), texture(smileyTexture, texCoords), texture(smileyTexture, texCoords).a * 0.2); as was suggested in the comments on learnopengl but it still doesn't work

CodePudding user response:

ourTexture has 3 color channels (RGB). smileyTexture has 4 color channels (RGBA). You have to mix the RGB channels of the textures depending on the alpha channel of smileyTexture:

vec4 color = texture(ourTexture, texCoords);
vec4 smileyColor = texture(smileyTexture, texCoords);
Frag_Color = vec4(mix(color.rgb, smileyColor.rgb, smileyColor.a), 1.0);
  • Related