Monday, May 5, 2025
spot_img

My fragment shader is being run on each pixel of the display


That is my first time utilizing this web site and I am a newbie too, so sorry if what I am asking does not make sense.

I’m utilizing C++ and OpenGL to make a fundamental platformer.
My problem is that the fragment shader is being run on each pixel of the display as a substitute of the rasterized geometry. I’m making an attempt to make a platformer with tiles. I’ve a tile that’s being rendered. At first the tile coordinates are in what I name tile area. Then I rework them into pixel by area by multiplying them by the tile’s dimension in pixels, uSize. After having the coordinates in pixel area I rework them to NDC. Then the fragment shader is executed, however for some cause the fragment shader is utilized to each pixel on display. I believe it could be linked to my use of gl_FragCoord.xy within the fragment shader. This results in the picture tiling throughout the display. The pixel sampling is working superb, as the feel atlas is an array of uSize by uSize textures I simply want to determine what the tile’s starting coordinates within the atlas could be then add the coordinates of the place we’re within the tile.

That is the feel atlas (the bizarre pixels have been used for debugging):

enter image description here

And that is a picture of the consequence.
enter image description here

The vertex shader:

#model 330 core
structure(location = 0) in uvec2 aPos;
structure(location = 1) in uint aBlock_id;

flat out uint fTile_ID;

uniform uint uSize;            
uniform vec2 uScreenSize;     
uniform uvec2 uPlayerCoords;

void primary() {
    fTile_ID = aBlock_id;

    // Add perspective
    ivec2 perspectiveCoords = ivec2(aPos) - ivec2(uPlayerCoords);

    // Convert from tile coordinates to display coordinates
    vec2 screenPos = vec2(vec2(ivec2(aPos)) * float(uSize));

    // Convert from display coordinates to NDC [-1,1]
    // Additionally account for facet ratio
    vec2 ndcPos = vec2(
       (screenPos.x / uScreenSize.x) * 2.0 - 1.0,
       (screenPos.y / uScreenSize.y) * 2.0 - 1.0
    );

    gl_Position = vec4(ndcPos, 0.0, 1.0);
}

That is the fragment shader:

#model 330 core

out vec4 FragColor;

uniform uint uSize;   
uniform sampler2D uAtlas;  // Texture atlas containing tiles
flat in uint fTile_ID;      // Tile ID for the present fragment

vec3 sampleAtlasPixel(sampler2D atlas, uint tileID, uint tileSize) {
    // Fragment place in display area (in pixels)
    ivec2 fragCoord = ivec2(gl_FragCoord.xy); 

    // the place we're within the tile vary 0:tileSize
    ivec2 tilePos = fragCoord % ivec2(tileSize); 
    // Because the atlas is an array begin y will at all times be 0 
    ivec2 tileStartPos = ivec2(tileID * tileSize, 0);

    ivec2 samplePos = tileStartPos + tilePos;

    // Get the dimensions of the atlas utilizing textureSize
    ivec2 atlasSize = textureSize(atlas, 0); // Degree 0 for the bottom mipmap stage

    // Convert the pixel place to normalised texture coordinates.
    vec2 uv = vec2(samplePos) / vec2(atlasSize);

    // Pattern and return the atlas coloration
    return texture(atlas, uv).rgb;
}

void primary() {
    vec3 coloration = sampleAtlasPixel(uAtlas, fTile_ID, uSize);
    FragColor = vec4(coloration, 1.0);
}

Thanks prematurely to whoever solutions!

Edit:

As you instructed me within the feedback that is the C++ code that offers with the geometry.

// Embody GLAD after SFML to deal with OpenGL operate pointers
#embrace <glad/glad.h>

#embrace <iostream>
#embrace <cmath>
#embrace <tuple>
#embrace <span>

// SFML contains
#embrace <SFML/Window.hpp>
#embrace <SFML/OpenGL.hpp>

#outline STB_IMAGE_IMPLEMENTATION
#embrace "stb_image.h"

