18.2 C
New York
Sunday, May 4, 2025

My fragment shador is run on every display pixel


That is the primary time I take advantage of this web site and I’m additionally a newbie, I am sorry if what I ask is mindless.

I’m utilizing C ++ and OpenGL to make a primary platform sport. My downside is that the fragments shador is executed in every pixel of the display as a substitute of the rasterized geometry. I’m attempting to make a platform sport with tiles. I’ve a mosaic that’s being represented. At first, mosaic coordinates are in what I name tile area. Then I remodel them into pixel by way of area by multiplying them by the dimensions of the mosaic in pixels, uSize. After having the coordinates within the pixel area, I remodel them into NDC. Then the fragments shader is executed, however for some purpose the fragments shador applies to every pixel on the display. I believe it may be linked to my use of gl_FragCoord.xy Within the fragment shador. This results in the picture within the mosaic by way of the display. Pixel sampling works effectively, for the reason that texture atlas is a matrix of uSize by uSize Textures I simply want to find what the preliminary coordinates of the mosaic can be within the Atlas after which add the coordinates of the place we’re within the mosaic.

That is the feel atlas (overseas pixels had been used for purification):

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

The vertex shador:

#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 major() {
    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 fragments shador:

#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 all the time 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); // Stage 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 shade
    return texture(atlas, uv).rgb;
}

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

Thanks upfront who solutions!

Edit:

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

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

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

// SFML consists of
#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 (similar 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, peak, num_colour_channels;
    stbi_set_flip_vertically_on_load(true);
    unsigned char *information = stbi_load(img_path.c_str(), &width, &peak, &num_colour_channels, 0);
    if (information) {
        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(information);
            return;
        }
        glTexImage2D(GL_TEXTURE_2D, 0, format, width, peak, 0, format, GL_UNSIGNED_BYTE, information);
        glGenerateMipmap(GL_TEXTURE_2D);
    } else {
        std::cout << "Did not load texture: " << img_path << std::endl;
    }
    stbi_image_free(information);
    
    // 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 major() {
    // 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::Model::Shut, contextSettings);
    window.setVerticalSyncEnabled(true);

    if (!gladLoadGL()) {
        std::cerr << "Did not initialize GLAD" << std::endl;
        return -1;
    }

    // Create and cargo shader program.
    GLuint shaderProgram = glCreateProgram();
    load_shader("major", 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;

    // Principal 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.measurement.width;
                windowHeight = occasion.measurement.peak;
                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 solely handles geometry and window. Create a 1×1 sq. within the origin in what I name mosaic area. Use a customized heading to symbolize 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.information(), 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->information(), GL_STATIC_DRAW);
    }

    // Configure vertex attributes
    setupAttributes();

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

    // 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 load shadows and works appropriately, so I didn’t embrace it, and if I assist I’m not transferring within the instance, so I actually doubt that my perspective try is what’s breaking it.

Thanks for answering me!

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles