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

Author Topic: Problem with VertexArrays and shaders  (Read 1217 times)

0 Members and 1 Guest are viewing this topic.

rfthejakohead

  • Newbie
  • *
  • Posts: 2
    • View Profile
Problem with VertexArrays and shaders
« on: February 18, 2016, 04:14:45 pm »
Hello! I'm doing a lighting system and I've been trying to apply shaders to a vertex array by doing the following. I generate the vertex array of the tilemap, generate the vertex array of the lightmap and draw it to a rendertexture and finally apply a shader to the tilemap which does a hard light blend of the tiles and the lights... but it doesn't work and I can't figure out where the problem is...

Minimal code:
#include "SFML/Graphics.hpp"
int main() {
        sf::Texture tileMapTex;
        tileMapTex.loadFromFile("tile.png");
        sf::Shader lightShader;
        lightShader.loadFromFile("shader.frag", sf::Shader::Fragment);
        sf::RenderWindow window(sf::VideoMode(200, 100), "Shader problem", sf::Style::Close);
        while (window.isOpen()) {
                sf::Event event;
                while (window.pollEvent(event)) {
                        if(event.type == sf::Event::Closed)
                                window.close();
                }
                window.clear(sf::Color(255, 127, 0));
                sf::VertexArray lightvertex(sf::PrimitiveType::Quads,10 * 10 * 4),
                                         tileVA(sf::PrimitiveType::Quads,10 * 10 * 4);
                sf::RenderTexture lightMapTex;
                unsigned int tileN = 0, lightN = 0;
                for (unsigned int x = 0; x < 10; ++x) {
                        for (unsigned int y = 0; y < 10; ++y) {
                                tileVA[tileN].position = sf::Vector2f(x * 8, y * 8);
                                tileVA[tileN].texCoords = sf::Vector2f(0, 0);
                                tileVA[tileN + 1].position = sf::Vector2f(x * 8 + 8, y * 8);
                                tileVA[tileN + 1].texCoords = sf::Vector2f(7, 0);
                                tileVA[tileN + 2].position = sf::Vector2f(x * 8 + 8, y * 8 + 8);
                                tileVA[tileN + 2].texCoords = sf::Vector2f(7, 7);
                                tileVA[tileN + 3].position = sf::Vector2f(x * 8, y * 8 + 8);
                                tileVA[tileN + 3].texCoords = sf::Vector2f(0, 7);
                                tileN += 4;
                                lightvertex[lightN].position = sf::Vector2f(x * 8, y * 8);
                                lightvertex[lightN].color = sf::Color(127, 127, 127);
                                lightvertex[lightN + 1].position = sf::Vector2f(x * 8 + 8, y * 8);
                                lightvertex[lightN + 1].color = sf::Color(127, 127, 127);
                                lightvertex[lightN + 2].position = sf::Vector2f(x * 8 + 8, y * 8 + 8);
                                lightvertex[lightN + 2].color = sf::Color(127, 127, 127);
                                lightvertex[lightN + 3].position = sf::Vector2f(x * 8, y * 8 + 8);
                                lightvertex[lightN + 3].color = sf::Color(127, 127, 127);
                                lightN+=4;
                        }
                }
                tileVA.resize(tileN);
                lightvertex.resize(lightN);
                lightMapTex.draw(lightvertex);
                lightShader.setParameter("tex", sf::Shader::CurrentTexture);
                lightShader.setParameter("map", lightMapTex.getTexture());
                sf::RenderStates states(&lightShader);
                states.texture = &tileMapTex;
                window.draw(tileVA, states);
                window.display();
        }
}
 

Fragment shader:
uniform sampler2D map;
uniform sampler2D tex;

void main(void)
{
        vec4 mapPix = texture2D(map, gl_TexCoord[0].xy);
        vec4 drawPix = texture2D(tex, gl_TexCoord[0].xy);
        vec4 finalPix;
        if(mapPix.r < 0.5) {
                finalPix.r = 2.0 * mapPix.r * gl_Color.r * drawPix.r;
        }
        else {
                finalPix.r = 1.0 - 2.0 * (1.0 - mapPix.r) * (1.0 - (gl_Color.r * drawPix.r));
        }
        if(mapPix.g < 0.5) {
                finalPix.g = 2.0 * mapPix.g * gl_Color.g * drawPix.g;
        }
        else {
                finalPix.g = 1.0 - 2.0 * (1.0 - mapPix.g) * (1.0 - (gl_Color.g * drawPix.g));
        }
        if(mapPix.b < 0.5) {
                finalPix.b = 2.0 * mapPix.b * gl_Color.b * drawPix.b;
        }
        else {
                finalPix.b = 1.0 - 2.0 * (1.0 - mapPix.b) * (1.0 - (gl_Color.b * drawPix.b));
        }
        finalPix.a = 1.0;
        gl_FragColor = finalPix;
}
 

Note: All tiles are a 8x8 red square, all lights are white and the tile map is 10x10 for this test. Orange is where nothing is rendered (clear color). The result should be only red squares but it outputs black squares. If I replace finalPix with gl_Color * drawPix in the fragment shader for disabling the lights it works fine, so the problem is with the lights.

rfthejakohead

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: Problem with VertexArrays and shaders
« Reply #1 on: February 18, 2016, 06:20:59 pm »
Turns out I forgot to call create() when making the renderTexture and I also forgot to call clear() and display() to update the renderTexture. It still didn't work but I noticed that it was very slow so I now simply use the multiply blend mode and everything works fine.