// Customized headers
#embrace "ShaderLoader.hpp"
#embrace "renderer.hpp"
#embrace "participant.hpp"

// Set vertex attribute pointers (identical as earlier than)
void setupAttributes() {
    // Every vertex is 6 bytes: 4 bytes for place (2 x uint16_t) and a couple of bytes for block_id (1 x uint16_t)
    glVertexAttribPointer(0, 2, GL_UNSIGNED_SHORT, GL_FALSE, 6, (void*)0);
    glEnableVertexAttribArray(0);

    glVertexAttribIPointer(1, 1, GL_UNSIGNED_SHORT, 6, (void*)4);
    glEnableVertexAttribArray(1);
}

void set_uniforms(GLuint shaderProgram, std::tuple<uint16_t, uint16_t> screen_dimensions, uint8_t tile_dimensions, Participant participant) {
    GLuint sizeLoc = glGetUniformLocation(shaderProgram, "uSize");
    GLuint screenSizeLoc = glGetUniformLocation(shaderProgram, "uScreenSize");
    GLuint playerCoordsLoc = glGetUniformLocation(shaderProgram, "uPlayerCoords");

    if (sizeLoc != -1) {
        glUniform1ui(sizeLoc, tile_dimensions);
    }
    
    if (screenSizeLoc != -1) {
        glUniform2f(screenSizeLoc, std::get<0>(screen_dimensions), std::get<1>(screen_dimensions));
    }

    if (playerCoordsLoc != -1) {
        glUniform2f(playerCoordsLoc, participant.coordinates.x, participant.coordinates.y);
    }
}

// Load texture from a picture file and bind it to a texture unit.
void load_texture(const GLuint shaderProgram, const std::string& img_path, const std::string& uniform_name, GLint tex_unit) {
    GLuint texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    
    // Set texture wrapping/filtering choices
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);  
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
    
    GLfloat borderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
    glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
    
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    
    int width, top, num_colour_channels;
    stbi_set_flip_vertically_on_load(true);
    unsigned char *knowledge = stbi_load(img_path.c_str(), &width, &top, &num_colour_channels, 0);
    if (knowledge) {
        GLenum format;
        if (num_colour_channels == 1)
            format = GL_RED;
        else if (num_colour_channels == 3)
            format = GL_RGB;
        else if (num_colour_channels == 4)
            format = GL_RGBA;
        else {
            std::cout << "Unsupported variety of color channels" << std::endl;
            stbi_image_free(knowledge);
            return;
        }
        glTexImage2D(GL_TEXTURE_2D, 0, format, width, top, 0, format, GL_UNSIGNED_BYTE, knowledge);
        glGenerateMipmap(GL_TEXTURE_2D);
    } else {
        std::cout << "Didn't load texture: " << img_path << std::endl;
    }
    stbi_image_free(knowledge);
    
    // Activate the feel unit and bind the feel
    glActiveTexture(GL_TEXTURE0 + tex_unit);
    glBindTexture(GL_TEXTURE_2D, texture);
    
    // Set the uniform within the shader to the corresponding texture unit
    GLuint textureUniformLocation = glGetUniformLocation(shaderProgram, uniform_name.c_str());
    glUniform1i(textureUniformLocation, tex_unit);
}

struct Vertex {
    uint16_t place[2]; // 2D place
    uint16_t tile_id;    // Block identifier
};

int primary() {
    // Create an SFML window with an OpenGL context.
    sf::ContextSettings contextSettings;
    contextSettings.depthBits = 24;
    contextSettings.stencilBits = 8;
    // OpenGL model 3.3 (core profile)
    contextSettings.majorVersion = 3;
    contextSettings.minorVersion = 3;
    contextSettings.attributeFlags = sf::ContextSettings::Core;

    unsigned int windowWidth = 800;
    unsigned int windowHeight = 800;
    sf::Window window(sf::VideoMode(windowWidth, windowHeight), "SFML OpenGL", sf::Fashion::Shut, contextSettings);
    window.setVerticalSyncEnabled(true);

    if (!gladLoadGL()) {
        std::cerr << "Didn't initialize GLAD" << std::endl;
        return -1;
    }

    // Create and cargo shader program.
    GLuint shaderProgram = glCreateProgram();
    load_shader("primary", shaderProgram);

    // Outline vertices and indices.
    Vertex vertices[] = {
        { {0, 0}, 1 },
        { {1, 0}, 1 },
        { {1, 1}, 1 },
        { {0, 1}, 1 }
    };

    GLuint indices[] = {
        0, 1, 2,  // First triangle
        0, 2, 3   // Second triangle
    };

    // Load texture and outline tile dimensions.
    uint8_t tile_dimensions = 64;
    load_texture(shaderProgram, "./belongings/atlas.png", "uAtlas", 0);

    Participant participant;

    // Essential render loop.
    bool operating = true;
    sf::Clock clock;
    whereas (operating) {
        // Course of SFML occasions.
        sf::Occasion occasion;
        whereas (window.pollEvent(occasion)) {
            if (occasion.sort == sf::Occasion::Closed)
                operating = false;
            // Replace viewport on window resize.
            if (occasion.sort == sf::Occasion::Resized) {
                windowWidth = occasion.dimension.width;
                windowHeight = occasion.dimension.top;
                glViewport(0, 0, windowWidth, windowHeight);
            }
        }
        sf::Time deltaTime = clock.restart(); // Get the time for the reason that final body
        float deltaSeconds = deltaTime.asSeconds(); // Convert to seconds
        participant.transfer(deltaSeconds);
        // Clear the display.
        glClearColor(0.07f, 0.13f, 0.17f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        // Replace uniforms with the present window dimensions.
        std::tuple<uint16_t, uint16_t> screen_dimensions(windowWidth, windowHeight);
        set_uniforms(shaderProgram, screen_dimensions, tile_dimensions, participant);

        std::span<Vertex> vertexSpan(vertices, sizeof(vertices) / sizeof(vertices[0]));
        std::span<GLuint> indexSpan(indices, sizeof(indices) / sizeof(indices[0]));

        // Render utilizing customized renderer.
        render(shaderProgram, vertexSpan, setupAttributes, indexSpan);

        // Show the rendered body.
        window.show();
    }

    // Cleanup.
    glDeleteProgram(shaderProgram);
    window.shut();

    return 0;
}

This code simply handles the geometry and and the window. It creates a 1×1 sq. on the origin in what I name tile area. It the makes use of a customized header to render the geometry.

#ifndef RENDERER
#outline RENDERER
#embrace <string>
#embrace <non-compulsory>

template<typename T>
void render(GLuint shaderProgram, std::span<T> vertices, void (*setupAttributes)(), const std::non-compulsory<std::span<GLuint>>& indices = std::nullopt) {
    glUseProgram(shaderProgram);
    
    // Generate buffers each body
    GLuint VAO, VBO, EBO;
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);
    if (indices) glGenBuffers(1, &EBO);

    // Bind VAO
    glBindVertexArray(VAO);

    // Setup VBO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, vertices.size_bytes(), vertices.knowledge(), GL_STATIC_DRAW);

    // Setup EBO if indices exist
    if (indices) {
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices->size_bytes(), indices->knowledge(), GL_STATIC_DRAW);
    }

    // Configure vertex attributes
    setupAttributes();

    // Draw command
    if (indices) {
        glDrawElements(GL_TRIANGLES, indices->dimension(), GL_UNSIGNED_INT, 0);
    } else {
        glDrawArrays(GL_TRIANGLES, 0, vertices.dimension());
    }

    // Cleanup
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    if (indices) glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
    
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    if (indices) glDeleteBuffers(1, &EBO);
}

#endif

ShaderLoader.hpp simply hundreds shaders and it really works correctly so I did not embrace it, and if it helps I’m not transferring within the instance, so i actually doubt that my try at perspective is what’s breaking it.

Thanks for answering me!

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisement -spot_img

Latest Articles